X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fspi%2Fspi-uclass.c;h=8003f9bfc8635cb32d0f7808f7c5a3e11bf2c2ed;hb=c6f086ddcbfb47918b82f6a135c61f432540da42;hp=63a6217cc62d0085b6c4ba259415fae514651ba9;hpb=358b8bc204f365be28fed94f23e53e04183a8c7f;p=u-boot diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index 63a6217cc6..8003f9bfc8 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -45,12 +45,12 @@ static int spi_set_speed_mode(struct udevice *bus, int speed, int mode) return 0; } -int spi_claim_bus(struct spi_slave *slave) +int dm_spi_claim_bus(struct udevice *dev) { - struct udevice *dev = slave->dev; struct udevice *bus = dev->parent; struct dm_spi_ops *ops = spi_get_ops(bus); - struct dm_spi_bus *spi = bus->uclass_priv; + struct dm_spi_bus *spi = dev_get_uclass_priv(bus); + struct spi_slave *slave = dev_get_parent_priv(dev); int speed; int ret; @@ -63,27 +63,28 @@ int spi_claim_bus(struct spi_slave *slave) } if (!speed) speed = 100000; - ret = spi_set_speed_mode(bus, speed, slave->mode); - if (ret) - return ret; + if (speed != slave->speed) { + ret = spi_set_speed_mode(bus, speed, slave->mode); + if (ret) + return ret; + slave->speed = speed; + } - return ops->claim_bus ? ops->claim_bus(bus) : 0; + return ops->claim_bus ? ops->claim_bus(dev) : 0; } -void spi_release_bus(struct spi_slave *slave) +void dm_spi_release_bus(struct udevice *dev) { - struct udevice *dev = slave->dev; struct udevice *bus = dev->parent; struct dm_spi_ops *ops = spi_get_ops(bus); if (ops->release_bus) - ops->release_bus(bus); + ops->release_bus(dev); } -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) +int dm_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) { - struct udevice *dev = slave->dev; struct udevice *bus = dev->parent; if (bus->uclass->uc_drv->id != UCLASS_SPI) @@ -92,13 +93,29 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, return spi_get_ops(bus)->xfer(dev, bitlen, dout, din, flags); } -int spi_post_bind(struct udevice *dev) +int spi_claim_bus(struct spi_slave *slave) +{ + return dm_spi_claim_bus(slave->dev); +} + +void spi_release_bus(struct spi_slave *slave) +{ + dm_spi_release_bus(slave->dev); +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + return dm_spi_xfer(slave->dev, bitlen, dout, din, flags); +} + +static int spi_post_bind(struct udevice *dev) { /* Scan the bus for devices */ return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); } -int spi_child_post_bind(struct udevice *dev) +static int spi_child_post_bind(struct udevice *dev) { struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); @@ -108,20 +125,40 @@ int spi_child_post_bind(struct udevice *dev) return spi_slave_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, plat); } -int spi_post_probe(struct udevice *bus) +static int spi_post_probe(struct udevice *bus) { - struct dm_spi_bus *spi = bus->uclass_priv; + struct dm_spi_bus *spi = dev_get_uclass_priv(bus); spi->max_hz = fdtdec_get_int(gd->fdt_blob, bus->of_offset, "spi-max-frequency", 0); +#if defined(CONFIG_NEEDS_MANUAL_RELOC) + struct dm_spi_ops *ops = spi_get_ops(bus); + + + if (ops->claim_bus) + ops->claim_bus += gd->reloc_off; + if (ops->release_bus) + ops->release_bus += gd->reloc_off; + if (ops->set_wordlen) + ops->set_wordlen += gd->reloc_off; + if (ops->xfer) + ops->xfer += gd->reloc_off; + if (ops->set_speed) + ops->set_speed += gd->reloc_off; + if (ops->set_mode) + ops->set_mode += gd->reloc_off; + if (ops->cs_info) + ops->cs_info += gd->reloc_off; +#endif + return 0; } -int spi_child_pre_probe(struct udevice *dev) +static int spi_child_pre_probe(struct udevice *dev) { struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); - struct spi_slave *slave = dev_get_parentdata(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); /* * This is needed because we pass struct spi_slave around the place @@ -134,6 +171,8 @@ int spi_child_pre_probe(struct udevice *dev) slave->max_hz = plat->max_hz; slave->mode = plat->mode; + slave->mode_rx = plat->mode_rx; + slave->wordlen = SPI_DEFAULT_WORDLEN; return 0; } @@ -239,6 +278,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode, struct udevice **busp, struct spi_slave **devp) { struct udevice *bus, *dev; + struct dm_spi_slave_platdata *plat; bool created = false; int ret; @@ -255,8 +295,6 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode, * SPI flash chip - we will bind to the correct driver. */ if (ret == -ENODEV && drv_name) { - struct dm_spi_slave_platdata *plat; - debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n", __func__, dev_name, busnum, cs, drv_name); ret = device_bind_driver(bus, drv_name, dev_name, &dev); @@ -279,22 +317,27 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode, ret = device_probe(dev); if (ret) goto err; - slave = dev_get_parentdata(dev); + slave = dev_get_parent_priv(dev); slave->dev = dev; } + plat = dev_get_parent_platdata(dev); + if (!speed) { + speed = plat->max_hz; + mode = plat->mode; + } ret = spi_set_speed_mode(bus, speed, mode); if (ret) goto err; *busp = bus; - *devp = dev_get_parentdata(dev); + *devp = dev_get_parent_priv(dev); debug("%s: bus=%p, slave=%p\n", __func__, bus, *devp); return 0; err: - debug("%s: Error path, credted=%d, device '%s'\n", __func__, + debug("%s: Error path, created=%d, device '%s'\n", __func__, created, dev->name); if (created) { device_remove(dev); @@ -317,7 +360,7 @@ struct spi_slave *spi_setup_slave_fdt(const void *blob, int node, ret = device_get_child_by_of_offset(bus, node, &dev); if (ret) return NULL; - return dev_get_parentdata(dev); + return dev_get_parent_priv(dev); } /* Compatibility function - to be removed */ @@ -345,7 +388,8 @@ void spi_free_slave(struct spi_slave *slave) int spi_slave_ofdata_to_platdata(const void *blob, int node, struct dm_spi_slave_platdata *plat) { - int mode = 0; + int mode = 0, mode_rx = 0; + int value; plat->cs = fdtdec_get_int(blob, node, "reg", -1); plat->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 0); @@ -355,10 +399,46 @@ int spi_slave_ofdata_to_platdata(const void *blob, int node, mode |= SPI_CPHA; if (fdtdec_get_bool(blob, node, "spi-cs-high")) mode |= SPI_CS_HIGH; + if (fdtdec_get_bool(blob, node, "spi-3wire")) + mode |= SPI_3WIRE; if (fdtdec_get_bool(blob, node, "spi-half-duplex")) mode |= SPI_PREAMBLE; + + /* Device DUAL/QUAD mode */ + value = fdtdec_get_uint(blob, node, "spi-tx-bus-width", 1); + switch (value) { + case 1: + break; + case 2: + mode |= SPI_TX_DUAL; + break; + case 4: + mode |= SPI_TX_QUAD; + break; + default: + error("spi-tx-bus-width %d not supported\n", value); + break; + } + plat->mode = mode; + value = fdtdec_get_uint(blob, node, "spi-rx-bus-width", 1); + switch (value) { + case 1: + break; + case 2: + mode_rx |= SPI_RX_DUAL; + break; + case 4: + mode_rx |= SPI_RX_QUAD; + break; + default: + error("spi-rx-bus-width %d not supported\n", value); + break; + } + + plat->mode_rx = mode_rx; + return 0; }