summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig4
-rw-r--r--drivers/Makefile4
-rw-r--r--drivers/ata/Kconfig62
-rw-r--r--drivers/ata/Makefile22
-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.c117
-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/Kconfig41
-rw-r--r--drivers/block/Makefile17
-rw-r--r--drivers/block/scsi-uclass.c27
-rw-r--r--drivers/block/sym53c8xx.c851
-rw-r--r--drivers/core/Makefile2
-rw-r--r--drivers/core/dump.c1
-rw-r--r--drivers/core/lists.c3
-rw-r--r--drivers/core/of_access.c24
-rw-r--r--drivers/core/ofnode.c72
-rw-r--r--drivers/core/read.c23
-rw-r--r--drivers/core/read_extra.c37
-rw-r--r--drivers/core/regmap.c4
-rw-r--r--drivers/core/uclass.c30
-rw-r--r--drivers/core/util.c5
-rw-r--r--drivers/misc/cros_ec_sandbox.c2
-rw-r--r--drivers/pci/pci-uclass.c8
-rw-r--r--drivers/pinctrl/pinctrl-uclass.c2
-rw-r--r--drivers/scsi/Kconfig17
-rw-r--r--drivers/scsi/Makefile20
-rw-r--r--drivers/scsi/sandbox_scsi.c (renamed from drivers/block/sandbox_scsi.c)9
-rw-r--r--drivers/scsi/scsi-uclass.c40
-rw-r--r--drivers/scsi/scsi.c709
-rw-r--r--drivers/serial/ns16550.c3
-rw-r--r--drivers/serial/serial-uclass.c92
-rw-r--r--drivers/usb/emul/sandbox_flash.c2
-rw-r--r--drivers/video/pwm_backlight.c22
-rw-r--r--drivers/video/simple_panel.c2
-rw-r--r--drivers/video/tegra124/display.c2
-rw-r--r--drivers/video/vidconsole-uclass.c1
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;
}