diff options
author | Tom Rini <trini@konsulko.com> | 2017-07-11 20:28:46 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2017-07-11 20:28:46 -0400 |
commit | 8d3a25685e4aac7070365a2b3c53c2c81b27930f (patch) | |
tree | 7956bf5e00e3490169a7fc41c42a4416da8db51f /drivers | |
parent | d43ef73bf26614af9b01fd57baa1a1fcf24bfade (diff) | |
parent | 8c9eaadaaad888e0cd77512553d0d02d476b4dde (diff) |
Merge git://git.denx.de/u-boot-dm
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/Kconfig | 4 | ||||
-rw-r--r-- | drivers/Makefile | 4 | ||||
-rw-r--r-- | drivers/ata/Kconfig | 62 | ||||
-rw-r--r-- | drivers/ata/Makefile | 22 | ||||
-rw-r--r-- | drivers/ata/ahci-uclass.c (renamed from drivers/block/ahci-uclass.c) | 0 | ||||
-rw-r--r-- | drivers/ata/ahci.c (renamed from drivers/block/ahci.c) | 395 | ||||
-rw-r--r-- | drivers/ata/dwc_ahci.c (renamed from drivers/block/dwc_ahci.c) | 10 | ||||
-rw-r--r-- | drivers/ata/dwc_ahsata.c (renamed from drivers/block/dwc_ahsata.c) | 74 | ||||
-rw-r--r-- | drivers/ata/dwc_ahsata.h (renamed from drivers/block/dwc_ahsata.h) | 0 | ||||
-rw-r--r-- | drivers/ata/fsl_sata.c (renamed from drivers/block/fsl_sata.c) | 0 | ||||
-rw-r--r-- | drivers/ata/fsl_sata.h (renamed from drivers/block/fsl_sata.h) | 0 | ||||
-rw-r--r-- | drivers/ata/libata.c (renamed from drivers/block/libata.c) | 0 | ||||
-rw-r--r-- | drivers/ata/mvsata_ide.c (renamed from drivers/block/mvsata_ide.c) | 0 | ||||
-rw-r--r-- | drivers/ata/mxc_ata.c (renamed from drivers/block/mxc_ata.c) | 0 | ||||
-rw-r--r-- | drivers/ata/sata.c | 117 | ||||
-rw-r--r-- | drivers/ata/sata_ceva.c (renamed from drivers/block/sata_ceva.c) | 9 | ||||
-rw-r--r-- | drivers/ata/sata_dwc.c (renamed from drivers/block/sata_dwc.c) | 0 | ||||
-rw-r--r-- | drivers/ata/sata_dwc.h (renamed from drivers/block/sata_dwc.h) | 0 | ||||
-rw-r--r-- | drivers/ata/sata_mv.c (renamed from drivers/block/sata_mv.c) | 0 | ||||
-rw-r--r-- | drivers/ata/sata_sandbox.c (renamed from drivers/block/sata_sandbox.c) | 0 | ||||
-rw-r--r-- | drivers/ata/sata_sil.c (renamed from drivers/block/sata_sil.c) | 0 | ||||
-rw-r--r-- | drivers/ata/sata_sil.h (renamed from drivers/block/sata_sil.h) | 0 | ||||
-rw-r--r-- | drivers/ata/sata_sil3114.c (renamed from drivers/block/sata_sil3114.c) | 0 | ||||
-rw-r--r-- | drivers/ata/sata_sil3114.h (renamed from drivers/block/sata_sil3114.h) | 0 | ||||
-rw-r--r-- | drivers/block/Kconfig | 41 | ||||
-rw-r--r-- | drivers/block/Makefile | 17 | ||||
-rw-r--r-- | drivers/block/scsi-uclass.c | 27 | ||||
-rw-r--r-- | drivers/block/sym53c8xx.c | 851 | ||||
-rw-r--r-- | drivers/core/Makefile | 2 | ||||
-rw-r--r-- | drivers/core/dump.c | 1 | ||||
-rw-r--r-- | drivers/core/lists.c | 3 | ||||
-rw-r--r-- | drivers/core/of_access.c | 24 | ||||
-rw-r--r-- | drivers/core/ofnode.c | 72 | ||||
-rw-r--r-- | drivers/core/read.c | 23 | ||||
-rw-r--r-- | drivers/core/read_extra.c | 37 | ||||
-rw-r--r-- | drivers/core/regmap.c | 4 | ||||
-rw-r--r-- | drivers/core/uclass.c | 30 | ||||
-rw-r--r-- | drivers/core/util.c | 5 | ||||
-rw-r--r-- | drivers/misc/cros_ec_sandbox.c | 2 | ||||
-rw-r--r-- | drivers/pci/pci-uclass.c | 8 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-uclass.c | 2 | ||||
-rw-r--r-- | drivers/scsi/Kconfig | 17 | ||||
-rw-r--r-- | drivers/scsi/Makefile | 20 | ||||
-rw-r--r-- | drivers/scsi/sandbox_scsi.c (renamed from drivers/block/sandbox_scsi.c) | 9 | ||||
-rw-r--r-- | drivers/scsi/scsi-uclass.c | 40 | ||||
-rw-r--r-- | drivers/scsi/scsi.c | 709 | ||||
-rw-r--r-- | drivers/serial/ns16550.c | 3 | ||||
-rw-r--r-- | drivers/serial/serial-uclass.c | 92 | ||||
-rw-r--r-- | drivers/usb/emul/sandbox_flash.c | 2 | ||||
-rw-r--r-- | drivers/video/pwm_backlight.c | 22 | ||||
-rw-r--r-- | drivers/video/simple_panel.c | 2 | ||||
-rw-r--r-- | drivers/video/tegra124/display.c | 2 | ||||
-rw-r--r-- | drivers/video/vidconsole-uclass.c | 1 |
53 files changed, 1548 insertions, 1217 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index a736386a0d..2e03133c43 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -6,6 +6,8 @@ source "drivers/core/Kconfig" source "drivers/adc/Kconfig" +source "drivers/ata/Kconfig" + source "drivers/block/Kconfig" source "drivers/clk/Kconfig" @@ -70,6 +72,8 @@ source "drivers/reset/Kconfig" source "drivers/rtc/Kconfig" +source "drivers/scsi/Kconfig" + source "drivers/serial/Kconfig" source "drivers/sound/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 058bccb761..8624bd86f1 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -45,7 +45,7 @@ obj-$(CONFIG_SPL_DFU_SUPPORT) += dfu/ obj-$(CONFIG_SPL_WATCHDOG_SUPPORT) += watchdog/ obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += usb/host/ obj-$(CONFIG_OMAP_USB_PHY) += usb/phy/ -obj-$(CONFIG_SPL_SATA_SUPPORT) += block/ +obj-$(CONFIG_SPL_SATA_SUPPORT) += ata/ scsi/ obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += block/ obj-$(CONFIG_SPL_MMC_SUPPORT) += block/ endif @@ -66,6 +66,7 @@ endif ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),) obj-y += adc/ +obj-y += ata/ obj-$(CONFIG_DM_DEMO) += demo/ obj-$(CONFIG_BIOSEMU) += bios_emulator/ obj-y += block/ @@ -81,6 +82,7 @@ obj-y += dfu/ obj-$(CONFIG_X86) += pch/ obj-y += phy/marvell/ obj-y += rtc/ +obj-y += scsi/ obj-y += sound/ obj-y += spmi/ obj-y += sysreset/ diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig new file mode 100644 index 0000000000..6427f1b94a --- /dev/null +++ b/drivers/ata/Kconfig @@ -0,0 +1,62 @@ +config AHCI + bool "Support SATA controllers with driver model" + depends on DM + help + This enables a uclass for disk controllers in U-Boot. Various driver + types can use this, such as AHCI/SATA. It does not provide any standard + operations at present. The block device interface has not been converted + to driver model. + +config SATA + bool "Support SATA controllers" + help + This enables support for SATA (Serial Advanced Technology + Attachment), a serial bus standard for connecting to hard drives and + other storage devices. + + SATA replaces PATA (originally just ATA), which stands for Parallel AT + Attachment, where AT refers to an IBM AT (Advanced Technology) + computer released in 1984. + + See also CMD_SATA which provides command-line support. + +config SCSI + bool "Support SCSI controllers" + help + This enables support for SCSI (Small Computer System Interface), + a parallel interface widely used with storage peripherals such as + hard drives and optical drives. The SCSI standards define physical + interfaces as well as protocols for controlling devices and + tranferring data. + +config DM_SCSI + bool "Support SCSI controllers with driver model" + depends on BLK + help + This option enables the SCSI (Small Computer System Interface) uclass + which supports SCSI and SATA HDDs. For every device configuration + (IDs/LUNs) a block device is created with RAW read/write and + filesystem support. + +menu "SATA/SCSI device support" + +config SATA_CEVA + bool "Ceva Sata controller" + depends on AHCI + depends on DM_SCSI + help + This option enables Ceva Sata controller hard IP available on Xilinx + ZynqMP. Support up to 2 external devices. Complient with SATA 3.1 and + AHCI 1.3 specifications with hot-plug detect feature. + + +config DWC_AHCI + bool "Enable Synopsys DWC AHCI driver support" + select SCSI_AHCI + select PHY + depends on DM_SCSI + help + Enable this driver to support Sata devices through + Synopsys DWC AHCI module. + +endmenu diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile new file mode 100644 index 0000000000..c48184c4c3 --- /dev/null +++ b/drivers/ata/Makefile @@ -0,0 +1,22 @@ +# +# (C) Copyright 2000-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_DWC_AHCI) += dwc_ahci.o +obj-$(CONFIG_AHCI) += ahci-uclass.o +obj-$(CONFIG_SCSI_AHCI) += ahci.o +obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o +obj-$(CONFIG_FSL_SATA) += fsl_sata.o +obj-$(CONFIG_LIBATA) += libata.o +obj-$(CONFIG_MVSATA_IDE) += mvsata_ide.o +obj-$(CONFIG_MX51_PATA) += mxc_ata.o +obj-$(CONFIG_SATA) += sata.o +obj-$(CONFIG_SATA_CEVA) += sata_ceva.o +obj-$(CONFIG_SATA_DWC) += sata_dwc.o +obj-$(CONFIG_SATA_MV) += sata_mv.o +obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o +obj-$(CONFIG_SATA_SIL) += sata_sil.o +obj-$(CONFIG_SANDBOX) += sata_sandbox.o diff --git a/drivers/block/ahci-uclass.c b/drivers/ata/ahci-uclass.c index 7b8c32699f..7b8c32699f 100644 --- a/drivers/block/ahci-uclass.c +++ b/drivers/ata/ahci-uclass.c diff --git a/drivers/block/ahci.c b/drivers/ata/ahci.c index 3fa14a76b8..6da412d178 100644 --- a/drivers/block/ahci.c +++ b/drivers/ata/ahci.c @@ -6,6 +6,8 @@ * 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 <common.h> @@ -17,15 +19,19 @@ #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(u8 port); +static int ata_io_flush(struct ahci_uc_priv *uc_priv, u8 port); -struct ahci_probe_ent *probe_ent = NULL; -u16 *ataid[AHCI_MAX_PORTS]; +#ifndef CONFIG_DM_SCSI +struct ahci_uc_priv *probe_ent = NULL; +#endif #define writel_with_flush(a,b) do { writel(a,b); readl(b); } while (0) @@ -109,11 +115,11 @@ static int waiting_for_cmd_completed(void __iomem *offset, return (i < timeout_msec) ? 0 : -1; } -int __weak ahci_link_up(struct ahci_probe_ent *probe_ent, u8 port) +int __weak ahci_link_up(struct ahci_uc_priv *uc_priv, u8 port) { u32 tmp; int j = 0; - void __iomem *port_mmio = probe_ent->port[port].port_mmio; + void __iomem *port_mmio = uc_priv->port[port].port_mmio; /* * Bring up SATA link. @@ -166,19 +172,19 @@ int ahci_reset(void __iomem *base) return 0; } -static int ahci_host_init(struct ahci_probe_ent *probe_ent) +static int ahci_host_init(struct ahci_uc_priv *uc_priv) { #if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) # ifdef CONFIG_DM_PCI - struct udevice *dev = probe_ent->dev; + struct udevice *dev = uc_priv->dev; struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); # else - pci_dev_t pdev = probe_ent->dev; + pci_dev_t pdev = uc_priv->dev; unsigned short vendor; # endif u16 tmp16; #endif - void __iomem *mmio = probe_ent->mmio_base; + void __iomem *mmio = uc_priv->mmio_base; u32 tmp, cap_save, cmd; int i, j, ret; void __iomem *port_mmio; @@ -190,7 +196,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) cap_save &= ((1 << 28) | (1 << 17)); cap_save |= (1 << 27); /* Staggered Spin-up. Not needed. */ - ret = ahci_reset(probe_ent->mmio_base); + ret = ahci_reset(uc_priv->mmio_base); if (ret) return ret; @@ -217,23 +223,23 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) } # endif #endif - probe_ent->cap = readl(mmio + HOST_CAP); - probe_ent->port_map = readl(mmio + HOST_PORTS_IMPL); - port_map = probe_ent->port_map; - probe_ent->n_ports = (probe_ent->cap & 0x1f) + 1; + uc_priv->cap = readl(mmio + HOST_CAP); + uc_priv->port_map = readl(mmio + HOST_PORTS_IMPL); + port_map = uc_priv->port_map; + uc_priv->n_ports = (uc_priv->cap & 0x1f) + 1; debug("cap 0x%x port_map 0x%x n_ports %d\n", - probe_ent->cap, probe_ent->port_map, probe_ent->n_ports); + uc_priv->cap, uc_priv->port_map, uc_priv->n_ports); - if (probe_ent->n_ports > CONFIG_SYS_SCSI_MAX_SCSI_ID) - probe_ent->n_ports = CONFIG_SYS_SCSI_MAX_SCSI_ID; + if (uc_priv->n_ports > CONFIG_SYS_SCSI_MAX_SCSI_ID) + uc_priv->n_ports = CONFIG_SYS_SCSI_MAX_SCSI_ID; - for (i = 0; i < probe_ent->n_ports; i++) { + for (i = 0; i < uc_priv->n_ports; i++) { if (!(port_map & (1 << i))) continue; - probe_ent->port[i].port_mmio = ahci_port_base(mmio, i); - port_mmio = (u8 *) probe_ent->port[i].port_mmio; - ahci_setup_port(&probe_ent->port[i], mmio, i); + uc_priv->port[i].port_mmio = ahci_port_base(mmio, i); + port_mmio = (u8 *)uc_priv->port[i].port_mmio; + ahci_setup_port(&uc_priv->port[i], mmio, i); /* make sure port is not active */ tmp = readl(port_mmio + PORT_CMD); @@ -262,7 +268,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) writel_with_flush(cmd, port_mmio + PORT_CMD); /* Bring up SATA link. */ - ret = ahci_link_up(probe_ent, i); + ret = ahci_link_up(uc_priv, i); if (ret) { printf("SATA link %d timeout.\n", i); continue; @@ -319,7 +325,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) tmp = readl(port_mmio + PORT_SCR_STAT); debug("SATA port %d status: 0x%x\n", i, tmp); if ((tmp & PORT_SCR_STAT_DET_MASK) == PORT_SCR_STAT_DET_PHYRDY) - probe_ent->link_port_map |= (0x01 << i); + uc_priv->link_port_map |= (0x01 << i); } tmp = readl(mmio + HOST_CTL); @@ -344,25 +350,25 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) } -static void ahci_print_info(struct ahci_probe_ent *probe_ent) +static void ahci_print_info(struct ahci_uc_priv *uc_priv) { #if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) # if defined(CONFIG_DM_PCI) - struct udevice *dev = probe_ent->dev; + struct udevice *dev = uc_priv->dev; # else - pci_dev_t pdev = probe_ent->dev; + pci_dev_t pdev = uc_priv->dev; # endif u16 cc; #endif - void __iomem *mmio = probe_ent->mmio_base; + void __iomem *mmio = uc_priv->mmio_base; u32 vers, cap, cap2, impl, speed; const char *speed_s; const char *scc_s; vers = readl(mmio + HOST_VERSION); - cap = probe_ent->cap; + cap = uc_priv->cap; cap2 = readl(mmio + HOST_CAP2); - impl = probe_ent->port_map; + impl = uc_priv->port_map; speed = (cap >> 20) & 0xf; if (speed == 1) @@ -427,9 +433,9 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent) #ifndef CONFIG_SCSI_AHCI_PLAT # if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) -static int ahci_init_one(struct udevice *dev) +static int ahci_init_one(struct ahci_uc_priv *uc_priv, struct udevice *dev) # else -static int ahci_init_one(pci_dev_t dev) +static int ahci_init_one(struct ahci_uc_priv *uc_priv, pci_dev_t dev) # endif { #if !defined(CONFIG_DM_SCSI) @@ -437,26 +443,19 @@ static int ahci_init_one(pci_dev_t dev) #endif int rc; - probe_ent = malloc(sizeof(struct ahci_probe_ent)); - if (!probe_ent) { - printf("%s: No memory for probe_ent\n", __func__); - return -ENOMEM; - } - - memset(probe_ent, 0, sizeof(struct ahci_probe_ent)); - probe_ent->dev = dev; + uc_priv->dev = dev; - probe_ent->host_flags = ATA_FLAG_SATA + uc_priv->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_NO_ATAPI; - probe_ent->pio_mask = 0x1f; - probe_ent->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ + uc_priv->pio_mask = 0x1f; + uc_priv->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ #if !defined(CONFIG_DM_SCSI) #ifdef CONFIG_DM_PCI - probe_ent->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5, + uc_priv->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5, PCI_REGION_MEM); /* Take from kernel: @@ -467,7 +466,7 @@ static int ahci_init_one(pci_dev_t dev) if (vendor == 0x197b) dm_pci_write_config8(dev, 0x41, 0xa1); #else - probe_ent->mmio_base = pci_map_bar(dev, PCI_BASE_ADDRESS_5, + uc_priv->mmio_base = pci_map_bar(dev, PCI_BASE_ADDRESS_5, PCI_REGION_MEM); /* Take from kernel: @@ -479,17 +478,17 @@ static int ahci_init_one(pci_dev_t dev) pci_write_config_byte(dev, 0x41, 0xa1); #endif #else - struct scsi_platdata *plat = dev_get_platdata(dev); - probe_ent->mmio_base = (void *)plat->base; + struct scsi_platdata *plat = dev_get_uclass_platdata(dev); + uc_priv->mmio_base = (void *)plat->base; #endif - debug("ahci mmio_base=0x%p\n", probe_ent->mmio_base); + debug("ahci mmio_base=0x%p\n", uc_priv->mmio_base); /* initialize adapter */ - rc = ahci_host_init(probe_ent); + rc = ahci_host_init(uc_priv); if (rc) goto err_out; - ahci_print_info(probe_ent); + ahci_print_info(uc_priv); return 0; @@ -500,9 +499,10 @@ static int ahci_init_one(pci_dev_t dev) #define MAX_DATA_BYTE_COUNT (4*1024*1024) -static int ahci_fill_sg(u8 port, unsigned char *buf, int buf_len) +static int ahci_fill_sg(struct ahci_uc_priv *uc_priv, u8 port, + unsigned char *buf, int buf_len) { - struct ahci_ioports *pp = &(probe_ent->port[port]); + struct ahci_ioports *pp = &(uc_priv->port[port]); struct ahci_sg *ahci_sg = pp->cmd_tbl_sg; u32 sg_count; int i; @@ -555,9 +555,9 @@ static int wait_spinup(void __iomem *port_mmio) return -ETIMEDOUT; } -static int ahci_port_start(u8 port) +static int ahci_port_start(struct ahci_uc_priv *uc_priv, u8 port) { - struct ahci_ioports *pp = &(probe_ent->port[port]); + struct ahci_ioports *pp = &(uc_priv->port[port]); void __iomem *port_mmio = pp->port_mmio; u32 port_status; void __iomem *mem; @@ -630,11 +630,11 @@ static int ahci_port_start(u8 port) } -static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf, - int buf_len, u8 is_write) +static int ahci_device_data_io(struct ahci_uc_priv *uc_priv, u8 port, u8 *fis, + int fis_len, u8 *buf, int buf_len, u8 is_write) { - struct ahci_ioports *pp = &(probe_ent->port[port]); + struct ahci_ioports *pp = &(uc_priv->port[port]); void __iomem *port_mmio = pp->port_mmio; u32 opts; u32 port_status; @@ -642,7 +642,7 @@ static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf, debug("Enter %s: for port %d\n", __func__, port); - if (port > probe_ent->n_ports) { + if (port > uc_priv->n_ports) { printf("Invalid port number %d\n", port); return -1; } @@ -655,7 +655,7 @@ static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf, memcpy((unsigned char *)pp->cmd_tbl, fis, fis_len); - sg_count = ahci_fill_sg(port, buf, buf_len); + sg_count = ahci_fill_sg(uc_priv, port, buf, buf_len); opts = (fis_len >> 2) | (sg_count << 16) | (is_write << 6); ahci_fill_cmd_slot(pp, opts); @@ -689,7 +689,8 @@ static char *ata_id_strcpy(u16 *target, u16 *src, int len) /* * SCSI INQUIRY command operation. */ -static int ata_scsiop_inquiry(ccb *pccb) +static int ata_scsiop_inquiry(struct ahci_uc_priv *uc_priv, + struct scsi_cmd *pccb) { static const u8 hdr[] = { 0, @@ -720,21 +721,21 @@ static int ata_scsiop_inquiry(ccb *pccb) /* Read id from sata */ port = pccb->target; - if (ahci_device_data_io(port, (u8 *) &fis, sizeof(fis), (u8 *)tmpid, - ATA_ID_WORDS * 2, 0)) { + if (ahci_device_data_io(uc_priv, port, (u8 *)&fis, sizeof(fis), + (u8 *)tmpid, ATA_ID_WORDS * 2, 0)) { debug("scsi_ahci: SCSI inquiry command failure.\n"); return -EIO; } - if (!ataid[port]) { - ataid[port] = malloc(ATA_ID_WORDS * 2); - if (!ataid[port]) { + if (!uc_priv->ataid[port]) { + uc_priv->ataid[port] = malloc(ATA_ID_WORDS * 2); + if (!uc_priv->ataid[port]) { printf("%s: No memory for ataid[port]\n", __func__); return -ENOMEM; } } - idbuf = ataid[port]; + idbuf = uc_priv->ataid[port]; memcpy(idbuf, tmpid, ATA_ID_WORDS * 2); ata_swap_buf_le16(idbuf, ATA_ID_WORDS); @@ -753,7 +754,8 @@ static int ata_scsiop_inquiry(ccb *pccb) /* * SCSI READ10/WRITE10 command operation. */ -static int ata_scsiop_read_write(ccb *pccb, u8 is_write) +static int ata_scsiop_read_write(struct ahci_uc_priv *uc_priv, + struct scsi_cmd *pccb, u8 is_write) { lbaint_t lba = 0; u16 blocks = 0; @@ -833,8 +835,8 @@ static int ata_scsiop_read_write(ccb *pccb, u8 is_write) fis[13] = (now_blocks >> 8) & 0xff; /* Read/Write from ahci */ - if (ahci_device_data_io(pccb->target, (u8 *) &fis, sizeof(fis), - user_buffer, transfer_size, + if (ahci_device_data_io(uc_priv, pccb->target, (u8 *)&fis, + sizeof(fis), user_buffer, transfer_size, is_write)) { debug("scsi_ahci: SCSI %s10 command failure.\n", is_write ? "WRITE" : "READ"); @@ -848,7 +850,7 @@ static int ata_scsiop_read_write(ccb *pccb, u8 is_write) * usually, one extra flush when the rare writes do happen. */ if (is_write) { - if (-EIO == ata_io_flush(pccb->target)) + if (-EIO == ata_io_flush(uc_priv, pccb->target)) return -EIO; } user_buffer += transfer_size; @@ -864,20 +866,21 @@ static int ata_scsiop_read_write(ccb *pccb, u8 is_write) /* * SCSI READ CAPACITY10 command operation. */ -static int ata_scsiop_read_capacity10(ccb *pccb) +static int ata_scsiop_read_capacity10(struct ahci_uc_priv *uc_priv, + struct scsi_cmd *pccb) { u32 cap; u64 cap64; u32 block_size; - if (!ataid[pccb->target]) { + if (!uc_priv->ataid[pccb->target]) { printf("scsi_ahci: SCSI READ CAPACITY10 command failure. " "\tNo ATA info!\n" "\tPlease run SCSI command INQUIRY first!\n"); return -EPERM; } - cap64 = ata_id_n_sectors(ataid[pccb->target]); + cap64 = ata_id_n_sectors(uc_priv->ataid[pccb->target]); if (cap64 > 0x100000000ULL) cap64 = 0xffffffff; @@ -894,19 +897,20 @@ static int ata_scsiop_read_capacity10(ccb *pccb) /* * SCSI READ CAPACITY16 command operation. */ -static int ata_scsiop_read_capacity16(ccb *pccb) +static int ata_scsiop_read_capacity16(struct ahci_uc_priv *uc_priv, + struct scsi_cmd *pccb) { u64 cap; u64 block_size; - if (!ataid[pccb->target]) { + if (!uc_priv->ataid[pccb->target]) { printf("scsi_ahci: SCSI READ CAPACITY16 command failure. " "\tNo ATA info!\n" "\tPlease run SCSI command INQUIRY first!\n"); return -EPERM; } - cap = ata_id_n_sectors(ataid[pccb->target]); + cap = ata_id_n_sectors(uc_priv->ataid[pccb->target]); cap = cpu_to_be64(cap); memcpy(pccb->pdata, &cap, sizeof(cap)); @@ -920,59 +924,87 @@ static int ata_scsiop_read_capacity16(ccb *pccb) /* * SCSI TEST UNIT READY command operation. */ -static int ata_scsiop_test_unit_ready(ccb *pccb) +static int ata_scsiop_test_unit_ready(struct ahci_uc_priv *uc_priv, + struct scsi_cmd *pccb) { - return (ataid[pccb->target]) ? 0 : -EPERM; + return (uc_priv->ataid[pccb->target]) ? 0 : -EPERM; } -int scsi_exec(ccb *pccb) +static int ahci_scsi_exec(struct udevice *dev, struct scsi_cmd *pccb) { + struct ahci_uc_priv *uc_priv; +#ifdef CONFIG_DM_SCSI + uc_priv = dev_get_uclass_priv(dev); +#else + uc_priv = probe_ent; +#endif int ret; switch (pccb->cmd[0]) { case SCSI_READ16: case SCSI_READ10: - ret = ata_scsiop_read_write(pccb, 0); + ret = ata_scsiop_read_write(uc_priv, pccb, 0); break; case SCSI_WRITE10: - ret = ata_scsiop_read_write(pccb, 1); + ret = ata_scsiop_read_write(uc_priv, pccb, 1); break; case SCSI_RD_CAPAC10: - ret = ata_scsiop_read_capacity10(pccb); + ret = ata_scsiop_read_capacity10(uc_priv, pccb); break; case SCSI_RD_CAPAC16: - ret = ata_scsiop_read_capacity16(pccb); + ret = ata_scsiop_read_capacity16(uc_priv, pccb); break; case SCSI_TST_U_RDY: - ret = ata_scsiop_test_unit_ready(pccb); + ret = ata_scsiop_test_unit_ready(uc_priv, pccb); break; case SCSI_INQUIRY: - ret = ata_scsiop_inquiry(pccb); + ret = ata_scsiop_inquiry(uc_priv, pccb); 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; } -#if defined(CONFIG_DM_SCSI) -void scsi_low_level_init(int busdevfunc, struct udevice *dev) -#else -void scsi_low_level_init(int busdevfunc) -#endif +static int ahci_start_ports(struct ahci_uc_priv *uc_priv) { - int i; u32 linkmap; + int i; + + linkmap = uc_priv->link_port_map; + + for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { + if (((linkmap >> i) & 0x01)) { + if (ahci_port_start(uc_priv, (u8) i)) { + printf("Can not start port %d\n", i); + continue; + } + } + } + + return 0; +} + +#ifndef CONFIG_DM_SCSI +void scsi_low_level_init(int busdevfunc) +{ + struct ahci_uc_priv *uc_priv; #ifndef CONFIG_SCSI_AHCI_PLAT + probe_ent = calloc(1, sizeof(struct ahci_uc_priv)); + if (!probe_ent) { + printf("%s: No memory for uc_priv\n", __func__); + return; + } + uc_priv = probe_ent; # if defined(CONFIG_DM_PCI) struct udevice *dev; int ret; @@ -980,76 +1012,94 @@ void scsi_low_level_init(int busdevfunc) ret = dm_pci_bus_find_bdf(busdevfunc, &dev); if (ret) return; - ahci_init_one(dev); -# elif defined(CONFIG_DM_SCSI) - ahci_init_one(dev); + ahci_init_one(uc_priv, dev); # else - ahci_init_one(busdevfunc); + ahci_init_one(uc_priv, busdevfunc); # endif +#else + uc_priv = probe_ent; #endif - linkmap = probe_ent->link_port_map; + ahci_start_ports(uc_priv); +} +#endif - for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { - if (((linkmap >> i) & 0x01)) { - if (ahci_port_start((u8) i)) { - printf("Can not start port %d\n", i); - continue; - } - } - } +#ifndef CONFIG_SCSI_AHCI_PLAT +# if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) +int achi_init_one_dm(struct udevice *dev) +{ + struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev); + + return ahci_init_one(uc_priv, dev); } +#endif +#endif -#ifdef CONFIG_SCSI_AHCI_PLAT -int ahci_init(void __iomem *base) +int achi_start_ports_dm(struct udevice *dev) { - int i, rc = 0; - u32 linkmap; + struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev); - probe_ent = malloc(sizeof(struct ahci_probe_ent)); - if (!probe_ent) { - printf("%s: No memory for probe_ent\n", __func__); - return -ENOMEM; - } + return ahci_start_ports(uc_priv); +} - memset(probe_ent, 0, sizeof(struct ahci_probe_ent)); +#ifdef CONFIG_SCSI_AHCI_PLAT +static int ahci_init_common(struct ahci_uc_priv *uc_priv, void __iomem *base) +{ + int rc; - probe_ent->host_flags = ATA_FLAG_SATA + uc_priv->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_NO_ATAPI; - probe_ent->pio_mask = 0x1f; - probe_ent->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ + uc_priv->pio_mask = 0x1f; + uc_priv->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ - probe_ent->mmio_base = base; + uc_priv->mmio_base = base; /* initialize adapter */ - rc = ahci_host_init(probe_ent); + rc = ahci_host_init(uc_priv); if (rc) goto err_out; - ahci_print_info(probe_ent); + ahci_print_info(uc_priv); - linkmap = probe_ent->link_port_map; + rc = ahci_start_ports(uc_priv); - for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { - if (((linkmap >> i) & 0x01)) { - if (ahci_port_start((u8) i)) { - printf("Can not start port %d\n", i); - continue; - } - } - } err_out: return rc; } +#ifndef CONFIG_DM_SCSI +int ahci_init(void __iomem *base) +{ + struct ahci_uc_priv *uc_priv; + + probe_ent = malloc(sizeof(struct ahci_uc_priv)); + if (!probe_ent) { + printf("%s: No memory for uc_priv\n", __func__); + return -ENOMEM; + } + + uc_priv = probe_ent; + memset(uc_priv, 0, sizeof(struct ahci_uc_priv)); + + return ahci_init_common(uc_priv, base); +} +#endif + +int ahci_init_dm(struct udevice *dev, void __iomem *base) +{ + struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev); + + return ahci_init_common(uc_priv, base); +} + void __weak scsi_init(void) { } -#endif +#endif /* CONFIG_SCSI_AHCI_PLAT */ /* * In the general case of generic rotating media it makes sense to have a @@ -1060,10 +1110,10 @@ void __weak scsi_init(void) * is the last write is difficult. Because writing to the disk in u-boot is * very rare, this flush command will be invoked after every block write. */ -static int ata_io_flush(u8 port) +static int ata_io_flush(struct ahci_uc_priv *uc_priv, u8 port) { u8 fis[20]; - struct ahci_ioports *pp = &(probe_ent->port[port]); + struct ahci_ioports *pp = &(uc_priv->port[port]); void __iomem *port_mmio = pp->port_mmio; u32 cmd_fis_len = 5; /* five dwords */ @@ -1087,13 +1137,82 @@ static int ata_io_flush(u8 port) return 0; } +static int ahci_scsi_bus_reset(struct udevice *dev) +{ + /* Not implemented */ + + 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) +{ +#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, +}; -__weak void scsi_bus_reset(void) +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) { - /*Not implement*/ + return ahci_scsi_exec(dev, pccb); } -void scsi_print_error(ccb * pccb) +__weak int scsi_bus_reset(struct udevice *dev) { - /*The ahci error info can be read in the ahci driver*/ + return ahci_scsi_bus_reset(dev); + + return 0; } +#endif diff --git a/drivers/block/dwc_ahci.c b/drivers/ata/dwc_ahci.c index 3f839bf987..f6147989b1 100644 --- a/drivers/block/dwc_ahci.c +++ b/drivers/ata/dwc_ahci.c @@ -28,7 +28,7 @@ struct dwc_ahci_priv { static int dwc_ahci_ofdata_to_platdata(struct udevice *dev) { struct dwc_ahci_priv *priv = dev_get_priv(dev); - struct scsi_platdata *plat = dev_get_platdata(dev); + struct scsi_platdata *plat = dev_get_uclass_platdata(dev); fdt_addr_t addr; plat->max_id = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), @@ -81,7 +81,11 @@ static int dwc_ahci_probe(struct udevice *dev) writel(val, priv->wrapper_base + TI_SATA_SYSCONFIG); } - return ahci_init(priv->base); + ret = ahci_init_dm(dev, priv->base); + if (ret) + return ret; + + return achi_start_ports_dm(dev); } static const struct udevice_id dwc_ahci_ids[] = { @@ -94,8 +98,8 @@ U_BOOT_DRIVER(dwc_ahci) = { .id = UCLASS_SCSI, .of_match = dwc_ahci_ids, .ofdata_to_platdata = dwc_ahci_ofdata_to_platdata, + .ops = &scsi_ops, .probe = dwc_ahci_probe, .priv_auto_alloc_size = sizeof(struct dwc_ahci_priv), - .platdata_auto_alloc_size = sizeof(struct scsi_platdata), .flags = DM_FLAG_ALLOC_PRIV_DMA, }; diff --git a/drivers/block/dwc_ahsata.c b/drivers/ata/dwc_ahsata.c index c306e927db..78572a5b73 100644 --- a/drivers/block/dwc_ahsata.c +++ b/drivers/ata/dwc_ahsata.c @@ -100,7 +100,7 @@ static int waiting_for_cmd_completed(u8 *offset, return (i < timeout_msec) ? 0 : -1; } -static int ahci_setup_oobr(struct ahci_probe_ent *probe_ent, +static int ahci_setup_oobr(struct ahci_uc_priv *probe_ent, int clk) { struct sata_host_regs *host_mmio = @@ -112,7 +112,7 @@ static int ahci_setup_oobr(struct ahci_probe_ent *probe_ent, return 0; } -static int ahci_host_init(struct ahci_probe_ent *probe_ent) +static int ahci_host_init(struct ahci_uc_priv *probe_ent) { u32 tmp, cap_save, num_ports; int i, j, timeout = 1000; @@ -275,7 +275,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) return 0; } -static void ahci_print_info(struct ahci_probe_ent *probe_ent) +static void ahci_print_info(struct ahci_uc_priv *probe_ent) { struct sata_host_regs *host_mmio = (struct sata_host_regs *)probe_ent->mmio_base; @@ -331,10 +331,10 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent) static int ahci_init_one(int pdev) { int rc; - struct ahci_probe_ent *probe_ent = NULL; + struct ahci_uc_priv *probe_ent = NULL; - probe_ent = malloc(sizeof(struct ahci_probe_ent)); - memset(probe_ent, 0, sizeof(struct ahci_probe_ent)); + probe_ent = malloc(sizeof(struct ahci_uc_priv)); + memset(probe_ent, 0, sizeof(struct ahci_uc_priv)); probe_ent->dev = pdev; probe_ent->host_flags = ATA_FLAG_SATA @@ -361,7 +361,7 @@ err_out: return rc; } -static int ahci_fill_sg(struct ahci_probe_ent *probe_ent, +static int ahci_fill_sg(struct ahci_uc_priv *probe_ent, u8 port, unsigned char *buf, int buf_len) { struct ahci_ioports *pp = &(probe_ent->port[port]); @@ -408,7 +408,7 @@ static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 cmd_slot, u32 opts) #define AHCI_GET_CMD_SLOT(c) ((c) ? ffs(c) : 0) -static int ahci_exec_ata_cmd(struct ahci_probe_ent *probe_ent, +static int ahci_exec_ata_cmd(struct ahci_uc_priv *probe_ent, u8 port, struct sata_fis_h2d *cfis, u8 *buf, u32 buf_len, s32 is_write) { @@ -461,8 +461,8 @@ static int ahci_exec_ata_cmd(struct ahci_probe_ent *probe_ent, static void ahci_set_feature(u8 dev, u8 port) { - struct ahci_probe_ent *probe_ent = - (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + struct ahci_uc_priv *probe_ent = + (struct ahci_uc_priv *)sata_dev_desc[dev].priv; struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); struct sata_fis_h2d *cfis = &h2d; @@ -476,7 +476,7 @@ static void ahci_set_feature(u8 dev, u8 port) ahci_exec_ata_cmd(probe_ent, port, cfis, NULL, 0, READ_CMD); } -static int ahci_port_start(struct ahci_probe_ent *probe_ent, +static int ahci_port_start(struct ahci_uc_priv *probe_ent, u8 port) { struct ahci_ioports *pp = &(probe_ent->port[port]); @@ -560,7 +560,7 @@ int init_sata(int dev) { int i; u32 linkmap; - struct ahci_probe_ent *probe_ent = NULL; + struct ahci_uc_priv *probe_ent = NULL; #if defined(CONFIG_MX6) if (!is_mx6dq() && !is_mx6dqp()) @@ -573,7 +573,7 @@ int init_sata(int dev) ahci_init_one(dev); - probe_ent = (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + probe_ent = (struct ahci_uc_priv *)sata_dev_desc[dev].priv; linkmap = probe_ent->link_port_map; if (0 == linkmap) { @@ -597,7 +597,7 @@ int init_sata(int dev) int reset_sata(int dev) { - struct ahci_probe_ent *probe_ent; + struct ahci_uc_priv *probe_ent; struct sata_host_regs *host_mmio; if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) { @@ -605,7 +605,7 @@ int reset_sata(int dev) return -1; } - probe_ent = (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + probe_ent = (struct ahci_uc_priv *)sata_dev_desc[dev].priv; if (NULL == probe_ent) /* not initialized, so nothing to reset */ return 0; @@ -636,8 +636,8 @@ static void dwc_ahsata_print_info(int dev) static void dwc_ahsata_identify(int dev, u16 *id) { - struct ahci_probe_ent *probe_ent = - (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + struct ahci_uc_priv *probe_ent = + (struct ahci_uc_priv *)sata_dev_desc[dev].priv; struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); struct sata_fis_h2d *cfis = &h2d; u8 port = probe_ent->hard_port_no; @@ -655,8 +655,8 @@ static void dwc_ahsata_identify(int dev, u16 *id) static void dwc_ahsata_xfer_mode(int dev, u16 *id) { - struct ahci_probe_ent *probe_ent = - (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + struct ahci_uc_priv *probe_ent = + (struct ahci_uc_priv *)sata_dev_desc[dev].priv; probe_ent->pio_mask = id[ATA_ID_PIO_MODES]; probe_ent->udma_mask = id[ATA_ID_UDMA_MODES]; @@ -667,8 +667,8 @@ static void dwc_ahsata_xfer_mode(int dev, u16 *id) static u32 dwc_ahsata_rw_cmd(int dev, u32 start, u32 blkcnt, u8 *buffer, int is_write) { - struct ahci_probe_ent *probe_ent = - (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + struct ahci_uc_priv *probe_ent = + (struct ahci_uc_priv *)sata_dev_desc[dev].priv; struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); struct sata_fis_h2d *cfis = &h2d; u8 port = probe_ent->hard_port_no; @@ -698,8 +698,8 @@ static u32 dwc_ahsata_rw_cmd(int dev, u32 start, u32 blkcnt, void dwc_ahsata_flush_cache(int dev) { - struct ahci_probe_ent *probe_ent = - (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + struct ahci_uc_priv *probe_ent = + (struct ahci_uc_priv *)sata_dev_desc[dev].priv; struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); struct sata_fis_h2d *cfis = &h2d; u8 port = probe_ent->hard_port_no; @@ -716,8 +716,8 @@ void dwc_ahsata_flush_cache(int dev) static u32 dwc_ahsata_rw_cmd_ext(int dev, u32 start, lbaint_t blkcnt, u8 *buffer, int is_write) { - struct ahci_probe_ent *probe_ent = - (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + struct ahci_uc_priv *probe_ent = + (struct ahci_uc_priv *)sata_dev_desc[dev].priv; struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); struct sata_fis_h2d *cfis = &h2d; u8 port = probe_ent->hard_port_no; @@ -753,8 +753,8 @@ static u32 dwc_ahsata_rw_cmd_ext(int dev, u32 start, lbaint_t blkcnt, u32 dwc_ahsata_rw_ncq_cmd(int dev, u32 start, lbaint_t blkcnt, u8 *buffer, int is_write) { - struct ahci_probe_ent *probe_ent = - (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + struct ahci_uc_priv *probe_ent = + (struct ahci_uc_priv *)sata_dev_desc[dev].priv; struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); struct sata_fis_h2d *cfis = &h2d; u8 port = probe_ent->hard_port_no; @@ -795,8 +795,8 @@ u32 dwc_ahsata_rw_ncq_cmd(int dev, u32 start, lbaint_t blkcnt, void dwc_ahsata_flush_cache_ext(int dev) { - struct ahci_probe_ent *probe_ent = - (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + struct ahci_uc_priv *probe_ent = + (struct ahci_uc_priv *)sata_dev_desc[dev].priv; struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); struct sata_fis_h2d *cfis = &h2d; u8 port = probe_ent->hard_port_no; @@ -812,8 +812,8 @@ void dwc_ahsata_flush_cache_ext(int dev) static void dwc_ahsata_init_wcache(int dev, u16 *id) { - struct ahci_probe_ent *probe_ent = - (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + struct ahci_uc_priv *probe_ent = + (struct ahci_uc_priv *)sata_dev_desc[dev].priv; if (ata_id_has_wcache(id) && ata_id_wcache_enabled(id)) probe_ent->flags |= SATA_FLAG_WCACHE; @@ -893,7 +893,7 @@ u32 ata_low_level_rw_lba28(int dev, u32 blknr, lbaint_t blkcnt, int sata_port_status(int dev, int port) { struct sata_port_regs *port_mmio; - struct ahci_probe_ent *probe_ent = NULL; + struct ahci_uc_priv *probe_ent = NULL; if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) return -EINVAL; @@ -901,7 +901,7 @@ int sata_port_status(int dev, int port) if (sata_dev_desc[dev].priv == NULL) return -ENODEV; - probe_ent = (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + probe_ent = (struct ahci_uc_priv *)sata_dev_desc[dev].priv; port_mmio = (struct sata_port_regs *)probe_ent->port[port].port_mmio; return readl(&(port_mmio->ssts)) & SATA_PORT_SSTS_DET_MASK; @@ -926,8 +926,8 @@ ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer) ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer) { u32 rc; - struct ahci_probe_ent *probe_ent = - (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + struct ahci_uc_priv *probe_ent = + (struct ahci_uc_priv *)sata_dev_desc[dev].priv; u32 flags = probe_ent->flags; if (sata_dev_desc[dev].lba48) { @@ -953,8 +953,8 @@ int scan_sata(int dev) u8 product[ATA_ID_PROD_LEN + 1] = { 0 }; u16 *id; u64 n_sectors; - struct ahci_probe_ent *probe_ent = - (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + struct ahci_uc_priv *probe_ent = + (struct ahci_uc_priv *)sata_dev_desc[dev].priv; u8 port = probe_ent->hard_port_no; struct blk_desc *pdev = &(sata_dev_desc[dev]); diff --git a/drivers/block/dwc_ahsata.h b/drivers/ata/dwc_ahsata.h index caa2e501f9..caa2e501f9 100644 --- a/drivers/block/dwc_ahsata.h +++ b/drivers/ata/dwc_ahsata.h diff --git a/drivers/block/fsl_sata.c b/drivers/ata/fsl_sata.c index 31f7fab8b4..31f7fab8b4 100644 --- a/drivers/block/fsl_sata.c +++ b/drivers/ata/fsl_sata.c diff --git a/drivers/block/fsl_sata.h b/drivers/ata/fsl_sata.h index 18d679e782..18d679e782 100644 --- a/drivers/block/fsl_sata.h +++ b/drivers/ata/fsl_sata.h diff --git a/drivers/block/libata.c b/drivers/ata/libata.c index d684270dcd..d684270dcd 100644 --- a/drivers/block/libata.c +++ b/drivers/ata/libata.c diff --git a/drivers/block/mvsata_ide.c b/drivers/ata/mvsata_ide.c index 7b6a1558d2..7b6a1558d2 100644 --- a/drivers/block/mvsata_ide.c +++ b/drivers/ata/mvsata_ide.c diff --git a/drivers/block/mxc_ata.c b/drivers/ata/mxc_ata.c index 44bb406f4d..44bb406f4d 100644 --- a/drivers/block/mxc_ata.c +++ b/drivers/ata/mxc_ata.c diff --git a/drivers/ata/sata.c b/drivers/ata/sata.c new file mode 100644 index 0000000000..42ff5c7755 --- /dev/null +++ b/drivers/ata/sata.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2000-2005, DENX Software Engineering + * Wolfgang Denk <wd@denx.de> + * Copyright (C) Procsys. All rights reserved. + * Mushtaq Khan <mushtaq_k@procsys.com> + * <mushtaqk_921@yahoo.co.in> + * Copyright (C) 2008 Freescale Semiconductor, Inc. + * Dave Liu <daveliu@freescale.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <sata.h> + +struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; + +#ifdef CONFIG_PARTITIONS +struct blk_desc *sata_get_dev(int dev) +{ + return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL; +} +#endif + +#ifdef CONFIG_BLK +static unsigned long sata_bread(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, void *dst) +{ + return -ENOSYS; +} + +static unsigned long sata_bwrite(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + return -ENOSYS; +} +#else +static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start, + lbaint_t blkcnt, void *dst) +{ + return sata_read(block_dev->devnum, start, blkcnt, dst); +} + +static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + return sata_write(block_dev->devnum, start, blkcnt, buffer); +} +#endif + +int __sata_initialize(void) +{ + int rc, ret = -1; + int i; + + for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) { + memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc)); + sata_dev_desc[i].if_type = IF_TYPE_SATA; + sata_dev_desc[i].devnum = i; + sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + sata_dev_desc[i].type = DEV_TYPE_HARDDISK; + sata_dev_desc[i].lba = 0; + sata_dev_desc[i].blksz = 512; + sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); +#ifndef CONFIG_BLK + sata_dev_desc[i].block_read = sata_bread; + sata_dev_desc[i].block_write = sata_bwrite; +#endif + rc = init_sata(i); + if (!rc) { + rc = scan_sata(i); + if (!rc && sata_dev_desc[i].lba > 0 && + sata_dev_desc[i].blksz > 0) { + part_init(&sata_dev_desc[i]); + ret = i; + } + } + } + + return ret; +} +int sata_initialize(void) __attribute__((weak, alias("__sata_initialize"))); + +__weak int __sata_stop(void) +{ + int i, err = 0; + + for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) + err |= reset_sata(i); + + if (err) + printf("Could not reset some SATA devices\n"); + + return err; +} +int sata_stop(void) __attribute__((weak, alias("__sata_stop"))); + +#ifdef CONFIG_BLK +static const struct blk_ops sata_blk_ops = { + .read = sata_bread, + .write = sata_bwrite, +}; + +U_BOOT_DRIVER(sata_blk) = { + .name = "sata_blk", + .id = UCLASS_BLK, + .ops = &sata_blk_ops, +}; +#else +U_BOOT_LEGACY_BLK(sata) = { + .if_typename = "sata", + .if_type = IF_TYPE_SATA, + .max_devs = CONFIG_SYS_SATA_MAX_DEVICE, + .desc = sata_dev_desc, +}; +#endif diff --git a/drivers/block/sata_ceva.c b/drivers/ata/sata_ceva.c index 0c24fce8dc..d582e5ba80 100644 --- a/drivers/block/sata_ceva.c +++ b/drivers/ata/sata_ceva.c @@ -113,10 +113,11 @@ static int ceva_init_sata(ulong mmio) static int sata_ceva_probe(struct udevice *dev) { - struct scsi_platdata *plat = dev_get_platdata(dev); + struct scsi_platdata *plat = dev_get_uclass_platdata(dev); ceva_init_sata(plat->base); - return 0; + + return achi_init_one_dm(dev); } static const struct udevice_id sata_ceva_ids[] = { @@ -126,7 +127,7 @@ static const struct udevice_id sata_ceva_ids[] = { static int sata_ceva_ofdata_to_platdata(struct udevice *dev) { - struct scsi_platdata *plat = dev_get_platdata(dev); + struct scsi_platdata *plat = dev_get_uclass_platdata(dev); plat->base = devfdt_get_addr(dev); if (plat->base == FDT_ADDR_T_NONE) @@ -143,7 +144,7 @@ U_BOOT_DRIVER(ceva_host_blk) = { .name = "ceva_sata", .id = UCLASS_SCSI, .of_match = sata_ceva_ids, + .ops = &scsi_ops, .probe = sata_ceva_probe, .ofdata_to_platdata = sata_ceva_ofdata_to_platdata, - .platdata_auto_alloc_size = sizeof(struct scsi_platdata), }; diff --git a/drivers/block/sata_dwc.c b/drivers/ata/sata_dwc.c index a226ca2dec..a226ca2dec 100644 --- a/drivers/block/sata_dwc.c +++ b/drivers/ata/sata_dwc.c diff --git a/drivers/block/sata_dwc.h b/drivers/ata/sata_dwc.h index e2d9e0c1fc..e2d9e0c1fc 100644 --- a/drivers/block/sata_dwc.h +++ b/drivers/ata/sata_dwc.h diff --git a/drivers/block/sata_mv.c b/drivers/ata/sata_mv.c index 78e3da442d..78e3da442d 100644 --- a/drivers/block/sata_mv.c +++ b/drivers/ata/sata_mv.c diff --git a/drivers/block/sata_sandbox.c b/drivers/ata/sata_sandbox.c index bd967d290c..bd967d290c 100644 --- a/drivers/block/sata_sandbox.c +++ b/drivers/ata/sata_sandbox.c diff --git a/drivers/block/sata_sil.c b/drivers/ata/sata_sil.c index daff7d4ab5..daff7d4ab5 100644 --- a/drivers/block/sata_sil.c +++ b/drivers/ata/sata_sil.c diff --git a/drivers/block/sata_sil.h b/drivers/ata/sata_sil.h index 55954efdd6..55954efdd6 100644 --- a/drivers/block/sata_sil.h +++ b/drivers/ata/sata_sil.h diff --git a/drivers/block/sata_sil3114.c b/drivers/ata/sata_sil3114.c index 61ffb66a77..61ffb66a77 100644 --- a/drivers/block/sata_sil3114.c +++ b/drivers/ata/sata_sil3114.c diff --git a/drivers/block/sata_sil3114.h b/drivers/ata/sata_sil3114.h index 091fca1d40..091fca1d40 100644 --- a/drivers/block/sata_sil3114.h +++ b/drivers/ata/sata_sil3114.h diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 931defd2ae..ca7692d8a5 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -10,24 +10,6 @@ config BLK be partitioned into several areas, called 'partitions' in U-Boot. A filesystem can be placed in each partition. -config AHCI - bool "Support SATA controllers with driver model" - depends on DM - help - This enables a uclass for disk controllers in U-Boot. Various driver - types can use this, such as AHCI/SATA. It does not provide any standard - operations at present. The block device interface has not been converted - to driver model. - -config DM_SCSI - bool "Support SCSI controllers with driver model" - depends on BLK - help - This option enables the SCSI (Small Computer System Interface) uclass - which supports SCSI and SATA HDDs. For every device configuration - (IDs/LUNs) a block device is created with RAW read/write and - filesystem support. - config BLOCK_CACHE bool "Use block device cache" default n @@ -37,29 +19,6 @@ config BLOCK_CACHE it will prevent repeated reads from directory structures and other filesystem data structures. -menu "SATA/SCSI device support" - -config SATA_CEVA - bool "Ceva Sata controller" - depends on AHCI - depends on DM_SCSI - help - This option enables Ceva Sata controller hard IP available on Xilinx - ZynqMP. Support up to 2 external devices. Complient with SATA 3.1 and - AHCI 1.3 specifications with hot-plug detect feature. - - -config DWC_AHCI - bool "Enable Synopsys DWC AHCI driver support" - select SCSI_AHCI - select PHY - depends on DM_SCSI - help - Enable this driver to support Sata devices through - Synopsys DWC AHCI module. - -endmenu - config IDE bool "Support IDE controllers" help diff --git a/drivers/block/Makefile b/drivers/block/Makefile index adea6c61ea..a5e7307c97 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -11,23 +11,8 @@ ifndef CONFIG_BLK obj-y += blk_legacy.o endif -obj-$(CONFIG_DWC_AHCI) += dwc_ahci.o -obj-$(CONFIG_AHCI) += ahci-uclass.o -obj-$(CONFIG_DM_SCSI) += scsi-uclass.o -obj-$(CONFIG_SCSI_AHCI) += ahci.o -obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o -obj-$(CONFIG_FSL_SATA) += fsl_sata.o obj-$(CONFIG_IDE) += ide.o obj-$(CONFIG_IDE_FTIDE020) += ftide020.o -obj-$(CONFIG_LIBATA) += libata.o -obj-$(CONFIG_MVSATA_IDE) += mvsata_ide.o -obj-$(CONFIG_MX51_PATA) += mxc_ata.o -obj-$(CONFIG_SATA_CEVA) += sata_ceva.o -obj-$(CONFIG_SATA_DWC) += sata_dwc.o -obj-$(CONFIG_SATA_MV) += sata_mv.o -obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o -obj-$(CONFIG_SATA_SIL) += sata_sil.o -obj-$(CONFIG_SANDBOX) += sandbox.o sandbox_scsi.o sata_sandbox.o -obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o +obj-$(CONFIG_SANDBOX) += sandbox.o obj-$(CONFIG_SYSTEMACE) += systemace.o obj-$(CONFIG_BLOCK_CACHE) += blkcache.o diff --git a/drivers/block/scsi-uclass.c b/drivers/block/scsi-uclass.c deleted file mode 100644 index 05da6cdeab..0000000000 --- a/drivers/block/scsi-uclass.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2015 Google, Inc - * Written by Simon Glass <sjg@chromium.org> - * Copyright (c) 2016 Xilinx, Inc - * Written by Michal Simek - * - * Based on ahci-uclass.c - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <dm.h> -#include <scsi.h> - -static int scsi_post_probe(struct udevice *dev) -{ - debug("%s: device %p\n", __func__, dev); - scsi_low_level_init(0, dev); - return 0; -} - -UCLASS_DRIVER(scsi) = { - .id = UCLASS_SCSI, - .name = "scsi", - .post_probe = scsi_post_probe, -}; diff --git a/drivers/block/sym53c8xx.c b/drivers/block/sym53c8xx.c deleted file mode 100644 index 50043e68af..0000000000 --- a/drivers/block/sym53c8xx.c +++ /dev/null @@ -1,851 +0,0 @@ -/* - * (C) Copyright 2001 - * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch. - * - * SPDX-License-Identifier: GPL-2.0+ - * partly derived from - * linux/drivers/scsi/sym53c8xx.c - * - */ - -/* - * SCSI support based on the chip sym53C810. - * - * 09-19-2001 Andreas Heppel, Sysgo RTS GmbH <aheppel@sysgo.de> - * The local version of this driver for the BAB750 board does not - * use interrupts but polls the chip instead (see the call of - * 'handle_scsi_int()' in 'scsi_issue()'. - */ - -#include <common.h> - -#include <command.h> -#include <pci.h> -#include <asm/processor.h> -#include <sym53c8xx.h> -#include <scsi.h> - -#undef SYM53C8XX_DEBUG - -#ifdef SYM53C8XX_DEBUG -#define PRINTF(fmt,args...) printf (fmt ,##args) -#else -#define PRINTF(fmt,args...) -#endif - -#if defined(CONFIG_SCSI) && defined(CONFIG_SCSI_SYM53C8XX) - -#undef SCSI_SINGLE_STEP -/* - * Single Step is only used for debug purposes - */ -#ifdef SCSI_SINGLE_STEP -static unsigned long start_script_select; -static unsigned long start_script_msgout; -static unsigned long start_script_msgin; -static unsigned long start_script_msg_ext; -static unsigned long start_script_cmd; -static unsigned long start_script_data_in; -static unsigned long start_script_data_out; -static unsigned long start_script_status; -static unsigned long start_script_complete; -static unsigned long start_script_error; -static unsigned long start_script_reselection; -static unsigned int len_script_select; -static unsigned int len_script_msgout; -static unsigned int len_script_msgin; -static unsigned int len_script_msg_ext; -static unsigned int len_script_cmd; -static unsigned int len_script_data_in; -static unsigned int len_script_data_out; -static unsigned int len_script_status; -static unsigned int len_script_complete; -static unsigned int len_script_error; -static unsigned int len_script_reselection; -#endif - - -static unsigned short scsi_int_mask; /* shadow register for SCSI related interrupts */ -static unsigned char script_int_mask; /* shadow register for SCRIPT related interrupts */ -static unsigned long script_select[8]; /* script for selection */ -static unsigned long script_msgout[8]; /* script for message out phase (NOT USED) */ -static unsigned long script_msgin[14]; /* script for message in phase */ -static unsigned long script_msg_ext[32]; /* script for message in phase when more than 1 byte message */ -static unsigned long script_cmd[18]; /* script for command phase */ -static unsigned long script_data_in[8]; /* script for data in phase */ -static unsigned long script_data_out[8]; /* script for data out phase */ -static unsigned long script_status[6]; /* script for status phase */ -static unsigned long script_complete[10]; /* script for complete */ -static unsigned long script_reselection[4]; /* script for reselection (NOT USED) */ -static unsigned long script_error[2]; /* script for error handling */ - -static unsigned long int_stat[3]; /* interrupt status */ -static unsigned long scsi_mem_addr; /* base memory address =SCSI_MEM_ADDRESS; */ - -#define bus_to_phys(a) pci_mem_to_phys(busdevfunc, (unsigned long) (a)) -#define phys_to_bus(a) pci_phys_to_mem(busdevfunc, (unsigned long) (a)) - -#define SCSI_MAX_RETRY 3 /* number of retries in scsi_issue() */ - -#define SCSI_MAX_RETRY_NOT_READY 10 /* number of retries when device is not ready */ -#define SCSI_NOT_READY_TIME_OUT 500 /* timeout per retry when not ready */ - -/********************************************************************************* - * forward declerations - */ - -void scsi_chip_init(void); -void handle_scsi_int(void); - - -/******************************************************************************** - * reports SCSI errors to the user - */ -void scsi_print_error (ccb * pccb) -{ - int i; - - printf ("SCSI Error: Target %d LUN %d Command %02X\n", pccb->target, - pccb->lun, pccb->cmd[0]); - printf (" CCB: "); - for (i = 0; i < pccb->cmdlen; i++) - printf ("%02X ", pccb->cmd[i]); - printf ("(len=%d)\n", pccb->cmdlen); - printf (" Cntrl: "); - switch (pccb->contr_stat) { - case SIR_COMPLETE: - printf ("Complete (no Error)\n"); - break; - case SIR_SEL_ATN_NO_MSG_OUT: - printf ("Selected with ATN no MSG out phase\n"); - break; - case SIR_CMD_OUT_ILL_PH: - printf ("Command out illegal phase\n"); - break; - case SIR_MSG_RECEIVED: - printf ("MSG received Error\n"); - break; - case SIR_DATA_IN_ERR: - printf ("Data in Error\n"); - break; - case SIR_DATA_OUT_ERR: - printf ("Data out Error\n"); - break; - case SIR_SCRIPT_ERROR: - printf ("Script Error\n"); - break; - case SIR_MSG_OUT_NO_CMD: - printf ("MSG out no Command phase\n"); - break; - case SIR_MSG_OVER7: - printf ("MSG in over 7 bytes\n"); - break; - case INT_ON_FY: - printf ("Interrupt on fly\n"); - break; - case SCSI_SEL_TIME_OUT: - printf ("SCSI Selection Timeout\n"); - break; - case SCSI_HNS_TIME_OUT: - printf ("SCSI Handshake Timeout\n"); - break; - case SCSI_MA_TIME_OUT: - printf ("SCSI Phase Error\n"); - break; - case SCSI_UNEXP_DIS: - printf ("SCSI unexpected disconnect\n"); - break; - default: - printf ("unknown status %lx\n", pccb->contr_stat); - break; - } - printf (" Sense: SK %x (", pccb->sense_buf[2] & 0x0f); - switch (pccb->sense_buf[2] & 0xf) { - case SENSE_NO_SENSE: - printf ("No Sense)"); - break; - case SENSE_RECOVERED_ERROR: - printf ("Recovered Error)"); - break; - case SENSE_NOT_READY: - printf ("Not Ready)"); - break; - case SENSE_MEDIUM_ERROR: - printf ("Medium Error)"); - break; - case SENSE_HARDWARE_ERROR: - printf ("Hardware Error)"); - break; - case SENSE_ILLEGAL_REQUEST: - printf ("Illegal request)"); - break; - case SENSE_UNIT_ATTENTION: - printf ("Unit Attention)"); - break; - case SENSE_DATA_PROTECT: - printf ("Data Protect)"); - break; - case SENSE_BLANK_CHECK: - printf ("Blank check)"); - break; - case SENSE_VENDOR_SPECIFIC: - printf ("Vendor specific)"); - break; - case SENSE_COPY_ABORTED: - printf ("Copy aborted)"); - break; - case SENSE_ABORTED_COMMAND: - printf ("Aborted Command)"); - break; - case SENSE_VOLUME_OVERFLOW: - printf ("Volume overflow)"); - break; - case SENSE_MISCOMPARE: - printf ("Misscompare\n"); - break; - default: - printf ("Illegal Sensecode\n"); - break; - } - printf (" ASC %x ASCQ %x\n", pccb->sense_buf[12], - pccb->sense_buf[13]); - printf (" Status: "); - switch (pccb->status) { - case S_GOOD: - printf ("Good\n"); - break; - case S_CHECK_COND: - printf ("Check condition\n"); - break; - case S_COND_MET: - printf ("Condition Met\n"); - break; - case S_BUSY: - printf ("Busy\n"); - break; - case S_INT: - printf ("Intermediate\n"); - break; - case S_INT_COND_MET: - printf ("Intermediate condition met\n"); - break; - case S_CONFLICT: - printf ("Reservation conflict\n"); - break; - case S_TERMINATED: - printf ("Command terminated\n"); - break; - case S_QUEUE_FULL: - printf ("Task set full\n"); - break; - default: - printf ("unknown: %02X\n", pccb->status); - break; - } - -} - - -/****************************************************************************** - * sets-up the SCSI controller - * the base memory address is retrieved via the pci_read_config_dword - */ -void scsi_low_level_init(int busdevfunc) -{ - unsigned int cmd; - unsigned int addr; - unsigned char vec; - - pci_read_config_byte(busdevfunc, PCI_INTERRUPT_LINE, &vec); - pci_read_config_dword(busdevfunc, PCI_BASE_ADDRESS_1, &addr); - - addr = bus_to_phys(addr & ~0xf); - - /* - * Enable bus mastering in case this has not been done, yet. - */ - pci_read_config_dword(busdevfunc, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - pci_write_config_dword(busdevfunc, PCI_COMMAND, cmd); - - scsi_mem_addr = addr; - - scsi_chip_init(); - scsi_bus_reset(); -} - - -/************************************************************************************ - * Low level Part of SCSI Driver - */ - -/* - * big-endian -> little endian conversion for the script - */ -unsigned long swap_script(unsigned long val) -{ - return ((val >> 24) & 0xff) | ((val >> 8) & 0xff00) | - ((val << 8) & 0xff0000) | ((val << 24) & 0xff000000); -} - - -void scsi_write_byte(ulong offset,unsigned char val) -{ - out8(scsi_mem_addr+offset,val); -} - - -unsigned char scsi_read_byte(ulong offset) -{ - return(in8(scsi_mem_addr+offset)); -} - - -/******************************************************************************** - * interrupt handler - */ -void handle_scsi_int(void) -{ - unsigned char stat,stat1,stat2; - unsigned short sstat; - int i; -#ifdef SCSI_SINGLE_STEP - unsigned long tt; -#endif - stat=scsi_read_byte(ISTAT); - if((stat & DIP)==DIP) { /* DMA Interrupt pending */ - stat1=scsi_read_byte(DSTAT); -#ifdef SCSI_SINGLE_STEP - if((stat1 & SSI)==SSI) { - tt=in32r(scsi_mem_addr+DSP); - if(((tt)>=start_script_select) && ((tt)<start_script_select+len_script_select)) { - printf("select %d\n",(tt-start_script_select)>>2); - goto end_single; - } - if(((tt)>=start_script_msgout) && ((tt)<start_script_msgout+len_script_msgout)) { - printf("msgout %d\n",(tt-start_script_msgout)>>2); - goto end_single; - } - if(((tt)>=start_script_msgin) && ((tt)<start_script_msgin+len_script_msgin)) { - printf("msgin %d\n",(tt-start_script_msgin)>>2); - goto end_single; - } - if(((tt)>=start_script_msg_ext) && ((tt)<start_script_msg_ext+len_script_msg_ext)) { - printf("msgin_ext %d\n",(tt-start_script_msg_ext)>>2); - goto end_single; - } - if(((tt)>=start_script_cmd) && ((tt)<start_script_cmd+len_script_cmd)) { - printf("cmd %d\n",(tt-start_script_cmd)>>2); - goto end_single; - } - if(((tt)>=start_script_data_in) && ((tt)<start_script_data_in+len_script_data_in)) { - printf("data_in %d\n",(tt-start_script_data_in)>>2); - goto end_single; - } - if(((tt)>=start_script_data_out) && ((tt)<start_script_data_out+len_script_data_out)) { - printf("data_out %d\n",(tt-start_script_data_out)>>2); - goto end_single; - } - if(((tt)>=start_script_status) && ((tt)<start_script_status+len_script_status)) { - printf("status %d\n",(tt-start_script_status)>>2); - goto end_single; - } - if(((tt)>=start_script_complete) && ((tt)<start_script_complete+len_script_complete)) { - printf("complete %d\n",(tt-start_script_complete)>>2); - goto end_single; - } - if(((tt)>=start_script_error) && ((tt)<start_script_error+len_script_error)) { - printf("error %d\n",(tt-start_script_error)>>2); - goto end_single; - } - if(((tt)>=start_script_reselection) && ((tt)<start_script_reselection+len_script_reselection)) { - printf("reselection %d\n",(tt-start_script_reselection)>>2); - goto end_single; - } - printf("sc: %lx\n",tt); -end_single: - stat2=scsi_read_byte(DCNTL); - stat2|=STD; - scsi_write_byte(DCNTL,stat2); - } -#endif - if((stat1 & SIR)==SIR) /* script interrupt */ - { - int_stat[0]=in32(scsi_mem_addr+DSPS); - } - if((stat1 & DFE)==0) { /* fifo not epmty */ - scsi_write_byte(CTEST3,CLF); /* Clear DMA FIFO */ - stat2=scsi_read_byte(STEST3); - scsi_write_byte(STEST3,(stat2 | CSF)); /* Clear SCSI FIFO */ - } - } - if((stat & SIP)==SIP) { /* scsi interrupt */ - sstat = (unsigned short)scsi_read_byte(SIST+1); - sstat <<=8; - sstat |= (unsigned short)scsi_read_byte(SIST); - for(i=0;i<3;i++) { - if(int_stat[i]==0) - break; /* found an empty int status */ - } - int_stat[i]=SCSI_INT_STATE | sstat; - stat1=scsi_read_byte(DSTAT); - if((stat1 & DFE)==0) { /* fifo not epmty */ - scsi_write_byte(CTEST3,CLF); /* Clear DMA FIFO */ - stat2=scsi_read_byte(STEST3); - scsi_write_byte(STEST3,(stat2 | CSF)); /* Clear SCSI FIFO */ - } - } - if((stat & INTF)==INTF) { /* interrupt on Fly */ - scsi_write_byte(ISTAT,stat); /* clear it */ - for(i=0;i<3;i++) { - if(int_stat[i]==0) - break; /* found an empty int status */ - } - int_stat[i]=INT_ON_FY; - } -} - -void scsi_bus_reset(void) -{ - unsigned char t; - int i; - int end = CONFIG_SYS_SCSI_SPIN_UP_TIME*1000; - - t=scsi_read_byte(SCNTL1); - scsi_write_byte(SCNTL1,(t | CRST)); - udelay(50); - scsi_write_byte(SCNTL1,t); - - puts("waiting for devices to spin up"); - for(i=0;i<end;i++) { - udelay(1000); /* give the devices time to spin up */ - if (i % 1000 == 0) - putc('.'); - } - putc('\n'); - scsi_chip_init(); /* reinit the chip ...*/ - -} - -void scsi_int_enable(void) -{ - scsi_write_byte(SIEN,(unsigned char)scsi_int_mask); - scsi_write_byte(SIEN+1,(unsigned char)(scsi_int_mask>>8)); - scsi_write_byte(DIEN,script_int_mask); -} - -void scsi_write_dsp(unsigned long start) -{ -#ifdef SCSI_SINGLE_STEP - unsigned char t; -#endif - out32r(scsi_mem_addr + DSP,start); -#ifdef SCSI_SINGLE_STEP - t=scsi_read_byte(DCNTL); - t|=STD; - scsi_write_byte(DCNTL,t); -#endif -} - -/* only used for debug purposes */ -void scsi_print_script(void) -{ - printf("script_select @ 0x%08lX\n",(unsigned long)&script_select[0]); - printf("script_msgout @ 0x%08lX\n",(unsigned long)&script_msgout[0]); - printf("script_msgin @ 0x%08lX\n",(unsigned long)&script_msgin[0]); - printf("script_msgext @ 0x%08lX\n",(unsigned long)&script_msg_ext[0]); - printf("script_cmd @ 0x%08lX\n",(unsigned long)&script_cmd[0]); - printf("script_data_in @ 0x%08lX\n",(unsigned long)&script_data_in[0]); - printf("script_data_out @ 0x%08lX\n",(unsigned long)&script_data_out[0]); - printf("script_status @ 0x%08lX\n",(unsigned long)&script_status[0]); - printf("script_complete @ 0x%08lX\n",(unsigned long)&script_complete[0]); - printf("script_error @ 0x%08lX\n",(unsigned long)&script_error[0]); -} - - -void scsi_set_script(ccb *pccb) -{ - int busdevfunc = pccb->priv; - int i; - i=0; - script_select[i++]=swap_script(SCR_REG_REG(GPREG, SCR_AND, 0xfe)); - script_select[i++]=0; /* LED ON */ - script_select[i++]=swap_script(SCR_CLR(SCR_TRG)); /* select initiator mode */ - script_select[i++]=0; - /* script_select[i++]=swap_script(SCR_SEL_ABS_ATN | pccb->target << 16); */ - script_select[i++]=swap_script(SCR_SEL_ABS | pccb->target << 16); - script_select[i++]=swap_script(phys_to_bus(&script_cmd[4])); /* error handling */ - script_select[i++]=swap_script(SCR_JUMP); /* next section */ - /* script_select[i++]=swap_script((unsigned long)&script_msgout[0]); */ /* message out */ - script_select[i++]=swap_script(phys_to_bus(&script_cmd[0])); /* command out */ - -#ifdef SCSI_SINGLE_STEP - start_script_select=(unsigned long)&script_select[0]; - len_script_select=i*4; -#endif - - i=0; - script_msgout[i++]=swap_script(SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT))); - script_msgout[i++]=SIR_SEL_ATN_NO_MSG_OUT; - script_msgout[i++]=swap_script( SCR_MOVE_ABS(1) ^ SCR_MSG_OUT); - script_msgout[i++]=swap_script(phys_to_bus(&pccb->msgout[0])); - script_msgout[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_COMMAND))); /* if Command phase */ - script_msgout[i++]=swap_script(phys_to_bus(&script_cmd[0])); /* switch to command */ - script_msgout[i++]=swap_script(SCR_INT); /* interrupt if not */ - script_msgout[i++]=SIR_MSG_OUT_NO_CMD; - -#ifdef SCSI_SINGLE_STEP - start_script_msgout=(unsigned long)&script_msgout[0]; - len_script_msgout=i*4; -#endif - i=0; - script_cmd[i++]=swap_script(SCR_MOVE_ABS(pccb->cmdlen) ^ SCR_COMMAND); - script_cmd[i++]=swap_script(phys_to_bus(&pccb->cmd[0])); - script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN))); /* message in ? */ - script_cmd[i++]=swap_script(phys_to_bus(&script_msgin[0])); - script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT))); /* data out ? */ - script_cmd[i++]=swap_script(phys_to_bus(&script_data_out[0])); - script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN))); /* data in ? */ - script_cmd[i++]=swap_script(phys_to_bus(&script_data_in[0])); - script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_STATUS))); /* status ? */ - script_cmd[i++]=swap_script(phys_to_bus(&script_status[0])); - script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND))); /* command ? */ - script_cmd[i++]=swap_script(phys_to_bus(&script_cmd[0])); - script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT))); /* message out ? */ - script_cmd[i++]=swap_script(phys_to_bus(&script_msgout[0])); - script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_MSG_IN))); /* just for error handling message in ? */ - script_cmd[i++]=swap_script(phys_to_bus(&script_msgin[0])); - script_cmd[i++]=swap_script(SCR_INT); /* interrupt if not */ - script_cmd[i++]=SIR_CMD_OUT_ILL_PH; -#ifdef SCSI_SINGLE_STEP - start_script_cmd=(unsigned long)&script_cmd[0]; - len_script_cmd=i*4; -#endif - i=0; - script_data_out[i++]=swap_script(SCR_MOVE_ABS(pccb->datalen)^ SCR_DATA_OUT); /* move */ - script_data_out[i++]=swap_script(phys_to_bus(pccb->pdata)); /* pointer to buffer */ - script_data_out[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS))); - script_data_out[i++]=swap_script(phys_to_bus(&script_status[0])); - script_data_out[i++]=swap_script(SCR_INT); - script_data_out[i++]=SIR_DATA_OUT_ERR; - -#ifdef SCSI_SINGLE_STEP - start_script_data_out=(unsigned long)&script_data_out[0]; - len_script_data_out=i*4; -#endif - i=0; - script_data_in[i++]=swap_script(SCR_MOVE_ABS(pccb->datalen)^ SCR_DATA_IN); /* move */ - script_data_in[i++]=swap_script(phys_to_bus(pccb->pdata)); /* pointer to buffer */ - script_data_in[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS))); - script_data_in[i++]=swap_script(phys_to_bus(&script_status[0])); - script_data_in[i++]=swap_script(SCR_INT); - script_data_in[i++]=SIR_DATA_IN_ERR; -#ifdef SCSI_SINGLE_STEP - start_script_data_in=(unsigned long)&script_data_in[0]; - len_script_data_in=i*4; -#endif - i=0; - script_msgin[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); - script_msgin[i++]=swap_script(phys_to_bus(&pccb->msgin[0])); - script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE))); - script_msgin[i++]=swap_script(phys_to_bus(&script_complete[0])); - script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT))); - script_msgin[i++]=swap_script(phys_to_bus(&script_complete[0])); - script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP))); - script_msgin[i++]=swap_script(phys_to_bus(&script_complete[0])); - script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP))); - script_msgin[i++]=swap_script(phys_to_bus(&script_complete[0])); - script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED))); - script_msgin[i++]=swap_script(phys_to_bus(&script_msg_ext[0])); - script_msgin[i++]=swap_script(SCR_INT); - script_msgin[i++]=SIR_MSG_RECEIVED; -#ifdef SCSI_SINGLE_STEP - start_script_msgin=(unsigned long)&script_msgin[0]; - len_script_msgin=i*4; -#endif - i=0; - script_msg_ext[i++]=swap_script(SCR_CLR (SCR_ACK)); /* clear ACK */ - script_msg_ext[i++]=0; - script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* assuming this is the msg length */ - script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[1])); - script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); - script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */ - script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */ - script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[2])); - script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); - script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */ - script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */ - script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[3])); - script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); - script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */ - script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */ - script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[4])); - script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); - script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */ - script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */ - script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[5])); - script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); - script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */ - script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */ - script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[6])); - script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); - script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */ - script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */ - script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[7])); - script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); - script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */ - script_msg_ext[i++]=swap_script(SCR_INT); - script_msg_ext[i++]=SIR_MSG_OVER7; -#ifdef SCSI_SINGLE_STEP - start_script_msg_ext=(unsigned long)&script_msg_ext[0]; - len_script_msg_ext=i*4; -#endif - i=0; - script_status[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_STATUS); - script_status[i++]=swap_script(phys_to_bus(&pccb->status)); - script_status[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN))); - script_status[i++]=swap_script(phys_to_bus(&script_msgin[0])); - script_status[i++]=swap_script(SCR_INT); - script_status[i++]=SIR_STATUS_ILL_PH; -#ifdef SCSI_SINGLE_STEP - start_script_status=(unsigned long)&script_status[0]; - len_script_status=i*4; -#endif - i=0; - script_complete[i++]=swap_script(SCR_REG_REG (SCNTL2, SCR_AND, 0x7f)); - script_complete[i++]=0; - script_complete[i++]=swap_script(SCR_CLR (SCR_ACK|SCR_ATN)); - script_complete[i++]=0; - script_complete[i++]=swap_script(SCR_WAIT_DISC); - script_complete[i++]=0; - script_complete[i++]=swap_script(SCR_REG_REG(GPREG, SCR_OR, 0x01)); - script_complete[i++]=0; /* LED OFF */ - script_complete[i++]=swap_script(SCR_INT); - script_complete[i++]=SIR_COMPLETE; -#ifdef SCSI_SINGLE_STEP - start_script_complete=(unsigned long)&script_complete[0]; - len_script_complete=i*4; -#endif - i=0; - script_error[i++]=swap_script(SCR_INT); /* interrupt if error */ - script_error[i++]=SIR_SCRIPT_ERROR; -#ifdef SCSI_SINGLE_STEP - start_script_error=(unsigned long)&script_error[0]; - len_script_error=i*4; -#endif - i=0; - script_reselection[i++]=swap_script(SCR_CLR (SCR_TRG)); /* target status */ - script_reselection[i++]=0; - script_reselection[i++]=swap_script(SCR_WAIT_RESEL); - script_reselection[i++]=swap_script(phys_to_bus(&script_select[0])); /* len = 4 */ -#ifdef SCSI_SINGLE_STEP - start_script_reselection=(unsigned long)&script_reselection[0]; - len_script_reselection=i*4; -#endif -} - - -void scsi_issue(ccb *pccb) -{ - int busdevfunc = pccb->priv; - int i; - unsigned short sstat; - int retrycnt; /* retry counter */ - for(i=0;i<3;i++) - int_stat[i]=0; /* delete all int status */ - /* struct pccb must be set-up correctly */ - retrycnt=0; - PRINTF("ID %d issue cmd %02X\n",pccb->target,pccb->cmd[0]); - pccb->trans_bytes=0; /* no bytes transferred yet */ - scsi_set_script(pccb); /* fill in SCRIPT */ - scsi_int_mask=STO | UDC | MA; /* | CMP; / * Interrupts which are enabled */ - script_int_mask=0xff; /* enable all Ints */ - scsi_int_enable(); - scsi_write_dsp(phys_to_bus(&script_select[0])); /* start script */ - /* now we have to wait for IRQs */ -retry: - /* - * This version of the driver is _not_ interrupt driven, - * but polls the chip's interrupt registers (ISTAT, DSTAT). - */ - while(int_stat[0]==0) - handle_scsi_int(); - - if(int_stat[0]==SIR_COMPLETE) { - if(pccb->msgin[0]==M_DISCONNECT) { - PRINTF("Wait for reselection\n"); - for(i=0;i<3;i++) - int_stat[i]=0; /* delete all int status */ - scsi_write_dsp(phys_to_bus(&script_reselection[0])); /* start reselection script */ - goto retry; - } - pccb->contr_stat=SIR_COMPLETE; - return; - } - if((int_stat[0] & SCSI_INT_STATE)==SCSI_INT_STATE) { /* scsi interrupt */ - sstat=(unsigned short)int_stat[0]; - if((sstat & STO)==STO) { /* selection timeout */ - pccb->contr_stat=SCSI_SEL_TIME_OUT; - scsi_write_byte(GPREG,0x01); - PRINTF("ID: %X Selection Timeout\n",pccb->target); - return; - } - if((sstat & UDC)==UDC) { /* unexpected disconnect */ - pccb->contr_stat=SCSI_UNEXP_DIS; - scsi_write_byte(GPREG,0x01); - PRINTF("ID: %X Unexpected Disconnect\n",pccb->target); - return; - } - if((sstat & RSL)==RSL) { /* reselection */ - pccb->contr_stat=SCSI_UNEXP_DIS; - scsi_write_byte(GPREG,0x01); - PRINTF("ID: %X Unexpected Disconnect\n",pccb->target); - return; - } - if(((sstat & MA)==MA)||((sstat & HTH)==HTH)) { /* phase missmatch */ - if(retrycnt<SCSI_MAX_RETRY) { - pccb->trans_bytes=pccb->datalen - - ((unsigned long)scsi_read_byte(DBC) | - ((unsigned long)scsi_read_byte(DBC+1)<<8) | - ((unsigned long)scsi_read_byte(DBC+2)<<16)); - for(i=0;i<3;i++) - int_stat[i]=0; /* delete all int status */ - retrycnt++; - PRINTF("ID: %X Phase Missmatch Retry %d Phase %02X transferred %lx\n", - pccb->target,retrycnt,scsi_read_byte(SBCL),pccb->trans_bytes); - scsi_write_dsp(phys_to_bus(&script_cmd[4])); /* start retry script */ - goto retry; - } - if((sstat & MA)==MA) - pccb->contr_stat=SCSI_MA_TIME_OUT; - else - pccb->contr_stat=SCSI_HNS_TIME_OUT; - PRINTF("Phase Missmatch stat %lx\n",pccb->contr_stat); - return; - } /* no phase int */ -/* if((sstat & CMP)==CMP) { - pccb->contr_stat=SIR_COMPLETE; - return; - } -*/ - PRINTF("SCSI INT %lX\n",int_stat[0]); - pccb->contr_stat=int_stat[0]; - return; - } /* end scsi int */ - PRINTF("SCRIPT INT %lX phase %02X\n",int_stat[0],scsi_read_byte(SBCL)); - pccb->contr_stat=int_stat[0]; - return; -} - -int scsi_exec(ccb *pccb) -{ - unsigned char tmpcmd[16],tmpstat; - int i,retrycnt,t; - unsigned long transbytes,datalen; - unsigned char *tmpptr; - retrycnt=0; -retry: - scsi_issue(pccb); - if(pccb->contr_stat!=SIR_COMPLETE) - return false; - if(pccb->status==S_GOOD) - return true; - if(pccb->status==S_CHECK_COND) { /* check condition */ - for(i=0;i<16;i++) - tmpcmd[i]=pccb->cmd[i]; - pccb->cmd[0]=SCSI_REQ_SENSE; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=0; - pccb->cmd[3]=0; - pccb->cmd[4]=14; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; - transbytes=pccb->trans_bytes; - tmpptr=pccb->pdata; - pccb->pdata = &pccb->sense_buf[0]; - datalen=pccb->datalen; - pccb->datalen=14; - tmpstat=pccb->status; - scsi_issue(pccb); - for(i=0;i<16;i++) - pccb->cmd[i]=tmpcmd[i]; - pccb->trans_bytes=transbytes; - pccb->pdata=tmpptr; - pccb->datalen=datalen; - pccb->status=tmpstat; - PRINTF("Request_sense sense key %x ASC %x ASCQ %x\n",pccb->sense_buf[2]&0x0f, - pccb->sense_buf[12],pccb->sense_buf[13]); - switch(pccb->sense_buf[2]&0xf) { - case SENSE_NO_SENSE: - case SENSE_RECOVERED_ERROR: - /* seems to be ok */ - return true; - break; - case SENSE_NOT_READY: - if((pccb->sense_buf[12]!=0x04)||(pccb->sense_buf[13]!=0x01)) { - /* if device is not in process of becoming ready */ - return false; - break; - } /* else fall through */ - case SENSE_UNIT_ATTENTION: - if(retrycnt<SCSI_MAX_RETRY_NOT_READY) { - PRINTF("Target %d not ready, retry %d\n",pccb->target,retrycnt); - for(t=0;t<SCSI_NOT_READY_TIME_OUT;t++) - udelay(1000); /* 1sec wait */ - retrycnt++; - goto retry; - } - PRINTF("Target %d not ready, %d retried\n",pccb->target,retrycnt); - return false; - default: - return false; - } - } - PRINTF("Status = %X\n",pccb->status); - return false; -} - - -void scsi_chip_init(void) -{ - /* first we issue a soft reset */ - scsi_write_byte(ISTAT,SRST); - udelay(1000); - scsi_write_byte(ISTAT,0); - /* setup chip */ - scsi_write_byte(SCNTL0,0xC0); /* full arbitration no start, no message, parity disabled, master */ - scsi_write_byte(SCNTL1,0x00); - scsi_write_byte(SCNTL2,0x00); -#ifndef CONFIG_SYS_SCSI_SYM53C8XX_CCF /* config value for none 40 MHz clocks */ - scsi_write_byte(SCNTL3,0x13); /* synchronous clock 40/4=10MHz, asynchronous 40MHz */ -#else - scsi_write_byte(SCNTL3,CONFIG_SYS_SCSI_SYM53C8XX_CCF); /* config value for none 40 MHz clocks */ -#endif - scsi_write_byte(SCID,0x47); /* ID=7, enable reselection */ - scsi_write_byte(SXFER,0x00); /* synchronous transfer period 10MHz, asynchronous */ - scsi_write_byte(SDID,0x00); /* targed SCSI ID = 0 */ - scsi_int_mask=0x0000; /* no Interrupt is enabled */ - script_int_mask=0x00; - scsi_int_enable(); - scsi_write_byte(GPREG,0x01); /* GPIO0 is LED (off) */ - scsi_write_byte(GPCNTL,0x0E); /* GPIO0 is Output */ - scsi_write_byte(STIME0,0x08); /* handshake timer disabled, selection timeout 512msec */ - scsi_write_byte(RESPID,0x80); /* repond only to the own ID (reselection) */ - scsi_write_byte(STEST1,0x00); /* not isolated, SCLK is used */ - scsi_write_byte(STEST2,0x00); /* no Lowlevel Mode? */ - scsi_write_byte(STEST3,0x80); /* enable tolerANT */ - scsi_write_byte(CTEST3,0x04); /* clear FIFO */ - scsi_write_byte(CTEST4,0x00); - scsi_write_byte(CTEST5,0x00); -#ifdef SCSI_SINGLE_STEP -/* scsi_write_byte(DCNTL,IRQM | SSM); */ - scsi_write_byte(DCNTL,IRQD | SSM); - scsi_write_byte(DMODE,MAN); -#else -/* scsi_write_byte(DCNTL,IRQM); */ - scsi_write_byte(DCNTL,IRQD); - scsi_write_byte(DMODE,0x00); -#endif -} -#endif diff --git a/drivers/core/Makefile b/drivers/core/Makefile index 435cf98ae1..fd2d4de0c8 100644 --- a/drivers/core/Makefile +++ b/drivers/core/Makefile @@ -15,4 +15,4 @@ obj-$(CONFIG_OF_LIVE) += of_access.o of_addr.o ifndef CONFIG_DM_DEV_READ_INLINE obj-$(CONFIG_OF_CONTROL) += read.o endif -obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o +obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o diff --git a/drivers/core/dump.c b/drivers/core/dump.c index fd4596ee68..c3e109e7ed 100644 --- a/drivers/core/dump.c +++ b/drivers/core/dump.c @@ -8,6 +8,7 @@ #include <dm.h> #include <mapmem.h> #include <dm/root.h> +#include <dm/util.h> static void show_devices(struct udevice *dev, int depth, int last_flag) { diff --git a/drivers/core/lists.c b/drivers/core/lists.c index b79f26dbe6..6067914e81 100644 --- a/drivers/core/lists.c +++ b/drivers/core/lists.c @@ -141,8 +141,7 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp) name = ofnode_get_name(node); dm_dbg("bind node %s\n", name); - compat_list = (const char *)ofnode_read_prop(node, "compatible", - &compat_length); + compat_list = ofnode_get_property(node, "compatible", &compat_length); if (!compat_list) { if (compat_length == -FDT_ERR_NOTFOUND) { dm_dbg("Device '%s' has no compatible string\n", name); diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c index 93a6560496..2bb23eef88 100644 --- a/drivers/core/of_access.c +++ b/drivers/core/of_access.c @@ -96,6 +96,30 @@ int of_n_size_cells(const struct device_node *np) return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; } +int of_simple_addr_cells(const struct device_node *np) +{ + const __be32 *ip; + + ip = of_get_property(np, "#address-cells", NULL); + if (ip) + return be32_to_cpup(ip); + + /* Return a default of 2 to match fdt_address_cells()*/ + return 2; +} + +int of_simple_size_cells(const struct device_node *np) +{ + const __be32 *ip; + + ip = of_get_property(np, "#size-cells", NULL); + if (ip) + return be32_to_cpup(ip); + + /* Return a default of 2 to match fdt_size_cells()*/ + return 2; +} + struct property *of_find_property(const struct device_node *np, const char *name, int *lenp) { diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index ac312d6546..fd068b06ef 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -23,7 +23,7 @@ int ofnode_read_u32(ofnode node, const char *propname, u32 *outp) if (ofnode_is_np(node)) { return of_read_u32(ofnode_to_np(node), propname, outp); } else { - const int *cell; + const fdt32_t *cell; int len; cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), @@ -57,20 +57,16 @@ int ofnode_read_s32_default(ofnode node, const char *propname, s32 def) bool ofnode_read_bool(ofnode node, const char *propname) { - bool val; + const void *prop; assert(ofnode_valid(node)); debug("%s: %s: ", __func__, propname); - if (ofnode_is_np(node)) { - val = !!of_find_property(ofnode_to_np(node), propname, NULL); - } else { - val = !!fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), - propname, NULL); - } - debug("%s\n", val ? "true" : "false"); + prop = ofnode_get_property(node, propname, NULL); + + debug("%s\n", prop ? "true" : "false"); - return val; + return prop ? true : false; } const char *ofnode_read_string(ofnode node, const char *propname) @@ -260,6 +256,16 @@ int ofnode_read_string_index(ofnode node, const char *property, int index, } } +int ofnode_read_string_count(ofnode node, const char *property) +{ + if (ofnode_is_np(node)) { + return of_property_count_strings(ofnode_to_np(node), property); + } else { + return fdt_stringlist_count(gd->fdt_blob, + ofnode_to_offset(node), property); + } +} + static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in, struct ofnode_phandle_args *out) { @@ -422,19 +428,13 @@ int ofnode_decode_display_timing(ofnode parent, int index, return ret; } -const u32 *ofnode_read_prop(ofnode node, const char *propname, int *lenp) +const void *ofnode_get_property(ofnode node, const char *propname, int *lenp) { - if (ofnode_is_np(node)) { - struct property *prop; - - prop = of_find_property(ofnode_to_np(node), propname, lenp); - if (!prop) - return NULL; - return prop->value; - } else { + if (ofnode_is_np(node)) + return of_get_property(ofnode_to_np(node), propname, lenp); + else return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname, lenp); - } } bool ofnode_is_available(ofnode node) @@ -487,7 +487,7 @@ const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname, int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, const char *propname, struct fdt_pci_addr *addr) { - const u32 *cell; + const fdt32_t *cell; int len; int ret = -ENOENT; @@ -499,7 +499,7 @@ int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, * #size-cells. They need to be 3 and 2 accordingly. However, * for simplicity we skip the check here. */ - cell = ofnode_read_prop(node, propname, &len); + cell = ofnode_get_property(node, propname, &len); if (!cell) goto fail; @@ -542,7 +542,7 @@ int ofnode_read_addr_cells(ofnode node) { if (ofnode_is_np(node)) return of_n_addr_cells(ofnode_to_np(node)); - else + else /* NOTE: this call should walk up the parent stack */ return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node)); } @@ -550,28 +550,44 @@ int ofnode_read_size_cells(ofnode node) { if (ofnode_is_np(node)) return of_n_size_cells(ofnode_to_np(node)); + else /* NOTE: this call should walk up the parent stack */ + return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node)); +} + +int ofnode_read_simple_addr_cells(ofnode node) +{ + if (ofnode_is_np(node)) + return of_simple_addr_cells(ofnode_to_np(node)); + else + return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node)); +} + +int ofnode_read_simple_size_cells(ofnode node) +{ + if (ofnode_is_np(node)) + return of_simple_size_cells(ofnode_to_np(node)); else return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node)); } bool ofnode_pre_reloc(ofnode node) { - if (ofnode_read_prop(node, "u-boot,dm-pre-reloc", NULL)) + if (ofnode_read_bool(node, "u-boot,dm-pre-reloc")) return true; #ifdef CONFIG_TPL_BUILD - if (ofnode_read_prop(node, "u-boot,dm-tpl", NULL)) + if (ofnode_read_bool(node, "u-boot,dm-tpl")) return true; #elif defined(CONFIG_SPL_BUILD) - if (ofnode_read_prop(node, "u-boot,dm-spl", NULL)) + if (ofnode_read_bool(node, "u-boot,dm-spl")) return true; #else /* * In regular builds individual spl and tpl handling both * count as handled pre-relocation for later second init. */ - if (ofnode_read_prop(node, "u-boot,dm-spl", NULL) || - ofnode_read_prop(node, "u-boot,dm-tpl", NULL)) + if (ofnode_read_bool(node, "u-boot,dm-spl") || + ofnode_read_bool(node, "u-boot,dm-tpl")) return true; #endif diff --git a/drivers/core/read.c b/drivers/core/read.c index 3131e5379c..eafe727f03 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -94,6 +94,16 @@ int dev_read_size_cells(struct udevice *dev) return ofnode_read_size_cells(dev_ofnode(dev)); } +int dev_read_simple_addr_cells(struct udevice *dev) +{ + return ofnode_read_simple_addr_cells(dev_ofnode(dev)); +} + +int dev_read_simple_size_cells(struct udevice *dev) +{ + return ofnode_read_simple_size_cells(dev_ofnode(dev)); +} + int dev_read_phandle(struct udevice *dev) { ofnode node = dev_ofnode(dev); @@ -106,7 +116,7 @@ int dev_read_phandle(struct udevice *dev) const u32 *dev_read_prop(struct udevice *dev, const char *propname, int *lenp) { - return ofnode_read_prop(dev_ofnode(dev), propname, lenp); + return ofnode_get_property(dev_ofnode(dev), propname, lenp); } int dev_read_alias_seq(struct udevice *dev, int *devnump) @@ -138,3 +148,14 @@ const uint8_t *dev_read_u8_array_ptr(struct udevice *dev, const char *propname, { return ofnode_read_u8_array_ptr(dev_ofnode(dev), propname, sz); } + +int dev_read_enabled(struct udevice *dev) +{ + ofnode node = dev_ofnode(dev); + + if (ofnode_is_np(node)) + return of_device_is_available(ofnode_to_np(node)); + else + return fdtdec_get_is_enabled(gd->fdt_blob, + ofnode_to_offset(node)); +} diff --git a/drivers/core/read_extra.c b/drivers/core/read_extra.c new file mode 100644 index 0000000000..a6d2f342d9 --- /dev/null +++ b/drivers/core/read_extra.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <dm/of_addr.h> +#include <dm/read.h> +#include <linux/ioport.h> + +int dev_read_resource(struct udevice *dev, uint index, struct resource *res) +{ + ofnode node = dev_ofnode(dev); + +#ifdef CONFIG_OF_LIVE + if (ofnode_is_np(node)) { + return of_address_to_resource(ofnode_to_np(node), index, res); + } else +#endif + { + struct fdt_resource fres; + int ret; + + ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node), + "reg", index, &fres); + if (ret < 0) + return -EINVAL; + memset(res, '\0', sizeof(*res)); + res->start = fres.start; + res->end = fres.end; + + return 0; + } +} diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index 749d913372..d4e16a27ef 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -72,8 +72,8 @@ int regmap_init_mem(struct udevice *dev, struct regmap **mapp) ofnode node = dev_ofnode(dev); struct resource r; - addr_len = dev_read_addr_cells(dev->parent); - size_len = dev_read_size_cells(dev->parent); + addr_len = dev_read_simple_addr_cells(dev->parent); + size_len = dev_read_simple_size_cells(dev->parent); both_len = addr_len + size_len; len = dev_read_size(dev, "reg"); diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 21dc696da3..f5e4067922 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -366,8 +366,7 @@ int uclass_get_device_by_driver(enum uclass_id id, return -ENODEV; } -int uclass_get_device_tail(struct udevice *dev, int ret, - struct udevice **devp) +int uclass_get_device_tail(struct udevice *dev, int ret, struct udevice **devp) { if (ret) return ret; @@ -493,6 +492,33 @@ int uclass_next_device(struct udevice **devp) return uclass_get_device_tail(dev, ret, devp); } +int uclass_first_device_check(enum uclass_id id, struct udevice **devp) +{ + int ret; + + *devp = NULL; + ret = uclass_find_first_device(id, devp); + if (ret) + return ret; + if (!*devp) + return 0; + + return device_probe(*devp); +} + +int uclass_next_device_check(struct udevice **devp) +{ + int ret; + + ret = uclass_find_next_device(devp); + if (ret) + return ret; + if (!*devp) + return 0; + + return device_probe(*devp); +} + int uclass_bind_device(struct udevice *dev) { struct uclass *uc; diff --git a/drivers/core/util.c b/drivers/core/util.c index 5ceac8bbb1..2e232d57a1 100644 --- a/drivers/core/util.c +++ b/drivers/core/util.c @@ -5,9 +5,11 @@ */ #include <common.h> +#include <dm/util.h> #include <libfdt.h> #include <vsprintf.h> +#ifdef CONFIG_DM_WARN void dm_warn(const char *fmt, ...) { va_list args; @@ -16,7 +18,9 @@ void dm_warn(const char *fmt, ...) vprintf(fmt, args); va_end(args); } +#endif +#ifdef DEBUG void dm_dbg(const char *fmt, ...) { va_list args; @@ -25,6 +29,7 @@ void dm_dbg(const char *fmt, ...) vprintf(fmt, args); va_end(args); } +#endif int list_count_items(struct list_head *head) { diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index c96e26e6b7..5924adee40 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -197,7 +197,7 @@ static int keyscan_read_fdt_matrix(struct ec_state *ec, ofnode node) int upto; int len; - cell = ofnode_read_prop(node, "linux,keymap", &len); + cell = ofnode_get_property(node, "linux,keymap", &len); ec->matrix_count = len / 4; ec->matrix = calloc(ec->matrix_count, sizeof(*ec->matrix)); if (!ec->matrix) { diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index b36ef3338c..86df141d60 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -763,12 +763,12 @@ static int decode_regions(struct pci_controller *hose, ofnode parent_node, int len; int i; - prop = ofnode_read_prop(node, "ranges", &len); + prop = ofnode_get_property(node, "ranges", &len); if (!prop) return -EINVAL; - pci_addr_cells = ofnode_read_addr_cells(node); - addr_cells = ofnode_read_addr_cells(parent_node); - size_cells = ofnode_read_size_cells(node); + pci_addr_cells = ofnode_read_simple_addr_cells(node); + addr_cells = ofnode_read_simple_addr_cells(parent_node); + size_cells = ofnode_read_simple_size_cells(node); /* PCI addresses are always 3-cells */ len /= sizeof(u32); diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index 02e269020d..114952a1da 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -134,7 +134,7 @@ static int pinconfig_post_bind(struct udevice *dev) * If this node has "compatible" property, this is not * a pin configuration node, but a normal device. skip. */ - ofnode_read_prop(node, "compatible", &ret); + ofnode_get_property(node, "compatible", &ret); if (ret >= 0) continue; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig new file mode 100644 index 0000000000..db1606e3ce --- /dev/null +++ b/drivers/scsi/Kconfig @@ -0,0 +1,17 @@ +config SCSI + bool "Support SCSI controllers" + help + This enables support for SCSI (Small Computer System Interface), + a parallel interface widely used with storage peripherals such as + hard drives and optical drives. The SCSI standards define physical + interfaces as well as protocols for controlling devices and + tranferring data. + +config DM_SCSI + bool "Support SCSI controllers with driver model" + depends on BLK + help + This option enables the SCSI (Small Computer System Interface) uclass + which supports SCSI and SATA HDDs. For every device configuration + (IDs/LUNs) a block device is created with RAW read/write and + filesystem support. diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile new file mode 100644 index 0000000000..9e23699b68 --- /dev/null +++ b/drivers/scsi/Makefile @@ -0,0 +1,20 @@ +# +# (C) Copyright 2000-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_DM_SCSI) += scsi-uclass.o +obj-$(CONFIG_SCSI) += scsi.o +endif + +ifdef CONFIG_SPL_BUILD +ifdef CONFIG_SPL_SATA_SUPPORT +obj-$(CONFIG_DM_SCSI) += scsi-uclass.o +obj-$(CONFIG_SCSI) += scsi.o +endif +endif + +obj-$(CONFIG_SANDBOX) += sandbox_scsi.o diff --git a/drivers/block/sandbox_scsi.c b/drivers/scsi/sandbox_scsi.c index ad961bd225..ac60ae01ca 100644 --- a/drivers/block/sandbox_scsi.c +++ b/drivers/scsi/sandbox_scsi.c @@ -11,19 +11,16 @@ #include <common.h> #include <scsi.h> -void scsi_bus_reset(void) +int scsi_bus_reset(struct udevice *dev) { + return 0; } void scsi_init(void) { } -int scsi_exec(ccb *pccb) +int scsi_exec(struct udevice *dev, struct scsi_cmd *pccb) { return 0; } - -void scsi_print_error(ccb *pccb) -{ -} diff --git a/drivers/scsi/scsi-uclass.c b/drivers/scsi/scsi-uclass.c new file mode 100644 index 0000000000..31e8999297 --- /dev/null +++ b/drivers/scsi/scsi-uclass.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * Copyright (c) 2016 Xilinx, Inc + * Written by Michal Simek + * + * Based on ahci-uclass.c + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <scsi.h> + +int scsi_exec(struct udevice *dev, struct scsi_cmd *pccb) +{ + struct scsi_ops *ops = scsi_get_ops(dev); + + if (!ops->exec) + return -ENOSYS; + + return ops->exec(dev, pccb); +} + +int scsi_bus_reset(struct udevice *dev) +{ + struct scsi_ops *ops = scsi_get_ops(dev); + + if (!ops->bus_reset) + return -ENOSYS; + + return ops->bus_reset(dev); +} + +UCLASS_DRIVER(scsi) = { + .id = UCLASS_SCSI, + .name = "scsi", + .per_device_platdata_auto_alloc_size = sizeof(struct scsi_platdata), +}; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c new file mode 100644 index 0000000000..7ec7ecc295 --- /dev/null +++ b/drivers/scsi/scsi.c @@ -0,0 +1,709 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <inttypes.h> +#include <pci.h> +#include <scsi.h> +#include <dm/device-internal.h> +#include <dm/uclass-internal.h> + +#if !defined(CONFIG_DM_SCSI) +# ifdef CONFIG_SCSI_DEV_LIST +# define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST +# else +# ifdef CONFIG_SATA_ULI5288 + +# define SCSI_VEND_ID 0x10b9 +# define SCSI_DEV_ID 0x5288 + +# elif !defined(CONFIG_SCSI_AHCI_PLAT) +# error no scsi device defined +# endif +# define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID} +# endif +#endif + +#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) && \ + !defined(CONFIG_DM_SCSI) +const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST }; +#endif +static struct scsi_cmd tempccb; /* temporary scsi command buffer */ + +static unsigned char tempbuff[512]; /* temporary data buffer */ + +#if !defined(CONFIG_DM_SCSI) +static int scsi_max_devs; /* number of highest available scsi device */ + +static int scsi_curr_dev; /* current device */ + +static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; +#endif + +/* almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_READ_BLK 0xFFFF +#define SCSI_LBA48_READ 0xFFFFFFF + +static void scsi_print_error(struct scsi_cmd *pccb) +{ + /* Dummy function that could print an error for debugging */ +} + +#ifdef CONFIG_SYS_64BIT_LBA +void scsi_setup_read16(struct scsi_cmd *pccb, lbaint_t start, + unsigned long blocks) +{ + pccb->cmd[0] = SCSI_READ16; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff; + pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff; + pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[9] = (unsigned char)start & 0xff; + pccb->cmd[10] = 0; + pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff; + pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff; + pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff; + pccb->cmd[14] = (unsigned char)blocks & 0xff; + pccb->cmd[15] = 0; + pccb->cmdlen = 16; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], + pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); +} +#endif + +static void scsi_setup_read_ext(struct scsi_cmd *pccb, lbaint_t start, + unsigned short blocks) +{ + pccb->cmd[0] = SCSI_READ10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[5] = (unsigned char)start & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[6] = 0; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[7], pccb->cmd[8]); +} + +static void scsi_setup_write_ext(struct scsi_cmd *pccb, lbaint_t start, + unsigned short blocks) +{ + pccb->cmd[0] = SCSI_WRITE10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[5] = (unsigned char)start & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[9] = 0; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", + __func__, + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[7], pccb->cmd[8]); +} + +static void scsi_setup_inquiry(struct scsi_cmd *pccb) +{ + pccb->cmd[0] = SCSI_INQUIRY; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = 0; + pccb->cmd[3] = 0; + if (pccb->datalen > 255) + pccb->cmd[4] = 255; + else + pccb->cmd[4] = (unsigned char)pccb->datalen; + pccb->cmd[5] = 0; + pccb->cmdlen = 6; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ +} + +#ifdef CONFIG_BLK +static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +#else +static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, + lbaint_t blkcnt, void *buffer) +#endif +{ +#ifdef CONFIG_BLK + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); + struct udevice *bdev = dev->parent; +#else + struct udevice *bdev = NULL; +#endif + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks = 0; + struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb; + + /* Setup device */ + pccb->target = block_dev->target; + pccb->lun = block_dev->lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; + debug("\nscsi_read: dev %d startblk " LBAF + ", blccnt " LBAF " buffer %lx\n", + block_dev->devnum, start, blks, (unsigned long)buffer); + do { + pccb->pdata = (unsigned char *)buf_addr; +#ifdef CONFIG_SYS_64BIT_LBA + if (start > SCSI_LBA48_READ) { + unsigned long blocks; + blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); + pccb->datalen = block_dev->blksz * blocks; + scsi_setup_read16(pccb, start, blocks); + start += blocks; + blks -= blocks; + } else +#endif + if (blks > SCSI_MAX_READ_BLK) { + pccb->datalen = block_dev->blksz * + SCSI_MAX_READ_BLK; + smallblks = SCSI_MAX_READ_BLK; + scsi_setup_read_ext(pccb, start, smallblks); + start += SCSI_MAX_READ_BLK; + blks -= SCSI_MAX_READ_BLK; + } else { + pccb->datalen = block_dev->blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_read_ext(pccb, start, smallblks); + start += blks; + blks = 0; + } + debug("scsi_read_ext: startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", + start, smallblks, buf_addr); + if (scsi_exec(bdev, pccb)) { + scsi_print_error(pccb); + blkcnt -= blks; + break; + } + buf_addr += pccb->datalen; + } while (blks != 0); + debug("scsi_read_ext: end startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); + return blkcnt; +} + +/******************************************************************************* + * scsi_write + */ + +/* Almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_WRITE_BLK 0xFFFF + +#ifdef CONFIG_BLK +static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +#else +static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, + lbaint_t blkcnt, const void *buffer) +#endif +{ +#ifdef CONFIG_BLK + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); + struct udevice *bdev = dev->parent; +#else + struct udevice *bdev = NULL; +#endif + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks; + struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb; + + /* Setup device */ + pccb->target = block_dev->target; + pccb->lun = block_dev->lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; + debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", + __func__, block_dev->devnum, start, blks, (unsigned long)buffer); + do { + pccb->pdata = (unsigned char *)buf_addr; + if (blks > SCSI_MAX_WRITE_BLK) { + pccb->datalen = (block_dev->blksz * + SCSI_MAX_WRITE_BLK); + smallblks = SCSI_MAX_WRITE_BLK; + scsi_setup_write_ext(pccb, start, smallblks); + start += SCSI_MAX_WRITE_BLK; + blks -= SCSI_MAX_WRITE_BLK; + } else { + pccb->datalen = block_dev->blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_write_ext(pccb, start, smallblks); + start += blks; + blks = 0; + } + debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + if (scsi_exec(bdev, pccb)) { + scsi_print_error(pccb); + blkcnt -= blks; + break; + } + buf_addr += pccb->datalen; + } while (blks != 0); + debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + return blkcnt; +} + +#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) && \ + !defined(CONFIG_DM_SCSI) +void scsi_init(void) +{ + int busdevfunc = -1; + int i; + /* + * Find a device from the list, this driver will support a single + * controller. + */ + for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { + /* get PCI Device ID */ +#ifdef CONFIG_DM_PCI + struct udevice *dev; + int ret; + + ret = dm_pci_find_device(scsi_device_list[i].vendor, + scsi_device_list[i].device, 0, &dev); + if (!ret) { + busdevfunc = dm_pci_get_bdf(dev); + break; + } +#else + busdevfunc = pci_find_device(scsi_device_list[i].vendor, + scsi_device_list[i].device, + 0); +#endif + if (busdevfunc != -1) + break; + } + + if (busdevfunc == -1) { + printf("Error: SCSI Controller(s) "); + for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { + printf("%04X:%04X ", + scsi_device_list[i].vendor, + scsi_device_list[i].device); + } + printf("not found\n"); + return; + } +#ifdef DEBUG + else { + printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n", + scsi_device_list[i].vendor, + scsi_device_list[i].device, + (busdevfunc >> 16) & 0xFF, + (busdevfunc >> 11) & 0x1F, + (busdevfunc >> 8) & 0x7); + } +#endif + bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci"); + scsi_low_level_init(busdevfunc); + scsi_scan(true); + bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI); +} +#endif + +/* copy src to dest, skipping leading and trailing blanks + * and null terminate the string + */ +static void scsi_ident_cpy(unsigned char *dest, unsigned char *src, + unsigned int len) +{ + int start, end; + + start = 0; + while (start < len) { + if (src[start] != ' ') + break; + start++; + } + end = len-1; + while (end > start) { + if (src[end] != ' ') + break; + end--; + } + for (; start <= end; start++) + *dest ++= src[start]; + *dest = '\0'; +} + +static int scsi_read_capacity(struct udevice *dev, struct scsi_cmd *pccb, + lbaint_t *capacity, unsigned long *blksz) +{ + *capacity = 0; + + memset(pccb->cmd, '\0', sizeof(pccb->cmd)); + pccb->cmd[0] = SCSI_RD_CAPAC10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + + pccb->datalen = 8; + if (scsi_exec(dev, pccb)) + return 1; + + *capacity = ((lbaint_t)pccb->pdata[0] << 24) | + ((lbaint_t)pccb->pdata[1] << 16) | + ((lbaint_t)pccb->pdata[2] << 8) | + ((lbaint_t)pccb->pdata[3]); + + if (*capacity != 0xffffffff) { + /* Read capacity (10) was sufficient for this drive. */ + *blksz = ((unsigned long)pccb->pdata[4] << 24) | + ((unsigned long)pccb->pdata[5] << 16) | + ((unsigned long)pccb->pdata[6] << 8) | + ((unsigned long)pccb->pdata[7]); + return 0; + } + + /* Read capacity (10) was insufficient. Use read capacity (16). */ + memset(pccb->cmd, '\0', sizeof(pccb->cmd)); + pccb->cmd[0] = SCSI_RD_CAPAC16; + pccb->cmd[1] = 0x10; + pccb->cmdlen = 16; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + + pccb->datalen = 16; + if (scsi_exec(dev, pccb)) + return 1; + + *capacity = ((uint64_t)pccb->pdata[0] << 56) | + ((uint64_t)pccb->pdata[1] << 48) | + ((uint64_t)pccb->pdata[2] << 40) | + ((uint64_t)pccb->pdata[3] << 32) | + ((uint64_t)pccb->pdata[4] << 24) | + ((uint64_t)pccb->pdata[5] << 16) | + ((uint64_t)pccb->pdata[6] << 8) | + ((uint64_t)pccb->pdata[7]); + + *blksz = ((uint64_t)pccb->pdata[8] << 56) | + ((uint64_t)pccb->pdata[9] << 48) | + ((uint64_t)pccb->pdata[10] << 40) | + ((uint64_t)pccb->pdata[11] << 32) | + ((uint64_t)pccb->pdata[12] << 24) | + ((uint64_t)pccb->pdata[13] << 16) | + ((uint64_t)pccb->pdata[14] << 8) | + ((uint64_t)pccb->pdata[15]); + + return 0; +} + + +/* + * Some setup (fill-in) routines + */ +static void scsi_setup_test_unit_ready(struct scsi_cmd *pccb) +{ + pccb->cmd[0] = SCSI_TST_U_RDY; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = 0; + pccb->cmd[3] = 0; + pccb->cmd[4] = 0; + pccb->cmd[5] = 0; + pccb->cmdlen = 6; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ +} + +/** + * scsi_init_dev_desc_priv - initialize only SCSI specific blk_desc properties + * + * @dev_desc: Block device description pointer + */ +static void scsi_init_dev_desc_priv(struct blk_desc *dev_desc) +{ + dev_desc->target = 0xff; + dev_desc->lun = 0xff; + dev_desc->log2blksz = + LOG2_INVALID(typeof(dev_desc->log2blksz)); + dev_desc->type = DEV_TYPE_UNKNOWN; + dev_desc->vendor[0] = 0; + dev_desc->product[0] = 0; + dev_desc->revision[0] = 0; + dev_desc->removable = false; +#ifndef CONFIG_BLK + dev_desc->block_read = scsi_read; + dev_desc->block_write = scsi_write; +#endif +} + +#if !defined(CONFIG_DM_SCSI) +/** + * scsi_init_dev_desc - initialize all SCSI specific blk_desc properties + * + * @dev_desc: Block device description pointer + * @devnum: Device number + */ +static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum) +{ + dev_desc->lba = 0; + dev_desc->blksz = 0; + dev_desc->if_type = IF_TYPE_SCSI; + dev_desc->devnum = devnum; + dev_desc->part_type = PART_TYPE_UNKNOWN; + + scsi_init_dev_desc_priv(dev_desc); +} +#endif + +/** + * scsi_detect_dev - Detect scsi device + * + * @target: target id + * @lun: target lun + * @dev_desc: block device description + * + * The scsi_detect_dev detects and fills a dev_desc structure when the device is + * detected. + * + * Return: 0 on success, error value otherwise + */ +static int scsi_detect_dev(struct udevice *dev, int target, int lun, + struct blk_desc *dev_desc) +{ + unsigned char perq, modi; + lbaint_t capacity; + unsigned long blksz; + struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb; + + pccb->target = target; + pccb->lun = lun; + pccb->pdata = (unsigned char *)&tempbuff; + pccb->datalen = 512; + scsi_setup_inquiry(pccb); + if (scsi_exec(dev, pccb)) { + if (pccb->contr_stat == SCSI_SEL_TIME_OUT) { + /* + * selection timeout => assuming no + * device present + */ + debug("Selection timeout ID %d\n", + pccb->target); + return -ETIMEDOUT; + } + scsi_print_error(pccb); + return -ENODEV; + } + perq = tempbuff[0]; + modi = tempbuff[1]; + if ((perq & 0x1f) == 0x1f) + return -ENODEV; /* skip unknown devices */ + if ((modi & 0x80) == 0x80) /* drive is removable */ + dev_desc->removable = true; + /* get info for this device */ + scsi_ident_cpy((unsigned char *)dev_desc->vendor, + &tempbuff[8], 8); + scsi_ident_cpy((unsigned char *)dev_desc->product, + &tempbuff[16], 16); + scsi_ident_cpy((unsigned char *)dev_desc->revision, + &tempbuff[32], 4); + dev_desc->target = pccb->target; + dev_desc->lun = pccb->lun; + + pccb->datalen = 0; + scsi_setup_test_unit_ready(pccb); + if (scsi_exec(dev, pccb)) { + if (dev_desc->removable) { + dev_desc->type = perq; + goto removable; + } + scsi_print_error(pccb); + return -EINVAL; + } + if (scsi_read_capacity(dev, pccb, &capacity, &blksz)) { + scsi_print_error(pccb); + return -EINVAL; + } + dev_desc->lba = capacity; + dev_desc->blksz = blksz; + dev_desc->log2blksz = LOG2(dev_desc->blksz); + dev_desc->type = perq; +removable: + return 0; +} + +/* + * (re)-scan the scsi bus and reports scsi device info + * to the user if mode = 1 + */ +#if defined(CONFIG_DM_SCSI) +static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose) +{ + int ret; + struct udevice *bdev; + struct blk_desc bd; + struct blk_desc *bdesc; + char str[10]; + + /* + * detect the scsi driver to get information about its geometry (block + * size, number of blocks) and other parameters (ids, type, ...) + */ + scsi_init_dev_desc_priv(&bd); + if (scsi_detect_dev(dev, id, lun, &bd)) + return -ENODEV; + + /* + * Create only one block device and do detection + * to make sure that there won't be a lot of + * block devices created + */ + snprintf(str, sizeof(str), "id%dlun%d", id, lun); + ret = blk_create_devicef(dev, "scsi_blk", str, IF_TYPE_SCSI, -1, + bd.blksz, bd.blksz * bd.lba, &bdev); + if (ret) { + debug("Can't create device\n"); + return ret; + } + + bdesc = dev_get_uclass_platdata(bdev); + bdesc->target = id; + bdesc->lun = lun; + bdesc->removable = bd.removable; + bdesc->type = bd.type; + memcpy(&bdesc->vendor, &bd.vendor, sizeof(bd.vendor)); + memcpy(&bdesc->product, &bd.product, sizeof(bd.product)); + memcpy(&bdesc->revision, &bd.revision, sizeof(bd.revision)); + part_init(bdesc); + + if (verbose) { + printf(" Device %d: ", 0); + dev_print(bdesc); + } + return 0; +} + +int scsi_scan_dev(struct udevice *dev, bool verbose) +{ + struct scsi_platdata *uc_plat; /* scsi controller platdata */ + int ret; + int i; + int lun; + + /* probe SCSI controller driver */ + ret = device_probe(dev); + if (ret) + return ret; + + /* Get controller platdata */ + uc_plat = dev_get_uclass_platdata(dev); + + for (i = 0; i < uc_plat->max_id; i++) + for (lun = 0; lun < uc_plat->max_lun; lun++) + do_scsi_scan_one(dev, i, lun, verbose); + + return 0; +} + +int scsi_scan(bool verbose) +{ + struct uclass *uc; + struct udevice *dev; /* SCSI controller */ + int ret; + + if (verbose) + printf("scanning bus for devices...\n"); + + blk_unbind_all(IF_TYPE_SCSI); + + ret = uclass_get(UCLASS_SCSI, &uc); + if (ret) + return ret; + + uclass_foreach_dev(dev, uc) { + ret = scsi_scan_dev(dev, verbose); + if (ret) + return ret; + } + + return 0; +} +#else +int scsi_scan(bool verbose) +{ + unsigned char i, lun; + int ret; + + if (verbose) + printf("scanning bus for devices...\n"); + for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++) + scsi_init_dev_desc(&scsi_dev_desc[i], i); + + scsi_max_devs = 0; + for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { + for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) { + ret = scsi_detect_dev(NULL, i, lun, + &scsi_dev_desc[scsi_max_devs]); + if (ret) + continue; + part_init(&scsi_dev_desc[scsi_max_devs]); + + if (verbose) { + printf(" Device %d: ", 0); + dev_print(&scsi_dev_desc[scsi_max_devs]); + } + scsi_max_devs++; + } /* next LUN */ + } + if (scsi_max_devs > 0) + scsi_curr_dev = 0; + else + scsi_curr_dev = -1; + + printf("Found %d device(s).\n", scsi_max_devs); +#ifndef CONFIG_SPL_BUILD + setenv_ulong("scsidevs", scsi_max_devs); +#endif + return 0; +} +#endif + +#ifdef CONFIG_BLK +static const struct blk_ops scsi_blk_ops = { + .read = scsi_read, + .write = scsi_write, +}; + +U_BOOT_DRIVER(scsi_blk) = { + .name = "scsi_blk", + .id = UCLASS_BLK, + .ops = &scsi_blk_ops, +}; +#else +U_BOOT_LEGACY_BLK(scsi) = { + .if_typename = "scsi", + .if_type = IF_TYPE_SCSI, + .max_devs = CONFIG_SYS_SCSI_MAX_DEVICE, + .desc = scsi_dev_desc, +}; +#endif diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index e0e70244ce..c702304e79 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -8,7 +8,6 @@ #include <clk.h> #include <dm.h> #include <errno.h> -#include <fdtdec.h> #include <ns16550.h> #include <serial.h> #include <watchdog.h> @@ -395,7 +394,7 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev) int err; /* try Processor Local Bus device first */ - addr = devfdt_get_addr(dev); + addr = dev_read_addr(dev); #if defined(CONFIG_PCI) && defined(CONFIG_DM_PCI) if (addr == FDT_ADDR_T_NONE) { /* then try pci device */ diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 200f4b9fd7..f360534683 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -8,13 +8,13 @@ #include <dm.h> #include <environment.h> #include <errno.h> -#include <fdtdec.h> #include <os.h> #include <serial.h> #include <stdio_dev.h> #include <watchdog.h> #include <dm/lists.h> #include <dm/device-internal.h> +#include <dm/of_access.h> DECLARE_GLOBAL_DATA_PTR; @@ -27,11 +27,53 @@ static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE; #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work" #endif +static int serial_check_stdout(const void *blob, struct udevice **devp) +{ + int node; + + /* Check for a chosen console */ + node = fdtdec_get_chosen_node(blob, "stdout-path"); + if (node < 0) { + const char *str, *p, *name; + + /* + * Deal with things like + * stdout-path = "serial0:115200n8"; + * + * We need to look up the alias and then follow it to the + * correct node. + */ + str = fdtdec_get_chosen_prop(blob, "stdout-path"); + if (str) { + p = strchr(str, ':'); + name = fdt_get_alias_namelen(blob, str, + p ? p - str : strlen(str)); + if (name) + node = fdt_path_offset(blob, name); + } + } + if (node < 0) + node = fdt_path_offset(blob, "console"); + if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, devp)) + return 0; + + /* + * If the console is not marked to be bound before relocation, bind it + * anyway. + */ + if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node), + devp)) { + if (!device_probe(*devp)) + return 0; + } + + return -ENODEV; +} + static void serial_find_console_or_panic(void) { const void *blob = gd->fdt_blob; struct udevice *dev; - int node; if (CONFIG_IS_ENABLED(OF_PLATDATA)) { uclass_first_device(UCLASS_SERIAL, &dev); @@ -40,43 +82,17 @@ static void serial_find_console_or_panic(void) return; } } else if (CONFIG_IS_ENABLED(OF_CONTROL) && blob) { - /* Check for a chosen console */ - node = fdtdec_get_chosen_node(blob, "stdout-path"); - if (node < 0) { - const char *str, *p, *name; - - /* - * Deal with things like - * stdout-path = "serial0:115200n8"; - * - * We need to look up the alias and then follow it to - * the correct node. - */ - str = fdtdec_get_chosen_prop(blob, "stdout-path"); - if (str) { - p = strchr(str, ':'); - name = fdt_get_alias_namelen(blob, str, - p ? p - str : strlen(str)); - if (name) - node = fdt_path_offset(blob, name); - } - } - if (node < 0) - node = fdt_path_offset(blob, "console"); - if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, - &dev)) { - gd->cur_serial_dev = dev; - return; - } + /* Live tree has support for stdout */ + if (of_live_active()) { + struct device_node *np = of_get_stdout(); - /* - * If the console is not marked to be bound before relocation, - * bind it anyway. - */ - if (node > 0 && - !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node), - &dev)) { - if (!device_probe(dev)) { + if (np && !uclass_get_device_by_ofnode(UCLASS_SERIAL, + np_to_ofnode(np), &dev)) { + gd->cur_serial_dev = dev; + return; + } + } else { + if (!serial_check_stdout(blob, &dev)) { gd->cur_serial_dev = dev; return; } diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index 73fa82b8e6..98d20c0bc1 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -244,7 +244,7 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, struct sandbox_flash_priv *priv, const void *buff, int len) { - const struct SCSI_cmd_block *req = buff; + const struct scsi_cmd *req = buff; switch (*req->cmd) { case SCSI_INQUIRY: { diff --git a/drivers/video/pwm_backlight.c b/drivers/video/pwm_backlight.c index 3697f4905c..fbd7bf7838 100644 --- a/drivers/video/pwm_backlight.c +++ b/drivers/video/pwm_backlight.c @@ -28,11 +28,13 @@ struct pwm_backlight_priv { static int pwm_backlight_enable(struct udevice *dev) { struct pwm_backlight_priv *priv = dev_get_priv(dev); + struct dm_regulator_uclass_platdata *plat; uint duty_cycle; int ret; - debug("%s: Enable '%s', regulator '%s'\n", __func__, dev->name, - priv->reg->name); + plat = dev_get_uclass_platdata(priv->reg); + debug("%s: Enable '%s', regulator '%s'/'%s'\n", __func__, dev->name, + priv->reg->name, plat->name); ret = regulator_set_enable(priv->reg, true); if (ret) { debug("%s: Cannot enable regulator for PWM '%s'\n", __func__, @@ -59,12 +61,11 @@ static int pwm_backlight_enable(struct udevice *dev) static int pwm_backlight_ofdata_to_platdata(struct udevice *dev) { struct pwm_backlight_priv *priv = dev_get_priv(dev); - struct fdtdec_phandle_args args; - const void *blob = gd->fdt_blob; - int node = dev_of_offset(dev); + struct ofnode_phandle_args args; int index, ret, count, len; const u32 *cell; + debug("%s: start\n", __func__); ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, "power-supply", &priv->reg); if (ret) { @@ -79,14 +80,14 @@ static int pwm_backlight_ofdata_to_platdata(struct udevice *dev) if (ret != -ENOENT) return ret; } - ret = fdtdec_parse_phandle_with_args(blob, node, "pwms", "#pwm-cells", - 0, 0, &args); + ret = dev_read_phandle_with_args(dev, "pwms", "#pwm-cells", 0, 0, + &args); if (ret) { debug("%s: Cannot get PWM phandle: ret=%d\n", __func__, ret); return ret; } - ret = uclass_get_device_by_of_offset(UCLASS_PWM, args.node, &priv->pwm); + ret = uclass_get_device_by_ofnode(UCLASS_PWM, args.node, &priv->pwm); if (ret) { debug("%s: Cannot get PWM: ret=%d\n", __func__, ret); return ret; @@ -94,8 +95,8 @@ static int pwm_backlight_ofdata_to_platdata(struct udevice *dev) priv->channel = args.args[0]; priv->period_ns = args.args[1]; - index = fdtdec_get_int(blob, node, "default-brightness-level", 255); - cell = fdt_getprop(blob, node, "brightness-levels", &len); + index = dev_read_u32_default(dev, "default-brightness-level", 255); + cell = dev_read_prop(dev, "brightness-levels", &len); count = len / sizeof(u32); if (cell && count > index) { priv->default_level = fdt32_to_cpu(cell[index]); @@ -104,6 +105,7 @@ static int pwm_backlight_ofdata_to_platdata(struct udevice *dev) priv->default_level = index; priv->max_level = 255; } + debug("%s: done\n", __func__); return 0; diff --git a/drivers/video/simple_panel.c b/drivers/video/simple_panel.c index baa95f6a12..c0ce199c6a 100644 --- a/drivers/video/simple_panel.c +++ b/drivers/video/simple_panel.c @@ -25,8 +25,10 @@ static int simple_panel_enable_backlight(struct udevice *dev) struct simple_panel_priv *priv = dev_get_priv(dev); int ret; + debug("%s: start, backlight = '%s'\n", __func__, priv->backlight->name); dm_gpio_set_value(&priv->enable, 1); ret = backlight_enable(priv->backlight); + debug("%s: done, ret = %d\n", __func__, ret); if (ret) return ret; diff --git a/drivers/video/tegra124/display.c b/drivers/video/tegra124/display.c index bbbca13bdc..47752b27f1 100644 --- a/drivers/video/tegra124/display.c +++ b/drivers/video/tegra124/display.c @@ -471,7 +471,9 @@ static int tegra124_lcd_probe(struct udevice *dev) int ret; start = get_timer(0); + bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "lcd"); ret = tegra124_lcd_init(dev, (void *)plat->base, VIDEO_BPP16); + bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD); debug("LCD init took %lu ms\n", get_timer(start)); if (ret) printf("%s: Error %d\n", __func__, ret); diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index e9a90b1b9b..b5afd72227 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -77,6 +77,7 @@ static int vidconsole_back(struct udevice *dev) if (priv->ycur < 0) priv->ycur = 0; } + video_sync(dev->parent); return 0; } |