[U-Boot] [PATCH v2 1/7] scsi: Extract block device initialization

Extract block device initialization to specific function.
Signed-off-by: Michal Simek michal.simek@xilinx.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/scsi.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-)
diff --git a/common/scsi.c b/common/scsi.c index dbbf4043b22a..0bce91dfa099 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -458,6 +458,28 @@ void scsi_setup_test_unit_ready(ccb *pccb) pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ }
+static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum) +{ + dev_desc->target = 0xff; + dev_desc->lun = 0xff; + dev_desc->lba = 0; + dev_desc->blksz = 0; + 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; + dev_desc->if_type = IF_TYPE_SCSI; + dev_desc->devnum = devnum; + dev_desc->part_type = PART_TYPE_UNKNOWN; +#ifndef CONFIG_BLK + dev_desc->block_read = scsi_read; + dev_desc->block_write = scsi_write; +#endif +} + /* * (re)-scan the scsi bus and reports scsi device info * to the user if mode = 1 @@ -471,26 +493,9 @@ void scsi_scan(int mode)
if (mode == 1) printf("scanning bus for devices...\n"); - for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++) { - scsi_dev_desc[i].target = 0xff; - scsi_dev_desc[i].lun = 0xff; - scsi_dev_desc[i].lba = 0; - scsi_dev_desc[i].blksz = 0; - scsi_dev_desc[i].log2blksz = - LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz)); - scsi_dev_desc[i].type = DEV_TYPE_UNKNOWN; - scsi_dev_desc[i].vendor[0] = 0; - scsi_dev_desc[i].product[0] = 0; - scsi_dev_desc[i].revision[0] = 0; - scsi_dev_desc[i].removable = false; - scsi_dev_desc[i].if_type = IF_TYPE_SCSI; - scsi_dev_desc[i].devnum = i; - scsi_dev_desc[i].part_type = PART_TYPE_UNKNOWN; -#ifndef CONFIG_BLK - scsi_dev_desc[i].block_read = scsi_read; - scsi_dev_desc[i].block_write = scsi_write; -#endif - } + 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++) { pccb->target = i;

The patch enables running detection algorithm on block device description structure.
Signed-off-by: Michal Simek michal.simek@xilinx.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Remove 's/&dev_desc[0].vendor[0]/dev_desc->vendor/g' the same for product and revisions in scsi_detect_dev()
common/scsi.c | 143 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 82 insertions(+), 61 deletions(-)
diff --git a/common/scsi.c b/common/scsi.c index 0bce91dfa099..89926e7a68ae 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -480,15 +480,88 @@ static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum) #endif }
+/** + * scsi_detect_dev - Detect scsi device + * + * @pccb: pointer to temporary SCSI command block + * @dev_desc: block device description + * @lun: Logical unit number + * + * 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(ccb *pccb, struct blk_desc *dev_desc, int lun) +{ + unsigned char perq, modi; + lbaint_t capacity; + unsigned long blksz; + + pccb->lun = lun; + pccb->pdata = (unsigned char *)&tempbuff; + pccb->datalen = 512; + scsi_setup_inquiry(pccb); + if (scsi_exec(pccb) != true) { + 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(pccb) != true) { + if (dev_desc->removable) { + dev_desc->type = perq; + goto removable; + } + scsi_print_error(pccb); + return -EINVAL; + } + if (scsi_read_capacity(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; + part_init(&dev_desc[0]); +removable: + return 0; +} + /* * (re)-scan the scsi bus and reports scsi device info * to the user if mode = 1 */ void scsi_scan(int mode) { - unsigned char i, perq, modi, lun; - lbaint_t capacity; - unsigned long blksz; + unsigned char i, lun; + int ret; ccb *pccb = (ccb *)&tempccb;
if (mode == 1) @@ -500,66 +573,14 @@ void scsi_scan(int mode) for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { pccb->target = i; for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) { - pccb->lun = lun; - pccb->pdata = (unsigned char *)&tempbuff; - pccb->datalen = 512; - scsi_setup_inquiry(pccb); - if (scsi_exec(pccb) != true) { - if (pccb->contr_stat == SCSI_SEL_TIME_OUT) { - /* - * selection timeout => assuming no - * device present - */ - debug("Selection timeout ID %d\n", - pccb->target); - continue; - } - scsi_print_error(pccb); - continue; - } - perq = tempbuff[0]; - modi = tempbuff[1]; - if ((perq & 0x1f) == 0x1f) - continue; /* skip unknown devices */ - if ((modi & 0x80) == 0x80) /* drive is removable */ - scsi_dev_desc[scsi_max_devs].removable = true; - /* get info for this device */ - scsi_ident_cpy((unsigned char *)&scsi_dev_desc - [scsi_max_devs].vendor[0], - &tempbuff[8], 8); - scsi_ident_cpy((unsigned char *)&scsi_dev_desc - [scsi_max_devs].product[0], - &tempbuff[16], 16); - scsi_ident_cpy((unsigned char *)&scsi_dev_desc - [scsi_max_devs].revision[0], - &tempbuff[32], 4); - scsi_dev_desc[scsi_max_devs].target = pccb->target; - scsi_dev_desc[scsi_max_devs].lun = pccb->lun; - - pccb->datalen = 0; - scsi_setup_test_unit_ready(pccb); - if (scsi_exec(pccb) != true) { - if (scsi_dev_desc[scsi_max_devs].removable) { - scsi_dev_desc[scsi_max_devs].type = - perq; - goto removable; - } - scsi_print_error(pccb); - continue; - } - if (scsi_read_capacity(pccb, &capacity, &blksz)) { - scsi_print_error(pccb); + ret = scsi_detect_dev(pccb, + &scsi_dev_desc[scsi_max_devs], + lun); + if (ret) continue; - } - scsi_dev_desc[scsi_max_devs].lba = capacity; - scsi_dev_desc[scsi_max_devs].blksz = blksz; - scsi_dev_desc[scsi_max_devs].log2blksz = - LOG2(scsi_dev_desc[scsi_max_devs].blksz); - scsi_dev_desc[scsi_max_devs].type = perq; - part_init(&scsi_dev_desc[scsi_max_devs]); -removable: + if (mode == 1) { - printf(" Device %d: ", scsi_max_devs); + printf(" Device %d: ", 0); dev_print(&scsi_dev_desc[scsi_max_devs]); } /* if mode */ scsi_max_devs++;

Prepare LUN(Logical unit number) directly in block description structure and reuse it.
Signed-off-by: Michal Simek michal.simek@xilinx.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/scsi.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/common/scsi.c b/common/scsi.c index 89926e7a68ae..e8f102a8a4b5 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -485,20 +485,19 @@ static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum) * * @pccb: pointer to temporary SCSI command block * @dev_desc: block device description - * @lun: Logical unit number * * The scsi_detect_dev detects and fills a dev_desc structure when the device is - * detected. + * detected. The LUN number is taken from the struct blk_desc *dev_desc. * * Return: 0 on success, error value otherwise */ -static int scsi_detect_dev(ccb *pccb, struct blk_desc *dev_desc, int lun) +static int scsi_detect_dev(ccb *pccb, struct blk_desc *dev_desc) { unsigned char perq, modi; lbaint_t capacity; unsigned long blksz;
- pccb->lun = lun; + pccb->lun = dev_desc->lun; pccb->pdata = (unsigned char *)&tempbuff; pccb->datalen = 512; scsi_setup_inquiry(pccb); @@ -573,9 +572,9 @@ void scsi_scan(int mode) for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { pccb->target = i; for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) { + scsi_dev_desc[scsi_max_devs].lun = lun; ret = scsi_detect_dev(pccb, - &scsi_dev_desc[scsi_max_devs], - lun); + &scsi_dev_desc[scsi_max_devs]); if (ret) continue;

pccb is pointer to temporary buffer which is used only for sending command. Make it local as is done in scsi_read/scsi_write.
Signed-off-by: Michal Simek michal.simek@xilinx.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/scsi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/common/scsi.c b/common/scsi.c index e8f102a8a4b5..5a925bafda28 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -480,10 +480,11 @@ static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum) #endif }
+ /** * scsi_detect_dev - Detect scsi device * - * @pccb: pointer to temporary SCSI command block + * @target: target id * @dev_desc: block device description * * The scsi_detect_dev detects and fills a dev_desc structure when the device is @@ -491,12 +492,14 @@ static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum) * * Return: 0 on success, error value otherwise */ -static int scsi_detect_dev(ccb *pccb, struct blk_desc *dev_desc) +static int scsi_detect_dev(int target, struct blk_desc *dev_desc) { unsigned char perq, modi; lbaint_t capacity; unsigned long blksz; + ccb *pccb = (ccb *)&tempccb;
+ pccb->target = target; pccb->lun = dev_desc->lun; pccb->pdata = (unsigned char *)&tempbuff; pccb->datalen = 512; @@ -561,7 +564,6 @@ void scsi_scan(int mode) { unsigned char i, lun; int ret; - ccb *pccb = (ccb *)&tempccb;
if (mode == 1) printf("scanning bus for devices...\n"); @@ -570,11 +572,9 @@ void scsi_scan(int mode)
scsi_max_devs = 0; for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { - pccb->target = i; for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) { scsi_dev_desc[scsi_max_devs].lun = lun; - ret = scsi_detect_dev(pccb, - &scsi_dev_desc[scsi_max_devs]); + ret = scsi_detect_dev(i, &scsi_dev_desc[scsi_max_devs]); if (ret) continue;

There is no reason to directly point to static allocated array when we have proper block_dev pointer available via parameter in !CONFIG_BLK. For CONFIG_BLK this is read directly from uclass platdata.
Signed-off-by: Michal Simek michal.simek@xilinx.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/scsi.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-)
diff --git a/common/scsi.c b/common/scsi.c index 5a925bafda28..9e4ef54a9be8 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -161,43 +161,41 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, #ifdef CONFIG_BLK struct blk_desc *block_dev = dev_get_uclass_platdata(dev); #endif - int device = block_dev->devnum; lbaint_t start, blks; uintptr_t buf_addr; unsigned short smallblks = 0; ccb *pccb = (ccb *)&tempccb; - device &= 0xff;
/* Setup device */ - pccb->target = scsi_dev_desc[device].target; - pccb->lun = scsi_dev_desc[device].lun; + 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", - device, start, blks, (unsigned long)buffer); + 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 = scsi_dev_desc[device].blksz * blocks; + 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 = scsi_dev_desc[device].blksz * + 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 = scsi_dev_desc[device].blksz * blks; + pccb->datalen = block_dev->blksz * blks; smallblks = (unsigned short)blks; scsi_setup_read_ext(pccb, start, smallblks); start += blks; @@ -236,33 +234,30 @@ static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, #ifdef CONFIG_BLK struct blk_desc *block_dev = dev_get_uclass_platdata(dev); #endif - int device = block_dev->devnum; lbaint_t start, blks; uintptr_t buf_addr; unsigned short smallblks; ccb *pccb = (ccb *)&tempccb;
- device &= 0xff; - /* Setup device */ - pccb->target = scsi_dev_desc[device].target; - pccb->lun = scsi_dev_desc[device].lun; + 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__, device, start, blks, (unsigned long)buffer); + __func__, block_dev->devnum, start, blks, (unsigned long)buffer); do { pccb->pdata = (unsigned char *)buf_addr; if (blks > SCSI_MAX_WRITE_BLK) { - pccb->datalen = (scsi_dev_desc[device].blksz * + 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 = scsi_dev_desc[device].blksz * blks; + pccb->datalen = block_dev->blksz * blks; smallblks = (unsigned short)blks; scsi_setup_write_ext(pccb, start, smallblks); start += blks;

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 ---
Changes in v2: - Use CONFIG_DM_SCSI instead of mix of DM_SCSI and DM_SATA Ceva sata has never used sata commands that's why keep it in SCSI part only. - Separate scsi_scan() for DM_SCSI and do not change cmd/scsi.c - Extend platdata
common/board_r.c | 4 +-- common/scsi.c | 81 +++++++++++++++++++++++++++++++++++++++++++++ drivers/block/Kconfig | 7 ++++ drivers/block/Makefile | 1 + drivers/block/ahci.c | 30 ++++++++++++----- drivers/block/blk-uclass.c | 2 +- drivers/block/scsi-uclass.c | 29 ++++++++++++++++ include/ahci.h | 2 +- include/dm/uclass-id.h | 1 + include/sata.h | 3 ++ include/scsi.h | 19 ++++++++++- 11 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 drivers/block/scsi-uclass.c
diff --git a/common/board_r.c b/common/board_r.c index d959ad3c6f90..108cabbd023b 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -620,7 +620,7 @@ static int initr_ambapp_print(void) } #endif
-#if defined(CONFIG_SCSI) +#if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI) static int initr_scsi(void) { puts("SCSI: "); @@ -923,7 +923,7 @@ init_fnc_t init_sequence_r[] = { initr_ambapp_print, #endif #endif -#ifdef CONFIG_SCSI +#if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI) INIT_FUNC_WATCHDOG_RESET initr_scsi, #endif diff --git a/common/scsi.c b/common/scsi.c index 9e4ef54a9be8..bc55512913da 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -7,10 +7,14 @@
#include <common.h> #include <dm.h> +#if defined(CONFIG_DM_SCSI) +#include <dm/uclass-internal.h> +#endif #include <inttypes.h> #include <pci.h> #include <scsi.h>
+#if !defined(CONFIG_DM_SCSI) #ifdef CONFIG_SCSI_DEV_LIST #define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST #else @@ -31,6 +35,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 }; @@ -41,9 +46,11 @@ static unsigned char tempbuff[512]; /* temporary data buffer */
static int scsi_max_devs; /* number of highest available scsi device */
+#if !defined(CONFIG_DM_SCSI) 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 @@ -555,6 +562,79 @@ removable: * (re)-scan the scsi bus and reports scsi device info * to the user if mode = 1 */ +#if defined(CONFIG_DM_SCSI) +void 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; + + uclass_foreach_dev(dev, uc) { + struct scsi_platdata *plat; /* scsi controller platdata */ + struct blk_desc *bdesc = NULL; /* block device description */ + struct udevice *bdev; /* block device */ + struct udevice **devp = NULL; + int dev_num = 0; + int last_dev_num = -1; + + /* probe SCSI controller driver */ + ret = uclass_get_device_tail(dev, 0, devp); + if (ret) + return; + + /* Get controller platdata */ + plat = dev_get_platdata(dev); + + for (i = 0; i < plat->max_id; i++) { + for (lun = 0; lun < plat->max_lun; lun++) { + /* + * Create only one block device and do detection + * to make sure that there won't be a lot of + * block devices created + */ + if (last_dev_num != dev_num) { + char str[10]; + snprintf(str, sizeof(str), "lun%d", + lun); + ret = blk_create_devicef(dev, + "scsi_blk", + str, + IF_TYPE_SCSI, + -1, 512, + dev_num, + &bdev); + if (ret) { + printf("Can't create device\n"); + return; + } + last_dev_num = dev_num; + bdesc = dev_get_uclass_platdata(bdev); + } + + scsi_init_dev_desc(bdesc, dev_num); + bdesc->lun = lun; + ret = scsi_detect_dev(i, bdesc); + if (ret) + continue; + + if (mode == 1) { + printf(" Device %d: ", 0); + dev_print(bdesc); + dev_num++; + } /* if mode */ + } /* next LUN */ + } + } +} +#else void scsi_scan(int mode) { unsigned char i, lun; @@ -590,6 +670,7 @@ void scsi_scan(int mode) setenv_ulong("scsidevs", scsi_max_devs); #endif } +#endif
#ifdef CONFIG_BLK static const struct blk_ops scsi_blk_ops = { diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index fe5aa07f921a..55edae71eec3 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -2,6 +2,7 @@ config BLK bool "Support block devices" depends on DM default y if DM_MMC + default y if DM_SCSI help Enable support for block devices, such as SCSI, MMC and USB flash sticks. These provide a block-level interface which permits @@ -19,6 +20,12 @@ config AHCI operations at present. The block device interface has not been converted to driver model.
+config DM_SCSI + bool "DM for SCSI" + depends on DM + help + This option enables the SCSI uclass. + config BLOCK_CACHE bool "Use block device cache" default n diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 436b79f98165..a72feecd5456 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -12,6 +12,7 @@ obj-y += blk_legacy.o endif
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 diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index 5139989d0b5f..0dd4a2ea5814 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -168,7 +168,7 @@ int ahci_reset(void __iomem *base)
static int ahci_host_init(struct ahci_probe_ent *probe_ent) { -#ifndef CONFIG_SCSI_AHCI_PLAT +#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) # ifdef CONFIG_DM_PCI struct udevice *dev = probe_ent->dev; struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); @@ -198,7 +198,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) writel(cap_save, mmio + HOST_CAP); writel_with_flush(0xf, mmio + HOST_PORTS_IMPL);
-#ifndef CONFIG_SCSI_AHCI_PLAT +#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) # ifdef CONFIG_DM_PCI if (pplat->vendor == PCI_VENDOR_ID_INTEL) { u16 tmp16; @@ -327,6 +327,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL); tmp = readl(mmio + HOST_CTL); debug("HOST_CTL 0x%x\n", tmp); +#if !defined(CONFIG_DM_SCSI) #ifndef CONFIG_SCSI_AHCI_PLAT # ifdef CONFIG_DM_PCI dm_pci_read_config16(dev, PCI_COMMAND, &tmp16); @@ -338,14 +339,15 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) pci_write_config_word(pdev, PCI_COMMAND, tmp16); # endif #endif +#endif return 0; }
static void ahci_print_info(struct ahci_probe_ent *probe_ent) { -#ifndef CONFIG_SCSI_AHCI_PLAT -# ifdef CONFIG_DM_PCI +#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) +# if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) struct udevice *dev = probe_ent->dev; # else pci_dev_t pdev = probe_ent->dev; @@ -372,7 +374,7 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent) else speed_s = "?";
-#ifdef CONFIG_SCSI_AHCI_PLAT +#if defined(CONFIG_SCSI_AHCI_PLAT) || defined(CONFIG_DM_SCSI) scc_s = "SATA"; #else # ifdef CONFIG_DM_PCI @@ -424,13 +426,15 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent) }
#ifndef CONFIG_SCSI_AHCI_PLAT -# ifdef CONFIG_DM_PCI +# if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) static int ahci_init_one(struct udevice *dev) # else static int ahci_init_one(pci_dev_t dev) # endif { +#if defined(CONFIG_DM_PCI) u16 vendor; +#endif int rc;
probe_ent = malloc(sizeof(struct ahci_probe_ent)); @@ -450,6 +454,7 @@ static int ahci_init_one(pci_dev_t dev) probe_ent->pio_mask = 0x1f; probe_ent->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, PCI_REGION_MEM); @@ -473,6 +478,10 @@ static int ahci_init_one(pci_dev_t dev) if (vendor == 0x197b) pci_write_config_byte(dev, 0x41, 0xa1); #endif +#else + struct scsi_platdata *plat = dev_get_platdata(dev); + probe_ent->mmio_base = (void *)plat->base; +#endif
debug("ahci mmio_base=0x%p\n", probe_ent->mmio_base); /* initialize adapter */ @@ -954,14 +963,17 @@ int scsi_exec(ccb *pccb)
}
- +#if defined(CONFIG_DM_SCSI) +void scsi_low_level_init(int busdevfunc, struct udevice *dev) +#else void scsi_low_level_init(int busdevfunc) +#endif { int i; u32 linkmap;
#ifndef CONFIG_SCSI_AHCI_PLAT -# ifdef CONFIG_DM_PCI +# if defined(CONFIG_DM_PCI) struct udevice *dev; int ret;
@@ -969,6 +981,8 @@ void scsi_low_level_init(int busdevfunc) if (ret) return; ahci_init_one(dev); +# elif defined(CONFIG_DM_SCSI) + ahci_init_one(dev); # else ahci_init_one(busdevfunc); # endif diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 2e041c2b3dc7..38cb9388da6f 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -26,7 +26,7 @@ static const char *if_typename_str[IF_TYPE_COUNT] = {
static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { [IF_TYPE_IDE] = UCLASS_INVALID, - [IF_TYPE_SCSI] = UCLASS_INVALID, + [IF_TYPE_SCSI] = UCLASS_SCSI, [IF_TYPE_ATAPI] = UCLASS_INVALID, [IF_TYPE_USB] = UCLASS_MASS_STORAGE, [IF_TYPE_DOC] = UCLASS_INVALID, diff --git a/drivers/block/scsi-uclass.c b/drivers/block/scsi-uclass.c new file mode 100644 index 000000000000..123b25c406a4 --- /dev/null +++ b/drivers/block/scsi-uclass.c @@ -0,0 +1,29 @@ +/* + * 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> + +#if !defined(CONFIG_SPL_BUILD) +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, +}; +#endif diff --git a/include/ahci.h b/include/ahci.h index a956c6ff5df7..4876b41e9010 100644 --- a/include/ahci.h +++ b/include/ahci.h @@ -145,7 +145,7 @@ struct ahci_ioports { };
struct ahci_probe_ent { -#ifdef CONFIG_DM_PCI +#if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) struct udevice *dev; #else pci_dev_t dev; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index eb78c4dac485..8c92d0b03088 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -66,6 +66,7 @@ enum uclass_id { UCLASS_REMOTEPROC, /* Remote Processor device */ UCLASS_RESET, /* Reset controller device */ UCLASS_RTC, /* Real time clock device */ + UCLASS_SCSI, /* SCSI device */ UCLASS_SERIAL, /* Serial UART */ UCLASS_SPI, /* SPI bus */ UCLASS_SPMI, /* System Power Management Interface bus */ diff --git a/include/sata.h b/include/sata.h index b35359aa5a19..dbf77f8c7039 100644 --- a/include/sata.h +++ b/include/sata.h @@ -2,6 +2,8 @@ #define __SATA_H__ #include <part.h>
+#if !defined(CONFIG_DM_SCSI) + int init_sata(int dev); int reset_sata(int dev); int scan_sata(int dev); @@ -15,5 +17,6 @@ int __sata_stop(void); int sata_port_status(int dev, int port);
extern struct blk_desc sata_dev_desc[]; +#endif
#endif diff --git a/include/scsi.h b/include/scsi.h index 7e3759140b34..7396994b91fc 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -166,8 +166,11 @@ typedef struct SCSI_cmd_block{ void scsi_print_error(ccb *pccb); int scsi_exec(ccb *pccb); void scsi_bus_reset(void); +#if !defined(CONFIG_DM_SCSI) void scsi_low_level_init(int busdevfunc); - +#else +void scsi_low_level_init(int busdevfunc, struct udevice *dev); +#endif
/*************************************************************************** * functions residing inside cmd_scsi.c @@ -175,6 +178,20 @@ void scsi_low_level_init(int busdevfunc); void scsi_init(void); void scsi_scan(int mode);
+#if defined(CONFIG_DM_SCSI) +/** + * struct scsi_platdata - stores information about SCSI controller + * + * @max_lun: Maximum number of logical units + * @max_id: Maximum number of target ids + */ +struct scsi_platdata { + unsigned long base; + unsigned long max_lun; + unsigned long max_id; +}; +#endif + /** @return the number of scsi disks */ int scsi_get_disk_count(void);

Hi Michal,
On 25 November 2016 at 08:00, Michal Simek michal.simek@xilinx.com wrote:
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
Changes in v2:
- Use CONFIG_DM_SCSI instead of mix of DM_SCSI and DM_SATA Ceva sata has never used sata commands that's why keep it in SCSI part only.
- Separate scsi_scan() for DM_SCSI and do not change cmd/scsi.c
- Extend platdata
common/board_r.c | 4 +-- common/scsi.c | 81 +++++++++++++++++++++++++++++++++++++++++++++ drivers/block/Kconfig | 7 ++++ drivers/block/Makefile | 1 + drivers/block/ahci.c | 30 ++++++++++++----- drivers/block/blk-uclass.c | 2 +- drivers/block/scsi-uclass.c | 29 ++++++++++++++++ include/ahci.h | 2 +- include/dm/uclass-id.h | 1 + include/sata.h | 3 ++ include/scsi.h | 19 ++++++++++- 11 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 drivers/block/scsi-uclass.c
This looks really good. I've made some comments below.
diff --git a/common/board_r.c b/common/board_r.c index d959ad3c6f90..108cabbd023b 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -620,7 +620,7 @@ static int initr_ambapp_print(void) } #endif
-#if defined(CONFIG_SCSI) +#if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI) static int initr_scsi(void) { puts("SCSI: "); @@ -923,7 +923,7 @@ init_fnc_t init_sequence_r[] = { initr_ambapp_print, #endif #endif -#ifdef CONFIG_SCSI +#if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI) INIT_FUNC_WATCHDOG_RESET initr_scsi, #endif diff --git a/common/scsi.c b/common/scsi.c index 9e4ef54a9be8..bc55512913da 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -7,10 +7,14 @@
#include <common.h> #include <dm.h> +#if defined(CONFIG_DM_SCSI) +#include <dm/uclass-internal.h> +#endif
You can drop that #ifdef - also please put the dm/ include at the end, after scsi.h.
#include <inttypes.h> #include <pci.h> #include <scsi.h>
+#if !defined(CONFIG_DM_SCSI) #ifdef CONFIG_SCSI_DEV_LIST #define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST #else @@ -31,6 +35,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 }; @@ -41,9 +46,11 @@ static unsigned char tempbuff[512]; /* temporary data buffer */
static int scsi_max_devs; /* number of highest available scsi device */
I think this should be bracketed by !CONFIG_DM_SCSI, also.
+#if !defined(CONFIG_DM_SCSI) 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 @@ -555,6 +562,79 @@ removable:
- (re)-scan the scsi bus and reports scsi device info
- to the user if mode = 1
*/ +#if defined(CONFIG_DM_SCSI) +void scsi_scan(int mode)
This function can generate errors - can you update it to return 'int' so you can return them?
+{
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;
uclass_foreach_dev(dev, uc) {
struct scsi_platdata *plat; /* scsi controller platdata */
struct blk_desc *bdesc = NULL; /* block device description */
I don't think you need the = NULL
struct udevice *bdev; /* block device */
struct udevice **devp = NULL;
You should be able to drop this
int dev_num = 0;
int last_dev_num = -1;
/* probe SCSI controller driver */
ret = uclass_get_device_tail(dev, 0, devp);
ret = device_probe(dev);
if (ret)
return;
/* Get controller platdata */
plat = dev_get_platdata(dev);
for (i = 0; i < plat->max_id; i++) {
for (lun = 0; lun < plat->max_lun; lun++) {
/*
Can this whole block go in a separate function?
* Create only one block device and do detection
* to make sure that there won't be a lot of
* block devices created
*/
if (last_dev_num != dev_num) {
char str[10];
snprintf(str, sizeof(str), "lun%d",
lun);
ret = blk_create_devicef(dev,
"scsi_blk",
str,
IF_TYPE_SCSI,
-1, 512,
dev_num,
&bdev);
if (ret) {
printf("Can't create device\n");
debug()
return;
}
last_dev_num = dev_num;
Or perhaps set bdev to NULL when it is 'used up'. Then check for NULL in the if() above.
bdesc = dev_get_uclass_platdata(bdev);
Consider moving this down one line, before the scsi_init_dev_desc() call, so you know it is valid?
}
scsi_init_dev_desc(bdesc, dev_num);
Actually this is set up by blk_create_device() so you should not overwrite it. I would much rather that this function be behind '#ifndef CONFIG_DM_SCSI'. You can update particular fields if needed?
bdesc->lun = lun;
ret = scsi_detect_dev(i, bdesc);
if (ret)
continue;
device_unbind() here (or perhaps in the following block), since you don't want the device hanging around.
Or perhaps you intend to reuse this device for the next one you try? Which is probably better, I agree. But in that case if you have one left over that you don't use, it should be unbound when exiting scsi_scan.
if (mode == 1) {
printf(" Device %d: ", 0);
dev_print(bdesc);
dev_num++;
} /* if mode */
} /* next LUN */
}
}
+} +#else void scsi_scan(int mode) { unsigned char i, lun; @@ -590,6 +670,7 @@ void scsi_scan(int mode) setenv_ulong("scsidevs", scsi_max_devs); #endif } +#endif
#ifdef CONFIG_BLK static const struct blk_ops scsi_blk_ops = { diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index fe5aa07f921a..55edae71eec3 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -2,6 +2,7 @@ config BLK bool "Support block devices" depends on DM default y if DM_MMC
default y if DM_SCSI help Enable support for block devices, such as SCSI, MMC and USB flash sticks. These provide a block-level interface which permits
@@ -19,6 +20,12 @@ config AHCI operations at present. The block device interface has not been converted to driver model.
+config DM_SCSI
bool "DM for SCSI"
depends on DM
&& BLK ?
Or perhaps 'select BLK' ? We should not allow DM_SCSI without BLK.
help
This option enables the SCSI uclass.
Can you please add more detail here? Write out SCSI in full also and mention what SCSI is used for.
config BLOCK_CACHE bool "Use block device cache" default n diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 436b79f98165..a72feecd5456 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -12,6 +12,7 @@ obj-y += blk_legacy.o endif
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 diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index 5139989d0b5f..0dd4a2ea5814 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -168,7 +168,7 @@ int ahci_reset(void __iomem *base)
static int ahci_host_init(struct ahci_probe_ent *probe_ent) { -#ifndef CONFIG_SCSI_AHCI_PLAT +#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) # ifdef CONFIG_DM_PCI struct udevice *dev = probe_ent->dev; struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); @@ -198,7 +198,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) writel(cap_save, mmio + HOST_CAP); writel_with_flush(0xf, mmio + HOST_PORTS_IMPL);
-#ifndef CONFIG_SCSI_AHCI_PLAT +#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) # ifdef CONFIG_DM_PCI if (pplat->vendor == PCI_VENDOR_ID_INTEL) { u16 tmp16; @@ -327,6 +327,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL); tmp = readl(mmio + HOST_CTL); debug("HOST_CTL 0x%x\n", tmp); +#if !defined(CONFIG_DM_SCSI) #ifndef CONFIG_SCSI_AHCI_PLAT # ifdef CONFIG_DM_PCI dm_pci_read_config16(dev, PCI_COMMAND, &tmp16); @@ -338,14 +339,15 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) pci_write_config_word(pdev, PCI_COMMAND, tmp16); # endif #endif +#endif return 0; }
static void ahci_print_info(struct ahci_probe_ent *probe_ent) { -#ifndef CONFIG_SCSI_AHCI_PLAT -# ifdef CONFIG_DM_PCI +#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) +# if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) struct udevice *dev = probe_ent->dev; # else pci_dev_t pdev = probe_ent->dev; @@ -372,7 +374,7 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent) else speed_s = "?";
-#ifdef CONFIG_SCSI_AHCI_PLAT +#if defined(CONFIG_SCSI_AHCI_PLAT) || defined(CONFIG_DM_SCSI) scc_s = "SATA"; #else # ifdef CONFIG_DM_PCI @@ -424,13 +426,15 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent) }
#ifndef CONFIG_SCSI_AHCI_PLAT -# ifdef CONFIG_DM_PCI +# if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) static int ahci_init_one(struct udevice *dev) # else static int ahci_init_one(pci_dev_t dev) # endif { +#if defined(CONFIG_DM_PCI) u16 vendor; +#endif int rc;
probe_ent = malloc(sizeof(struct ahci_probe_ent));
@@ -450,6 +454,7 @@ static int ahci_init_one(pci_dev_t dev) probe_ent->pio_mask = 0x1f; probe_ent->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, PCI_REGION_MEM); @@ -473,6 +478,10 @@ static int ahci_init_one(pci_dev_t dev) if (vendor == 0x197b) pci_write_config_byte(dev, 0x41, 0xa1); #endif +#else
struct scsi_platdata *plat = dev_get_platdata(dev);
probe_ent->mmio_base = (void *)plat->base;
+#endif
debug("ahci mmio_base=0x%p\n", probe_ent->mmio_base); /* initialize adapter */
@@ -954,14 +963,17 @@ int scsi_exec(ccb *pccb)
}
+#if defined(CONFIG_DM_SCSI) +void scsi_low_level_init(int busdevfunc, struct udevice *dev)
Do we need this function for DM? At some point the first param should go away, since if we are using PCI (device_is_on_pci_bus()) we can use dm_pci_get_bdf().
+#else void scsi_low_level_init(int busdevfunc) +#endif { int i; u32 linkmap;
#ifndef CONFIG_SCSI_AHCI_PLAT -# ifdef CONFIG_DM_PCI +# if defined(CONFIG_DM_PCI) struct udevice *dev; int ret;
@@ -969,6 +981,8 @@ void scsi_low_level_init(int busdevfunc) if (ret) return; ahci_init_one(dev); +# elif defined(CONFIG_DM_SCSI)
ahci_init_one(dev);
# else ahci_init_one(busdevfunc); # endif diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 2e041c2b3dc7..38cb9388da6f 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -26,7 +26,7 @@ static const char *if_typename_str[IF_TYPE_COUNT] = {
static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { [IF_TYPE_IDE] = UCLASS_INVALID,
[IF_TYPE_SCSI] = UCLASS_INVALID,
[IF_TYPE_SCSI] = UCLASS_SCSI, [IF_TYPE_ATAPI] = UCLASS_INVALID, [IF_TYPE_USB] = UCLASS_MASS_STORAGE, [IF_TYPE_DOC] = UCLASS_INVALID,
diff --git a/drivers/block/scsi-uclass.c b/drivers/block/scsi-uclass.c new file mode 100644 index 000000000000..123b25c406a4 --- /dev/null +++ b/drivers/block/scsi-uclass.c @@ -0,0 +1,29 @@ +/*
- 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>
+#if !defined(CONFIG_SPL_BUILD) +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,
Should this be pre_probe(). Even if we need the low-level init, I suspect it needs to be done before the device is used in its probe() method.
+}; +#endif diff --git a/include/ahci.h b/include/ahci.h index a956c6ff5df7..4876b41e9010 100644 --- a/include/ahci.h +++ b/include/ahci.h @@ -145,7 +145,7 @@ struct ahci_ioports { };
struct ahci_probe_ent { -#ifdef CONFIG_DM_PCI +#if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) struct udevice *dev; #else pci_dev_t dev; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index eb78c4dac485..8c92d0b03088 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -66,6 +66,7 @@ enum uclass_id { UCLASS_REMOTEPROC, /* Remote Processor device */ UCLASS_RESET, /* Reset controller device */ UCLASS_RTC, /* Real time clock device */
UCLASS_SCSI, /* SCSI device */ UCLASS_SERIAL, /* Serial UART */ UCLASS_SPI, /* SPI bus */ UCLASS_SPMI, /* System Power Management Interface bus */
diff --git a/include/sata.h b/include/sata.h index b35359aa5a19..dbf77f8c7039 100644 --- a/include/sata.h +++ b/include/sata.h @@ -2,6 +2,8 @@ #define __SATA_H__ #include <part.h>
+#if !defined(CONFIG_DM_SCSI)
int init_sata(int dev); int reset_sata(int dev); int scan_sata(int dev); @@ -15,5 +17,6 @@ int __sata_stop(void); int sata_port_status(int dev, int port);
extern struct blk_desc sata_dev_desc[]; +#endif
#endif diff --git a/include/scsi.h b/include/scsi.h index 7e3759140b34..7396994b91fc 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -166,8 +166,11 @@ typedef struct SCSI_cmd_block{ void scsi_print_error(ccb *pccb); int scsi_exec(ccb *pccb); void scsi_bus_reset(void); +#if !defined(CONFIG_DM_SCSI) void scsi_low_level_init(int busdevfunc);
+#else +void scsi_low_level_init(int busdevfunc, struct udevice *dev); +#endif
/***************************************************************************
- functions residing inside cmd_scsi.c
@@ -175,6 +178,20 @@ void scsi_low_level_init(int busdevfunc); void scsi_init(void); void scsi_scan(int mode);
+#if defined(CONFIG_DM_SCSI) +/**
- struct scsi_platdata - stores information about SCSI controller
@base
- @max_lun: Maximum number of logical units
- @max_id: Maximum number of target ids
- */
+struct scsi_platdata {
unsigned long base;
unsigned long max_lun;
unsigned long max_id;
+}; +#endif
/** @return the number of scsi disks */ int scsi_get_disk_count(void);
-- 1.9.1
Also we should have a sandbox SCSI driver for tests.
Regards, SImon

On 30.11.2016 01:32, Simon Glass wrote:
Hi Michal,
On 25 November 2016 at 08:00, Michal Simek michal.simek@xilinx.com wrote:
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
Changes in v2:
- Use CONFIG_DM_SCSI instead of mix of DM_SCSI and DM_SATA Ceva sata has never used sata commands that's why keep it in SCSI part only.
- Separate scsi_scan() for DM_SCSI and do not change cmd/scsi.c
- Extend platdata
common/board_r.c | 4 +-- common/scsi.c | 81 +++++++++++++++++++++++++++++++++++++++++++++ drivers/block/Kconfig | 7 ++++ drivers/block/Makefile | 1 + drivers/block/ahci.c | 30 ++++++++++++----- drivers/block/blk-uclass.c | 2 +- drivers/block/scsi-uclass.c | 29 ++++++++++++++++ include/ahci.h | 2 +- include/dm/uclass-id.h | 1 + include/sata.h | 3 ++ include/scsi.h | 19 ++++++++++- 11 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 drivers/block/scsi-uclass.c
This looks really good. I've made some comments below.
diff --git a/common/board_r.c b/common/board_r.c index d959ad3c6f90..108cabbd023b 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -620,7 +620,7 @@ static int initr_ambapp_print(void) } #endif
-#if defined(CONFIG_SCSI) +#if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI) static int initr_scsi(void) { puts("SCSI: "); @@ -923,7 +923,7 @@ init_fnc_t init_sequence_r[] = { initr_ambapp_print, #endif #endif -#ifdef CONFIG_SCSI +#if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI) INIT_FUNC_WATCHDOG_RESET initr_scsi, #endif diff --git a/common/scsi.c b/common/scsi.c index 9e4ef54a9be8..bc55512913da 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -7,10 +7,14 @@
#include <common.h> #include <dm.h> +#if defined(CONFIG_DM_SCSI) +#include <dm/uclass-internal.h> +#endif
You can drop that #ifdef - also please put the dm/ include at the end, after scsi.h.
done in v3
#include <inttypes.h> #include <pci.h> #include <scsi.h>
+#if !defined(CONFIG_DM_SCSI) #ifdef CONFIG_SCSI_DEV_LIST #define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST #else @@ -31,6 +35,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 }; @@ -41,9 +46,11 @@ static unsigned char tempbuff[512]; /* temporary data buffer */
static int scsi_max_devs; /* number of highest available scsi device */
I think this should be bracketed by !CONFIG_DM_SCSI, also.
scsi_get_disk_count() was using it but none called this function. I have prepared two additional patches to cleanup sparse warnings and then this is visible that should be protected.
It means fixed as you suggested.
+#if !defined(CONFIG_DM_SCSI) 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 @@ -555,6 +562,79 @@ removable:
- (re)-scan the scsi bus and reports scsi device info
- to the user if mode = 1
*/ +#if defined(CONFIG_DM_SCSI) +void scsi_scan(int mode)
This function can generate errors - can you update it to return 'int' so you can return them?
Done by one more separate patch before this one and this one was fixed to return error codes.
+{
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;
uclass_foreach_dev(dev, uc) {
struct scsi_platdata *plat; /* scsi controller platdata */
struct blk_desc *bdesc = NULL; /* block device description */
I don't think you need the = NULL
I couldn't because of that logic with last_dev_num below. This warning was generated.
common/scsi.c: In function 'scsi_scan': common/scsi.c:500:34: warning: 'bdesc' may be used uninitialized in this function [-Wmaybe-uninitialized] scsi_ident_cpy((unsigned char *)dev_desc->revision, ^ common/scsi.c:549:20: note: 'bdesc' was declared here struct blk_desc *bdesc; /* block device description */ ^
Anyway I have resort that function to behaves differently. It creates block device all the time for every configuration and if it is not valid it is removed by device_unbind function. Not sure if this has any side effect in core (malloc area) etc but it behaves better than before. I have extended name of block device with also ID there to illustrate problem with this version where you generate block device with id0 and lun0 and use it for others configurations like id1 and lun0 (my configuration).
Output from this patch scsi [ + ] |-- ahci@fd0c0000 blk [ ] | `-- ahci@fd0c0000.id0lun0
After fixing scsi [ + ] |-- ahci@fd0c0000 blk [ ] | `-- ahci@fd0c0000.id1lun0
As you see from above block name reflects ids and lun correctly now.
struct udevice *bdev; /* block device */
struct udevice **devp = NULL;
You should be able to drop this
removed
int dev_num = 0;
int last_dev_num = -1;
/* probe SCSI controller driver */
ret = uclass_get_device_tail(dev, 0, devp);
ret = device_probe(dev);
changed.
if (ret)
return;
/* Get controller platdata */
plat = dev_get_platdata(dev);
for (i = 0; i < plat->max_id; i++) {
for (lun = 0; lun < plat->max_lun; lun++) {
/*
Can this whole block go in a separate function?
It can for sure but after redesigning it is my cleaner to read. Also handling different errors won't look nice. Please look at next version and let me know if you think that make sense to separate it. Code looks much better now.
* Create only one block device and do detection
* to make sure that there won't be a lot of
* block devices created
*/
if (last_dev_num != dev_num) {
char str[10];
snprintf(str, sizeof(str), "lun%d",
lun);
ret = blk_create_devicef(dev,
"scsi_blk",
str,
IF_TYPE_SCSI,
-1, 512,
dev_num,
&bdev);
if (ret) {
printf("Can't create device\n");
debug()
fixed.
return;
}
last_dev_num = dev_num;
Or perhaps set bdev to NULL when it is 'used up'. Then check for NULL in the if() above.
Fixed by redesigning this function to generate block devices for every configuration and then removing it.
bdesc = dev_get_uclass_platdata(bdev);
Consider moving this down one line, before the scsi_init_dev_desc() call, so you know it is valid?
Removed by redesigning the code.
}
scsi_init_dev_desc(bdesc, dev_num);
Actually this is set up by blk_create_device() so you should not overwrite it. I would much rather that this function be behind '#ifndef CONFIG_DM_SCSI'. You can update particular fields if needed?
I have created one more patch to address this. It is separation of what block device creation is doing and what SCSI requires for code.
bdesc->lun = lun;
ret = scsi_detect_dev(i, bdesc);
if (ret)
continue;
device_unbind() here (or perhaps in the following block), since you don't want the device hanging around.
Added.
Or perhaps you intend to reuse this device for the next one you try? Which is probably better, I agree. But in that case if you have one left over that you don't use, it should be unbound when exiting scsi_scan.
I have redesigned this as above. I wanted to reuse but there is side effect anyway and new way is cleaner.
if (mode == 1) {
printf(" Device %d: ", 0);
dev_print(bdesc);
dev_num++;
I have also removed this dev_num++ because this is generated by blk_create_device()
} /* if mode */
} /* next LUN */
}
}
+} +#else void scsi_scan(int mode) { unsigned char i, lun; @@ -590,6 +670,7 @@ void scsi_scan(int mode) setenv_ulong("scsidevs", scsi_max_devs); #endif } +#endif
#ifdef CONFIG_BLK static const struct blk_ops scsi_blk_ops = { diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index fe5aa07f921a..55edae71eec3 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -2,6 +2,7 @@ config BLK bool "Support block devices" depends on DM default y if DM_MMC
default y if DM_SCSI help Enable support for block devices, such as SCSI, MMC and USB flash sticks. These provide a block-level interface which permits
@@ -19,6 +20,12 @@ config AHCI operations at present. The block device interface has not been converted to driver model.
+config DM_SCSI
bool "DM for SCSI"
depends on DM
&& BLK ?
There are several ways how to do it. I have setup depends on BLK here and remove code above to remove recursive dependencies. Also I have added new menu for scsi/sata devices.
Or perhaps 'select BLK' ? We should not allow DM_SCSI without BLK.
help
This option enables the SCSI uclass.
Can you please add more detail here? Write out SCSI in full also and mention what SCSI is used for.
done.
config BLOCK_CACHE bool "Use block device cache" default n diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 436b79f98165..a72feecd5456 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -12,6 +12,7 @@ obj-y += blk_legacy.o endif
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 diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index 5139989d0b5f..0dd4a2ea5814 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -168,7 +168,7 @@ int ahci_reset(void __iomem *base)
static int ahci_host_init(struct ahci_probe_ent *probe_ent) { -#ifndef CONFIG_SCSI_AHCI_PLAT +#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) # ifdef CONFIG_DM_PCI struct udevice *dev = probe_ent->dev; struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); @@ -198,7 +198,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) writel(cap_save, mmio + HOST_CAP); writel_with_flush(0xf, mmio + HOST_PORTS_IMPL);
-#ifndef CONFIG_SCSI_AHCI_PLAT +#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) # ifdef CONFIG_DM_PCI if (pplat->vendor == PCI_VENDOR_ID_INTEL) { u16 tmp16; @@ -327,6 +327,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL); tmp = readl(mmio + HOST_CTL); debug("HOST_CTL 0x%x\n", tmp); +#if !defined(CONFIG_DM_SCSI) #ifndef CONFIG_SCSI_AHCI_PLAT # ifdef CONFIG_DM_PCI dm_pci_read_config16(dev, PCI_COMMAND, &tmp16); @@ -338,14 +339,15 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) pci_write_config_word(pdev, PCI_COMMAND, tmp16); # endif #endif +#endif return 0; }
static void ahci_print_info(struct ahci_probe_ent *probe_ent) { -#ifndef CONFIG_SCSI_AHCI_PLAT -# ifdef CONFIG_DM_PCI +#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) +# if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) struct udevice *dev = probe_ent->dev; # else pci_dev_t pdev = probe_ent->dev; @@ -372,7 +374,7 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent) else speed_s = "?";
-#ifdef CONFIG_SCSI_AHCI_PLAT +#if defined(CONFIG_SCSI_AHCI_PLAT) || defined(CONFIG_DM_SCSI) scc_s = "SATA"; #else # ifdef CONFIG_DM_PCI @@ -424,13 +426,15 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent) }
#ifndef CONFIG_SCSI_AHCI_PLAT -# ifdef CONFIG_DM_PCI +# if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) static int ahci_init_one(struct udevice *dev) # else static int ahci_init_one(pci_dev_t dev) # endif { +#if defined(CONFIG_DM_PCI) u16 vendor; +#endif int rc;
probe_ent = malloc(sizeof(struct ahci_probe_ent));
@@ -450,6 +454,7 @@ static int ahci_init_one(pci_dev_t dev) probe_ent->pio_mask = 0x1f; probe_ent->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, PCI_REGION_MEM); @@ -473,6 +478,10 @@ static int ahci_init_one(pci_dev_t dev) if (vendor == 0x197b) pci_write_config_byte(dev, 0x41, 0xa1); #endif +#else
struct scsi_platdata *plat = dev_get_platdata(dev);
probe_ent->mmio_base = (void *)plat->base;
+#endif
debug("ahci mmio_base=0x%p\n", probe_ent->mmio_base); /* initialize adapter */
@@ -954,14 +963,17 @@ int scsi_exec(ccb *pccb)
}
+#if defined(CONFIG_DM_SCSI) +void scsi_low_level_init(int busdevfunc, struct udevice *dev)
Do we need this function for DM? At some point the first param should go away, since if we are using PCI (device_is_on_pci_bus()) we can use dm_pci_get_bdf().
we need this right now but definitely this function requires more work in connection to PCI. I am not quite sure why they are calling dm_pci_bus_find_bdf() instead of passing pointer to udevice directly.
There should be patch on the top of this when someone who has access to pci scsi card will look at this.
I can extract just parts used when DM_SCSI is defined without busdevfunc but it will just create ifdef stuff somewhere else.
+#else void scsi_low_level_init(int busdevfunc) +#endif { int i; u32 linkmap;
#ifndef CONFIG_SCSI_AHCI_PLAT -# ifdef CONFIG_DM_PCI +# if defined(CONFIG_DM_PCI) struct udevice *dev; int ret;
@@ -969,6 +981,8 @@ void scsi_low_level_init(int busdevfunc) if (ret) return; ahci_init_one(dev); +# elif defined(CONFIG_DM_SCSI)
ahci_init_one(dev);
# else ahci_init_one(busdevfunc); # endif diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 2e041c2b3dc7..38cb9388da6f 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -26,7 +26,7 @@ static const char *if_typename_str[IF_TYPE_COUNT] = {
static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { [IF_TYPE_IDE] = UCLASS_INVALID,
[IF_TYPE_SCSI] = UCLASS_INVALID,
[IF_TYPE_SCSI] = UCLASS_SCSI, [IF_TYPE_ATAPI] = UCLASS_INVALID, [IF_TYPE_USB] = UCLASS_MASS_STORAGE, [IF_TYPE_DOC] = UCLASS_INVALID,
diff --git a/drivers/block/scsi-uclass.c b/drivers/block/scsi-uclass.c new file mode 100644 index 000000000000..123b25c406a4 --- /dev/null +++ b/drivers/block/scsi-uclass.c @@ -0,0 +1,29 @@ +/*
- 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>
+#if !defined(CONFIG_SPL_BUILD) +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,
Should this be pre_probe(). Even if we need the low-level init, I suspect it needs to be done before the device is used in its probe() method.
low level init is calling any ahci init code which requires device to be up. I haven't studied what exactly it does but it has to be called after device is up and running that's why it is done in post probe.
+}; +#endif diff --git a/include/ahci.h b/include/ahci.h index a956c6ff5df7..4876b41e9010 100644 --- a/include/ahci.h +++ b/include/ahci.h @@ -145,7 +145,7 @@ struct ahci_ioports { };
struct ahci_probe_ent { -#ifdef CONFIG_DM_PCI +#if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) struct udevice *dev; #else pci_dev_t dev; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index eb78c4dac485..8c92d0b03088 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -66,6 +66,7 @@ enum uclass_id { UCLASS_REMOTEPROC, /* Remote Processor device */ UCLASS_RESET, /* Reset controller device */ UCLASS_RTC, /* Real time clock device */
UCLASS_SCSI, /* SCSI device */ UCLASS_SERIAL, /* Serial UART */ UCLASS_SPI, /* SPI bus */ UCLASS_SPMI, /* System Power Management Interface bus */
diff --git a/include/sata.h b/include/sata.h index b35359aa5a19..dbf77f8c7039 100644 --- a/include/sata.h +++ b/include/sata.h @@ -2,6 +2,8 @@ #define __SATA_H__ #include <part.h>
+#if !defined(CONFIG_DM_SCSI)
int init_sata(int dev); int reset_sata(int dev); int scan_sata(int dev); @@ -15,5 +17,6 @@ int __sata_stop(void); int sata_port_status(int dev, int port);
extern struct blk_desc sata_dev_desc[]; +#endif
#endif diff --git a/include/scsi.h b/include/scsi.h index 7e3759140b34..7396994b91fc 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -166,8 +166,11 @@ typedef struct SCSI_cmd_block{ void scsi_print_error(ccb *pccb); int scsi_exec(ccb *pccb); void scsi_bus_reset(void); +#if !defined(CONFIG_DM_SCSI) void scsi_low_level_init(int busdevfunc);
+#else +void scsi_low_level_init(int busdevfunc, struct udevice *dev); +#endif
/***************************************************************************
- functions residing inside cmd_scsi.c
@@ -175,6 +178,20 @@ void scsi_low_level_init(int busdevfunc); void scsi_init(void); void scsi_scan(int mode);
+#if defined(CONFIG_DM_SCSI) +/**
- struct scsi_platdata - stores information about SCSI controller
@base
Fixed.
- @max_lun: Maximum number of logical units
- @max_id: Maximum number of target ids
- */
+struct scsi_platdata {
unsigned long base;
unsigned long max_lun;
unsigned long max_id;
+}; +#endif
/** @return the number of scsi disks */ int scsi_get_disk_count(void);
-- 1.9.1
Also we should have a sandbox SCSI driver for tests.
TBH: I have no idea how to create it and it can be done in separate patches when someone has time to do it.
I am running buildman to see error and then will send v3.
Thanks, Michal

This patch also includes ARM64 zynqmp changes: - Remove platform non DM initialization - Remove hardcoded sata base address
Signed-off-by: Michal Simek michal.simek@xilinx.com ---
Changes in v2: - make ceva_init_sata static - Move SATA_CEVA to defconfig - Initalized max_lun and max_id platdata
arch/arm/include/asm/arch-zynqmp/hardware.h | 2 -- board/xilinx/zynqmp/zynqmp.c | 11 -------- configs/xilinx_zynqmp_ep_defconfig | 2 ++ configs/xilinx_zynqmp_zcu102_defconfig | 2 ++ configs/xilinx_zynqmp_zcu102_revB_defconfig | 2 ++ drivers/block/Kconfig | 6 +++++ drivers/block/sata_ceva.c | 41 +++++++++++++++++++++++++++-- include/configs/xilinx_zynqmp.h | 5 ++-- include/configs/xilinx_zynqmp_ep.h | 1 - include/configs/xilinx_zynqmp_zcu102.h | 2 -- 10 files changed, 54 insertions(+), 20 deletions(-)
diff --git a/arch/arm/include/asm/arch-zynqmp/hardware.h b/arch/arm/include/asm/arch-zynqmp/hardware.h index e7738faaf896..d1970953e234 100644 --- a/arch/arm/include/asm/arch-zynqmp/hardware.h +++ b/arch/arm/include/asm/arch-zynqmp/hardware.h @@ -18,8 +18,6 @@
#define ARASAN_NAND_BASEADDR 0xFF100000
-#define ZYNQMP_SATA_BASEADDR 0xFD0C0000 - #define ZYNQMP_USB0_XHCI_BASEADDR 0xFE200000 #define ZYNQMP_USB1_XHCI_BASEADDR 0xFE300000
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index cef1f6a13aee..a23c38acd99d 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -311,17 +311,6 @@ void reset_cpu(ulong addr) { }
-#ifdef CONFIG_SCSI_AHCI_PLAT -void scsi_init(void) -{ -#if defined(CONFIG_SATA_CEVA) - init_sata(0); -#endif - ahci_init((void __iomem *)ZYNQMP_SATA_BASEADDR); - scsi_scan(1); -} -#endif - int board_late_init(void) { u32 reg = 0; diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig index f3cdf90c1f73..8d6a6cf5701e 100644 --- a/configs/xilinx_zynqmp_ep_defconfig +++ b/configs/xilinx_zynqmp_ep_defconfig @@ -49,6 +49,8 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DM_SCSI=y +CONFIG_SATA_CEVA=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/configs/xilinx_zynqmp_zcu102_defconfig b/configs/xilinx_zynqmp_zcu102_defconfig index fa6d6692040e..7e5e83fdc043 100644 --- a/configs/xilinx_zynqmp_zcu102_defconfig +++ b/configs/xilinx_zynqmp_zcu102_defconfig @@ -41,6 +41,8 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DM_SCSI=y +CONFIG_SATA_CEVA=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig index a4af8024e454..f57705b2cba9 100644 --- a/configs/xilinx_zynqmp_zcu102_revB_defconfig +++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig @@ -41,6 +41,8 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DM_SCSI=y +CONFIG_SATA_CEVA=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 55edae71eec3..0b289b2fc111 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -34,3 +34,9 @@ config BLOCK_CACHE This is most useful when accessing filesystems under U-Boot since it will prevent repeated reads from directory structures and other filesystem data structures. + +config SATA_CEVA + bool "Ceva Sata controller" + depends on DM_SCSI + help + This option enables Ceva Sata controller available on Xilinx ZynqMP. diff --git a/drivers/block/sata_ceva.c b/drivers/block/sata_ceva.c index dcc3b90b17f1..3f40b7efb6fa 100644 --- a/drivers/block/sata_ceva.c +++ b/drivers/block/sata_ceva.c @@ -9,6 +9,7 @@ #include <ahci.h> #include <scsi.h> #include <asm/arch/hardware.h> +#include <dm.h>
#include <asm/io.h>
@@ -73,10 +74,9 @@ #define DRV_NAME "ahci-ceva" #define CEVA_FLAG_BROKEN_GEN2 1
-int init_sata(int dev) +static int ceva_init_sata(ulong mmio) { ulong tmp; - ulong mmio = ZYNQMP_SATA_BASEADDR; int i;
/* @@ -111,3 +111,40 @@ int init_sata(int dev) } return 0; } + +static int sata_ceva_probe(struct udevice *dev) +{ + struct scsi_platdata *plat = dev_get_platdata(dev); + + ceva_init_sata(plat->base); + return 0; +} + +static const struct udevice_id sata_ceva_ids[] = { + { .compatible = "ceva,ahci-1v84" }, + { } +}; + +static int sata_ceva_ofdata_to_platdata(struct udevice *dev) +{ + struct scsi_platdata *plat = dev_get_platdata(dev); + + plat->base = dev_get_addr(dev); + if (plat->base == FDT_ADDR_T_NONE) + return -EINVAL; + + /* Hardcode number for ceva sata controller */ + plat->max_lun = 1; /* Actually two but untested */ + plat->max_id = 2; + + return 0; +} + +U_BOOT_DRIVER(ceva_host_blk) = { + .name = "ceva_sata", + .id = UCLASS_SCSI, + .of_match = sata_ceva_ids, + .probe = sata_ceva_probe, + .ofdata_to_platdata = sata_ceva_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct scsi_platdata), +}; diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h index 7452e92ff8da..673c864ebc6f 100644 --- a/include/configs/xilinx_zynqmp.h +++ b/include/configs/xilinx_zynqmp.h @@ -182,15 +182,16 @@ # define CONFIG_SYS_EEPROM_SIZE (64 * 1024) #endif
-#ifdef CONFIG_SATA_CEVA +#if defined(CONFIG_SATA_CEVA) && !defined(CONFIG_SPL_BUILD) #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI -#define CONFIG_SCSI_AHCI_PLAT #define CONFIG_SYS_SCSI_MAX_SCSI_ID 2 #define CONFIG_SYS_SCSI_MAX_LUN 1 #define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ CONFIG_SYS_SCSI_MAX_LUN) #define CONFIG_SCSI +#else +#undef CONFIG_SATA_CEVA #endif
#define CONFIG_SYS_BOOTM_LEN (60 * 1024 * 1024) diff --git a/include/configs/xilinx_zynqmp_ep.h b/include/configs/xilinx_zynqmp_ep.h index d0ce768e6e14..3a572b7a6c2f 100644 --- a/include/configs/xilinx_zynqmp_ep.h +++ b/include/configs/xilinx_zynqmp_ep.h @@ -16,7 +16,6 @@ #define CONFIG_ZYNQ_SDHCI_MAX_FREQ 52000000 #define CONFIG_ZYNQ_SDHCI_MIN_FREQ (CONFIG_ZYNQ_SDHCI_MAX_FREQ >> 9) #define CONFIG_ZYNQ_EEPROM -#define CONFIG_SATA_CEVA #define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR, \ ZYNQMP_USB1_XHCI_BASEADDR}
diff --git a/include/configs/xilinx_zynqmp_zcu102.h b/include/configs/xilinx_zynqmp_zcu102.h index adf2321c5d4f..8d018da23e34 100644 --- a/include/configs/xilinx_zynqmp_zcu102.h +++ b/include/configs/xilinx_zynqmp_zcu102.h @@ -41,8 +41,6 @@ #define CONFIG_CMD_PCA953X #define CONFIG_CMD_PCA953X_INFO
-#define CONFIG_SATA_CEVA - #define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR}
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1

Hi Michal,
On 25 November 2016 at 08:00, Michal Simek michal.simek@xilinx.com wrote:
This patch also includes ARM64 zynqmp changes:
- Remove platform non DM initialization
- Remove hardcoded sata base address
Signed-off-by: Michal Simek michal.simek@xilinx.com
Changes in v2:
- make ceva_init_sata static
- Move SATA_CEVA to defconfig
- Initalized max_lun and max_id platdata
arch/arm/include/asm/arch-zynqmp/hardware.h | 2 -- board/xilinx/zynqmp/zynqmp.c | 11 -------- configs/xilinx_zynqmp_ep_defconfig | 2 ++ configs/xilinx_zynqmp_zcu102_defconfig | 2 ++ configs/xilinx_zynqmp_zcu102_revB_defconfig | 2 ++ drivers/block/Kconfig | 6 +++++ drivers/block/sata_ceva.c | 41 +++++++++++++++++++++++++++-- include/configs/xilinx_zynqmp.h | 5 ++-- include/configs/xilinx_zynqmp_ep.h | 1 - include/configs/xilinx_zynqmp_zcu102.h | 2 -- 10 files changed, 54 insertions(+), 20 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
nits below
diff --git a/arch/arm/include/asm/arch-zynqmp/hardware.h b/arch/arm/include/asm/arch-zynqmp/hardware.h index e7738faaf896..d1970953e234 100644 --- a/arch/arm/include/asm/arch-zynqmp/hardware.h +++ b/arch/arm/include/asm/arch-zynqmp/hardware.h @@ -18,8 +18,6 @@
#define ARASAN_NAND_BASEADDR 0xFF100000
-#define ZYNQMP_SATA_BASEADDR 0xFD0C0000
#define ZYNQMP_USB0_XHCI_BASEADDR 0xFE200000 #define ZYNQMP_USB1_XHCI_BASEADDR 0xFE300000
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index cef1f6a13aee..a23c38acd99d 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -311,17 +311,6 @@ void reset_cpu(ulong addr) { }
-#ifdef CONFIG_SCSI_AHCI_PLAT -void scsi_init(void) -{ -#if defined(CONFIG_SATA_CEVA)
init_sata(0);
-#endif
ahci_init((void __iomem *)ZYNQMP_SATA_BASEADDR);
scsi_scan(1);
-} -#endif
int board_late_init(void) { u32 reg = 0; diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig index f3cdf90c1f73..8d6a6cf5701e 100644 --- a/configs/xilinx_zynqmp_ep_defconfig +++ b/configs/xilinx_zynqmp_ep_defconfig @@ -49,6 +49,8 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DM_SCSI=y +CONFIG_SATA_CEVA=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/configs/xilinx_zynqmp_zcu102_defconfig b/configs/xilinx_zynqmp_zcu102_defconfig index fa6d6692040e..7e5e83fdc043 100644 --- a/configs/xilinx_zynqmp_zcu102_defconfig +++ b/configs/xilinx_zynqmp_zcu102_defconfig @@ -41,6 +41,8 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DM_SCSI=y +CONFIG_SATA_CEVA=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig index a4af8024e454..f57705b2cba9 100644 --- a/configs/xilinx_zynqmp_zcu102_revB_defconfig +++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig @@ -41,6 +41,8 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DM_SCSI=y +CONFIG_SATA_CEVA=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 55edae71eec3..0b289b2fc111 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -34,3 +34,9 @@ config BLOCK_CACHE This is most useful when accessing filesystems under U-Boot since it will prevent repeated reads from directory structures and other filesystem data structures.
+config SATA_CEVA
bool "Ceva Sata controller"
depends on DM_SCSI
help
This option enables Ceva Sata controller available on Xilinx ZynqMP.
Can you add more detail? What does it support? Is this soft IP?
diff --git a/drivers/block/sata_ceva.c b/drivers/block/sata_ceva.c index dcc3b90b17f1..3f40b7efb6fa 100644 --- a/drivers/block/sata_ceva.c +++ b/drivers/block/sata_ceva.c @@ -9,6 +9,7 @@ #include <ahci.h> #include <scsi.h> #include <asm/arch/hardware.h> +#include <dm.h>
please put these in order with http://www.denx.de/wiki/U-Boot/CodingStyle
#include <asm/io.h>
@@ -73,10 +74,9 @@ #define DRV_NAME "ahci-ceva" #define CEVA_FLAG_BROKEN_GEN2 1
-int init_sata(int dev) +static int ceva_init_sata(ulong mmio) { ulong tmp;
ulong mmio = ZYNQMP_SATA_BASEADDR; int i; /*
@@ -111,3 +111,40 @@ int init_sata(int dev) } return 0; }
+static int sata_ceva_probe(struct udevice *dev) +{
struct scsi_platdata *plat = dev_get_platdata(dev);
ceva_init_sata(plat->base);
return 0;
+}
+static const struct udevice_id sata_ceva_ids[] = {
{ .compatible = "ceva,ahci-1v84" },
{ }
+};
+static int sata_ceva_ofdata_to_platdata(struct udevice *dev) +{
struct scsi_platdata *plat = dev_get_platdata(dev);
plat->base = dev_get_addr(dev);
if (plat->base == FDT_ADDR_T_NONE)
return -EINVAL;
/* Hardcode number for ceva sata controller */
plat->max_lun = 1; /* Actually two but untested */
plat->max_id = 2;
return 0;
+}
+U_BOOT_DRIVER(ceva_host_blk) = {
.name = "ceva_sata",
.id = UCLASS_SCSI,
.of_match = sata_ceva_ids,
.probe = sata_ceva_probe,
.ofdata_to_platdata = sata_ceva_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct scsi_platdata),
+}; diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h index 7452e92ff8da..673c864ebc6f 100644 --- a/include/configs/xilinx_zynqmp.h +++ b/include/configs/xilinx_zynqmp.h @@ -182,15 +182,16 @@ # define CONFIG_SYS_EEPROM_SIZE (64 * 1024) #endif
-#ifdef CONFIG_SATA_CEVA +#if defined(CONFIG_SATA_CEVA) && !defined(CONFIG_SPL_BUILD) #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI -#define CONFIG_SCSI_AHCI_PLAT #define CONFIG_SYS_SCSI_MAX_SCSI_ID 2 #define CONFIG_SYS_SCSI_MAX_LUN 1 #define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ CONFIG_SYS_SCSI_MAX_LUN) #define CONFIG_SCSI +#else +#undef CONFIG_SATA_CEVA
Are you trying to undefine it for SPL? I suspect DM_SCSI already does this, but you should do this in the Makefile (ifndef CONFIG_SPL_BUILD) or perhaps create CONFIG_SPL_SATA_CEVA if you might want to add it to SPL.
We should not #undef Kconfig options.
#endif
#define CONFIG_SYS_BOOTM_LEN (60 * 1024 * 1024) diff --git a/include/configs/xilinx_zynqmp_ep.h b/include/configs/xilinx_zynqmp_ep.h index d0ce768e6e14..3a572b7a6c2f 100644 --- a/include/configs/xilinx_zynqmp_ep.h +++ b/include/configs/xilinx_zynqmp_ep.h @@ -16,7 +16,6 @@ #define CONFIG_ZYNQ_SDHCI_MAX_FREQ 52000000 #define CONFIG_ZYNQ_SDHCI_MIN_FREQ (CONFIG_ZYNQ_SDHCI_MAX_FREQ >> 9) #define CONFIG_ZYNQ_EEPROM -#define CONFIG_SATA_CEVA #define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR, \ ZYNQMP_USB1_XHCI_BASEADDR}
diff --git a/include/configs/xilinx_zynqmp_zcu102.h b/include/configs/xilinx_zynqmp_zcu102.h index adf2321c5d4f..8d018da23e34 100644 --- a/include/configs/xilinx_zynqmp_zcu102.h +++ b/include/configs/xilinx_zynqmp_zcu102.h @@ -41,8 +41,6 @@ #define CONFIG_CMD_PCA953X #define CONFIG_CMD_PCA953X_INFO
-#define CONFIG_SATA_CEVA
#define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR}
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
1.9.1
Regards, Simon

On 30.11.2016 01:32, Simon Glass wrote:
Hi Michal,
On 25 November 2016 at 08:00, Michal Simek michal.simek@xilinx.com wrote:
This patch also includes ARM64 zynqmp changes:
- Remove platform non DM initialization
- Remove hardcoded sata base address
Signed-off-by: Michal Simek michal.simek@xilinx.com
Changes in v2:
- make ceva_init_sata static
- Move SATA_CEVA to defconfig
- Initalized max_lun and max_id platdata
arch/arm/include/asm/arch-zynqmp/hardware.h | 2 -- board/xilinx/zynqmp/zynqmp.c | 11 -------- configs/xilinx_zynqmp_ep_defconfig | 2 ++ configs/xilinx_zynqmp_zcu102_defconfig | 2 ++ configs/xilinx_zynqmp_zcu102_revB_defconfig | 2 ++ drivers/block/Kconfig | 6 +++++ drivers/block/sata_ceva.c | 41 +++++++++++++++++++++++++++-- include/configs/xilinx_zynqmp.h | 5 ++-- include/configs/xilinx_zynqmp_ep.h | 1 - include/configs/xilinx_zynqmp_zcu102.h | 2 -- 10 files changed, 54 insertions(+), 20 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
nits below
diff --git a/arch/arm/include/asm/arch-zynqmp/hardware.h b/arch/arm/include/asm/arch-zynqmp/hardware.h index e7738faaf896..d1970953e234 100644 --- a/arch/arm/include/asm/arch-zynqmp/hardware.h +++ b/arch/arm/include/asm/arch-zynqmp/hardware.h @@ -18,8 +18,6 @@
#define ARASAN_NAND_BASEADDR 0xFF100000
-#define ZYNQMP_SATA_BASEADDR 0xFD0C0000
#define ZYNQMP_USB0_XHCI_BASEADDR 0xFE200000 #define ZYNQMP_USB1_XHCI_BASEADDR 0xFE300000
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index cef1f6a13aee..a23c38acd99d 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -311,17 +311,6 @@ void reset_cpu(ulong addr) { }
-#ifdef CONFIG_SCSI_AHCI_PLAT -void scsi_init(void) -{ -#if defined(CONFIG_SATA_CEVA)
init_sata(0);
-#endif
ahci_init((void __iomem *)ZYNQMP_SATA_BASEADDR);
scsi_scan(1);
-} -#endif
int board_late_init(void) { u32 reg = 0; diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig index f3cdf90c1f73..8d6a6cf5701e 100644 --- a/configs/xilinx_zynqmp_ep_defconfig +++ b/configs/xilinx_zynqmp_ep_defconfig @@ -49,6 +49,8 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DM_SCSI=y +CONFIG_SATA_CEVA=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/configs/xilinx_zynqmp_zcu102_defconfig b/configs/xilinx_zynqmp_zcu102_defconfig index fa6d6692040e..7e5e83fdc043 100644 --- a/configs/xilinx_zynqmp_zcu102_defconfig +++ b/configs/xilinx_zynqmp_zcu102_defconfig @@ -41,6 +41,8 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DM_SCSI=y +CONFIG_SATA_CEVA=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig index a4af8024e454..f57705b2cba9 100644 --- a/configs/xilinx_zynqmp_zcu102_revB_defconfig +++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig @@ -41,6 +41,8 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DM_SCSI=y +CONFIG_SATA_CEVA=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 55edae71eec3..0b289b2fc111 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -34,3 +34,9 @@ config BLOCK_CACHE This is most useful when accessing filesystems under U-Boot since it will prevent repeated reads from directory structures and other filesystem data structures.
+config SATA_CEVA
bool "Ceva Sata controller"
depends on DM_SCSI
help
This option enables Ceva Sata controller available on Xilinx ZynqMP.
Can you add more detail? What does it support? Is this soft IP?
Added
config SATA_CEVA bool "Ceva Sata controller" 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.
diff --git a/drivers/block/sata_ceva.c b/drivers/block/sata_ceva.c index dcc3b90b17f1..3f40b7efb6fa 100644 --- a/drivers/block/sata_ceva.c +++ b/drivers/block/sata_ceva.c @@ -9,6 +9,7 @@ #include <ahci.h> #include <scsi.h> #include <asm/arch/hardware.h> +#include <dm.h>
please put these in order with http://www.denx.de/wiki/U-Boot/CodingStyle
Fixed.
#include <asm/io.h>
@@ -73,10 +74,9 @@ #define DRV_NAME "ahci-ceva" #define CEVA_FLAG_BROKEN_GEN2 1
-int init_sata(int dev) +static int ceva_init_sata(ulong mmio) { ulong tmp;
ulong mmio = ZYNQMP_SATA_BASEADDR; int i; /*
@@ -111,3 +111,40 @@ int init_sata(int dev) } return 0; }
+static int sata_ceva_probe(struct udevice *dev) +{
struct scsi_platdata *plat = dev_get_platdata(dev);
ceva_init_sata(plat->base);
return 0;
+}
+static const struct udevice_id sata_ceva_ids[] = {
{ .compatible = "ceva,ahci-1v84" },
{ }
+};
+static int sata_ceva_ofdata_to_platdata(struct udevice *dev) +{
struct scsi_platdata *plat = dev_get_platdata(dev);
plat->base = dev_get_addr(dev);
if (plat->base == FDT_ADDR_T_NONE)
return -EINVAL;
/* Hardcode number for ceva sata controller */
plat->max_lun = 1; /* Actually two but untested */
plat->max_id = 2;
return 0;
+}
+U_BOOT_DRIVER(ceva_host_blk) = {
.name = "ceva_sata",
.id = UCLASS_SCSI,
.of_match = sata_ceva_ids,
.probe = sata_ceva_probe,
.ofdata_to_platdata = sata_ceva_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct scsi_platdata),
+}; diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h index 7452e92ff8da..673c864ebc6f 100644 --- a/include/configs/xilinx_zynqmp.h +++ b/include/configs/xilinx_zynqmp.h @@ -182,15 +182,16 @@ # define CONFIG_SYS_EEPROM_SIZE (64 * 1024) #endif
-#ifdef CONFIG_SATA_CEVA +#if defined(CONFIG_SATA_CEVA) && !defined(CONFIG_SPL_BUILD) #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI -#define CONFIG_SCSI_AHCI_PLAT #define CONFIG_SYS_SCSI_MAX_SCSI_ID 2 #define CONFIG_SYS_SCSI_MAX_LUN 1 #define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ CONFIG_SYS_SCSI_MAX_LUN) #define CONFIG_SCSI +#else +#undef CONFIG_SATA_CEVA
Are you trying to undefine it for SPL? I suspect DM_SCSI already does this, but you should do this in the Makefile (ifndef CONFIG_SPL_BUILD) or perhaps create CONFIG_SPL_SATA_CEVA if you might want to add it to SPL.
We should not #undef Kconfig options.
you are right - this is not needed now.
#endif
#define CONFIG_SYS_BOOTM_LEN (60 * 1024 * 1024) diff --git a/include/configs/xilinx_zynqmp_ep.h b/include/configs/xilinx_zynqmp_ep.h index d0ce768e6e14..3a572b7a6c2f 100644 --- a/include/configs/xilinx_zynqmp_ep.h +++ b/include/configs/xilinx_zynqmp_ep.h @@ -16,7 +16,6 @@ #define CONFIG_ZYNQ_SDHCI_MAX_FREQ 52000000 #define CONFIG_ZYNQ_SDHCI_MIN_FREQ (CONFIG_ZYNQ_SDHCI_MAX_FREQ >> 9) #define CONFIG_ZYNQ_EEPROM -#define CONFIG_SATA_CEVA #define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR, \ ZYNQMP_USB1_XHCI_BASEADDR}
diff --git a/include/configs/xilinx_zynqmp_zcu102.h b/include/configs/xilinx_zynqmp_zcu102.h index adf2321c5d4f..8d018da23e34 100644 --- a/include/configs/xilinx_zynqmp_zcu102.h +++ b/include/configs/xilinx_zynqmp_zcu102.h @@ -41,8 +41,6 @@ #define CONFIG_CMD_PCA953X #define CONFIG_CMD_PCA953X_INFO
-#define CONFIG_SATA_CEVA
#define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR}
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
1.9.1
Thanks, Michal
participants (2)
-
Michal Simek
-
Simon Glass