summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2017-12-21 09:59:57 +0100
committerchrome-bot <chrome-bot@chromium.org>2018-01-12 14:31:07 -0800
commit47c7e189b9adb5819316be66a410e47149a2ddea (patch)
tree1961105f05b0a1698e2938194e3d873cc51f6697
parenta41c59598de1d335af76e6bc4b1178720154d48c (diff)
downloadchrome-ec-47c7e189b9adb5819316be66a410e47149a2ddea.tar.gz
stm32: add SPI slave support for STM32H7
Update the host command support on the STM32 SPI slave for the STM32H7 silicon. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BRANCH=none BUG=b:67081508 TEST=with a servo v2 connected to ZerbleBarn, send host commands v3 through the servo FTDI SPI interface. Change-Id: I26ff4b6a3a45e446cd16e9da43c6932c24c37256 Reviewed-on: https://chromium-review.googlesource.com/839864 Commit-Ready: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Shawn N <shawnn@chromium.org>
-rw-r--r--chip/stm32/registers.h8
-rw-r--r--chip/stm32/spi.c54
2 files changed, 51 insertions, 11 deletions
diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h
index e8a8f826aa..df9b83b3d8 100644
--- a/chip/stm32/registers.h
+++ b/chip/stm32/registers.h
@@ -1597,6 +1597,7 @@ struct stm32_spi_regs {
uint32_t crcpoly;
uint32_t rxcrcr;
uint32_t txcrcr;
+ uint32_t udrdr;
#else /* !CHIP_FAMILY_STM32H7 */
uint16_t cr1;
uint16_t _pad0;
@@ -1628,6 +1629,12 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
#define STM32_SPI_CR1_DIV(div) ((div) << 28)
#define STM32_SPI_CFG1_DATASIZE(n) (((n) - 1) << 0)
#define STM32_SPI_CFG1_FTHLV(n) (((n) - 1) << 5)
+#define STM32_SPI_CFG1_UDRCFG_CONST (0 << 9)
+#define STM32_SPI_CFG1_UDRCFG_LAST_RX (1 << 9)
+#define STM32_SPI_CFG1_UDRCFG_LAST_TX (2 << 9)
+#define STM32_SPI_CFG1_UDRDET_BEGIN_FRM (0 << 11)
+#define STM32_SPI_CFG1_UDRDET_END_FRM (1 << 11)
+#define STM32_SPI_CFG1_UDRDET_BEGIN_SS (2 << 11)
#define STM32_SPI_CFG1_RXDMAEN (1 << 14)
#define STM32_SPI_CFG1_TXDMAEN (1 << 15)
#define STM32_SPI_CFG1_CRCSIZE(n) (((n) - 1) << 16)
@@ -1636,6 +1643,7 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
#define STM32_SPI_CFG2_AFCNTR (1 << 31)
#define STM32_SPI_SR_RXNE (1 << 0)
+#define STM32_SPI_SR_UDR (1 << 5)
#define STM32_SPI_SR_FRLVL (3 << 13)
#define STM32_SPI_SR_TXC (1 << 12)
#else /* !CHIP_FAMILY_STM32H7 */
diff --git a/chip/stm32/spi.c b/chip/stm32/spi.c
index cdb1e0666b..570f371d27 100644
--- a/chip/stm32/spi.c
+++ b/chip/stm32/spi.c
@@ -27,14 +27,23 @@
#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args)
#define CPRINTF(format, args...) cprintf(CC_SPI, format, ## args)
+/* SPI FIFO registers */
+#ifdef CHIP_FAMILY_STM32H7
+#define SPI_TXDR REG8(&STM32_SPI1_REGS->txdr)
+#define SPI_RXDR REG8(&STM32_SPI1_REGS->rxdr)
+#else
+#define SPI_TXDR STM32_SPI1_REGS->dr
+#define SPI_RXDR STM32_SPI1_REGS->dr
+#endif
+
/* DMA channel option */
static const struct dma_option dma_tx_option = {
- STM32_DMAC_SPI1_TX, (void *)&STM32_SPI1_REGS->dr,
+ STM32_DMAC_SPI1_TX, (void *)&SPI_TXDR,
STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT
};
static const struct dma_option dma_rx_option = {
- STM32_DMAC_SPI1_RX, (void *)&STM32_SPI1_REGS->dr,
+ STM32_DMAC_SPI1_RX, (void *)&SPI_RXDR,
STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT
};
@@ -157,7 +166,7 @@ enum spi_state {
* @param nss GPIO signal for NSS control line
* @return 0 if bytes received, -1 if we hit a timeout or NSS went high
*/
-static int wait_for_bytes(stm32_dma_chan_t *rxdma, int needed,
+static int wait_for_bytes(dma_chan_t *rxdma, int needed,
enum gpio_signal nss)
{
timestamp_t deadline;
@@ -215,7 +224,7 @@ static int wait_for_bytes(stm32_dma_chan_t *rxdma, int needed,
* SPI_PROTO2_OFFSET bytes into out_msg
* @param msg_len Number of message bytes to send
*/
-static void reply(stm32_dma_chan_t *txdma,
+static void reply(dma_chan_t *txdma,
enum ec_status status, char *msg_ptr, int msg_len)
{
char *msg = out_msg;
@@ -271,7 +280,7 @@ static void tx_status(uint8_t byte)
{
stm32_spi_regs_t *spi = STM32_SPI1_REGS;
- spi->dr = byte;
+ SPI_TXDR = byte;
#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32L4)
/* It sends the byte 4 times in order to be sure it bypassed the FIFO
* from the STM32F0 line.
@@ -279,6 +288,8 @@ static void tx_status(uint8_t byte)
spi->dr = byte;
spi->dr = byte;
spi->dr = byte;
+#elif defined(CHIP_FAMILY_STM32H7)
+ spi->ifcr = STM32_SPI_SR_UDR;
#endif
}
@@ -309,7 +320,7 @@ static void setup_for_transaction(void)
* Read dummy bytes in case there are some pending; this prevents the
* receive DMA from getting that byte right when we start it.
*/
- dummy = spi->dr;
+ dummy = SPI_RXDR;
#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32L4)
/* 4 Bytes makes sure the RX FIFO on the F0 is empty as well. */
dummy = spi->dr;
@@ -320,6 +331,10 @@ static void setup_for_transaction(void)
/* Start DMA */
dma_start_rx(&dma_rx_option, sizeof(in_msg), in_msg);
+#ifdef CHIP_FAMILY_STM32H7
+ spi->cr1 |= STM32_SPI_CR1_SPE;
+#endif
+
/* Ready to receive */
state = SPI_STATE_READY_TO_RX;
tx_status(EC_SPI_OLD_READY);
@@ -355,7 +370,7 @@ static void check_setup_transaction_later(void)
static void spi_send_response(struct host_cmd_handler_args *args)
{
enum ec_status result = args->result;
- stm32_dma_chan_t *txdma;
+ dma_chan_t *txdma;
/*
* If we're not processing, then the AP has already terminated the
@@ -391,7 +406,7 @@ static void spi_send_response(struct host_cmd_handler_args *args)
*/
static void spi_send_response_packet(struct host_packet *pkt)
{
- stm32_dma_chan_t *txdma;
+ dma_chan_t *txdma;
/*
* If we're not processing, then the AP has already terminated the
@@ -418,6 +433,10 @@ static void spi_send_response_packet(struct host_packet *pkt)
dma_prepare_tx(&dma_tx_option, sizeof(out_preamble) + pkt->response_size
+ EC_SPI_PAST_END_LENGTH, out_msg);
dma_go(txdma);
+#ifdef CHIP_FAMILY_STM32H7
+ /* clear any previous underrun */
+ STM32_SPI1_REGS->ifcr = STM32_SPI_SR_UDR;
+#endif /* CHIP_FAMILY_STM32H7 */
/*
* Before the state is set to SENDING, any CS de-assertion would
@@ -437,7 +456,7 @@ static void spi_send_response_packet(struct host_packet *pkt)
*/
void spi_event(enum gpio_signal signal)
{
- stm32_dma_chan_t *rxdma;
+ dma_chan_t *rxdma;
uint16_t i;
/* If not enabled, ignore glitches on NSS */
@@ -633,8 +652,8 @@ static void spi_init(void)
/* Fix for bug chrome-os-partner:31390 */
enabled = 0;
state = SPI_STATE_DISABLED;
- STM32_RCC_APB2RSTR |= (1 << 12);
- STM32_RCC_APB2RSTR &= ~(1 << 12);
+ STM32_RCC_APB2RSTR |= STM32_RCC_PB2_SPI1;
+ STM32_RCC_APB2RSTR &= ~STM32_RCC_PB2_SPI1;
/* 40 MHz pin speed */
STM32_GPIO_OSPEEDR(GPIO_A) |= 0xff00;
@@ -649,16 +668,29 @@ static void spi_init(void)
#ifdef CHIP_FAMILY_STM32L4
dma_select_channel(STM32_DMAC_SPI1_TX, 1);
dma_select_channel(STM32_DMAC_SPI1_RX, 1);
+#elif defined(CHIP_FAMILY_STM32H7)
+ dma_select_channel(STM32_DMAC_SPI1_TX, DMAMUX1_REQ_SPI1_TX);
+ dma_select_channel(STM32_DMAC_SPI1_RX, DMAMUX1_REQ_SPI1_RX);
#endif
/*
* Enable rx/tx DMA and get ready to receive our first transaction and
* "disable" FIFO by setting event to happen after only 1 byte
*/
+#ifdef CHIP_FAMILY_STM32H7
+ spi->cfg2 = 0;
+ spi->cfg1 = STM32_SPI_CFG1_DATASIZE(8) | STM32_SPI_CFG1_FTHLV(4) |
+ STM32_SPI_CFG1_CRCSIZE(8) |
+ STM32_SPI_CFG1_TXDMAEN | STM32_SPI_CFG1_RXDMAEN |
+ STM32_SPI_CFG1_UDRCFG_LAST_TX |
+ STM32_SPI_CFG1_UDRDET_BEGIN_FRM;
+ spi->cr1 = 0;
+#else /* !CHIP_FAMILY_STM32H7 */
spi->cr2 = STM32_SPI_CR2_RXDMAEN | STM32_SPI_CR2_TXDMAEN |
STM32_SPI_CR2_FRXTH | STM32_SPI_CR2_DATASIZE(8);
/* Enable the SPI peripheral */
spi->cr1 |= STM32_SPI_CR1_SPE;
+#endif /* !CHIP_FAMILY_STM32H7 */
gpio_enable_interrupt(GPIO_SPI1_NSS);