Commit bce4d18c9d96ffb16f2c9bb4f0549543c5c7e240
1 parent
3cfb67d041
Exists in
v2017.01-smarct4x
and in
25 other branches
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
common/board_r.c
... | ... | @@ -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 |
common/scsi.c
... | ... | @@ -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
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 | +}; |
include/ahci.h
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 */ |
include/sata.h
... | ... | @@ -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 |
include/scsi.h
... | ... | @@ -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 |