1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <device/mmio.h>
5 #include <boot_device.h>
7 #include <commonlib/region.h>
8 #include <console/console.h>
16 #if defined(CONFIG_DEBUG_SPI) && CONFIG_DEBUG_SPI
17 # define DEBUG_SPI(x,...) printk(BIOS_DEBUG, "EXYNOS_SPI: " x)
19 # define DEBUG_SPI(x,...)
22 static void exynos_spi_rx_tx(struct exynos_spi
*regs
, int todo
,
23 void *dinp
, void const *doutp
, int i
)
26 unsigned int *rxp
= (unsigned int *)(dinp
+ (i
* (32 * 1024)));
27 unsigned int out_bytes
, in_bytes
;
29 // TODO In current implementation, every read/write must be aligned to
30 // 4 bytes, otherwise you may get timeout or other unexpected results.
31 ASSERT(todo
% 4 == 0);
33 out_bytes
= in_bytes
= todo
;
34 setbits32(®s
->ch_cfg
, SPI_CH_RST
);
35 clrbits32(®s
->ch_cfg
, SPI_CH_RST
);
36 write32(®s
->pkt_cnt
, ((todo
* 8) / 32) | SPI_PACKET_CNT_EN
);
42 spi_sts
= read32(®s
->spi_sts
);
43 rx_lvl
= ((spi_sts
>> 15) & 0x7f);
44 tx_lvl
= ((spi_sts
>> 6) & 0x7f);
45 while (tx_lvl
< 32 && out_bytes
) {
46 // TODO The "writing" (tx) is not supported now; that's
47 // why we write garbage to keep driving FIFO clock.
49 write32(®s
->tx_data
, temp
);
53 while (rx_lvl
>= 4 && in_bytes
) {
54 temp
= read32(®s
->rx_data
);
63 /* set up SPI channel */
64 int exynos_spi_open(struct exynos_spi
*regs
)
66 /* set the spi1 GPIO */
68 /* set pktcnt and enable it */
69 write32(®s
->pkt_cnt
, 4 | SPI_PACKET_CNT_EN
);
71 write32(®s
->fb_clk
, SPI_FB_DELAY_180
);
72 /* set CH_WIDTH and BUS_WIDTH as word */
73 setbits32(®s
->mode_cfg
,
74 SPI_MODE_CH_WIDTH_WORD
| SPI_MODE_BUS_WIDTH_WORD
);
75 clrbits32(®s
->ch_cfg
, SPI_CH_CPOL_L
); /* CPOL: active high */
77 /* clear rx and tx channel if set previously */
78 clrbits32(®s
->ch_cfg
, SPI_RX_CH_ON
| SPI_TX_CH_ON
);
80 setbits32(®s
->swap_cfg
,
81 SPI_RX_SWAP_EN
| SPI_RX_BYTE_SWAP
| SPI_RX_HWORD_SWAP
);
84 setbits32(®s
->ch_cfg
, SPI_CH_RST
);
85 clrbits32(®s
->ch_cfg
, SPI_CH_RST
);
87 /* now set rx and tx channel ON */
88 setbits32(®s
->ch_cfg
, SPI_RX_CH_ON
| SPI_TX_CH_ON
| SPI_CH_HS_EN
);
92 int exynos_spi_read(struct exynos_spi
*regs
, void *dest
, u32 len
, u32 off
)
96 clrbits32(®s
->cs_reg
, SPI_SLAVE_SIG_INACT
); /* CS low */
98 /* Send read instruction (0x3h) followed by a 24 bit addr */
99 write32(®s
->tx_data
, (SF_READ_DATA_CMD
<< 24) | off
);
101 /* waiting for TX done */
102 while (!(read32(®s
->spi_sts
) & SPI_ST_TX_DONE
));
104 for (upto
= 0, i
= 0; upto
< len
; upto
+= todo
, i
++) {
105 todo
= MIN(len
- upto
, (1 << 15));
106 exynos_spi_rx_tx(regs
, todo
, dest
, (void *)(off
), i
);
109 setbits32(®s
->cs_reg
, SPI_SLAVE_SIG_INACT
);/* make the CS high */
114 int exynos_spi_close(struct exynos_spi
*regs
)
117 * Let put controller mode to BYTE as
118 * SPI driver does not support WORD mode yet
120 clrbits32(®s
->mode_cfg
,
121 SPI_MODE_CH_WIDTH_WORD
| SPI_MODE_BUS_WIDTH_WORD
);
122 write32(®s
->swap_cfg
, 0);
125 * Flush spi tx, rx fifos and reset the SPI controller
126 * and clear rx/tx channel
128 clrsetbits32(®s
->ch_cfg
, SPI_CH_HS_EN
, SPI_CH_RST
);
129 clrbits32(®s
->ch_cfg
, SPI_CH_RST
);
130 clrbits32(®s
->ch_cfg
, SPI_TX_CH_ON
| SPI_RX_CH_ON
);
134 static struct exynos_spi
*boot_slave_regs
;
136 static ssize_t
exynos_spi_readat(const struct region_device
*rdev
, void *dest
,
137 size_t offset
, size_t count
)
140 DEBUG_SPI("exynos_spi_cbfs_read(%u)\n", count
);
141 exynos_spi_open(boot_slave_regs
);
142 bytes
= exynos_spi_read(boot_slave_regs
, dest
, count
, offset
);
143 exynos_spi_close(boot_slave_regs
);
147 static void *exynos_spi_map(const struct region_device
*rdev
,
148 size_t offset
, size_t count
)
150 DEBUG_SPI("exynos_spi_cbfs_map\n");
151 // exynos: spi_rx_tx may work in 4 byte-width-transmission mode and
152 // requires buffer memory address to be aligned.
154 count
+= 4 - (count
% 4);
155 return mmap_helper_rdev_mmap(rdev
, offset
, count
);
158 static const struct region_device_ops exynos_spi_ops
= {
159 .mmap
= exynos_spi_map
,
160 .munmap
= mmap_helper_rdev_munmap
,
161 .readat
= exynos_spi_readat
,
164 static struct mmap_helper_region_device mdev
=
165 MMAP_HELPER_DEV_INIT(&exynos_spi_ops
, 0, CONFIG_ROM_SIZE
, &cbfs_cache
);
167 void exynos_init_spi_boot_device(void)
169 boot_slave_regs
= (void *)EXYNOS5_SPI1_BASE
;
172 const struct region_device
*exynos_spi_boot_device(void)