summaryrefslogtreecommitdiff
path: root/chip/stm32/usb_pd_phy.c
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /chip/stm32/usb_pd_phy.c
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-stabilize-14498.B-ish.tar.gz
In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'chip/stm32/usb_pd_phy.c')
-rw-r--r--chip/stm32/usb_pd_phy.c680
1 files changed, 0 insertions, 680 deletions
diff --git a/chip/stm32/usb_pd_phy.c b/chip/stm32/usb_pd_phy.c
deleted file mode 100644
index 90506d8975..0000000000
--- a/chip/stm32/usb_pd_phy.c
+++ /dev/null
@@ -1,680 +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 "clock.h"
-#include "common.h"
-#include "console.h"
-#include "crc.h"
-#include "dma.h"
-#include "gpio.h"
-#include "hwtimer.h"
-#include "hooks.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-#include "usb_pd.h"
-#include "usb_pd_config.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-#define PD_DATARATE 300000 /* Hz */
-
-/*
- * Maximum size of a Power Delivery packet (in bits on the wire) :
- * 16-bit header + 0..7 32-bit data objects (+ 4b5b encoding)
- * 64-bit preamble + SOP (4x 5b) + message in 4b5b + 32-bit CRC + EOP (1x 5b)
- * = 64 + 4*5 + 16 * 5/4 + 7 * 32 * 5/4 + 32 * 5/4 + 5
- */
-#define PD_BIT_LEN 429
-
-#define PD_MAX_RAW_SIZE (PD_BIT_LEN*2)
-
-/* maximum number of consecutive similar bits with Biphase Mark Coding */
-#define MAX_BITS 2
-
-/* alternating bit sequence used for packet preamble : 00 10 11 01 00 .. */
-#define PD_PREAMBLE 0xB4B4B4B4 /* starts with 0, ends with 1 */
-
-#define TX_CLOCK_DIV ((clock_get_freq() / (2*PD_DATARATE)))
-
-/* threshold for 1 300-khz period */
-#define PERIOD 4
-#define NB_PERIOD(from, to) ((((to) - (from) + (PERIOD/2)) & 0xFF) / PERIOD)
-#define PERIOD_THRESHOLD ((PERIOD + 2*PERIOD) / 2)
-
-static struct pd_physical {
- /* samples for the PD messages */
- uint32_t raw_samples[DIV_ROUND_UP(PD_MAX_RAW_SIZE, sizeof(uint32_t))];
-
- /* state of the bit decoder */
- int d_toggle;
- int d_lastlen;
- uint32_t d_last;
- int b_toggle;
-
- /* DMA structures for each PD port */
- struct dma_option dma_tx_option;
- struct dma_option dma_tim_option;
-
- /* Pointers to timer register for each port */
- timer_ctlr_t *tim_tx;
- timer_ctlr_t *tim_rx;
-} pd_phy[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* keep track of RX edge timing in order to trigger receive */
-static timestamp_t
- rx_edge_ts[CONFIG_USB_PD_PORT_MAX_COUNT][PD_RX_TRANSITION_COUNT];
-static int rx_edge_ts_idx[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* keep track of transmit polarity for DMA interrupt */
-static int tx_dma_polarities[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-void pd_init_dequeue(int port)
-{
- /* preamble ends with 1 */
- pd_phy[port].d_toggle = 0;
- pd_phy[port].d_last = 0;
- pd_phy[port].d_lastlen = 0;
-}
-
-static int wait_bits(int port, int nb)
-{
- int avail;
- stm32_dma_chan_t *rx = dma_get_channel(DMAC_TIM_RX(port));
-
- avail = dma_bytes_done(rx, PD_MAX_RAW_SIZE);
- if (avail < nb) { /* no received yet ... */
- while ((dma_bytes_done(rx, PD_MAX_RAW_SIZE) < nb)
- && !(pd_phy[port].tim_rx->sr & 4))
- ; /* optimized for latency, not CPU usage ... */
- if (dma_bytes_done(rx, PD_MAX_RAW_SIZE) < nb) {
- CPRINTS("PD TMOUT RX %d/%d",
- dma_bytes_done(rx, PD_MAX_RAW_SIZE), nb);
- return -1;
- }
- }
- return nb;
-}
-
-int pd_dequeue_bits(int port, int off, int len, uint32_t *val)
-{
- int w;
- uint8_t cnt = 0xff;
- uint8_t *samples = (uint8_t *)pd_phy[port].raw_samples;
-
- while ((pd_phy[port].d_lastlen < len) && (off < PD_MAX_RAW_SIZE - 1)) {
- w = wait_bits(port, off + 2);
- if (w < 0)
- goto stream_err;
- cnt = samples[off] - samples[off-1];
- if (!cnt || (cnt > 3*PERIOD))
- goto stream_err;
- off++;
- if (cnt <= PERIOD_THRESHOLD) {
- /*
- w = wait_bits(port, off + 1);
- if (w < 0)
- goto stream_err;
- */
- cnt = samples[off] - samples[off-1];
- if (cnt > PERIOD_THRESHOLD)
- goto stream_err;
- off++;
- }
-
- /* enqueue the bit of the last period */
- pd_phy[port].d_last = (pd_phy[port].d_last >> 1)
- | (cnt <= PERIOD_THRESHOLD ? 0x80000000 : 0);
- pd_phy[port].d_lastlen++;
- }
- if (off < PD_MAX_RAW_SIZE) {
- *val = (pd_phy[port].d_last << (pd_phy[port].d_lastlen - len))
- >> (32 - len);
- pd_phy[port].d_lastlen -= len;
- return off;
- } else {
- return -1;
- }
-stream_err:
- /* CPRINTS("PD Invalid %d @%d", cnt, off); */
- return -1;
-}
-
-int pd_find_preamble(int port)
-{
- int bit;
- uint8_t *vals = (uint8_t *)pd_phy[port].raw_samples;
-
- /*
- * Detect preamble
- * Alternate 1-period 1-period & 2-period.
- */
- uint32_t all = 0;
- stm32_dma_chan_t *rx = dma_get_channel(DMAC_TIM_RX(port));
-
- for (bit = 1; bit < PD_MAX_RAW_SIZE - 1; bit++) {
- uint8_t cnt;
- /* wait if the bit is not received yet ... */
- if (PD_MAX_RAW_SIZE - rx->cndtr < bit + 1) {
- while ((PD_MAX_RAW_SIZE - rx->cndtr < bit + 1) &&
- !(pd_phy[port].tim_rx->sr & 4))
- ;
- if (pd_phy[port].tim_rx->sr & 4) {
- CPRINTS("PD TMOUT RX %d/%d",
- PD_MAX_RAW_SIZE - rx->cndtr, bit);
- return -1;
- }
- }
- cnt = vals[bit] - vals[bit-1];
- all = (all >> 1) | (cnt <= PERIOD_THRESHOLD ? BIT(31) : 0);
- if (all == 0x36db6db6)
- return bit - 1; /* should be SYNC-1 */
- if (all == 0xF33F3F3F)
- return PD_RX_ERR_HARD_RESET; /* got HARD-RESET */
- if (all == 0x3c7fe0ff)
- return PD_RX_ERR_CABLE_RESET; /* got CABLE-RESET */
- }
- return -1;
-}
-
-int pd_write_preamble(int port)
-{
- uint32_t *msg = pd_phy[port].raw_samples;
-
- /* 64-bit x2 preamble */
- msg[0] = PD_PREAMBLE;
- msg[1] = PD_PREAMBLE;
- msg[2] = PD_PREAMBLE;
- msg[3] = PD_PREAMBLE;
- pd_phy[port].b_toggle = 0x3FF; /* preamble ends with 1 */
- return 2*64;
-}
-
-int pd_write_sym(int port, int bit_off, uint32_t val10)
-{
- uint32_t *msg = pd_phy[port].raw_samples;
- int word_idx = bit_off / 32;
- int bit_idx = bit_off % 32;
- uint32_t val = pd_phy[port].b_toggle ^ val10;
- pd_phy[port].b_toggle = val & 0x200 ? 0x3FF : 0;
- if (bit_idx <= 22) {
- if (bit_idx == 0)
- msg[word_idx] = 0;
- msg[word_idx] |= val << bit_idx;
- } else {
- msg[word_idx] |= val << bit_idx;
- msg[word_idx+1] = val >> (32 - bit_idx);
- /* side effect: clear the new word when starting it */
- }
- return bit_off + 5*2;
-}
-
-int pd_write_last_edge(int port, int bit_off)
-{
- uint32_t *msg = pd_phy[port].raw_samples;
- int word_idx = bit_off / 32;
- int bit_idx = bit_off % 32;
-
- if (bit_idx == 0)
- msg[word_idx] = 0;
-
- if (!pd_phy[port].b_toggle /* last bit was 0 */) {
- /* transition to 1, another 1, then 0 */
- if (bit_idx == 31) {
- msg[word_idx++] |= 1 << bit_idx;
- msg[word_idx] = 1;
- } else {
- msg[word_idx] |= 3 << bit_idx;
- }
- }
- /* ensure that the trailer is 0 */
- msg[word_idx+1] = 0;
-
- return bit_off + 3;
-}
-
-#ifdef CONFIG_COMMON_RUNTIME
-void pd_dump_packet(int port, const char *msg)
-{
- uint8_t *vals = (uint8_t *)pd_phy[port].raw_samples;
- int bit;
-
- CPRINTF("ERR %s:\n000:- ", msg);
- /* Packet debug output */
- for (bit = 1; bit < PD_MAX_RAW_SIZE; bit++) {
- int cnt = NB_PERIOD(vals[bit-1], vals[bit]);
- if ((bit & 31) == 0)
- CPRINTF("\n%03d:", bit);
- CPRINTF("%1d ", cnt);
- }
- CPRINTF("><\n");
- cflush();
- for (bit = 0; bit < PD_MAX_RAW_SIZE; bit++) {
- if ((bit & 31) == 0)
- CPRINTF("\n%03d:", bit);
- CPRINTF("%02x ", vals[bit]);
- }
- CPRINTF("||\n");
- cflush();
-}
-#endif /* CONFIG_COMMON_RUNTIME */
-
-/* --- SPI TX operation --- */
-
-void pd_tx_spi_init(int port)
-{
- stm32_spi_regs_t *spi = SPI_REGS(port);
-
- /* Enable Tx DMA for our first transaction */
- spi->cr2 = STM32_SPI_CR2_TXDMAEN | STM32_SPI_CR2_DATASIZE(8);
-
- /* Enable the slave SPI: LSB first, force NSS, TX only, CPHA */
- spi->cr1 = STM32_SPI_CR1_SPE | STM32_SPI_CR1_LSBFIRST
- | STM32_SPI_CR1_SSM | STM32_SPI_CR1_BIDIMODE
- | STM32_SPI_CR1_BIDIOE | STM32_SPI_CR1_CPHA;
-}
-
-static void tx_dma_done(void *data)
-{
- int port = (int)data;
- int polarity = tx_dma_polarities[port];
- stm32_spi_regs_t *spi = SPI_REGS(port);
-
- while (spi->sr & STM32_SPI_SR_FTLVL)
- ; /* wait for TX FIFO empty */
- while (spi->sr & STM32_SPI_SR_BSY)
- ; /* wait for BSY == 0 */
-
- /* Stop counting */
- pd_phy[port].tim_tx->cr1 &= ~1;
-
- /* put TX pins and reference in Hi-Z */
- pd_tx_disable(port, polarity);
-
-#if defined(CONFIG_COMMON_RUNTIME) && defined(CONFIG_DMA_DEFAULT_HANDLERS)
- task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_DMA_TC);
-#endif
-}
-
-int pd_start_tx(int port, int polarity, int bit_len)
-{
- stm32_dma_chan_t *tx = dma_get_channel(DMAC_SPI_TX(port));
-
-#ifndef CONFIG_USB_PD_TX_PHY_ONLY
- /* disable RX detection interrupt */
- pd_rx_disable_monitoring(port);
-
- /* Check that we are not receiving a frame to avoid collisions */
- if (pd_rx_started(port))
- return -5;
-#endif /* !CONFIG_USB_PD_TX_PHY_ONLY */
-
- /* Initialize spi peripheral to prepare for transmission. */
- pd_tx_spi_init(port);
-
- /*
- * Set timer to one tick before reset so that the first tick causes
- * a rising edge on the output.
- */
- pd_phy[port].tim_tx->cnt = TX_CLOCK_DIV - 1;
-
- /* update DMA configuration */
- dma_prepare_tx(&(pd_phy[port].dma_tx_option),
- DIV_ROUND_UP(bit_len, 8),
- pd_phy[port].raw_samples);
- /* Flush data in write buffer so that DMA can get the latest data */
- asm volatile("dmb;");
-
- /* Kick off the DMA to send the data */
- dma_clear_isr(DMAC_SPI_TX(port));
-#if defined(CONFIG_COMMON_RUNTIME) && defined(CONFIG_DMA_DEFAULT_HANDLERS)
- tx_dma_polarities[port] = polarity;
- if (!(pd_phy[port].dma_tx_option.flags & STM32_DMA_CCR_CIRC)) {
- /* Only enable interrupt if not in circular mode */
- dma_enable_tc_interrupt_callback(DMAC_SPI_TX(port),
- &tx_dma_done,
- (void *)port);
- }
-#endif
- dma_go(tx);
-
- /*
- * Drive the CC line from the TX block :
- * - put SPI function on TX pin.
- * - set the low level reference.
- * Call this last before enabling timer in order to meet spec on
- * timing between enabling TX and clocking out bits.
- */
- pd_tx_enable(port, polarity);
-
- /* Start counting at 300Khz*/
- pd_phy[port].tim_tx->cr1 |= 1;
-
- return bit_len;
-}
-
-void pd_tx_done(int port, int polarity)
-{
-#if defined(CONFIG_COMMON_RUNTIME) && defined(CONFIG_DMA_DEFAULT_HANDLERS)
- /* wait for DMA, DMA interrupt will stop the SPI clock */
- task_wait_event_mask(TASK_EVENT_DMA_TC, DMA_TRANSFER_TIMEOUT_US);
- dma_disable_tc_interrupt(DMAC_SPI_TX(port));
-#else
- tx_dma_polarities[port] = polarity;
- tx_dma_done((void *)port);
-#endif
-
- /* Reset SPI to clear remaining data in buffer */
- pd_tx_spi_reset(port);
-}
-
-void pd_tx_set_circular_mode(int port)
-{
- pd_phy[port].dma_tx_option.flags |= STM32_DMA_CCR_CIRC;
-}
-
-void pd_tx_clear_circular_mode(int port)
-{
- /* clear the circular mode bit in flag variable */
- pd_phy[port].dma_tx_option.flags &= ~STM32_DMA_CCR_CIRC;
- /* disable dma transaction underway */
- dma_disable(DMAC_SPI_TX(port));
-#if defined(CONFIG_COMMON_RUNTIME) && defined(CONFIG_DMA_DEFAULT_HANDLERS)
- tx_dma_done((void *)port);
-#endif
-}
-
-/* --- RX operation using comparator linked to timer --- */
-
-void pd_rx_start(int port)
-{
- /* start sampling the edges on the CC line using the RX timer */
- dma_start_rx(&(pd_phy[port].dma_tim_option), PD_MAX_RAW_SIZE,
- pd_phy[port].raw_samples);
- /* enable TIM2 DMA requests */
- pd_phy[port].tim_rx->egr = 0x0001; /* reset counter / reload PSC */;
- pd_phy[port].tim_rx->sr = 0; /* clear overflows */
- pd_phy[port].tim_rx->cr1 |= 1;
-}
-
-void pd_rx_complete(int port)
-{
- /* stop stampling TIM2 */
- pd_phy[port].tim_rx->cr1 &= ~1;
- /* stop DMA */
- dma_disable(DMAC_TIM_RX(port));
-}
-
-int pd_rx_started(int port)
-{
- /* is the sampling timer running ? */
- return pd_phy[port].tim_rx->cr1 & 1;
-}
-
-void pd_rx_enable_monitoring(int port)
-{
- /* clear comparator external interrupt */
- STM32_EXTI_PR = EXTI_COMP_MASK(port);
- /* enable comparator external interrupt */
- STM32_EXTI_IMR |= EXTI_COMP_MASK(port);
-}
-
-void pd_rx_disable_monitoring(int port)
-{
- /* disable comparator external interrupt */
- STM32_EXTI_IMR &= ~EXTI_COMP_MASK(port);
- /* clear comparator external interrupt */
- STM32_EXTI_PR = EXTI_COMP_MASK(port);
-}
-
-uint64_t get_time_since_last_edge(int port)
-{
- int prev_idx = (rx_edge_ts_idx[port] == 0) ?
- PD_RX_TRANSITION_COUNT - 1 :
- rx_edge_ts_idx[port] - 1;
- return get_time().val - rx_edge_ts[port][prev_idx].val;
-}
-
-/* detect an edge on the PD RX pin */
-void pd_rx_handler(void)
-{
- int pending, i;
- int next_idx;
- pending = STM32_EXTI_PR;
-
-#ifdef CONFIG_USB_CTVPD
- /* Charge-Through Side detach event */
- if (pending & EXTI_COMP2_MASK) {
- task_wake(PD_PORT_TO_TASK_ID(0));
- /* Clear interrupt */
- STM32_EXTI_PR = EXTI_COMP2_MASK;
- pending &= ~EXTI_COMP2_MASK;
- }
-#endif
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- if (pending & EXTI_COMP_MASK(i)) {
- rx_edge_ts[i][rx_edge_ts_idx[i]].val = get_time().val;
- next_idx = (rx_edge_ts_idx[i] ==
- PD_RX_TRANSITION_COUNT - 1) ?
- 0 : rx_edge_ts_idx[i] + 1;
-
-#if defined(CONFIG_LOW_POWER_IDLE) && \
-defined(CONFIG_USB_PD_LOW_POWER_IDLE_WHEN_CONNECTED)
- /*
- * Do not deep sleep while waiting for more edges. For
- * most boards, sleep is already disabled due to being
- * in PD connected state, but boards which define
- * CONFIG_USB_PD_LOW_POWER_IDLE_WHEN_CONNECTED can
- * sleep while connected.
- */
- disable_sleep(SLEEP_MASK_USB_PD);
-#endif
-
- /*
- * If we have seen enough edges in a certain amount of
- * time, then trigger RX start.
- */
- if ((rx_edge_ts[i][rx_edge_ts_idx[i]].val -
- rx_edge_ts[i][next_idx].val)
- < PD_RX_TRANSITION_WINDOW) {
- /* start sampling */
- pd_rx_start(i);
- /*
- * ignore the comparator IRQ until we are done
- * with current message
- */
- pd_rx_disable_monitoring(i);
- /* trigger the analysis in the task */
- pd_rx_event(i);
- } else {
- /* do not trigger RX start, just clear int */
- STM32_EXTI_PR = EXTI_COMP_MASK(i);
- }
- rx_edge_ts_idx[i] = next_idx;
- }
- }
-}
-#ifdef CONFIG_USB_PD_RX_COMP_IRQ
-DECLARE_IRQ(STM32_IRQ_COMP, pd_rx_handler, 1);
-#endif
-
-/* --- release hardware --- */
-void pd_hw_release(int port)
-{
- __hw_timer_enable_clock(TIM_CLOCK_PD_RX(port), 0);
- __hw_timer_enable_clock(TIM_CLOCK_PD_TX(port), 0);
- dma_disable(DMAC_SPI_TX(port));
-}
-
-/* --- Startup initialization --- */
-
-void pd_hw_init_rx(int port)
-{
- struct pd_physical *phy = &pd_phy[port];
-
- /* configure registers used for timers */
- phy->tim_rx = (void *)TIM_REG_RX(port);
-
- /* configure RX DMA */
- phy->dma_tim_option.channel = DMAC_TIM_RX(port);
- phy->dma_tim_option.periph = (void *)(TIM_RX_CCR_REG(port));
- phy->dma_tim_option.flags = STM32_DMA_CCR_MSIZE_8_BIT |
- STM32_DMA_CCR_PSIZE_16_BIT;
-
- /* --- set counter for RX timing : 2.4Mhz rate, free-running --- */
- __hw_timer_enable_clock(TIM_CLOCK_PD_RX(port), 1);
- /* Timer configuration */
- phy->tim_rx->cr1 = 0x0000;
- phy->tim_rx->cr2 = 0x0000;
- phy->tim_rx->dier = 0x0000;
- /* Auto-reload value : 16-bit free running counter */
- phy->tim_rx->arr = 0xFFFF;
-
- /* Timeout for message receive */
- phy->tim_rx->ccr[2] = (2400000 / 1000) * USB_PD_RX_TMOUT_US / 1000;
- /* Timer ICx input configuration */
- if (TIM_RX_CCR_IDX(port) == 1)
- phy->tim_rx->ccmr1 |= TIM_CCR_CS << 0;
- else if (TIM_RX_CCR_IDX(port) == 2)
- phy->tim_rx->ccmr1 |= TIM_CCR_CS << 8;
- else if (TIM_RX_CCR_IDX(port) == 4)
- phy->tim_rx->ccmr2 |= TIM_CCR_CS << 8;
- else
- /* Unsupported RX timer capture input */
- ASSERT(0);
-
- phy->tim_rx->ccer = 0xB << ((TIM_RX_CCR_IDX(port) - 1) * 4);
- /* configure DMA request on CCRx update */
- phy->tim_rx->dier |= 1 << (8 + TIM_RX_CCR_IDX(port)); /* CCxDE */;
- /* set prescaler to /26 (F=1.2Mhz, T=0.8us) */
- phy->tim_rx->psc = (clock_get_freq() / 2400000) - 1;
- /* Reload the pre-scaler and reset the counter (clear CCRx) */
- phy->tim_rx->egr = 0x0001 | (1 << TIM_RX_CCR_IDX(port));
- /* clear update event from reloading */
- phy->tim_rx->sr = 0;
-
- /* --- DAC configuration for comparator at 850mV --- */
-#ifdef CONFIG_PD_USE_DAC_AS_REF
- /* Enable DAC interface clock. */
- STM32_RCC_APB1ENR |= BIT(29);
- /* Delay 1 APB clock cycle after the clock is enabled */
- clock_wait_bus_cycles(BUS_APB, 1);
- /* set voltage Vout=0.850V (Vref = 3.0V) */
- STM32_DAC_DHR12RD = 850 * 4096 / 3000;
- /* Start DAC channel 1 */
- STM32_DAC_CR = STM32_DAC_CR_EN1;
-#endif
-
- /* --- COMP2 as comparator for RX vs Vmid = 850mV --- */
-#ifdef CONFIG_USB_PD_INTERNAL_COMP
-#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
- /* turn on COMP/SYSCFG */
- STM32_RCC_APB2ENR |= BIT(0);
- /* Delay 1 APB clock cycle after the clock is enabled */
- clock_wait_bus_cycles(BUS_APB, 1);
- /* currently in hi-speed mode : TODO revisit later, INM = PA0(INM6) */
- STM32_COMP_CSR = STM32_COMP_CMP1MODE_LSPEED |
- STM32_COMP_CMP1INSEL_INM6 |
- CMP1OUTSEL |
- STM32_COMP_CMP1HYST_HI |
- STM32_COMP_CMP2MODE_LSPEED |
- STM32_COMP_CMP2INSEL_INM6 |
- CMP2OUTSEL |
- STM32_COMP_CMP2HYST_HI;
-#elif defined(CHIP_FAMILY_STM32L)
- STM32_RCC_APB1ENR |= BIT(31); /* turn on COMP */
-
- STM32_COMP_CSR = STM32_COMP_OUTSEL_TIM2_IC4 | STM32_COMP_INSEL_DAC_OUT1
- | STM32_COMP_SPEED_FAST;
- /* route PB4 to COMP input2 through GR6_1 bit 4 (or PB5->GR6_2 bit 5) */
- STM32_RI_ASCR2 |= BIT(4);
-#else
-#error Unsupported chip family
-#endif
-#endif /* CONFIG_USB_PD_INTERNAL_COMP */
-
- /* comparator interrupt setup */
- EXTI_XTSR |= EXTI_COMP_MASK(port);
- STM32_EXTI_IMR |= EXTI_COMP_MASK(port);
- task_enable_irq(IRQ_COMP);
-}
-
-void pd_hw_init(int port, enum pd_power_role role)
-{
- struct pd_physical *phy = &pd_phy[port];
- uint32_t val;
-
- /* Initialize all PD pins to default state based on desired role */
- pd_config_init(port, role);
-
- /* set 40 MHz pin speed on communication pins */
- pd_set_pins_speed(port);
-
- /* --- SPI init --- */
-
- /* Enable clocks to SPI module */
- spi_enable_clock(port);
-
- /* Initialize SPI peripheral registers */
- pd_tx_spi_init(port);
-
- /* configure TX DMA */
- phy->dma_tx_option.channel = DMAC_SPI_TX(port);
- phy->dma_tx_option.periph = (void *)&SPI_REGS(port)->dr;
- phy->dma_tx_option.flags = STM32_DMA_CCR_MSIZE_8_BIT |
- STM32_DMA_CCR_PSIZE_8_BIT;
- dma_prepare_tx(&(phy->dma_tx_option), PD_MAX_RAW_SIZE,
- phy->raw_samples);
-
- /* configure registers used for timers */
- phy->tim_tx = (void *)TIM_REG_TX(port);
-
- /* --- set the TX timer with updates at 600KHz (BMC frequency) --- */
- __hw_timer_enable_clock(TIM_CLOCK_PD_TX(port), 1);
- /* Timer configuration */
- phy->tim_tx->cr1 = 0x0000;
- phy->tim_tx->cr2 = 0x0000;
- phy->tim_tx->dier = 0x0000;
- /* Auto-reload value : 600000 Khz overflow */
- phy->tim_tx->arr = TX_CLOCK_DIV;
- /* 50% duty cycle on the output */
- phy->tim_tx->ccr[TIM_TX_CCR_IDX(port)] = phy->tim_tx->arr / 2;
- /* Timer channel output configuration */
- val = (6 << 4) | BIT(3);
- if ((TIM_TX_CCR_IDX(port) & 1) == 0) /* CH2 or CH4 */
- val <<= 8;
- if (TIM_TX_CCR_IDX(port) <= 2)
- phy->tim_tx->ccmr1 = val;
- else
- phy->tim_tx->ccmr2 = val;
-
- phy->tim_tx->ccer = 1 << ((TIM_TX_CCR_IDX(port) - 1) * 4);
- phy->tim_tx->bdtr = 0x8000;
- /* set prescaler to /1 */
- phy->tim_tx->psc = 0;
- /* Reload the pre-scaler and reset the counter */
- phy->tim_tx->egr = 0x0001;
-#ifndef CONFIG_USB_PD_TX_PHY_ONLY
- /* Configure the reception side : comparators + edge timer + DMA */
- pd_hw_init_rx(port);
-#endif /* CONFIG_USB_PD_TX_PHY_ONLY */
-
- CPRINTS("USB PD initialized");
-}
-
-void pd_set_clock(int port, int freq)
-{
- pd_phy[port].tim_tx->arr = clock_get_freq() / (2*freq);
-}