Commit bce4d18c9d96ffb16f2c9bb4f0549543c5c7e240

Authored by Michal Simek
1 parent 3cfb67d041

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>
Series-changes: 2
- 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

Series-changes: 3
- Fix scsi_scan return path
- Fix header location uclass-internal.h
- Add scsi_max_devs under !DM_SCSI
- Add new header device-internal because of device_probe()
- Redesign block device creation algorithm
- Use device_unbind in error path
- Create block device with id and lun numbers (lun was there in v2)
- Cleanup dev_num initialization in block device description
  with fixing parameters in blk_create_devicef
- Create new Kconfig menu for SATA/SCSI drivers
- Extend description for DM_SCSI
- Fix Kconfig dependencies
- Fix kernel doc format in scsi_platdata
- Fix ahci_init_one - vendor variable

Series-changes: 4
- Fix Kconfig entry
- Remove SPL ifdef around SCSI uclass
- Clean ahci_print_info() ifdef logic

Showing 11 changed files with 165 additions and 13 deletions Side-by-side Diff

... ... @@ -620,7 +620,7 @@
620 620 }
621 621 #endif
622 622  
623   -#if defined(CONFIG_SCSI)
  623 +#if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI)
624 624 static int initr_scsi(void)
625 625 {
626 626 puts("SCSI: ");
... ... @@ -923,7 +923,7 @@
923 923 initr_ambapp_print,
924 924 #endif
925 925 #endif
926   -#ifdef CONFIG_SCSI
  926 +#if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI)
927 927 INIT_FUNC_WATCHDOG_RESET
928 928 initr_scsi,
929 929 #endif
... ... @@ -10,7 +10,10 @@
10 10 #include <inttypes.h>
11 11 #include <pci.h>
12 12 #include <scsi.h>
  13 +#include <dm/device-internal.h>
  14 +#include <dm/uclass-internal.h>
13 15  
  16 +#if !defined(CONFIG_DM_SCSI)
14 17 #ifdef CONFIG_SCSI_DEV_LIST
15 18 #define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST
16 19 #else
... ... @@ -31,6 +34,7 @@
31 34 #endif
32 35 #define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID}
33 36 #endif
  37 +#endif
34 38  
35 39 #if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
36 40 const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
37 41  
... ... @@ -39,11 +43,13 @@
39 43  
40 44 static unsigned char tempbuff[512]; /* temporary data buffer */
41 45  
  46 +#if !defined(CONFIG_DM_SCSI)
42 47 static int scsi_max_devs; /* number of highest available scsi device */
43 48  
44 49 static int scsi_curr_dev; /* current device */
45 50  
46 51 static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
  52 +#endif
47 53  
48 54 /* almost the maximum amount of the scsi_ext command.. */
49 55 #define SCSI_MAX_READ_BLK 0xFFFF
... ... @@ -444,6 +450,7 @@
444 450 #endif
445 451 }
446 452  
  453 +#if !defined(CONFIG_DM_SCSI)
447 454 /**
448 455 * scsi_init_dev_desc - initialize all SCSI specific blk_desc properties
449 456 *
... ... @@ -460,6 +467,7 @@
460 467  
461 468 scsi_init_dev_desc_priv(dev_desc);
462 469 }
  470 +#endif
463 471  
464 472 /**
465 473 * scsi_detect_dev - Detect scsi device
466 474  
467 475  
... ... @@ -540,13 +548,80 @@
540 548 * (re)-scan the scsi bus and reports scsi device info
541 549 * to the user if mode = 1
542 550 */
  551 +#if defined(CONFIG_DM_SCSI)
543 552 int scsi_scan(int mode)
544 553 {
545 554 unsigned char i, lun;
  555 + struct uclass *uc;
  556 + struct udevice *dev; /* SCSI controller */
546 557 int ret;
547 558  
548 559 if (mode == 1)
549 560 printf("scanning bus for devices...\n");
  561 +
  562 + ret = uclass_get(UCLASS_SCSI, &uc);
  563 + if (ret)
  564 + return ret;
  565 +
  566 + uclass_foreach_dev(dev, uc) {
  567 + struct scsi_platdata *plat; /* scsi controller platdata */
  568 +
  569 + /* probe SCSI controller driver */
  570 + ret = device_probe(dev);
  571 + if (ret)
  572 + return ret;
  573 +
  574 + /* Get controller platdata */
  575 + plat = dev_get_platdata(dev);
  576 +
  577 + for (i = 0; i < plat->max_id; i++) {
  578 + for (lun = 0; lun < plat->max_lun; lun++) {
  579 + struct udevice *bdev; /* block device */
  580 + /* block device description */
  581 + struct blk_desc *bdesc;
  582 + char str[10];
  583 +
  584 + /*
  585 + * Create only one block device and do detection
  586 + * to make sure that there won't be a lot of
  587 + * block devices created
  588 + */
  589 + snprintf(str, sizeof(str), "id%dlun%d", i, lun);
  590 + ret = blk_create_devicef(dev, "scsi_blk",
  591 + str, IF_TYPE_SCSI,
  592 + -1, 0, 0, &bdev);
  593 + if (ret) {
  594 + debug("Can't create device\n");
  595 + return ret;
  596 + }
  597 + bdesc = dev_get_uclass_platdata(bdev);
  598 +
  599 + scsi_init_dev_desc_priv(bdesc);
  600 + bdesc->lun = lun;
  601 + ret = scsi_detect_dev(i, bdesc);
  602 + if (ret) {
  603 + device_unbind(bdev);
  604 + continue;
  605 + }
  606 +
  607 + if (mode == 1) {
  608 + printf(" Device %d: ", 0);
  609 + dev_print(bdesc);
  610 + } /* if mode */
  611 + } /* next LUN */
  612 + }
  613 + }
  614 +
  615 + return 0;
  616 +}
  617 +#else
  618 +int scsi_scan(int mode)
  619 +{
  620 + unsigned char i, lun;
  621 + int ret;
  622 +
  623 + if (mode == 1)
  624 + printf("scanning bus for devices...\n");
550 625 for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++)
551 626 scsi_init_dev_desc(&scsi_dev_desc[i], i);
552 627  
... ... @@ -576,6 +651,7 @@
576 651 #endif
577 652 return 0;
578 653 }
  654 +#endif
579 655  
580 656 #ifdef CONFIG_BLK
581 657 static const struct blk_ops scsi_blk_ops = {
drivers/block/Kconfig
... ... @@ -19,6 +19,15 @@
19 19 operations at present. The block device interface has not been converted
20 20 to driver model.
21 21  
  22 +config DM_SCSI
  23 + bool "Support SCSI controllers with driver model"
  24 + depends on BLK
  25 + help
  26 + This option enables the SCSI (Small Computer System Interface) uclass
  27 + which supports SCSI and SATA HDDs. For every device configuration
  28 + (IDs/LUNs) a block device is created with RAW read/write and
  29 + filesystem support.
  30 +
22 31 config BLOCK_CACHE
23 32 bool "Use block device cache"
24 33 default n
... ... @@ -27,4 +36,8 @@
27 36 This is most useful when accessing filesystems under U-Boot since
28 37 it will prevent repeated reads from directory structures and other
29 38 filesystem data structures.
  39 +
  40 +menu "SATA/SCSI device support"
  41 +
  42 +endmenu
drivers/block/Makefile
... ... @@ -12,6 +12,7 @@
12 12 endif
13 13  
14 14 obj-$(CONFIG_AHCI) += ahci-uclass.o
  15 +obj-$(CONFIG_DM_SCSI) += scsi-uclass.o
15 16 obj-$(CONFIG_SCSI_AHCI) += ahci.o
16 17 obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o
17 18 obj-$(CONFIG_FSL_SATA) += fsl_sata.o
drivers/block/ahci.c
... ... @@ -168,7 +168,7 @@
168 168  
169 169 static int ahci_host_init(struct ahci_probe_ent *probe_ent)
170 170 {
171   -#ifndef CONFIG_SCSI_AHCI_PLAT
  171 +#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI)
172 172 # ifdef CONFIG_DM_PCI
173 173 struct udevice *dev = probe_ent->dev;
174 174 struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
... ... @@ -198,7 +198,7 @@
198 198 writel(cap_save, mmio + HOST_CAP);
199 199 writel_with_flush(0xf, mmio + HOST_PORTS_IMPL);
200 200  
201   -#ifndef CONFIG_SCSI_AHCI_PLAT
  201 +#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI)
202 202 # ifdef CONFIG_DM_PCI
203 203 if (pplat->vendor == PCI_VENDOR_ID_INTEL) {
204 204 u16 tmp16;
... ... @@ -327,6 +327,7 @@
327 327 writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
328 328 tmp = readl(mmio + HOST_CTL);
329 329 debug("HOST_CTL 0x%x\n", tmp);
  330 +#if !defined(CONFIG_DM_SCSI)
330 331 #ifndef CONFIG_SCSI_AHCI_PLAT
331 332 # ifdef CONFIG_DM_PCI
332 333 dm_pci_read_config16(dev, PCI_COMMAND, &tmp16);
333 334  
... ... @@ -338,14 +339,15 @@
338 339 pci_write_config_word(pdev, PCI_COMMAND, tmp16);
339 340 # endif
340 341 #endif
  342 +#endif
341 343 return 0;
342 344 }
343 345  
344 346  
345 347 static void ahci_print_info(struct ahci_probe_ent *probe_ent)
346 348 {
347   -#ifndef CONFIG_SCSI_AHCI_PLAT
348   -# ifdef CONFIG_DM_PCI
  349 +#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI)
  350 +# if defined(CONFIG_DM_PCI)
349 351 struct udevice *dev = probe_ent->dev;
350 352 # else
351 353 pci_dev_t pdev = probe_ent->dev;
... ... @@ -372,7 +374,7 @@
372 374 else
373 375 speed_s = "?";
374 376  
375   -#ifdef CONFIG_SCSI_AHCI_PLAT
  377 +#if defined(CONFIG_SCSI_AHCI_PLAT) || defined(CONFIG_DM_SCSI)
376 378 scc_s = "SATA";
377 379 #else
378 380 # ifdef CONFIG_DM_PCI
379 381  
380 382  
... ... @@ -424,13 +426,15 @@
424 426 }
425 427  
426 428 #ifndef CONFIG_SCSI_AHCI_PLAT
427   -# ifdef CONFIG_DM_PCI
  429 +# if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI)
428 430 static int ahci_init_one(struct udevice *dev)
429 431 # else
430 432 static int ahci_init_one(pci_dev_t dev)
431 433 # endif
432 434 {
  435 +#if !defined(CONFIG_DM_SCSI)
433 436 u16 vendor;
  437 +#endif
434 438 int rc;
435 439  
436 440 probe_ent = malloc(sizeof(struct ahci_probe_ent));
... ... @@ -450,6 +454,7 @@
450 454 probe_ent->pio_mask = 0x1f;
451 455 probe_ent->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */
452 456  
  457 +#if !defined(CONFIG_DM_SCSI)
453 458 #ifdef CONFIG_DM_PCI
454 459 probe_ent->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5,
455 460 PCI_REGION_MEM);
... ... @@ -473,6 +478,10 @@
473 478 if (vendor == 0x197b)
474 479 pci_write_config_byte(dev, 0x41, 0xa1);
475 480 #endif
  481 +#else
  482 + struct scsi_platdata *plat = dev_get_platdata(dev);
  483 + probe_ent->mmio_base = (void *)plat->base;
  484 +#endif
476 485  
477 486 debug("ahci mmio_base=0x%p\n", probe_ent->mmio_base);
478 487 /* initialize adapter */
479 488  
480 489  
481 490  
... ... @@ -954,20 +963,25 @@
954 963  
955 964 }
956 965  
957   -
  966 +#if defined(CONFIG_DM_SCSI)
  967 +void scsi_low_level_init(int busdevfunc, struct udevice *dev)
  968 +#else
958 969 void scsi_low_level_init(int busdevfunc)
  970 +#endif
959 971 {
960 972 int i;
961 973 u32 linkmap;
962 974  
963 975 #ifndef CONFIG_SCSI_AHCI_PLAT
964   -# ifdef CONFIG_DM_PCI
  976 +# if defined(CONFIG_DM_PCI)
965 977 struct udevice *dev;
966 978 int ret;
967 979  
968 980 ret = dm_pci_bus_find_bdf(busdevfunc, &dev);
969 981 if (ret)
970 982 return;
  983 + ahci_init_one(dev);
  984 +# elif defined(CONFIG_DM_SCSI)
971 985 ahci_init_one(dev);
972 986 # else
973 987 ahci_init_one(busdevfunc);
drivers/block/blk-uclass.c
... ... @@ -26,7 +26,7 @@
26 26  
27 27 static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
28 28 [IF_TYPE_IDE] = UCLASS_INVALID,
29   - [IF_TYPE_SCSI] = UCLASS_INVALID,
  29 + [IF_TYPE_SCSI] = UCLASS_SCSI,
30 30 [IF_TYPE_ATAPI] = UCLASS_INVALID,
31 31 [IF_TYPE_USB] = UCLASS_MASS_STORAGE,
32 32 [IF_TYPE_DOC] = UCLASS_INVALID,
drivers/block/scsi-uclass.c
  1 +/*
  2 + * Copyright (c) 2015 Google, Inc
  3 + * Written by Simon Glass <sjg@chromium.org>
  4 + * Copyright (c) 2016 Xilinx, Inc
  5 + * Written by Michal Simek
  6 + *
  7 + * Based on ahci-uclass.c
  8 + *
  9 + * SPDX-License-Identifier: GPL-2.0+
  10 + */
  11 +
  12 +#include <common.h>
  13 +#include <dm.h>
  14 +#include <scsi.h>
  15 +
  16 +static int scsi_post_probe(struct udevice *dev)
  17 +{
  18 + debug("%s: device %p\n", __func__, dev);
  19 + scsi_low_level_init(0, dev);
  20 + return 0;
  21 +}
  22 +
  23 +UCLASS_DRIVER(scsi) = {
  24 + .id = UCLASS_SCSI,
  25 + .name = "scsi",
  26 + .post_probe = scsi_post_probe,
  27 +};
... ... @@ -145,7 +145,7 @@
145 145 };
146 146  
147 147 struct ahci_probe_ent {
148   -#ifdef CONFIG_DM_PCI
  148 +#if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI)
149 149 struct udevice *dev;
150 150 #else
151 151 pci_dev_t dev;
include/dm/uclass-id.h
... ... @@ -66,6 +66,7 @@
66 66 UCLASS_REMOTEPROC, /* Remote Processor device */
67 67 UCLASS_RESET, /* Reset controller device */
68 68 UCLASS_RTC, /* Real time clock device */
  69 + UCLASS_SCSI, /* SCSI device */
69 70 UCLASS_SERIAL, /* Serial UART */
70 71 UCLASS_SPI, /* SPI bus */
71 72 UCLASS_SPMI, /* System Power Management Interface bus */
... ... @@ -2,6 +2,7 @@
2 2 #define __SATA_H__
3 3 #include <part.h>
4 4  
  5 +#if !defined(CONFIG_DM_SCSI)
5 6 int init_sata(int dev);
6 7 int reset_sata(int dev);
7 8 int scan_sata(int dev);
... ... @@ -15,6 +16,7 @@
15 16 int sata_port_status(int dev, int port);
16 17  
17 18 extern struct blk_desc sata_dev_desc[];
  19 +#endif
18 20  
19 21 #endif
... ... @@ -166,14 +166,32 @@
166 166 void scsi_print_error(ccb *pccb);
167 167 int scsi_exec(ccb *pccb);
168 168 void scsi_bus_reset(void);
  169 +#if !defined(CONFIG_DM_SCSI)
169 170 void scsi_low_level_init(int busdevfunc);
  171 +#else
  172 +void scsi_low_level_init(int busdevfunc, struct udevice *dev);
  173 +#endif
170 174  
171   -
172 175 /***************************************************************************
173 176 * functions residing inside cmd_scsi.c
174 177 */
175 178 void scsi_init(void);
176 179 int scsi_scan(int mode);
  180 +
  181 +#if defined(CONFIG_DM_SCSI)
  182 +/**
  183 + * struct scsi_platdata - stores information about SCSI controller
  184 + *
  185 + * @base: Controller base address
  186 + * @max_lun: Maximum number of logical units
  187 + * @max_id: Maximum number of target ids
  188 + */
  189 +struct scsi_platdata {
  190 + unsigned long base;
  191 + unsigned long max_lun;
  192 + unsigned long max_id;
  193 +};
  194 +#endif
177 195  
178 196 #define SCSI_IDENTIFY 0xC0 /* not used */
179 197