Hi Simon, On Tue, Jun 6, 2017 at 3:15 AM, Simon Glass <s...@chromium.org> wrote: > Some AHCI drivers use SCSI under the hood. Rather than making the AHCI > driver be in the SCSI uclass it makes sense to have the AHCI device create > a SCSI device as a child. That way we can handle any AHCI-specific > operations rather than trying to pretend tha the device is just SCSI. > > To handle this we need to provide a way for AHCI drivers to bind a SCSI > device as its child, and probe it. Add functions for this. > > Signed-off-by: Simon Glass <s...@chromium.org> > --- > > drivers/ata/ahci.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > include/ahci.h | 22 ++++++++++++++++++++++ > 2 files changed, 74 insertions(+) > > diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c > index 3528a1f3da..c67a144f02 100644 > --- a/drivers/ata/ahci.c > +++ b/drivers/ata/ahci.c > @@ -23,6 +23,8 @@ > #include <libata.h> > #include <linux/ctype.h> > #include <ahci.h> > +#include <dm/device-internal.h> > +#include <dm/lists.h> > > static int ata_io_flush(struct ahci_uc_priv *uc_priv, u8 port); > > @@ -1142,10 +1144,60 @@ static int ahci_scsi_bus_reset(struct udevice *dev) > } > > #ifdef CONFIG_DM_SCSI > +int ahci_bind_scsi(struct udevice *ahci_dev, struct udevice **devp) > +{ > + struct udevice *dev; > + int ret; > + > + ret = device_bind_driver(ahci_dev, "ahci_scsi", "ahci_scsi", &dev); > + if (ret) > + return ret; > + *devp = dev; > + > + return 0; > +} > + > +int ahci_probe_scsi(struct udevice *ahci_dev) > +{ > + struct ahci_uc_priv *uc_priv; > + struct scsi_platdata *uc_plat; > + struct udevice *dev; > + int ret; > + > + device_find_first_child(ahci_dev, &dev); > + if (!dev) > + return -ENODEV; > + uc_plat = dev_get_uclass_platdata(dev); > + uc_plat->base = (ulong)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_5, > + PCI_REGION_MEM);
This assumes AHCI controller is on PCI bus. How about other AHCI controllers integrated directly into the SoC? > + uc_plat->max_lun = 1; > + uc_plat->max_id = 2; > + uc_priv = dev_get_uclass_priv(dev); > + ret = ahci_init_one(uc_priv, dev); > + if (ret) > + return ret; > + ret = ahci_start_ports(uc_priv); > + if (ret) > + return ret; > + > + debug("Scanning %s\n", dev->name); > + ret = scsi_scan_dev(dev, true); > + if (ret) > + return ret; > + > + return 0; > +} > + > struct scsi_ops scsi_ops = { > .exec = ahci_scsi_exec, > .bus_reset = ahci_scsi_bus_reset, > }; > + > +U_BOOT_DRIVER(ahci_scsi) = { > + .name = "ahci_scsi", > + .id = UCLASS_SCSI, > + .ops = &scsi_ops, > +}; > #else > int scsi_exec(struct udevice *dev, struct scsi_cmd *pccb) > { > diff --git a/include/ahci.h b/include/ahci.h > index 648e56a4cf..746bff083a 100644 > --- a/include/ahci.h > +++ b/include/ahci.h > @@ -203,4 +203,26 @@ int achi_start_ports_dm(struct udevice *dev); > */ > int ahci_init_dm(struct udevice *dev, void __iomem *base); > > +/** > + * ahci_bind_scsi() - bind a new SCSI bus as a child > + * > + * Note that the SCSI bus device will itself bind block devices > + * > + * @ahci_dev: AHCI parent device > + * @devp: Returns new SCSI bus device > + * @return 0 if OK, -ve on error > + */ > +int ahci_bind_scsi(struct udevice *ahci_dev, struct udevice **devp); > + > +/** > + * ahci_probe_scsi() - probe and scan the attached SCSI bus > + * > + * Note that the SCSI device will itself bind block devices for any storage > + * devices it finds. > + * > + * @ahci_dev: AHCI parent device > + * @return 0 if OK, -ve on error > + */ > +int ahci_probe_scsi(struct udevice *ahci_dev); > + > #endif > -- Regards, Bin _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot