diff options
Diffstat (limited to 'board/twinkie/injector.c')
-rw-r--r-- | board/twinkie/injector.c | 603 |
1 files changed, 0 insertions, 603 deletions
diff --git a/board/twinkie/injector.c b/board/twinkie/injector.c deleted file mode 100644 index cae1d3557f..0000000000 --- a/board/twinkie/injector.c +++ /dev/null @@ -1,603 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "adc.h" -#include "common.h" -#include "console.h" -#include "dma.h" -#include "gpio.h" -#include "hooks.h" -#include "hwtimer.h" -#include "injector.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "usb_pd.h" -#include "usb_pd_config.h" -#include "util.h" -#include "watchdog.h" - -/* FSM command/data buffer */ -static uint32_t inj_cmds[INJ_CMD_COUNT]; - -/* Current polarity for sending operations */ -static enum inj_pol inj_polarity = INJ_POL_CC1; - -/* - * CCx Resistors control definition - * - * Resistor control GPIOs : - * CC1_RA A8 - * CC1_RPUSB A13 - * CC1_RP1A5 A14 - * CC1_RP3A0 A15 - * CC2_RPUSB B0 - * CC1_RD B5 - * CC2_RD B8 - * CC2_RA B15 - * CC2_RP1A5 C14 - * CC2_RP3A0 C15 - */ -static const struct res_cfg { - const char *name; - struct config { - enum gpio_signal signal; - uint32_t flags; - } cfgs[2]; -} res_cfg[] = { - [INJ_RES_NONE] = {"NONE"}, - [INJ_RES_RA] = {"RA", {{GPIO_CC1_RA, GPIO_ODR_LOW}, - {GPIO_CC2_RA, GPIO_ODR_LOW} } }, - [INJ_RES_RD] = {"RD", {{GPIO_CC1_RD, GPIO_ODR_LOW}, - {GPIO_CC2_RD, GPIO_ODR_LOW} } }, - [INJ_RES_RPUSB] = {"RPUSB", {{GPIO_CC1_RPUSB, GPIO_OUT_HIGH}, - {GPIO_CC2_RPUSB, GPIO_OUT_HIGH} } }, - [INJ_RES_RP1A5] = {"RP1A5", {{GPIO_CC1_RP1A5, GPIO_OUT_HIGH}, - {GPIO_CC2_RP1A5, GPIO_OUT_HIGH} } }, - [INJ_RES_RP3A0] = {"RP3A0", {{GPIO_CC1_RP3A0, GPIO_OUT_HIGH}, - {GPIO_CC2_RP3A0, GPIO_OUT_HIGH} } }, -}; - -#define CC_RA(cc) (cc < PD_SRC_RD_THRESHOLD) -#define CC_RD(cc) ((cc > PD_SRC_RD_THRESHOLD) && (cc < PD_SRC_VNC)) -#define GET_POLARITY(cc1, cc2) (CC_RD(cc2) || CC_RA(cc1)) - -#ifdef HAS_TASK_SNIFFER -/* we don't have the default DMA handlers */ -void dma_event_interrupt_channel_3(void) -{ - if (STM32_DMA1_REGS->isr & STM32_DMA_ISR_TCIF(STM32_DMAC_CH3)) { - dma_clear_isr(STM32_DMAC_CH3); - task_wake(TASK_ID_CONSOLE); - } -} -DECLARE_IRQ(STM32_IRQ_DMA_CHANNEL_2_3, dma_event_interrupt_channel_3, 3); -#endif - -static void twinkie_init(void) -{ - /* configure TX clock pins */ - gpio_config_module(MODULE_USB_PD, 1); - /* Initialize physical layer */ - pd_hw_init(0, PD_ROLE_SINK); -} -DECLARE_HOOK(HOOK_INIT, twinkie_init, HOOK_PRIO_DEFAULT); - -/* ------ Helper functions ------ */ - -static inline int disable_tracing_save(void) -{ - int tr_enabled = STM32_EXTI_IMR & EXTI_COMP_MASK(0); - - if (tr_enabled) - pd_rx_disable_monitoring(0); - return tr_enabled; -} - -static inline void enable_tracing_ifneeded(int flag) -{ - if (flag) - pd_rx_enable_monitoring(0); -} - -static int send_message(int polarity, uint16_t header, - uint8_t cnt, const uint32_t *data) -{ - int bit_len; - - /* Don't get preempted by the tracing */ - int flag = disable_tracing_save(); - - bit_len = prepare_message(0, header, cnt, data); - /* Transmit the packet */ - pd_start_tx(0, polarity, bit_len); - pd_tx_done(0, polarity); - - enable_tracing_ifneeded(flag); - - return bit_len; -} - -static int send_hrst(int polarity) -{ - int off; - int flag = disable_tracing_save(); - /* 64-bit preamble */ - off = pd_write_preamble(0); - /* Hard-Reset: 3x RST-1 + 1x RST-2 */ - off = pd_write_sym(0, off, 0b0011010101); /* RST-1 = 00111 */ - off = pd_write_sym(0, off, 0b0011010101); /* RST-1 = 00111 */ - off = pd_write_sym(0, off, 0b0011010101); /* RST-1 = 00111 */ - off = pd_write_sym(0, off, 0b0101001101); /* RST-2 = 11001 */ - /* Ensure that we have a final edge */ - off = pd_write_last_edge(0, off); - /* Transmit the packet */ - pd_start_tx(0, polarity, off); - pd_tx_done(0, polarity); - enable_tracing_ifneeded(flag); - - return off; -} - -static void set_resistor(int pol, enum inj_res res) -{ - /* reset everything on one CC to high impedance */ - gpio_set_flags(res_cfg[INJ_RES_RA].cfgs[pol].signal, GPIO_ODR_HIGH); - gpio_set_flags(res_cfg[INJ_RES_RD].cfgs[pol].signal, GPIO_ODR_HIGH); - gpio_set_flags(res_cfg[INJ_RES_RPUSB].cfgs[pol].signal, GPIO_ODR_HIGH); - gpio_set_flags(res_cfg[INJ_RES_RP1A5].cfgs[pol].signal, GPIO_ODR_HIGH); - gpio_set_flags(res_cfg[INJ_RES_RP3A0].cfgs[pol].signal, GPIO_ODR_HIGH); - - /* connect the resistor if needed */ - if (res != INJ_RES_NONE) - gpio_set_flags(res_cfg[res].cfgs[pol].signal, - res_cfg[res].cfgs[pol].flags); -} - -static enum inj_pol guess_polarity(enum inj_pol pol) -{ - int cc1_volt, cc2_volt; - /* polarity forced by the user */ - if (pol == INJ_POL_CC1 || pol == INJ_POL_CC2) - return pol; - /* Auto-detection */ - cc1_volt = pd_adc_read(0, 0); - cc2_volt = pd_adc_read(0, 1); - return GET_POLARITY(cc1_volt, cc2_volt); -} - -/* ------ FSM commands ------ */ - -static void fsm_send(uint32_t w) -{ - uint16_t header = INJ_ARG0(w); - int idx = INJ_ARG1(w); - uint8_t cnt = INJ_ARG2(w); - - /* Buffer overflow */ - if (idx > INJ_CMD_COUNT) - return; - - send_message(inj_polarity, header, cnt, inj_cmds + idx); -} - -static void fsm_wave(uint32_t w) -{ - uint16_t bit_len = INJ_ARG0(w); - int idx = INJ_ARG1(w); - int off = 0; - int nbwords = DIV_ROUND_UP(bit_len, 32); - int i; - int flag; - - /* Buffer overflow */ - if (idx + nbwords > INJ_CMD_COUNT) - return; - - flag = disable_tracing_save(); - - for (i = idx; i < idx + nbwords; i++) - off = encode_word(0, off, inj_cmds[i]); - /* Ensure that we have a final edge */ - off = pd_write_last_edge(0, bit_len); - /* Transmit the packet */ - pd_start_tx(0, inj_polarity, off); - pd_tx_done(0, inj_polarity); - enable_tracing_ifneeded(flag); -} - -static void fsm_wait(uint32_t w) -{ -#ifdef HAS_TASK_SNIFFER - uint32_t timeout_ms = INJ_ARG0(w); - uint32_t min_edges = INJ_ARG12(w); - - wait_packet(inj_polarity, min_edges, timeout_ms * 1000); -#endif -} - -static void fsm_expect(uint32_t w) -{ - uint32_t timeout_ms = INJ_ARG0(w); - uint8_t cmd = INJ_ARG2(w); - - expect_packet(inj_polarity, cmd, timeout_ms * 1000); -} -static void fsm_get(uint32_t w) -{ - int store_idx = INJ_ARG0(w); - int param_idx = INJ_ARG1(w); - uint32_t *store_ptr = inj_cmds + store_idx; - - /* Buffer overflow */ - if (store_idx > INJ_CMD_COUNT) - return; - - switch (param_idx) { - case INJ_GET_CC: - *store_ptr = pd_adc_read(0, 0) | (pd_adc_read(0, 1) << 16); - break; - case INJ_GET_VBUS: - *store_ptr = (ina2xx_get_voltage(0) & 0xffff) | - ((ina2xx_get_current(0) & 0xffff) << 16); - break; - case INJ_GET_VCONN: - *store_ptr = (ina2xx_get_voltage(1) & 0xffff) | - ((ina2xx_get_current(1) & 0xffff) << 16); - break; - case INJ_GET_POLARITY: - *store_ptr = inj_polarity; - break; - default: - /* Do nothing */ - break; - } -} - -static void fsm_set(uint32_t w) -{ - int val = INJ_ARG0(w); - int idx = INJ_ARG1(w); - - switch (idx) { - case INJ_SET_RESISTOR1: - case INJ_SET_RESISTOR2: - set_resistor(idx - INJ_SET_RESISTOR1, val); - break; - case INJ_SET_RECORD: -#ifdef HAS_TASK_SNIFFER - recording_enable(val); -#endif - break; - case INJ_SET_TX_SPEED: - pd_set_clock(0, val * 1000); - break; - case INJ_SET_RX_THRESH: - /* set DAC voltage (Vref = 3.3V) */ - STM32_DAC_DHR12RD = val * 4096 / 3300; - break; - case INJ_SET_POLARITY: - inj_polarity = guess_polarity(val); - break; - case INJ_SET_TRACE: - set_trace_mode(val); - break; - default: - /* Do nothing */ - break; - } -} - -static int fsm_run(int index) -{ - while (index < INJ_CMD_COUNT) { - uint32_t w = inj_cmds[index]; - int cmd = INJ_CMD(w); - switch (cmd) { - case INJ_CMD_END: - return index; - case INJ_CMD_SEND: - fsm_send(w); - break; - case INJ_CMD_WAVE: - fsm_wave(w); - break; - case INJ_CMD_HRST: - send_hrst(inj_polarity); - break; - case INJ_CMD_WAIT: - fsm_wait(w); - break; - case INJ_CMD_GET: - fsm_get(w); - break; - case INJ_CMD_SET: - fsm_set(w); - break; - case INJ_CMD_JUMP: - index = INJ_ARG0(w); - continue; /* do not increment index */ - case INJ_CMD_EXPCT: - fsm_expect(w); - break; - case INJ_CMD_NOP: - default: - /* Do nothing */ - break; - } - index += 1; - watchdog_reload(); - } - return index; -} - -/* ------ Console commands ------ */ - -static int hex8tou32(char *str, uint32_t *val) -{ - char *ptr = str; - uint32_t tmp = 0; - - while (*ptr) { - char c = *ptr++; - if (c >= '0' && c <= '9') - tmp = (tmp << 4) + (c - '0'); - else if (c >= 'A' && c <= 'F') - tmp = (tmp << 4) + (c - 'A' + 10); - else if (c >= 'a' && c <= 'f') - tmp = (tmp << 4) + (c - 'a' + 10); - else - return EC_ERROR_INVAL; - } - if (ptr != str + 8) - return EC_ERROR_INVAL; - *val = tmp; - return EC_SUCCESS; -} - -static int cmd_fsm(int argc, char **argv) -{ - int index; - char *e; - - if (argc < 1) - return EC_ERROR_PARAM2; - - index = strtoi(argv[0], &e, 10); - if (*e) - return EC_ERROR_PARAM2; - index = fsm_run(index); - ccprintf("FSM Done %d\n", index); - - return EC_SUCCESS; -} - - -static int cmd_send(int argc, char **argv) -{ - int pol, cnt, i; - uint16_t header; - uint32_t data[VDO_MAX_SIZE]; - char *e; - int bit_len; - - cnt = argc - 2; - if (argc < 2 || cnt > VDO_MAX_SIZE) - return EC_ERROR_PARAM_COUNT; - - pol = strtoi(argv[0], &e, 10) - 1; - if (*e || pol > 1 || pol < 0) - return EC_ERROR_PARAM2; - header = strtoi(argv[1], &e, 16); - if (*e) - return EC_ERROR_PARAM3; - - for (i = 0; i < cnt; i++) - if (hex8tou32(argv[i+2], data + i)) - return EC_ERROR_INVAL; - - bit_len = send_message(pol, header, cnt, data); - ccprintf("Sent CC%d %04x + %d = %d\n", pol + 1, header, cnt, bit_len); - - return EC_SUCCESS; -} - -static int cmd_cc_level(int argc, char **argv) -{ - ccprintf("CC1 = %d mV ; CC2 = %d mV\n", - pd_adc_read(0, 0), pd_adc_read(0, 1)); - - return EC_SUCCESS; -} - -static int cmd_resistor(int argc, char **argv) -{ - int p, r; - - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - - for (p = 0; p < 2; p++) { - int is_set = 0; - for (r = 0; r < ARRAY_SIZE(res_cfg); r++) - if (strcasecmp(res_cfg[r].name, argv[p]) == 0) { - set_resistor(p, r); - is_set = 1; - break; - } - /* Unknown name : set to No resistor */ - if (!is_set) - set_resistor(p, INJ_RES_NONE); - } - return EC_SUCCESS; -} - -static int cmd_tx_clock(int argc, char **argv) -{ - int freq; - char *e; - - if (argc < 1) - return EC_ERROR_PARAM2; - - freq = strtoi(argv[0], &e, 10); - if (*e) - return EC_ERROR_PARAM2; - pd_set_clock(0, freq); - ccprintf("TX frequency = %d Hz\n", freq); - - return EC_SUCCESS; -} - -static int cmd_rx_threshold(int argc, char **argv) -{ - int mv; - char *e; - - if (argc < 1) - return EC_ERROR_PARAM2; - - mv = strtoi(argv[0], &e, 10); - if (*e) - return EC_ERROR_PARAM2; - - /* set DAC voltage (Vref = 3.3V) */ - STM32_DAC_DHR12RD = mv * 4096 / 3300; - ccprintf("RX threshold = %d mV\n", mv); - - return EC_SUCCESS; -} - -static int cmd_ina_dump(int argc, char **argv, int index) -{ - if (index == 1) { /* VCONN INA is off by default, switch it on */ - ina2xx_write(index, INA2XX_REG_CONFIG, 0x4123); - /* - * wait for the end of conversion : 2x 1.1ms as defined - * by the Vb and Vsh CT bits in the CONFIG register above. - */ - udelay(2200); - } - - ccprintf("%s = %d mV ; %d mA\n", index == 0 ? "VBUS" : "VCONN", - ina2xx_get_voltage(index), ina2xx_get_current(index)); - - if (index == 1) /* power off VCONN INA */ - ina2xx_write(index, INA2XX_REG_CONFIG, 0); - - return EC_SUCCESS; -} - -static int cmd_bufwr(int argc, char **argv) -{ - int idx, cnt, i; - char *e; - - cnt = argc - 1; - if (argc < 2 || cnt > INJ_CMD_COUNT) - return EC_ERROR_PARAM_COUNT; - - idx = strtoi(argv[0], &e, 10); - if (*e || idx + cnt > INJ_CMD_COUNT) - return EC_ERROR_PARAM2; - - for (i = 0; i < cnt; i++) - if (hex8tou32(argv[i+1], inj_cmds + idx + i)) - return EC_ERROR_INVAL; - - return EC_SUCCESS; -} - -static int cmd_bufrd(int argc, char **argv) -{ - int idx, i; - int cnt = 1; - char *e; - - if (argc < 1) - return EC_ERROR_PARAM_COUNT; - - idx = strtoi(argv[0], &e, 10); - if (*e || idx > INJ_CMD_COUNT) - return EC_ERROR_PARAM2; - - if (argc >= 2) - cnt = strtoi(argv[1], &e, 10); - - if (*e || idx + cnt > INJ_CMD_COUNT) - return EC_ERROR_PARAM3; - - for (i = idx; i < idx + cnt; i++) - ccprintf("%08x ", inj_cmds[i]); - ccprintf("\n"); - - return EC_SUCCESS; -} - -static int cmd_sink(int argc, char **argv) -{ - /* - * Jump to the RW section which should contain a firmware acting - * as a USB PD sink - */ - system_run_image_copy(EC_IMAGE_RW); - - return EC_SUCCESS; -} - -static int cmd_trace(int argc, char **argv) -{ - if (argc < 1) - return EC_ERROR_PARAM_COUNT; - - if (!strcasecmp(argv[0], "on") || - !strcasecmp(argv[0], "1")) - set_trace_mode(TRACE_MODE_ON); - else if (!strcasecmp(argv[0], "raw")) - set_trace_mode(TRACE_MODE_RAW); - else if (!strcasecmp(argv[0], "off") || - !strcasecmp(argv[0], "0")) - set_trace_mode(TRACE_MODE_OFF); - else - return EC_ERROR_PARAM2; - - return EC_SUCCESS; -} - -static int command_tw(int argc, char **argv) -{ - if (!strcasecmp(argv[1], "send")) - return cmd_send(argc - 2, argv + 2); - else if (!strcasecmp(argv[1], "fsm")) - return cmd_fsm(argc - 2, argv + 2); - else if (!strcasecmp(argv[1], "bufwr")) - return cmd_bufwr(argc - 2, argv + 2); - else if (!strcasecmp(argv[1], "bufrd")) - return cmd_bufrd(argc - 2, argv + 2); - else if (!strcasecmp(argv[1], "cc")) - return cmd_cc_level(argc - 2, argv + 2); - else if (!strncasecmp(argv[1], "resistor", 3)) - return cmd_resistor(argc - 2, argv + 2); - else if (!strcasecmp(argv[1], "sink")) - return cmd_sink(argc - 2, argv + 2); - else if (!strcasecmp(argv[1], "trace")) - return cmd_trace(argc - 2, argv + 2); - else if (!strcasecmp(argv[1], "txclock")) - return cmd_tx_clock(argc - 2, argv + 2); - else if (!strncasecmp(argv[1], "rxthresh", 8)) - return cmd_rx_threshold(argc - 2, argv + 2); - else if (!strcasecmp(argv[1], "vbus")) - return cmd_ina_dump(argc - 2, argv + 2, 0); - else if (!strcasecmp(argv[1], "vconn")) - return cmd_ina_dump(argc - 2, argv + 2, 1); - else - return EC_ERROR_PARAM1; - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(twinkie, command_tw, - "[send|fsm|cc|resistor|txclock|rxthresh|vbus|vconn]", - "Manual Twinkie tweaking"); |