+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) Freescale Semiconductor, Inc. 2006.
* Author: Jason Jin<Jason.jin@freescale.com>
* Zhang Wei<wei.zhang@freescale.com>
*
- * SPDX-License-Identifier: GPL-2.0+
- *
* with the reference on libata and ahci drvier in kernel
*
* This driver provides a SCSI interface to SATA.
#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);
cap2 & (1 << 0) ? "boh " : "");
}
-#ifndef CONFIG_SCSI_AHCI_PLAT
+#if defined(CONFIG_DM_SCSI) || !defined(CONFIG_SCSI_AHCI_PLAT)
# if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI)
static int ahci_init_one(struct ahci_uc_priv *uc_priv, struct udevice *dev)
# else
{
struct ahci_uc_priv *uc_priv;
#ifdef CONFIG_DM_SCSI
- uc_priv = dev_get_uclass_priv(dev);
+ uc_priv = dev_get_uclass_priv(dev->parent);
#else
uc_priv = probe_ent;
#endif
break;
default:
printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]);
- return false;
+ return -ENOTSUPP;
}
if (ret) {
debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret);
- return false;
+ return ret;
}
- return true;
+ return 0;
}
#ifndef CONFIG_SCSI_AHCI_PLAT
# if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI)
-int achi_init_one_dm(struct udevice *dev)
+int ahci_init_one_dm(struct udevice *dev)
{
struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev);
#endif
#endif
-int achi_start_ports_dm(struct udevice *dev)
+int ahci_start_ports_dm(struct udevice *dev)
{
struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev);
return 0;
}
+#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, ulong base)
+{
+ 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 = base;
+ uc_plat->max_lun = 1;
+ uc_plat->max_id = 2;
+
+ uc_priv = dev_get_uclass_priv(ahci_dev);
+ ret = ahci_init_one(uc_priv, dev);
+ if (ret)
+ return ret;
+ ret = ahci_start_ports(uc_priv);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+#ifdef CONFIG_DM_PCI
+int ahci_probe_scsi_pci(struct udevice *ahci_dev)
+{
+ ulong base;
+
+ base = (ulong)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_5,
+ PCI_REGION_MEM);
+
+ return ahci_probe_scsi(ahci_dev, base);
+}
+#endif
+
+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)
{
return ahci_scsi_exec(dev, pccb);
return 0;
}
+#endif