coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
spi.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <assert.h>
5 #include <console/console.h>
6 #include <delay.h>
7 #include <endian.h>
8 #include <soc/addressmap.h>
9 #include <soc/spi.h>
10 #include <soc/clock.h>
11 #include <spi-generic.h>
12 #include <spi_flash.h>
13 #include <timer.h>
14 #include <types.h>
15 
17  struct rockchip_spi *regs;
18 };
19 
20 #define SPI_TIMEOUT_US 1000
21 #define SPI_SRCCLK_HZ (198*MHz)
22 #define SPI_FIFO_DEPTH 32
23 
24 static struct rockchip_spi_slave rockchip_spi_slaves[] = {
25  {
26  .regs = (void *)SPI0_BASE,
27  },
28  {
29  .regs = (void *)SPI1_BASE,
30  },
31  {
32  .regs = (void *)SPI2_BASE,
33  },
34 #ifdef SPI3_BASE
35  {
36  .regs = (void *)SPI3_BASE,
37  },
38 #ifdef SPI4_BASE
39  {
40  .regs = (void *)SPI4_BASE,
41  },
42 #ifdef SPI5_BASE
43  {
44  .regs = (void *)SPI5_BASE,
45  },
46 #endif
47 #endif
48 #endif
49 };
50 
51 static struct rockchip_spi_slave *to_rockchip_spi(const struct spi_slave *slave)
52 {
54  return &rockchip_spi_slaves[slave->bus];
55 }
56 
57 static void spi_cs_activate(const struct spi_slave *slave)
58 {
60  setbits32(&regs->ser, 1);
61 }
62 
63 static void spi_cs_deactivate(const struct spi_slave *slave)
64 {
66  clrbits32(&regs->ser, 1);
67 }
68 
69 static void rockchip_spi_enable_chip(struct rockchip_spi *regs, int enable)
70 {
71  if (enable == 1)
72  write32(&regs->spienr, 1);
73  else
74  write32(&regs->spienr, 0);
75 }
76 
77 static void rockchip_spi_set_clk(struct rockchip_spi *regs, unsigned int hz)
78 {
79  unsigned short clk_div = SPI_SRCCLK_HZ / hz;
80  assert(clk_div * hz == SPI_SRCCLK_HZ && !(clk_div & 1));
81  write32(&regs->baudr, clk_div);
82 }
83 
84 void rockchip_spi_init(unsigned int bus, unsigned int speed_hz)
85 {
88  unsigned int ctrlr0 = 0;
89 
92  rockchip_spi_set_clk(regs, speed_hz);
93 
94  /* Operation Mode */
96 
97  /* Data Frame Size */
99 
100  /* Chip Select Mode */
102 
103  /* SSN to Sclk_out delay */
105 
106  /* Serial Endian Mode */
108 
109  /* First Bit Mode */
111 
112  /* Frame Format */
114 
115  write32(&regs->ctrlr0, ctrlr0);
116 
117  /* fifo depth */
118  write32(&regs->txftlr, SPI_FIFO_DEPTH / 2 - 1);
119  write32(&regs->rxftlr, SPI_FIFO_DEPTH / 2 - 1);
120 }
121 
122 void rockchip_spi_set_sample_delay(unsigned int bus, unsigned int delay_ns)
123 {
126  unsigned int rsd;
127 
128  /* Rxd Sample Delay */
129  rsd = DIV_ROUND_CLOSEST(delay_ns * (SPI_SRCCLK_HZ >> 8), 1*GHz >> 8);
130  assert(rsd <= 3);
132  rsd << SPI_RXDSD_OFFSET);
133 }
134 
135 static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
136 {
138  return 0;
139 }
140 
141 static void spi_ctrlr_release_bus(const struct spi_slave *slave)
142 {
144 }
145 
147 {
148  struct stopwatch sw;
149 
151  do {
152  if (!(read32(&regs->sr) & SR_BUSY))
153  return 0;
154  } while (!stopwatch_expired(&sw));
156  "RK SPI: Status keeps busy for 1000us after a read/write!\n");
157  return -1;
158 }
159 
160 static void set_tmod(struct rockchip_spi *regs, unsigned int tmod)
161 {
163  tmod << SPI_TMOD_OFFSET);
164 }
165 
166 static void set_transfer_mode(struct rockchip_spi *regs,
167  unsigned int sout, unsigned int sin)
168 {
169  if (!sin && !sout)
170  return;
171  else if (sin && sout)
172  set_tmod(regs, SPI_TMOD_TR); /* tx and rx */
173  else if (!sin)
174  set_tmod(regs, SPI_TMOD_TO); /* tx only */
175  else if (!sout)
176  set_tmod(regs, SPI_TMOD_RO); /* rx only */
177 }
178 
179 /* returns 0 to indicate success, <0 otherwise */
180 static int do_xfer(struct rockchip_spi *regs, bool use_16bit, const void *dout,
181  size_t *bytes_out, void *din, size_t *bytes_in)
182 {
183  uint8_t *in_buf = din;
184  uint8_t *out_buf = (uint8_t *)dout;
185  size_t min_xfer;
186 
187  if (*bytes_out == 0)
188  min_xfer = *bytes_in;
189  else if (*bytes_in == 0)
190  min_xfer = *bytes_out;
191  else
192  min_xfer = MIN(*bytes_in, *bytes_out);
193 
194  while (min_xfer) {
195  uint32_t sr = read32(&regs->sr);
196  int xferred = 0; /* in either (or both) directions */
197 
198  if (*bytes_out && !(sr & SR_TF_FULL)) {
199  write32(&regs->txdr, *out_buf);
200  out_buf++;
201  *bytes_out -= 1;
202  xferred = 1;
203  }
204 
205  /*
206  * Try to read as many bytes as are available in one go.
207  * Reading the status registers probably requires
208  * sychronizing with the SPI clock which is pretty slow.
209  */
210  if (*bytes_in && !(sr & SR_RF_EMPT)) {
211  int w = use_16bit ? 2 : 1;
212  xferred = (read32(&regs->rxflr) & RXFLR_LEVEL_MASK) * w;
213  buffer_from_fifo32(in_buf, xferred, &regs->rxdr, 0, w);
214  *bytes_in -= xferred;
215  in_buf += xferred;
216  }
217 
218  min_xfer -= xferred;
219  }
220 
222  printk(BIOS_ERR, "Timed out waiting on SPI transfer\n");
223  return -1;
224  }
225 
226  return 0;
227 }
228 
229 static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
230  size_t bytes_out, void *din, size_t bytes_in)
231 {
233  int ret = 0;
234 
235  /*
236  * RK3288 SPI controller can transfer up to 65536 data frames (bytes
237  * in our case) continuously. Break apart large requests as necessary.
238  *
239  * FIXME: And by 65536, we really mean 65535. If 0xffff is written to
240  * ctrlr1, all bytes that we see in rxdr end up being 0x00. 0xffff - 1
241  * seems to work fine.
242  */
243  while (bytes_out || bytes_in) {
244  size_t in_now = MIN(bytes_in, 0xfffe);
245  size_t out_now = MIN(bytes_out, 0xfffe);
246  size_t in_rem, out_rem;
247  size_t mask;
248  bool use_16bit;
249 
251 
252  /*
253  * Use 16-bit transfers for higher-speed reads. If we are
254  * transferring an odd number of bytes, try to make it even.
255  */
256  use_16bit = false;
257  if (bytes_out == 0) {
258  if ((in_now & 1) && in_now > 1)
259  in_now--;
260  if (!(in_now & 1))
261  use_16bit = true;
262  }
264  if (use_16bit)
265  clrbits32(&regs->ctrlr0, mask);
266  else
267  setbits32(&regs->ctrlr0, mask);
268 
269  /* Enable/disable transmitter and receiver as needed to
270  * avoid sending or reading spurious bits. */
271  set_transfer_mode(regs, bytes_out, bytes_in);
272 
273  /* MAX() in case either counter is 0 */
274  write32(&regs->ctrlr1, MAX(in_now, out_now) - 1);
275 
277 
278  in_rem = in_now;
279  out_rem = out_now;
280  ret = do_xfer(regs, use_16bit, dout, &out_rem, din, &in_rem);
281  if (ret < 0)
282  break;
283 
284  if (bytes_out) {
285  size_t sent = out_now - out_rem;
286  bytes_out -= sent;
287  dout += sent;
288  }
289 
290  if (bytes_in) {
291  size_t received = in_now - in_rem;
292  bytes_in -= received;
293  din += received;
294  }
295  }
296 
298  return ret < 0 ? ret : 0;
299 }
300 
301 static const struct spi_ctrlr spi_ctrlr = {
303  .release_bus = spi_ctrlr_release_bus,
304  .xfer = spi_ctrlr_xfer,
305  .max_xfer_size = 65535,
306 };
307 
308 const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
309  {
310  .ctrlr = &spi_ctrlr,
311  .bus_start = 0,
312  .bus_end = ARRAY_SIZE(rockchip_spi_slaves) - 1,
313  },
314 };
315 
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define assert(statement)
Definition: assert.h:74
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define GHz
Definition: helpers.h:81
#define MIN(a, b)
Definition: helpers.h:37
#define MAX(a, b)
Definition: helpers.h:40
#define printk(level,...)
Definition: stdlib.h:16
void buffer_from_fifo32(void *buffer, size_t size, void *fifo, int fifo_stride, int fifo_width)
Definition: mmio.c:8
#define DIV_ROUND_CLOSEST(x, divisor)
Definition: helpers.h:17
#define setbits32(addr, set)
Definition: mmio.h:21
#define clrsetbits32(addr, clear, set)
Definition: mmio.h:16
#define clrbits32(addr, clear)
Definition: mmio.h:26
static int stopwatch_expired(struct stopwatch *sw)
Definition: timer.h:152
static void stopwatch_init_usecs_expire(struct stopwatch *sw, long us)
Definition: timer.h:127
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
const struct spi_ctrlr_buses spi_ctrlr_bus_map[]
Definition: spi.c:401
const size_t spi_ctrlr_bus_map_count
Definition: spi.c:408
static const int mask[4]
Definition: gpio.c:308
const struct spi_ctrlr spi_ctrlr
Definition: spi.c:261
#define SPI_TMOD_TR
Definition: spi.h:138
#define SR_BUSY
Definition: spi.h:163
#define SPI_SEM_OFFSET
Definition: spi.h:96
#define SPI_FRF_OFFSET
Definition: spi.h:124
#define SPI_CSM_OFFSET
Definition: spi.h:71
#define SPI_RXDSD_MASK
Definition: spi.h:121
#define SPI_FRF_SPI
Definition: spi.h:127
#define SR_TF_FULL
Definition: spi.h:164
#define SPI_TMOD_MASK
Definition: spi.h:136
#define SPI_OMOD_OFFSET
Definition: spi.h:146
#define SR_RF_EMPT
Definition: spi.h:166
#define SPI_TMOD_RO
Definition: spi.h:142
#define SPI_TMOD_OFFSET
Definition: spi.h:135
#define RXFLR_LEVEL_MASK
Definition: spi.h:159
#define SPI_SEM_LITTLE
Definition: spi.h:99
#define SPI_APB_8BIT
Definition: spi.h:117
#define SPI_DFS_8BIT
Definition: spi.h:42
#define SPI_FBM_MSB
Definition: spi.h:107
#define SPI_SSN_DELAY_OFFSET
Definition: spi.h:88
#define SPI_OMOD_MASTER
Definition: spi.h:149
#define SPI_SSN_DELAY_ONE
Definition: spi.h:93
#define SPI_CSM_KEEP
Definition: spi.h:75
#define SPI_FBM_OFFSET
Definition: spi.h:104
#define SPI_DFS_OFFSET
Definition: spi.h:39
#define SPI_RXDSD_OFFSET
Definition: spi.h:120
#define SPI_HALF_WORLD_TX_OFFSET
Definition: spi.h:112
#define SPI_TMOD_TO
Definition: spi.h:140
static void rockchip_spi_set_clk(struct rockchip_spi *regs, unsigned int hz)
Definition: spi.c:77
static void rockchip_spi_enable_chip(struct rockchip_spi *regs, int enable)
Definition: spi.c:69
static void set_transfer_mode(struct rockchip_spi *regs, unsigned int sout, unsigned int sin)
Definition: spi.c:166
static void spi_ctrlr_release_bus(const struct spi_slave *slave)
Definition: spi.c:141
static void spi_cs_activate(const struct spi_slave *slave)
Definition: spi.c:57
static void spi_cs_deactivate(const struct spi_slave *slave)
Definition: spi.c:63
static struct rockchip_spi_slave rockchip_spi_slaves[]
Definition: spi.c:24
#define SPI_SRCCLK_HZ
Definition: spi.c:21
void rockchip_spi_set_sample_delay(unsigned int bus, unsigned int delay_ns)
Definition: spi.c:122
void rockchip_spi_init(unsigned int bus, unsigned int speed_hz)
Definition: spi.c:84
#define SPI_FIFO_DEPTH
Definition: spi.c:22
static int rockchip_spi_wait_till_not_busy(struct rockchip_spi *regs)
Definition: spi.c:146
static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout, size_t bytes_out, void *din, size_t bytes_in)
Definition: spi.c:229
static int do_xfer(struct rockchip_spi *regs, bool use_16bit, const void *dout, size_t *bytes_out, void *din, size_t *bytes_in)
Definition: spi.c:180
static void set_tmod(struct rockchip_spi *regs, unsigned int tmod)
Definition: spi.c:160
#define SPI_TIMEOUT_US
Definition: spi.c:20
static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
Definition: spi.c:135
static struct rockchip_spi_slave * to_rockchip_spi(const struct spi_slave *slave)
Definition: spi.c:51
void rkclk_configure_spi(unsigned int bus, unsigned int hz)
Definition: clock.c:414
#define SPI1_BASE
Definition: addressmap.h:14
#define SPI2_BASE
Definition: addressmap.h:15
#define SPI0_BASE
Definition: addressmap.h:13
#define SPI5_BASE
Definition: addressmap.h:43
#define SPI4_BASE
Definition: addressmap.h:42
#define SPI3_BASE
Definition: addressmap.h:41
static struct spi_slave slave
Definition: spiconsole.c:7
unsigned int uint32_t
Definition: stdint.h:14
unsigned char uint8_t
Definition: stdint.h:8
Definition: device.h:76
struct rockchip_spi * regs
Definition: spi.c:17
u32 ctrlr0
Definition: spi.h:11
const struct spi_ctrlr * ctrlr
Definition: spi-generic.h:175
int(* claim_bus)(const struct spi_slave *slave)
Definition: spi-generic.h:149
unsigned int bus
Definition: spi-generic.h:41