[coreboot-gerrit] Patch set updated for coreboot: 2be890e armv7/exynos5420: Revise SPI open/close/reset procedure.

Gabe Black (gabeblack@chromium.org) gerrit at coreboot.org
Tue Jul 9 22:44:11 CEST 2013


Gabe Black (gabeblack at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3712

-gerrit

commit 2be890ecd9259f91c9a33ee5a8535f887dfbac34
Author: Hung-Te Lin <hungte at chromium.org>
Date:   Wed Jun 26 20:22:50 2013 +0800

    armv7/exynos5420: Revise SPI open/close/reset procedure.
    
    The original Exynos SPI open/close procedure was copied from U-Boot SPL with
    some assumptions that only works in SPL stage.  For example, it tries to always
    work in 4-byte transmission mode with only RX data is swapped, and claims a
    packet for initial address command (and with incorrect size).
    
    This commit revises open/close and reset so only the required SPI registers are
    configured.
    
    Change-Id: Ieba1f03d80a8949c39a6658218831ded39853744
    Signed-off-by: Hung-Te Lin <hungte at chromium.org>
    Signed-off-by: Gabe Black <gabeblack at chromium.org>
---
 src/cpu/samsung/exynos5420/spi.c | 76 +++++++++++++++++++++-------------------
 1 file changed, 39 insertions(+), 37 deletions(-)

diff --git a/src/cpu/samsung/exynos5420/spi.c b/src/cpu/samsung/exynos5420/spi.c
index 82c3765..6637aad 100644
--- a/src/cpu/samsung/exynos5420/spi.c
+++ b/src/cpu/samsung/exynos5420/spi.c
@@ -102,6 +102,26 @@ void spi_cs_deactivate(struct spi_slave *slave)
 	setbits_le32(&regs->cs_reg, SPI_SLAVE_SIG_INACT);
 }
 
+static inline void exynos_spi_soft_reset(struct exynos_spi *regs)
+{
+	/* The soft reset clears only FIFO and status register.
+	 * All special function registers are not changed. */
+	setbits_le32(&regs->ch_cfg, SPI_CH_RST);
+	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+}
+
+static inline void exynos_spi_flush_fifo(struct exynos_spi *regs)
+{
+	/*
+	 * Flush spi tx, rx fifos and reset the SPI controller
+	 * and clear rx/tx channel
+	 */
+	clrbits_le32(&regs->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON);
+	clrbits_le32(&regs->ch_cfg, SPI_CH_HS_EN);
+	exynos_spi_soft_reset(regs);
+	setbits_le32(&regs->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON);
+}
+
 static void exynos_spi_rx_tx(struct exynos_spi *regs, int todo,
 			     void *dinp, void const *doutp, int i)
 {
@@ -114,8 +134,7 @@ static void exynos_spi_rx_tx(struct exynos_spi *regs, int todo,
 	ASSERT(todo % 4 == 0);
 
 	out_bytes = in_bytes = todo;
-	setbits_le32(&regs->ch_cfg, SPI_CH_RST);
-	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+	exynos_spi_soft_reset(regs);
 	writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
 
 	while (in_bytes) {
@@ -143,35 +162,27 @@ static void exynos_spi_rx_tx(struct exynos_spi *regs, int todo,
 	}
 }
 
-/* set up SPI channel */
 int spi_claim_bus(struct spi_slave *slave)
 {
 	struct exynos_spi_slave *espi = to_exynos_spi(slave);
 	struct exynos_spi *regs = espi->regs;
 
-	/* set the spi1 GPIO */
+	exynos_spi_flush_fifo(regs);
 
-	/* set pktcnt and enable it */
-	writel(4 | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
-	/* set FB_CLK_SEL */
-	writel(SPI_FB_DELAY_180, &regs->fb_clk);
-	/* set CH_WIDTH and BUS_WIDTH as word */
-	setbits_le32(&regs->mode_cfg,
-		     SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD);
-	clrbits_le32(&regs->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */
+	// Select Active High Clock, Format A (SCP 30.2.1.8).
+	clrbits_le32(&regs->ch_cfg, SPI_CH_CPOL_L | SPI_CH_CPHA_B);
 
-	/* clear rx and tx channel if set priveously */
-	clrbits_le32(&regs->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON);
-
-	setbits_le32(&regs->swap_cfg,
-		     SPI_RX_SWAP_EN | SPI_RX_BYTE_SWAP | SPI_RX_HWORD_SWAP);
-
-	/* do a soft reset */
-	setbits_le32(&regs->ch_cfg, SPI_CH_RST);
-	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+	// Set FeedBack Clock Selection.
+	writel(SPI_FB_DELAY_180, &regs->fb_clk);
 
-	/* now set rx and tx channel ON */
-	setbits_le32(&regs->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN);
+	// HIGH speed is required for Tx/Rx to work in 50MHz (SCP 30.2.1.6).
+	if (espi->half_duplex) {
+		clrbits_le32(&regs->ch_cfg, SPI_CH_HS_EN);
+		printk(BIOS_DEBUG, "%s: LOW speed.\n", __func__);
+	} else {
+		setbits_le32(&regs->ch_cfg, SPI_CH_HS_EN);
+		printk(BIOS_DEBUG, "%s: HIGH speed.\n", __func__);
+	}
 	return 0;
 }
 
@@ -209,21 +220,12 @@ static int exynos_spi_read(struct spi_slave *slave, void *dest, uint32_t len,
 void spi_release_bus(struct spi_slave *slave)
 {
 	struct exynos_spi *regs = to_exynos_spi(slave)->regs;
-	/*
-	 * Let put controller mode to BYTE as
-	 * SPI driver does not support WORD mode yet
-	 */
-	clrbits_le32(&regs->mode_cfg,
-		     SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD);
+	/* Reset swap mode to make sure no one relying on default values (Ex,
+	 * payload or kernel) will go wrong. */
+	clrbits_le32(&regs->mode_cfg, (SPI_MODE_CH_WIDTH_WORD |
+				       SPI_MODE_BUS_WIDTH_WORD));
 	writel(0, &regs->swap_cfg);
-
-	/*
-	 * Flush spi tx, rx fifos and reset the SPI controller
-	 * and clear rx/tx channel
-	 */
-	clrsetbits_le32(&regs->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
-	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
-	clrbits_le32(&regs->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
+	exynos_spi_flush_fifo(regs);
 }
 
 // SPI as CBFS media.



More information about the coreboot-gerrit mailing list