[U-Boot] [PATCH 27/29] dm: ahci: Add a driver for SCSI on AHCI
Bin Meng
bmeng.cn at gmail.com
Tue Jun 13 03:14:53 UTC 2017
Hi Simon,
On Tue, Jun 6, 2017 at 3:15 AM, Simon Glass <sjg at 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 <sjg at 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
More information about the U-Boot
mailing list