]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - drivers/ata/ahci.c
dm: ahci: Add a driver for SCSI on AHCI
[people/ms/u-boot.git] / drivers / ata / ahci.c
index 3528a1f3da3174c091968a75b16caf0e92bd7c8f..6da412d178cc65a3b0a0d67b2a487c2a9589abdc 100644 (file)
 #include <asm/io.h>
 #include <malloc.h>
 #include <memalign.h>
+#include <pci.h>
 #include <scsi.h>
 #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 +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)
 {