Commit d0cff03e187cc1de3d6b477b92c376aae27c95e8

Authored by Simon Glass
1 parent 440714eeb8

dm: spi: Move slave details to child platdata

At present we go through various contortions to store the SPI slave's chip
select in its private data. This only exists when the slave is active so
must be set up when it is probed. Until the device is probed we don't
actually know what chip select it will appear on.

However, now that we can support per-child platform data, we can use that
instead. This allows us to set up the chip select when the child is bound,
and avoid the messy contortions.

Unfortunately this is a fairly large change and it seems to be difficult to
break it down further.

Signed-off-by: Simon Glass <sjg@chromium.org>

Showing 7 changed files with 91 additions and 76 deletions Side-by-side Diff

drivers/misc/cros_ec_spi.c
... ... @@ -202,25 +202,6 @@
202 202 #ifdef CONFIG_DM_CROS_EC
203 203 int cros_ec_probe(struct udevice *dev)
204 204 {
205   - struct spi_slave *slave = dev_get_parentdata(dev);
206   - int ret;
207   -
208   - /*
209   - * TODO(sjg@chromium.org)
210   - *
211   - * This is really horrible at present. It is an artifact of removing
212   - * the child_pre_probe() method for SPI. Everything here could go in
213   - * an automatic function, except that spi_get_bus_and_cs() wants to
214   - * set it up manually and call device_probe_child().
215   - *
216   - * The solution may be to re-enable the child_pre_probe() method for
217   - * SPI and have it do nothing if the child is already passed in via
218   - * device_probe_child().
219   - */
220   - slave->dev = dev;
221   - ret = spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, slave);
222   - if (ret)
223   - return ret;
224 205 return cros_ec_register(dev);
225 206 }
226 207  
drivers/mtd/spi/sandbox.c
... ... @@ -590,6 +590,11 @@
590 590  
591 591 void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs)
592 592 {
  593 + struct udevice *dev;
  594 +
  595 + dev = state->spi[busnum][cs].emul;
  596 + device_remove(dev);
  597 + device_unbind(dev);
593 598 state->spi[busnum][cs].emul = NULL;
594 599 }
595 600  
drivers/mtd/spi/sf_probe.c
... ... @@ -481,11 +481,12 @@
481 481 int spi_flash_std_probe(struct udevice *dev)
482 482 {
483 483 struct spi_slave *slave = dev_get_parentdata(dev);
  484 + struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
484 485 struct spi_flash *flash;
485 486  
486 487 flash = dev->uclass_priv;
487 488 flash->dev = dev;
488   - debug("%s: slave=%p, cs=%d\n", __func__, slave, slave->cs);
  489 + debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs);
489 490 return spi_flash_probe_slave(slave, flash);
490 491 }
491 492  
drivers/spi/soft_spi.c
... ... @@ -179,14 +179,6 @@
179 179 return 0;
180 180 }
181 181  
182   -static int soft_spi_child_pre_probe(struct udevice *dev)
183   -{
184   - struct spi_slave *slave = dev_get_parentdata(dev);
185   -
186   - slave->dev = dev;
187   - return spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, slave);
188   -}
189   -
190 182 static const struct dm_spi_ops soft_spi_ops = {
191 183 .claim_bus = soft_spi_claim_bus,
192 184 .release_bus = soft_spi_release_bus,
... ... @@ -241,6 +233,5 @@
241 233 .platdata_auto_alloc_size = sizeof(struct soft_spi_platdata),
242 234 .priv_auto_alloc_size = sizeof(struct soft_spi_priv),
243 235 .probe = soft_spi_probe,
244   - .child_pre_probe = soft_spi_child_pre_probe,
245 236 };
drivers/spi/spi-uclass.c
... ... @@ -98,11 +98,21 @@
98 98 return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
99 99 }
100 100  
101   -int spi_post_probe(struct udevice *dev)
  101 +int spi_child_post_bind(struct udevice *dev)
102 102 {
103   - struct dm_spi_bus *spi = dev->uclass_priv;
  103 + struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
104 104  
105   - spi->max_hz = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
  105 + if (dev->of_offset == -1)
  106 + return 0;
  107 +
  108 + return spi_slave_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, plat);
  109 +}
  110 +
  111 +int spi_post_probe(struct udevice *bus)
  112 +{
  113 + struct dm_spi_bus *spi = bus->uclass_priv;
  114 +
  115 + spi->max_hz = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
106 116 "spi-max-frequency", 0);
107 117  
108 118 return 0;
109 119  
110 120  
111 121  
112 122  
... ... @@ -110,18 +120,29 @@
110 120  
111 121 int spi_child_pre_probe(struct udevice *dev)
112 122 {
  123 + struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
113 124 struct spi_slave *slave = dev_get_parentdata(dev);
114 125  
  126 + /*
  127 + * This is needed because we pass struct spi_slave around the place
  128 + * instead slave->dev (a struct udevice). So we have to have some
  129 + * way to access the slave udevice given struct spi_slave. Once we
  130 + * change the SPI API to use udevice instead of spi_slave, we can
  131 + * drop this.
  132 + */
115 133 slave->dev = dev;
116 134  
  135 + slave->max_hz = plat->max_hz;
  136 + slave->mode = plat->mode;
  137 +
117 138 return 0;
118 139 }
119 140  
120 141 int spi_chip_select(struct udevice *dev)
121 142 {
122   - struct spi_slave *slave = dev_get_parentdata(dev);
  143 + struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
123 144  
124   - return slave ? slave->cs : -ENOENT;
  145 + return plat ? plat->cs : -ENOENT;
125 146 }
126 147  
127 148 int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp)
128 149  
... ... @@ -130,17 +151,11 @@
130 151  
131 152 for (device_find_first_child(bus, &dev); dev;
132 153 device_find_next_child(&dev)) {
133   - struct spi_slave store;
134   - struct spi_slave *slave = dev_get_parentdata(dev);
  154 + struct dm_spi_slave_platdata *plat;
135 155  
136   - if (!slave) {
137   - slave = &store;
138   - spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
139   - slave);
140   - }
141   - debug("%s: slave=%p, cs=%d\n", __func__, slave,
142   - slave ? slave->cs : -1);
143   - if (slave && slave->cs == cs) {
  156 + plat = dev_get_parent_platdata(dev);
  157 + debug("%s: plat=%p, cs=%d\n", __func__, plat, plat->cs);
  158 + if (plat->cs == cs) {
144 159 *devp = dev;
145 160 return 0;
146 161 }
... ... @@ -224,7 +239,6 @@
224 239 struct udevice **busp, struct spi_slave **devp)
225 240 {
226 241 struct udevice *bus, *dev;
227   - struct spi_slave *slave;
228 242 bool created = false;
229 243 int ret;
230 244  
231 245  
... ... @@ -241,11 +255,17 @@
241 255 * SPI flash chip - we will bind to the correct driver.
242 256 */
243 257 if (ret == -ENODEV && drv_name) {
  258 + struct dm_spi_slave_platdata *plat;
  259 +
244 260 debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n",
245 261 __func__, dev_name, busnum, cs, drv_name);
246 262 ret = device_bind_driver(bus, drv_name, dev_name, &dev);
247 263 if (ret)
248 264 return ret;
  265 + plat = dev_get_parent_platdata(dev);
  266 + plat->cs = cs;
  267 + plat->max_hz = speed;
  268 + plat->mode = mode;
249 269 created = true;
250 270 } else if (ret) {
251 271 printf("Invalid chip select %d:%d (err=%d)\n", busnum, cs,
252 272  
253 273  
254 274  
... ... @@ -254,23 +274,13 @@
254 274 }
255 275  
256 276 if (!device_active(dev)) {
257   - slave = (struct spi_slave *)calloc(1,
258   - sizeof(struct spi_slave));
259   - if (!slave) {
260   - ret = -ENOMEM;
261   - goto err;
262   - }
  277 + struct spi_slave *slave;
263 278  
264   - ret = spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
265   - slave);
  279 + ret = device_probe(dev);
266 280 if (ret)
267 281 goto err;
268   - slave->cs = cs;
  282 + slave = dev_get_parentdata(dev);
269 283 slave->dev = dev;
270   - ret = device_probe_child(dev, slave);
271   - free(slave);
272   - if (ret)
273   - goto err;
274 284 }
275 285  
276 286 ret = spi_set_speed_mode(bus, speed, mode);
... ... @@ -284,6 +294,8 @@
284 294 return 0;
285 295  
286 296 err:
  297 + debug("%s: Error path, credted=%d, device '%s'\n", __func__,
  298 + created, dev->name);
287 299 if (created) {
288 300 device_remove(dev);
289 301 device_unbind(dev);
290 302  
... ... @@ -330,13 +342,13 @@
330 342 slave->dev = NULL;
331 343 }
332 344  
333   -int spi_ofdata_to_platdata(const void *blob, int node,
334   - struct spi_slave *spi)
  345 +int spi_slave_ofdata_to_platdata(const void *blob, int node,
  346 + struct dm_spi_slave_platdata *plat)
335 347 {
336 348 int mode = 0;
337 349  
338   - spi->cs = fdtdec_get_int(blob, node, "reg", -1);
339   - spi->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 0);
  350 + plat->cs = fdtdec_get_int(blob, node, "reg", -1);
  351 + plat->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 0);
340 352 if (fdtdec_get_bool(blob, node, "spi-cpol"))
341 353 mode |= SPI_CPOL;
342 354 if (fdtdec_get_bool(blob, node, "spi-cpha"))
... ... @@ -345,7 +357,7 @@
345 357 mode |= SPI_CS_HIGH;
346 358 if (fdtdec_get_bool(blob, node, "spi-half-duplex"))
347 359 mode |= SPI_PREAMBLE;
348   - spi->mode = mode;
  360 + plat->mode = mode;
349 361  
350 362 return 0;
351 363 }
... ... @@ -359,6 +371,9 @@
359 371 .child_pre_probe = spi_child_pre_probe,
360 372 .per_device_auto_alloc_size = sizeof(struct dm_spi_bus),
361 373 .per_child_auto_alloc_size = sizeof(struct spi_slave),
  374 + .per_child_platdata_auto_alloc_size =
  375 + sizeof(struct dm_spi_slave_platdata),
  376 + .child_post_bind = spi_child_post_bind,
362 377 };
363 378  
364 379 UCLASS_DRIVER(spi_generic) = {
... ... @@ -56,21 +56,43 @@
56 56 #define SPI_DEFAULT_WORDLEN 8
57 57  
58 58 #ifdef CONFIG_DM_SPI
  59 +/* TODO(sjg@chromium.org): Remove this and use max_hz from struct spi_slave */
59 60 struct dm_spi_bus {
60 61 uint max_hz;
61 62 };
62 63  
  64 +/**
  65 + * struct dm_spi_platdata - platform data for all SPI slaves
  66 + *
  67 + * This describes a SPI slave, a child device of the SPI bus. To obtain this
  68 + * struct from a spi_slave, use dev_get_parent_platdata(dev) or
  69 + * dev_get_parent_platdata(slave->dev).
  70 + *
  71 + * This data is immuatable. Each time the device is probed, @max_hz and @mode
  72 + * will be copied to struct spi_slave.
  73 + *
  74 + * @cs: Chip select number (0..n-1)
  75 + * @max_hz: Maximum bus speed that this slave can tolerate
  76 + * @mode: SPI mode to use for this device (see SPI mode flags)
  77 + */
  78 +struct dm_spi_slave_platdata {
  79 + unsigned int cs;
  80 + uint max_hz;
  81 + uint mode;
  82 +};
  83 +
63 84 #endif /* CONFIG_DM_SPI */
64 85  
65 86 /**
66 87 * struct spi_slave - Representation of a SPI slave
67 88 *
68 89 * For driver model this is the per-child data used by the SPI bus. It can
69   - * be accessed using dev_get_parentdata() on the slave device. Each SPI
70   - * driver should define this child data in its U_BOOT_DRIVER() definition:
  90 + * be accessed using dev_get_parentdata() on the slave device. The SPI uclass
  91 + * sets uip per_child_auto_alloc_size to sizeof(struct spi_slave), and the
  92 + * driver should not override it. Two platform data fields (max_hz and mode)
  93 + * are copied into this structure to provide an initial value. This allows
  94 + * them to be changed, since we should never change platform data in drivers.
71 95 *
72   - * .per_child_auto_alloc_size = sizeof(struct spi_slave),
73   - *
74 96 * If not using driver model, drivers are expected to extend this with
75 97 * controller-specific data.
76 98 *
77 99  
... ... @@ -97,8 +119,8 @@
97 119 uint mode;
98 120 #else
99 121 unsigned int bus;
100   -#endif
101 122 unsigned int cs;
  123 +#endif
102 124 u8 op_mode_rx;
103 125 u8 op_mode_tx;
104 126 unsigned int wordlen;
105 127  
106 128  
107 129  
... ... @@ -545,16 +567,16 @@
545 567 int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp);
546 568  
547 569 /**
548   - * spi_ofdata_to_platdata() - decode standard SPI platform data
  570 + * spi_slave_ofdata_to_platdata() - decode standard SPI platform data
549 571 *
550   - * This decodes the speed and mode from a device tree node and puts it into
551   - * the spi_slave structure.
  572 + * This decodes the speed and mode for a slave from a device tree node
552 573 *
553 574 * @blob: Device tree blob
554 575 * @node: Node offset to read from
555   - * @spi: Place to put the decoded information
  576 + * @plat: Place to put the decoded information
556 577 */
557   -int spi_ofdata_to_platdata(const void *blob, int node, struct spi_slave *spi);
  578 +int spi_slave_ofdata_to_platdata(const void *blob, int node,
  579 + struct dm_spi_slave_platdata *plat);
558 580  
559 581 /**
560 582 * spi_cs_info() - Check information on a chip select
... ... @@ -36,7 +36,6 @@
36 36 ut_asserteq(0, uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus));
37 37 ut_assertok(spi_cs_info(bus, cs, &info));
38 38 of_offset = info.dev->of_offset;
39   - sandbox_sf_unbind_emul(state_get_current(), busnum, cs);
40 39 device_remove(info.dev);
41 40 device_unbind(info.dev);
42 41  
... ... @@ -45,7 +44,7 @@
45 44 * reports that CS 0 is present
46 45 */
47 46 ut_assertok(spi_cs_info(bus, cs, &info));
48   - ut_asserteq_ptr(info.dev, NULL);
  47 + ut_asserteq_ptr(NULL, info.dev);
49 48  
50 49 /* This finds nothing because we removed the device */
51 50 ut_asserteq(-ENODEV, spi_find_bus_and_cs(busnum, cs, &bus, &dev));
52 51  
... ... @@ -62,8 +61,9 @@
62 61 ut_asserteq(-ENOENT, spi_get_bus_and_cs(busnum, cs, speed, mode,
63 62 "spi_flash_std", "name", &bus,
64 63 &slave));
  64 + sandbox_sf_unbind_emul(state_get_current(), busnum, cs);
65 65 ut_assertok(spi_cs_info(bus, cs, &info));
66   - ut_asserteq_ptr(info.dev, NULL);
  66 + ut_asserteq_ptr(NULL, info.dev);
67 67  
68 68 /* Add the emulation and try again */
69 69 ut_assertok(sandbox_sf_bind_emul(state, busnum, cs, bus, of_offset,