summaryrefslogtreecommitdiff
path: root/common/scsi.c
diff options
context:
space:
mode:
authorMichal Simek <michal.simek@xilinx.com>2016-09-08 13:06:45 (GMT)
committerMichal Simek <michal.simek@xilinx.com>2016-12-20 08:15:27 (GMT)
commite8a016b53731bba820246c9509ce8ef74c944560 (patch)
treeb9382ac0cd9f4dcd9cb8cfae459770d09ea4d43f /common/scsi.c
parent720ba46e71b09d379a3590a4a35c35d5938338b5 (diff)
downloadu-boot-e8a016b53731bba820246c9509ce8ef74c944560.tar.xz
dm: Add support for scsi/sata based devices
All sata based drivers are bind and corresponding block device is created. Based on this find_scsi_device() is able to get back block device based on scsi_curr_dev pointer. intr_scsi() is commented now but it can be replaced by calling find_scsi_device() and scsi_scan(). scsi_dev_desc[] is commented out but common/scsi.c heavily depends on it. That's why CONFIG_SYS_SCSI_MAX_DEVICE is hardcoded to 1 and symbol is reassigned to a block description allocated by uclass. There is only one block description by device now but it doesn't need to be correct when more devices are present. scsi_bind() ensures corresponding block device creation. uclass post_probe (scsi_post_probe()) is doing low level init. SCSI/SATA DM based drivers requires to have 64bit base address as the first entry in platform data structure to setup mmio_base. Signed-off-by: Michal Simek <michal.simek@xilinx.com> Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'common/scsi.c')
-rw-r--r--common/scsi.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/common/scsi.c b/common/scsi.c
index 04add62..e7efa5a 100644
--- a/common/scsi.c
+++ b/common/scsi.c
@@ -10,7 +10,10 @@
#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
@@ -31,6 +34,7 @@
#endif
#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID}
#endif
+#endif
#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
@@ -39,11 +43,13 @@ static ccb 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
@@ -444,6 +450,7 @@ static void scsi_init_dev_desc_priv(struct blk_desc *dev_desc)
#endif
}
+#if !defined(CONFIG_DM_SCSI)
/**
* scsi_init_dev_desc - initialize all SCSI specific blk_desc properties
*
@@ -460,6 +467,7 @@ static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum)
scsi_init_dev_desc_priv(dev_desc);
}
+#endif
/**
* scsi_detect_dev - Detect scsi device
@@ -540,6 +548,73 @@ removable:
* (re)-scan the scsi bus and reports scsi device info
* to the user if mode = 1
*/
+#if defined(CONFIG_DM_SCSI)
+int scsi_scan(int mode)
+{
+ unsigned char i, lun;
+ struct uclass *uc;
+ struct udevice *dev; /* SCSI controller */
+ int ret;
+
+ if (mode == 1)
+ printf("scanning bus for devices...\n");
+
+ ret = uclass_get(UCLASS_SCSI, &uc);
+ if (ret)
+ return ret;
+
+ uclass_foreach_dev(dev, uc) {
+ struct scsi_platdata *plat; /* scsi controller platdata */
+
+ /* probe SCSI controller driver */
+ ret = device_probe(dev);
+ if (ret)
+ return ret;
+
+ /* Get controller platdata */
+ plat = dev_get_platdata(dev);
+
+ for (i = 0; i < plat->max_id; i++) {
+ for (lun = 0; lun < plat->max_lun; lun++) {
+ struct udevice *bdev; /* block device */
+ /* block device description */
+ struct blk_desc *bdesc;
+ char str[10];
+
+ /*
+ * 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", i, lun);
+ ret = blk_create_devicef(dev, "scsi_blk",
+ str, IF_TYPE_SCSI,
+ -1, 0, 0, &bdev);
+ if (ret) {
+ debug("Can't create device\n");
+ return ret;
+ }
+ bdesc = dev_get_uclass_platdata(bdev);
+
+ scsi_init_dev_desc_priv(bdesc);
+ bdesc->lun = lun;
+ ret = scsi_detect_dev(i, bdesc);
+ if (ret) {
+ device_unbind(bdev);
+ continue;
+ }
+
+ if (mode == 1) {
+ printf(" Device %d: ", 0);
+ dev_print(bdesc);
+ } /* if mode */
+ } /* next LUN */
+ }
+ }
+
+ return 0;
+}
+#else
int scsi_scan(int mode)
{
unsigned char i, lun;
@@ -576,6 +651,7 @@ int scsi_scan(int mode)
#endif
return 0;
}
+#endif
#ifdef CONFIG_BLK
static const struct blk_ops scsi_blk_ops = {