1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <device/mmio.h>
6 #include <console/console.h>
9 #include <spi-generic.h>
15 #define EXYNOS_SPI_MAX_TRANSFER_BYTES (65535)
17 #if defined(CONFIG_DEBUG_SPI) && CONFIG_DEBUG_SPI
18 # define DEBUG_SPI(x,...) printk(BIOS_DEBUG, "EXYNOS_SPI: " x)
20 # define DEBUG_SPI(x,...)
23 struct exynos_spi_slave
{
24 struct spi_slave slave
;
25 struct exynos_spi
*regs
;
29 /* TODO(hungte) Move the SPI param list to per-board configuration, probably
30 * Kconfig or mainboard.c */
31 static struct exynos_spi_slave exynos_spi_slaves
[3] = {
34 .slave
= { .bus
= 0, },
35 .regs
= (void *)EXYNOS5_SPI0_BASE
,
39 .slave
= { .bus
= 1, },
40 .regs
= (void *)EXYNOS5_SPI1_BASE
,
44 .slave
= { .bus
= 2, },
45 .regs
= (void *)EXYNOS5_SPI2_BASE
,
49 static inline struct exynos_spi_slave
*to_exynos_spi(const struct spi_slave
*slave
)
51 return &exynos_spi_slaves
[slave
->bus
];
54 static void spi_sw_reset(struct exynos_spi
*regs
, int word
)
56 const uint32_t orig_mode_cfg
= read32(®s
->mode_cfg
);
57 uint32_t mode_cfg
= orig_mode_cfg
;
58 const uint32_t orig_swap_cfg
= read32(®s
->swap_cfg
);
59 uint32_t swap_cfg
= orig_swap_cfg
;
61 mode_cfg
&= ~(SPI_MODE_CH_WIDTH_MASK
| SPI_MODE_BUS_WIDTH_MASK
);
63 mode_cfg
|= SPI_MODE_CH_WIDTH_WORD
| SPI_MODE_BUS_WIDTH_WORD
;
64 swap_cfg
|= SPI_RX_SWAP_EN
|
71 mode_cfg
|= SPI_MODE_CH_WIDTH_BYTE
| SPI_MODE_BUS_WIDTH_BYTE
;
75 if (mode_cfg
!= orig_mode_cfg
)
76 write32(®s
->mode_cfg
, mode_cfg
);
77 if (swap_cfg
!= orig_swap_cfg
)
78 write32(®s
->swap_cfg
, swap_cfg
);
80 clrbits32(®s
->ch_cfg
, SPI_RX_CH_ON
| SPI_TX_CH_ON
);
81 setbits32(®s
->ch_cfg
, SPI_CH_RST
);
82 clrbits32(®s
->ch_cfg
, SPI_CH_RST
);
83 setbits32(®s
->ch_cfg
, SPI_RX_CH_ON
| SPI_TX_CH_ON
);
86 static void exynos_spi_init(struct exynos_spi
*regs
)
89 write32(®s
->fb_clk
, SPI_FB_DELAY_180
);
91 clrbits32(®s
->ch_cfg
, SPI_CH_CPOL_L
);
93 // Clear rx and tx channel if set previously.
94 clrbits32(®s
->ch_cfg
, SPI_RX_CH_ON
| SPI_TX_CH_ON
);
96 setbits32(®s
->swap_cfg
,
97 SPI_RX_SWAP_EN
| SPI_RX_BYTE_SWAP
| SPI_RX_HWORD_SWAP
);
98 clrbits32(®s
->ch_cfg
, SPI_CH_HS_EN
);
100 // Do a soft reset, which will also enable both channels.
101 spi_sw_reset(regs
, 1);
104 static int spi_ctrlr_claim_bus(const struct spi_slave
*slave
)
106 struct exynos_spi
*regs
= to_exynos_spi(slave
)->regs
;
107 // TODO(hungte) Add some delay if too many transactions happen at once.
108 clrbits32(®s
->cs_reg
, SPI_SLAVE_SIG_INACT
);
112 static void spi_transfer(struct exynos_spi
*regs
, void *in
, const void *out
,
116 const u8
*outb
= out
;
118 size_t width
= (size
% 4) ? 1 : 4;
121 size_t packets
= size
/ width
;
122 // The packet count field is 16 bits wide.
123 packets
= MIN(packets
, (1 << 16) - 1);
125 size_t out_bytes
, in_bytes
;
126 out_bytes
= in_bytes
= packets
* width
;
128 spi_sw_reset(regs
, width
== 4);
129 write32(®s
->pkt_cnt
, packets
| SPI_PACKET_CNT_EN
);
131 while (out_bytes
|| in_bytes
) {
132 uint32_t spi_sts
= read32(®s
->spi_sts
);
133 int rx_lvl
= ((spi_sts
>> 15) & 0x1ff);
134 int tx_lvl
= ((spi_sts
>> 6) & 0x1ff);
136 if (tx_lvl
< 32 && tx_lvl
< out_bytes
) {
137 uint32_t data
= 0xffffffff;
140 memcpy(&data
, outb
, width
);
143 write32(®s
->tx_data
, data
);
148 if (rx_lvl
>= width
) {
149 uint32_t data
= read32(®s
->rx_data
);
152 memcpy(inb
, &data
, width
);
160 size
-= packets
* width
;
164 static int spi_ctrlr_xfer(const struct spi_slave
*slave
, const void *dout
, size_t bytes_out
,
165 void *din
, size_t bytes_in
)
167 struct exynos_spi
*regs
= to_exynos_spi(slave
)->regs
;
169 if (bytes_out
&& bytes_in
) {
170 size_t min_size
= MIN(bytes_out
, bytes_in
);
172 spi_transfer(regs
, din
, dout
, min_size
);
174 bytes_out
-= min_size
;
175 bytes_in
-= min_size
;
177 din
= (uint8_t *)din
+ min_size
;
178 dout
= (const uint8_t *)dout
+ min_size
;
182 spi_transfer(regs
, din
, NULL
, bytes_in
);
184 spi_transfer(regs
, NULL
, dout
, bytes_out
);
189 static void spi_ctrlr_release_bus(const struct spi_slave
*slave
)
191 struct exynos_spi
*regs
= to_exynos_spi(slave
)->regs
;
192 setbits32(®s
->cs_reg
, SPI_SLAVE_SIG_INACT
);
195 static int spi_ctrlr_setup(const struct spi_slave
*slave
)
197 ASSERT(slave
->bus
< 3);
198 struct exynos_spi_slave
*eslave
;
200 eslave
= to_exynos_spi(slave
);
201 if (!eslave
->initialized
) {
202 exynos_spi_init(eslave
->regs
);
203 eslave
->initialized
= 1;
208 static const struct spi_ctrlr spi_ctrlr
= {
209 .setup
= spi_ctrlr_setup
,
210 .claim_bus
= spi_ctrlr_claim_bus
,
211 .release_bus
= spi_ctrlr_release_bus
,
212 .xfer
= spi_ctrlr_xfer
,
213 .max_xfer_size
= SPI_CTRLR_DEFAULT_MAX_XFER_SIZE
,
216 const struct spi_ctrlr_buses spi_ctrlr_bus_map
[] = {
224 const size_t spi_ctrlr_bus_map_count
= ARRAY_SIZE(spi_ctrlr_bus_map
);
226 static int exynos_spi_read(struct spi_slave
*slave
, void *dest
, uint32_t len
,
229 struct exynos_spi
*regs
= to_exynos_spi(slave
)->regs
;
231 spi_claim_bus(slave
);
234 ASSERT(off
< (1 << 24));
235 command
= htonl(SF_READ_DATA_CMD
<< 24 | off
);
236 spi_transfer(regs
, NULL
, &command
, sizeof(command
));
239 spi_transfer(regs
, dest
, NULL
, len
);
240 spi_release_bus(slave
);
245 static struct exynos_spi_slave
*boot_slave
;
247 static ssize_t
exynos_spi_readat(const struct region_device
*rdev
, void *dest
,
248 size_t offset
, size_t count
)
250 DEBUG_SPI("exynos_spi_cbfs_read(%u)\n", count
);
251 return exynos_spi_read(&boot_slave
->slave
, dest
, count
, offset
);
254 static void *exynos_spi_map(const struct region_device
*rdev
,
255 size_t offset
, size_t count
)
257 DEBUG_SPI("exynos_spi_cbfs_map\n");
258 // exynos: spi_rx_tx may work in 4 byte-width-transmission mode and
259 // requires buffer memory address to be aligned.
261 count
+= 4 - (count
% 4);
262 return mmap_helper_rdev_mmap(rdev
, offset
, count
);
265 static const struct region_device_ops exynos_spi_ops
= {
266 .mmap
= exynos_spi_map
,
267 .munmap
= mmap_helper_rdev_munmap
,
268 .readat
= exynos_spi_readat
,
271 static struct mmap_helper_region_device mdev
=
272 MMAP_HELPER_DEV_INIT(&exynos_spi_ops
, 0, CONFIG_ROM_SIZE
, &cbfs_cache
);
274 void exynos_init_spi_boot_device(void)
276 boot_slave
= &exynos_spi_slaves
[1];
279 const struct region_device
*exynos_spi_boot_device(void)