]>
Commit | Line | Data |
---|---|---|
7ee49d03 BM |
1 | .. SPDX-License-Identifier: GPL-2.0+ |
2 | ||
3 | How to port a SPI driver to driver model | |
4 | ======================================== | |
5 | ||
6 | Here is a rough step-by-step guide. It is based around converting the | |
7 | exynos SPI driver to driver model (DM) and the example code is based | |
8 | around U-Boot v2014.10-rc2 (commit be9f643). This has been updated for | |
9 | v2015.04. | |
10 | ||
11 | It is quite long since it includes actual code examples. | |
12 | ||
13 | Before driver model, SPI drivers have their own private structure which | |
14 | contains 'struct spi_slave'. With driver model, 'struct spi_slave' still | |
15 | exists, but now it is 'per-child data' for the SPI bus. Each child of the | |
16 | SPI bus is a SPI slave. The information that was stored in the | |
17 | driver-specific slave structure can now be port in private data for the | |
18 | SPI bus. | |
19 | ||
20 | For example, struct tegra_spi_slave looks like this: | |
21 | ||
22 | .. code-block:: c | |
23 | ||
24 | struct tegra_spi_slave { | |
25 | struct spi_slave slave; | |
26 | struct tegra_spi_ctrl *ctrl; | |
27 | }; | |
28 | ||
29 | In this case 'slave' will be in per-child data, and 'ctrl' will be in the | |
30 | SPI's buses private data. | |
31 | ||
32 | ||
33 | How long does this take? | |
34 | ------------------------ | |
35 | ||
36 | You should be able to complete this within 2 hours, including testing but | |
37 | excluding preparing the patches. The API is basically the same as before | |
38 | with only minor changes: | |
39 | ||
40 | - methods to set speed and mode are separated out | |
41 | - cs_info is used to get information on a chip select | |
42 | ||
43 | ||
44 | Enable driver mode for SPI and SPI flash | |
45 | ---------------------------------------- | |
46 | ||
47 | Add these to your board config: | |
48 | ||
49 | * CONFIG_DM_SPI | |
50 | * CONFIG_DM_SPI_FLASH | |
51 | ||
52 | ||
53 | Add the skeleton | |
54 | ---------------- | |
55 | ||
56 | Put this code at the bottom of your existing driver file: | |
57 | ||
58 | .. code-block:: c | |
59 | ||
60 | struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs, | |
61 | unsigned int max_hz, unsigned int mode) | |
62 | { | |
63 | return NULL; | |
64 | } | |
65 | ||
66 | struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node, | |
67 | int spi_node) | |
68 | { | |
69 | return NULL; | |
70 | } | |
71 | ||
72 | static int exynos_spi_ofdata_to_platdata(struct udevice *dev) | |
73 | { | |
74 | return -ENODEV; | |
75 | } | |
76 | ||
77 | static int exynos_spi_probe(struct udevice *dev) | |
78 | { | |
79 | return -ENODEV; | |
80 | } | |
81 | ||
82 | static int exynos_spi_remove(struct udevice *dev) | |
83 | { | |
84 | return -ENODEV; | |
85 | } | |
86 | ||
87 | static int exynos_spi_claim_bus(struct udevice *dev) | |
88 | { | |
89 | ||
90 | return -ENODEV; | |
91 | } | |
92 | ||
93 | static int exynos_spi_release_bus(struct udevice *dev) | |
94 | { | |
95 | ||
96 | return -ENODEV; | |
97 | } | |
98 | ||
99 | static int exynos_spi_xfer(struct udevice *dev, unsigned int bitlen, | |
100 | const void *dout, void *din, unsigned long flags) | |
101 | { | |
102 | ||
103 | return -ENODEV; | |
104 | } | |
105 | ||
106 | static int exynos_spi_set_speed(struct udevice *dev, uint speed) | |
107 | { | |
108 | return -ENODEV; | |
109 | } | |
110 | ||
111 | static int exynos_spi_set_mode(struct udevice *dev, uint mode) | |
112 | { | |
113 | return -ENODEV; | |
114 | } | |
115 | ||
116 | static int exynos_cs_info(struct udevice *bus, uint cs, | |
117 | struct spi_cs_info *info) | |
118 | { | |
4b060003 | 119 | return -EINVAL; |
7ee49d03 BM |
120 | } |
121 | ||
122 | static const struct dm_spi_ops exynos_spi_ops = { | |
123 | .claim_bus = exynos_spi_claim_bus, | |
124 | .release_bus = exynos_spi_release_bus, | |
125 | .xfer = exynos_spi_xfer, | |
126 | .set_speed = exynos_spi_set_speed, | |
127 | .set_mode = exynos_spi_set_mode, | |
128 | .cs_info = exynos_cs_info, | |
129 | }; | |
130 | ||
131 | static const struct udevice_id exynos_spi_ids[] = { | |
132 | { .compatible = "samsung,exynos-spi" }, | |
133 | { } | |
134 | }; | |
135 | ||
136 | U_BOOT_DRIVER(exynos_spi) = { | |
137 | .name = "exynos_spi", | |
138 | .id = UCLASS_SPI, | |
139 | .of_match = exynos_spi_ids, | |
140 | .ops = &exynos_spi_ops, | |
141 | .ofdata_to_platdata = exynos_spi_ofdata_to_platdata, | |
142 | .probe = exynos_spi_probe, | |
143 | .remove = exynos_spi_remove, | |
144 | }; | |
145 | ||
146 | ||
147 | Replace 'exynos' in the above code with your driver name | |
148 | -------------------------------------------------------- | |
149 | ||
150 | ||
151 | #ifdef out all of the code in your driver except for the above | |
152 | -------------------------------------------------------------- | |
153 | ||
154 | This will allow you to get it building, which means you can work | |
155 | incrementally. Since all the methods return an error initially, there is | |
156 | less chance that you will accidentally leave something in. | |
157 | ||
158 | Also, even though your conversion is basically a rewrite, it might help | |
159 | reviewers if you leave functions in the same place in the file, | |
160 | particularly for large drivers. | |
161 | ||
162 | ||
163 | Add some includes | |
164 | ----------------- | |
165 | ||
166 | Add these includes to your driver: | |
167 | ||
168 | .. code-block:: c | |
169 | ||
170 | #include <dm.h> | |
171 | #include <errno.h> | |
172 | ||
173 | ||
174 | Build | |
175 | ----- | |
176 | ||
177 | At this point you should be able to build U-Boot for your board with the | |
178 | empty SPI driver. You still have empty methods in your driver, but we will | |
179 | write these one by one. | |
180 | ||
181 | Set up your platform data structure | |
182 | ----------------------------------- | |
183 | ||
184 | This will hold the information your driver to operate, like its hardware | |
185 | address or maximum frequency. | |
186 | ||
187 | You may already have a struct like this, or you may need to create one | |
188 | from some of the #defines or global variables in the driver. | |
189 | ||
190 | Note that this information is not the run-time information. It should not | |
191 | include state that changes. It should be fixed throughout the live of | |
192 | U-Boot. Run-time information comes later. | |
193 | ||
194 | Here is what was in the exynos spi driver: | |
195 | ||
196 | .. code-block:: c | |
197 | ||
198 | struct spi_bus { | |
199 | enum periph_id periph_id; | |
200 | s32 frequency; /* Default clock frequency, -1 for none */ | |
201 | struct exynos_spi *regs; | |
202 | int inited; /* 1 if this bus is ready for use */ | |
203 | int node; | |
204 | uint deactivate_delay_us; /* Delay to wait after deactivate */ | |
205 | }; | |
206 | ||
207 | Of these, inited is handled by DM and node is the device tree node, which | |
208 | DM tells you. The name is not quite right. So in this case we would use: | |
209 | ||
210 | .. code-block:: c | |
211 | ||
212 | struct exynos_spi_platdata { | |
213 | enum periph_id periph_id; | |
214 | s32 frequency; /* Default clock frequency, -1 for none */ | |
215 | struct exynos_spi *regs; | |
216 | uint deactivate_delay_us; /* Delay to wait after deactivate */ | |
217 | }; | |
218 | ||
219 | ||
220 | Write ofdata_to_platdata() [for device tree only] | |
221 | ------------------------------------------------- | |
222 | ||
223 | This method will convert information in the device tree node into a C | |
224 | structure in your driver (called platform data). If you are not using | |
225 | device tree, go to 8b. | |
226 | ||
227 | DM will automatically allocate the struct for us when we are using device | |
228 | tree, but we need to tell it the size: | |
229 | ||
230 | .. code-block:: c | |
231 | ||
232 | U_BOOT_DRIVER(spi_exynos) = { | |
233 | ... | |
caa4daa2 | 234 | .plat_auto = sizeof(struct exynos_spi_platdata), |
7ee49d03 BM |
235 | |
236 | ||
237 | Here is a sample function. It gets a pointer to the platform data and | |
238 | fills in the fields from device tree. | |
239 | ||
240 | .. code-block:: c | |
241 | ||
242 | static int exynos_spi_ofdata_to_platdata(struct udevice *bus) | |
243 | { | |
caa4daa2 | 244 | struct exynos_spi_platdata *plat = bus->plat; |
7ee49d03 BM |
245 | const void *blob = gd->fdt_blob; |
246 | int node = dev_of_offset(bus); | |
247 | ||
248 | plat->regs = (struct exynos_spi *)fdtdec_get_addr(blob, node, "reg"); | |
249 | plat->periph_id = pinmux_decode_periph_id(blob, node); | |
250 | ||
251 | if (plat->periph_id == PERIPH_ID_NONE) { | |
252 | debug("%s: Invalid peripheral ID %d\n", __func__, | |
253 | plat->periph_id); | |
254 | return -FDT_ERR_NOTFOUND; | |
255 | } | |
256 | ||
257 | /* Use 500KHz as a suitable default */ | |
258 | plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", | |
259 | 500000); | |
260 | plat->deactivate_delay_us = fdtdec_get_int(blob, node, | |
261 | "spi-deactivate-delay", 0); | |
262 | debug("%s: regs=%p, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n", | |
263 | __func__, plat->regs, plat->periph_id, plat->frequency, | |
264 | plat->deactivate_delay_us); | |
265 | ||
266 | return 0; | |
267 | } | |
268 | ||
269 | ||
270 | Add the platform data [non-device-tree only] | |
271 | -------------------------------------------- | |
272 | ||
273 | Specify this data in a U_BOOT_DEVICE() declaration in your board file: | |
274 | ||
275 | .. code-block:: c | |
276 | ||
277 | struct exynos_spi_platdata platdata_spi0 = { | |
278 | .periph_id = ... | |
279 | .frequency = ... | |
280 | .regs = ... | |
281 | .deactivate_delay_us = ... | |
282 | }; | |
283 | ||
284 | U_BOOT_DEVICE(board_spi0) = { | |
285 | .name = "exynos_spi", | |
caa4daa2 | 286 | .plat = &platdata_spi0, |
7ee49d03 BM |
287 | }; |
288 | ||
289 | You will unfortunately need to put the struct definition into a header file | |
290 | in this case so that your board file can use it. | |
291 | ||
292 | ||
293 | Add the device private data | |
294 | --------------------------- | |
295 | ||
296 | Most devices have some private data which they use to keep track of things | |
297 | while active. This is the run-time information and needs to be stored in | |
298 | a structure. There is probably a structure in the driver that includes a | |
299 | 'struct spi_slave', so you can use that. | |
300 | ||
301 | .. code-block:: c | |
302 | ||
303 | struct exynos_spi_slave { | |
304 | struct spi_slave slave; | |
305 | struct exynos_spi *regs; | |
306 | unsigned int freq; /* Default frequency */ | |
307 | unsigned int mode; | |
308 | enum periph_id periph_id; /* Peripheral ID for this device */ | |
309 | unsigned int fifo_size; | |
310 | int skip_preamble; | |
311 | struct spi_bus *bus; /* Pointer to our SPI bus info */ | |
312 | ulong last_transaction_us; /* Time of last transaction end */ | |
313 | }; | |
314 | ||
315 | ||
316 | We should rename this to make its purpose more obvious, and get rid of | |
317 | the slave structure, so we have: | |
318 | ||
319 | .. code-block:: c | |
320 | ||
321 | struct exynos_spi_priv { | |
322 | struct exynos_spi *regs; | |
323 | unsigned int freq; /* Default frequency */ | |
324 | unsigned int mode; | |
325 | enum periph_id periph_id; /* Peripheral ID for this device */ | |
326 | unsigned int fifo_size; | |
327 | int skip_preamble; | |
328 | ulong last_transaction_us; /* Time of last transaction end */ | |
329 | }; | |
330 | ||
331 | ||
332 | DM can auto-allocate this also: | |
333 | ||
334 | .. code-block:: c | |
335 | ||
336 | U_BOOT_DRIVER(spi_exynos) = { | |
337 | ... | |
41575d8e | 338 | .priv_auto = sizeof(struct exynos_spi_priv), |
7ee49d03 BM |
339 | |
340 | ||
341 | Note that this is created before the probe method is called, and destroyed | |
342 | after the remove method is called. It will be zeroed when the probe | |
343 | method is called. | |
344 | ||
345 | ||
346 | Add the probe() and remove() methods | |
347 | ------------------------------------ | |
348 | ||
349 | Note: It's a good idea to build repeatedly as you are working, to avoid a | |
350 | huge amount of work getting things compiling at the end. | |
351 | ||
352 | The probe method is supposed to set up the hardware. U-Boot used to use | |
353 | spi_setup_slave() to do this. So take a look at this function and see | |
354 | what you can copy out to set things up. | |
355 | ||
356 | .. code-block:: c | |
357 | ||
358 | static int exynos_spi_probe(struct udevice *bus) | |
359 | { | |
360 | struct exynos_spi_platdata *plat = dev_get_platdata(bus); | |
361 | struct exynos_spi_priv *priv = dev_get_priv(bus); | |
362 | ||
363 | priv->regs = plat->regs; | |
364 | if (plat->periph_id == PERIPH_ID_SPI1 || | |
365 | plat->periph_id == PERIPH_ID_SPI2) | |
366 | priv->fifo_size = 64; | |
367 | else | |
368 | priv->fifo_size = 256; | |
369 | ||
370 | priv->skip_preamble = 0; | |
371 | priv->last_transaction_us = timer_get_us(); | |
372 | priv->freq = plat->frequency; | |
373 | priv->periph_id = plat->periph_id; | |
374 | ||
375 | return 0; | |
376 | } | |
377 | ||
378 | This implementation doesn't actually touch the hardware, which is somewhat | |
379 | unusual for a driver. In this case we will do that when the device is | |
380 | claimed by something that wants to use the SPI bus. | |
381 | ||
382 | For remove we could shut down the clocks, but in this case there is | |
383 | nothing to do. DM frees any memory that it allocated, so we can just | |
384 | remove exynos_spi_remove() and its reference in U_BOOT_DRIVER. | |
385 | ||
386 | ||
387 | Implement set_speed() | |
388 | --------------------- | |
389 | ||
390 | This should set up clocks so that the SPI bus is running at the right | |
391 | speed. With the old API spi_claim_bus() would normally do this and several | |
392 | of the following functions, so let's look at that function: | |
393 | ||
394 | .. code-block:: c | |
395 | ||
396 | int spi_claim_bus(struct spi_slave *slave) | |
397 | { | |
398 | struct exynos_spi_slave *spi_slave = to_exynos_spi(slave); | |
399 | struct exynos_spi *regs = spi_slave->regs; | |
400 | u32 reg = 0; | |
401 | int ret; | |
402 | ||
403 | ret = set_spi_clk(spi_slave->periph_id, | |
404 | spi_slave->freq); | |
405 | if (ret < 0) { | |
406 | debug("%s: Failed to setup spi clock\n", __func__); | |
407 | return ret; | |
408 | } | |
409 | ||
410 | exynos_pinmux_config(spi_slave->periph_id, PINMUX_FLAG_NONE); | |
411 | ||
412 | spi_flush_fifo(slave); | |
413 | ||
414 | reg = readl(®s->ch_cfg); | |
415 | reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L); | |
416 | ||
417 | if (spi_slave->mode & SPI_CPHA) | |
418 | reg |= SPI_CH_CPHA_B; | |
419 | ||
420 | if (spi_slave->mode & SPI_CPOL) | |
421 | reg |= SPI_CH_CPOL_L; | |
422 | ||
423 | writel(reg, ®s->ch_cfg); | |
424 | writel(SPI_FB_DELAY_180, ®s->fb_clk); | |
425 | ||
426 | return 0; | |
427 | } | |
428 | ||
429 | ||
430 | It sets up the speed, mode, pinmux, feedback delay and clears the FIFOs. | |
431 | With DM these will happen in separate methods. | |
432 | ||
433 | ||
434 | Here is an example for the speed part: | |
435 | ||
436 | .. code-block:: c | |
437 | ||
438 | static int exynos_spi_set_speed(struct udevice *bus, uint speed) | |
439 | { | |
caa4daa2 | 440 | struct exynos_spi_platdata *plat = bus->plat; |
7ee49d03 BM |
441 | struct exynos_spi_priv *priv = dev_get_priv(bus); |
442 | int ret; | |
443 | ||
444 | if (speed > plat->frequency) | |
445 | speed = plat->frequency; | |
446 | ret = set_spi_clk(priv->periph_id, speed); | |
447 | if (ret) | |
448 | return ret; | |
449 | priv->freq = speed; | |
450 | debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq); | |
451 | ||
452 | return 0; | |
453 | } | |
454 | ||
455 | ||
456 | Implement set_mode() | |
457 | -------------------- | |
458 | ||
459 | This should adjust the SPI mode (polarity, etc.). Again this code probably | |
460 | comes from the old spi_claim_bus(). Here is an example: | |
461 | ||
462 | .. code-block:: c | |
463 | ||
464 | static int exynos_spi_set_mode(struct udevice *bus, uint mode) | |
465 | { | |
466 | struct exynos_spi_priv *priv = dev_get_priv(bus); | |
467 | uint32_t reg; | |
468 | ||
469 | reg = readl(&priv->regs->ch_cfg); | |
470 | reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L); | |
471 | ||
472 | if (mode & SPI_CPHA) | |
473 | reg |= SPI_CH_CPHA_B; | |
474 | ||
475 | if (mode & SPI_CPOL) | |
476 | reg |= SPI_CH_CPOL_L; | |
477 | ||
478 | writel(reg, &priv->regs->ch_cfg); | |
479 | priv->mode = mode; | |
480 | debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode); | |
481 | ||
482 | return 0; | |
483 | } | |
484 | ||
485 | ||
486 | Implement claim_bus() | |
487 | --------------------- | |
488 | ||
489 | This is where a client wants to make use of the bus, so claims it first. | |
490 | At this point we need to make sure everything is set up ready for data | |
491 | transfer. Note that this function is wholly internal to the driver - at | |
492 | present the SPI uclass never calls it. | |
493 | ||
494 | Here again we look at the old claim function and see some code that is | |
495 | needed. It is anything unrelated to speed and mode: | |
496 | ||
497 | .. code-block:: c | |
498 | ||
499 | static int exynos_spi_claim_bus(struct udevice *bus) | |
500 | { | |
501 | struct exynos_spi_priv *priv = dev_get_priv(bus); | |
502 | ||
503 | exynos_pinmux_config(priv->periph_id, PINMUX_FLAG_NONE); | |
504 | spi_flush_fifo(priv->regs); | |
505 | ||
506 | writel(SPI_FB_DELAY_180, &priv->regs->fb_clk); | |
507 | ||
508 | return 0; | |
509 | } | |
510 | ||
511 | The spi_flush_fifo() function is in the removed part of the code, so we | |
512 | need to expose it again (perhaps with an #endif before it and '#if 0' | |
513 | after it). It only needs access to priv->regs which is why we have | |
514 | passed that in: | |
515 | ||
516 | .. code-block:: c | |
517 | ||
518 | /** | |
519 | * Flush spi tx, rx fifos and reset the SPI controller | |
520 | * | |
521 | * @param regs Pointer to SPI registers | |
522 | */ | |
523 | static void spi_flush_fifo(struct exynos_spi *regs) | |
524 | { | |
525 | clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); | |
526 | clrbits_le32(®s->ch_cfg, SPI_CH_RST); | |
527 | setbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON); | |
528 | } | |
529 | ||
530 | ||
531 | Implement release_bus() | |
532 | ----------------------- | |
533 | ||
534 | This releases the bus - in our example the old code in spi_release_bus() | |
535 | is a call to spi_flush_fifo, so we add: | |
536 | ||
537 | .. code-block:: c | |
538 | ||
539 | static int exynos_spi_release_bus(struct udevice *bus) | |
540 | { | |
541 | struct exynos_spi_priv *priv = dev_get_priv(bus); | |
542 | ||
543 | spi_flush_fifo(priv->regs); | |
544 | ||
545 | return 0; | |
546 | } | |
547 | ||
548 | ||
549 | Implement xfer() | |
550 | ---------------- | |
551 | ||
552 | This is the final method that we need to create, and it is where all the | |
553 | work happens. The method parameters are the same as the old spi_xfer() with | |
554 | the addition of a 'struct udevice' so conversion is pretty easy. Start | |
555 | by copying the contents of spi_xfer() to your new xfer() method and proceed | |
556 | from there. | |
557 | ||
558 | If (flags & SPI_XFER_BEGIN) is non-zero then xfer() normally calls an | |
559 | activate function, something like this: | |
560 | ||
561 | .. code-block:: c | |
562 | ||
563 | void spi_cs_activate(struct spi_slave *slave) | |
564 | { | |
565 | struct exynos_spi_slave *spi_slave = to_exynos_spi(slave); | |
566 | ||
567 | /* If it's too soon to do another transaction, wait */ | |
568 | if (spi_slave->bus->deactivate_delay_us && | |
569 | spi_slave->last_transaction_us) { | |
570 | ulong delay_us; /* The delay completed so far */ | |
571 | delay_us = timer_get_us() - spi_slave->last_transaction_us; | |
572 | if (delay_us < spi_slave->bus->deactivate_delay_us) | |
573 | udelay(spi_slave->bus->deactivate_delay_us - delay_us); | |
574 | } | |
575 | ||
576 | clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT); | |
577 | debug("Activate CS, bus %d\n", spi_slave->slave.bus); | |
578 | spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE; | |
579 | } | |
580 | ||
581 | The new version looks like this: | |
582 | ||
583 | .. code-block:: c | |
584 | ||
585 | static void spi_cs_activate(struct udevice *dev) | |
586 | { | |
587 | struct udevice *bus = dev->parent; | |
588 | struct exynos_spi_platdata *pdata = dev_get_platdata(bus); | |
589 | struct exynos_spi_priv *priv = dev_get_priv(bus); | |
590 | ||
591 | /* If it's too soon to do another transaction, wait */ | |
592 | if (pdata->deactivate_delay_us && | |
593 | priv->last_transaction_us) { | |
594 | ulong delay_us; /* The delay completed so far */ | |
595 | delay_us = timer_get_us() - priv->last_transaction_us; | |
596 | if (delay_us < pdata->deactivate_delay_us) | |
597 | udelay(pdata->deactivate_delay_us - delay_us); | |
598 | } | |
599 | ||
600 | clrbits_le32(&priv->regs->cs_reg, SPI_SLAVE_SIG_INACT); | |
601 | debug("Activate CS, bus '%s'\n", bus->name); | |
602 | priv->skip_preamble = priv->mode & SPI_PREAMBLE; | |
603 | } | |
604 | ||
605 | All we have really done here is change the pointers and print the device name | |
606 | instead of the bus number. Other local static functions can be treated in | |
607 | the same way. | |
608 | ||
609 | ||
610 | Set up the per-child data and child pre-probe function | |
611 | ------------------------------------------------------ | |
612 | ||
613 | To minimise the pain and complexity of the SPI subsystem while the driver | |
614 | model change-over is in place, struct spi_slave is used to reference a | |
615 | SPI bus slave, even though that slave is actually a struct udevice. In fact | |
616 | struct spi_slave is the device's child data. We need to make sure this space | |
617 | is available. It is possible to allocate more space that struct spi_slave | |
618 | needs, but this is the minimum. | |
619 | ||
620 | .. code-block:: c | |
621 | ||
622 | U_BOOT_DRIVER(exynos_spi) = { | |
623 | ... | |
41575d8e | 624 | .per_child_auto = sizeof(struct spi_slave), |
7ee49d03 BM |
625 | } |
626 | ||
627 | ||
628 | Optional: Set up cs_info() if you want it | |
629 | ----------------------------------------- | |
630 | ||
631 | Sometimes it is useful to know whether a SPI chip select is valid, but this | |
632 | is not obvious from outside the driver. In this case you can provide a | |
633 | method for cs_info() to deal with this. If you don't provide it, then the | |
634 | device tree will be used to determine what chip selects are valid. | |
635 | ||
4b060003 | 636 | Return -EINVAL if the supplied chip select is invalid, or 0 if it is valid. |
4dd520b3 BM |
637 | If you don't provide the cs_info() method, 0 is assumed for all chip selects |
638 | that do not appear in the device tree. | |
7ee49d03 BM |
639 | |
640 | ||
641 | Test it | |
642 | ------- | |
643 | ||
644 | Now that you have the code written and it compiles, try testing it using | |
645 | the 'sf test' command. You may need to enable CONFIG_CMD_SF_TEST for your | |
646 | board. | |
647 | ||
648 | ||
649 | Prepare patches and send them to the mailing lists | |
650 | -------------------------------------------------- | |
651 | ||
652 | You can use 'tools/patman/patman' to prepare, check and send patches for | |
2cde3ea1 | 653 | your work. See tools/patman/README for details. |
7ee49d03 BM |
654 | |
655 | A little note about SPI uclass features | |
656 | --------------------------------------- | |
657 | ||
658 | The SPI uclass keeps some information about each device 'dev' on the bus: | |
659 | ||
660 | struct dm_spi_slave_platdata: | |
caa4daa2 | 661 | This is device_get_parent_plat(dev). |
7ee49d03 BM |
662 | This is where the chip select number is stored, along with |
663 | the default bus speed and mode. It is automatically read | |
664 | from the device tree in spi_child_post_bind(). It must not | |
665 | be changed at run-time after being set up because platform | |
666 | data is supposed to be immutable at run-time. | |
667 | struct spi_slave: | |
668 | This is device_get_parentdata(dev). | |
669 | Already mentioned above. It holds run-time information about | |
670 | the device. | |
671 | ||
672 | There are also some SPI uclass methods that get called behind the scenes: | |
673 | ||
674 | spi_post_bind(): | |
675 | Called when a new bus is bound. | |
676 | This scans the device tree for devices on the bus, and binds | |
677 | each one. This in turn causes spi_child_post_bind() to be | |
678 | called for each, which reads the device tree information | |
679 | into the parent (per-child) platform data. | |
680 | spi_child_post_bind(): | |
681 | Called when a new child is bound. | |
682 | As mentioned above this reads the device tree information | |
683 | into the per-child platform data | |
684 | spi_child_pre_probe(): | |
685 | Called before a new child is probed. | |
686 | This sets up the mode and speed in struct spi_slave by | |
687 | copying it from the parent's platform data for this child. | |
688 | It also sets the 'dev' pointer, needed to permit passing | |
689 | 'struct spi_slave' around the place without needing a | |
690 | separate 'struct udevice' pointer. | |
691 | ||
692 | The above housekeeping makes it easier to write your SPI driver. |