From 681357ffd9fe4528d020a878ef6ee61f519d8d85 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 14 Jun 2017 21:28:46 -0600 Subject: dm: ahci: Add a driver for SCSI on AHCI 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 Reviewed-by: Bin Meng --- drivers/ata/ahci.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 3528a1f3da..6da412d178 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -19,10 +19,13 @@ #include #include #include +#include #include #include #include #include +#include +#include static int ata_io_flush(struct ahci_uc_priv *uc_priv, u8 port); @@ -1142,10 +1145,64 @@ 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) +{ +#ifdef CONFIG_SCSI_AHCI_PLAT + return -ENOSYS; /* TODO(sjg@chromium.org): Support non-PCI AHCI */ +#else + 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); + 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; +#endif + + 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) { -- cgit v1.2.1