summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2016-05-17 13:58:27 -0400
committerTom Rini <trini@konsulko.com>2016-05-17 13:58:27 -0400
commit4b6e1fda107e5244e80ebc41865650ac2873dc88 (patch)
treef448089740af77c2987d12e2dd5b753b7659586f
parent27bec5c12757c80f598b704477c1bc6c250bcb4c (diff)
parent341392dd115f1385c31bb0b034ec15f542730e30 (diff)
downloadu-boot-imx-4b6e1fda107e5244e80ebc41865650ac2873dc88.zip
u-boot-imx-4b6e1fda107e5244e80ebc41865650ac2873dc88.tar.gz
u-boot-imx-4b6e1fda107e5244e80ebc41865650ac2873dc88.tar.bz2
Merge git://git.denx.de/u-boot-dm
-rw-r--r--README4
-rw-r--r--api/api_storage.c2
-rw-r--r--arch/arm/dts/exynos4210-universal_c210.dts10
-rw-r--r--arch/arm/dts/tegra20-seaboard.dts4
-rw-r--r--arch/arm/include/asm/arch-ls102xa/config.h2
-rw-r--r--arch/m68k/cpu/mcf5227x/start.S25
-rw-r--r--arch/m68k/cpu/mcf523x/start.S27
-rw-r--r--arch/m68k/cpu/mcf52x2/start.S26
-rw-r--r--arch/m68k/cpu/mcf530x/cpu_init.c2
-rw-r--r--arch/m68k/cpu/mcf530x/start.S25
-rw-r--r--arch/m68k/cpu/mcf532x/start.S27
-rw-r--r--arch/m68k/cpu/mcf5445x/start.S27
-rw-r--r--arch/m68k/cpu/mcf547x_8x/start.S25
-rw-r--r--arch/m68k/include/asm/config.h2
-rw-r--r--arch/sandbox/include/asm/io.h15
-rw-r--r--arch/x86/Kconfig3
-rw-r--r--arch/x86/cpu/broadwell/sata.c2
-rw-r--r--arch/x86/cpu/intel_common/cpu.c2
-rw-r--r--arch/x86/cpu/ivybridge/bd82x6x.c2
-rw-r--r--arch/x86/cpu/ivybridge/sata.c2
-rw-r--r--board/cm5200/fwupdate.c2
-rw-r--r--board/mpl/pip405/README6
-rw-r--r--board/sandbox/MAINTAINERS7
-rw-r--r--cmd/Makefile8
-rw-r--r--cmd/disk.c2
-rw-r--r--cmd/ide.c1352
-rw-r--r--cmd/mmc.c18
-rw-r--r--cmd/sata.c142
-rw-r--r--cmd/scsi.c753
-rw-r--r--cmd/usb.c16
-rw-r--r--common/Makefile6
-rw-r--r--common/board_r.c4
-rw-r--r--common/env_mmc.c6
-rw-r--r--common/ide.c1231
-rw-r--r--common/sata.c115
-rw-r--r--common/scsi.c592
-rw-r--r--common/spl/spl_mmc.c2
-rw-r--r--common/spl/spl_sata.c2
-rw-r--r--common/spl/spl_usb.c2
-rw-r--r--common/usb_storage.c37
-rw-r--r--configs/sandbox_defconfig2
-rw-r--r--configs/sandbox_noblk_defconfig168
-rw-r--r--disk/part.c83
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/block/Kconfig5
-rw-r--r--drivers/block/Makefile8
-rw-r--r--drivers/block/ahci-uclass.c (renamed from drivers/block/disk-uclass.c)6
-rw-r--r--drivers/block/blk-uclass.c361
-rw-r--r--drivers/block/blk_legacy.c261
-rw-r--r--drivers/block/sandbox.c103
-rw-r--r--drivers/block/sandbox_scsi.c29
-rw-r--r--drivers/block/sata_sandbox.c33
-rw-r--r--drivers/block/sym53c8xx.c2
-rw-r--r--drivers/block/systemace.c110
-rw-r--r--drivers/core/device-remove.c2
-rw-r--r--drivers/core/device.c10
-rw-r--r--drivers/core/lists.c4
-rw-r--r--drivers/dfu/dfu_mmc.c13
-rw-r--r--drivers/gpio/74x164_gpio.c193
-rw-r--r--drivers/gpio/Kconfig30
-rw-r--r--drivers/gpio/Makefile3
-rw-r--r--drivers/gpio/gpio-uclass.c30
-rw-r--r--drivers/gpio/intel_broadwell_gpio.c10
-rw-r--r--drivers/gpio/omap_gpio.c11
-rw-r--r--drivers/gpio/pca953x_gpio.c351
-rw-r--r--drivers/gpio/pic32_gpio.c10
-rw-r--r--drivers/gpio/rk_gpio.c11
-rw-r--r--drivers/gpio/s5p_gpio.c11
-rw-r--r--drivers/mmc/Kconfig11
-rw-r--r--drivers/mmc/Makefile12
-rw-r--r--drivers/mmc/mmc-uclass.c106
-rw-r--r--drivers/mmc/mmc.c311
-rw-r--r--drivers/mmc/mmc_legacy.c108
-rw-r--r--drivers/mmc/mmc_private.h33
-rw-r--r--drivers/mmc/mmc_write.c18
-rw-r--r--drivers/mmc/omap_hsmmc.c1
-rw-r--r--drivers/mmc/pic32_sdhci.c7
-rw-r--r--drivers/mmc/rockchip_dw_mmc.c1
-rw-r--r--drivers/mmc/sandbox_mmc.c134
-rw-r--r--drivers/mmc/socfpga_dw_mmc.c1
-rw-r--r--drivers/mmc/uniphier-sd.c1
-rw-r--r--drivers/mmc/zynq_sdhci.c1
-rw-r--r--drivers/pci/pci.c4
-rw-r--r--drivers/serial/mcfuart.c188
-rw-r--r--drivers/spi/soft_spi.c55
-rw-r--r--drivers/spi/spi-uclass.c28
-rw-r--r--drivers/usb/common/Makefile1
-rw-r--r--drivers/usb/common/common.c40
-rw-r--r--drivers/video/tegra.c7
-rw-r--r--fs/fat/fat.c2
-rw-r--r--include/asm-generic/gpio.h19
-rw-r--r--include/blk.h263
-rw-r--r--include/config_cmd_all.h2
-rw-r--r--include/config_distro_bootcmd.h6
-rw-r--r--include/config_fallbacks.h2
-rw-r--r--include/configs/MPC8544DS.h2
-rw-r--r--include/configs/MPC8572DS.h2
-rw-r--r--include/configs/MPC8610HPCD.h2
-rw-r--r--include/configs/MPC8641HPCN.h4
-rw-r--r--include/configs/PIP405.h2
-rw-r--r--include/configs/am57xx_evm.h2
-rw-r--r--include/configs/cm_t54.h2
-rw-r--r--include/configs/db-88f6820-gp.h2
-rw-r--r--include/configs/dra7xx_evm.h2
-rw-r--r--include/configs/efi-x86.h2
-rw-r--r--include/configs/galileo.h2
-rw-r--r--include/configs/highbank.h2
-rw-r--r--include/configs/ls1043aqds.h2
-rw-r--r--include/configs/ls2080aqds.h2
-rw-r--r--include/configs/ls2080ardb.h2
-rw-r--r--include/configs/omap5_uevm.h2
-rw-r--r--include/configs/qemu-x86.h2
-rw-r--r--include/configs/sandbox.h25
-rw-r--r--include/configs/sbc8641d.h2
-rw-r--r--include/configs/sunxi-common.h2
-rw-r--r--include/configs/x86-common.h2
-rw-r--r--include/configs/xilinx_zynqmp.h2
-rw-r--r--include/dm/device.h16
-rw-r--r--include/dm/platform_data/serial_coldfire.h23
-rw-r--r--include/dm/uclass-id.h2
-rw-r--r--include/ide.h8
-rw-r--r--include/iotrace.h5
-rw-r--r--include/linux/usb/otg.h9
-rw-r--r--include/mmc.h38
-rw-r--r--include/part.h33
-rw-r--r--include/spi.h52
-rw-r--r--include/systemace.h17
-rw-r--r--include/usb.h1
-rw-r--r--lib/efi_loader/efi_disk.c27
-rw-r--r--test/dm/blk.c4
-rw-r--r--test/dm/mmc.c19
-rw-r--r--tools/buildman/README42
-rw-r--r--tools/buildman/builder.py10
-rw-r--r--tools/buildman/builderthread.py24
-rw-r--r--tools/buildman/cmdline.py4
-rw-r--r--tools/buildman/control.py4
136 files changed, 5419 insertions, 2749 deletions
diff --git a/README b/README
index d881da2..94e9943 100644
--- a/README
+++ b/README
@@ -1066,7 +1066,7 @@ The following options need to be configured:
CONFIG_CMD_RUN run command in env variable
CONFIG_CMD_SANDBOX * sb command to access sandbox features
CONFIG_CMD_SAVES * save S record dump
- CONFIG_CMD_SCSI * SCSI Support
+ CONFIG_SCSI * SCSI Support
CONFIG_CMD_SDRAM * print SDRAM configuration information
(requires CONFIG_CMD_I2C)
CONFIG_CMD_SETGETDCR Support for DCR Register access
@@ -1254,7 +1254,7 @@ The following options need to be configured:
CONFIG_MTD_PARTITIONS Memory Technology Device partition table.
If IDE or SCSI support is enabled (CONFIG_CMD_IDE or
- CONFIG_CMD_SCSI) you must configure support for at
+ CONFIG_SCSI) you must configure support for at
least one non-MTD partition type as well.
- IDE Reset method:
diff --git a/api/api_storage.c b/api/api_storage.c
index 8c30c56..d425a9a 100644
--- a/api/api_storage.c
+++ b/api/api_storage.c
@@ -67,7 +67,7 @@ void dev_stor_init(void)
specs[ENUM_SATA].type = DEV_TYP_STOR | DT_STOR_SATA;
specs[ENUM_SATA].name = "sata";
#endif
-#if defined(CONFIG_CMD_SCSI)
+#if defined(CONFIG_SCSI)
specs[ENUM_SCSI].max_dev = CONFIG_SYS_SCSI_MAX_DEVICE;
specs[ENUM_SCSI].enum_started = 0;
specs[ENUM_SCSI].enum_ended = 0;
diff --git a/arch/arm/dts/exynos4210-universal_c210.dts b/arch/arm/dts/exynos4210-universal_c210.dts
index 16948c9..ad3527e 100644
--- a/arch/arm/dts/exynos4210-universal_c210.dts
+++ b/arch/arm/dts/exynos4210-universal_c210.dts
@@ -42,11 +42,11 @@
};
soft-spi {
- compatible = "u-boot,soft-spi";
- cs-gpio = <&gpy4 3 0>;
- sclk-gpio = <&gpy3 1 0>;
- mosi-gpio = <&gpy3 3 0>;
- miso-gpio = <&gpy3 0 0>;
+ compatible = "spi-gpio";
+ cs-gpios = <&gpy4 3 0>;
+ gpio-sck = <&gpy3 1 0>;
+ gpio-mosi = <&gpy3 3 0>;
+ gpio-miso = <&gpy3 0 0>;
spi-delay-us = <1>;
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/dts/tegra20-seaboard.dts b/arch/arm/dts/tegra20-seaboard.dts
index eada590..5893d2a 100644
--- a/arch/arm/dts/tegra20-seaboard.dts
+++ b/arch/arm/dts/tegra20-seaboard.dts
@@ -40,10 +40,6 @@
nvidia,panel = <&lcd_panel>;
};
};
-
- dc@54240000 {
- status = "disabled";
- };
};
/* This is not used in U-Boot, but is expected to be in kernel .dts */
diff --git a/arch/arm/include/asm/arch-ls102xa/config.h b/arch/arm/include/asm/arch-ls102xa/config.h
index 267bd17..d77c04a 100644
--- a/arch/arm/include/asm/arch-ls102xa/config.h
+++ b/arch/arm/include/asm/arch-ls102xa/config.h
@@ -82,7 +82,7 @@
/* SATA */
#define AHCI_BASE_ADDR (CONFIG_SYS_IMMR + 0x02200000)
#define CONFIG_BOARD_LATE_INIT
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#define CONFIG_LIBATA
#define CONFIG_SCSI_AHCI
#define CONFIG_SCSI_AHCI_PLAT
diff --git a/arch/m68k/cpu/mcf5227x/start.S b/arch/m68k/cpu/mcf5227x/start.S
index 23024f9..13c036f 100644
--- a/arch/m68k/cpu/mcf5227x/start.S
+++ b/arch/m68k/cpu/mcf5227x/start.S
@@ -372,14 +372,29 @@ _start:
move.l %d0, (%a1)
move.l %d0, (%a2)
- /* set stackpointer to end of internal ram to get some stackspace for
- the first c-code */
- move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
- clr.l %sp@-
+ /* put relocation table address to a5 */
+ move.l #__got_start, %a5
+
+ /* setup stack initially on top of internal static ram */
+ move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
+
+ /*
+ * if configured, malloc_f arena will be reserved first,
+ * then (and always) gd struct space will be reserved
+ */
+ move.l %sp, -(%sp)
+ bsr board_init_f_alloc_reserve
+
+ /* update stack and frame-pointers */
+ move.l %d0, %sp
+ move.l %sp, %fp
- move.l #__got_start, %a5 /* put relocation table address to a5 */
+ /* initialize reserved area */
+ move.l %d0, -(%sp)
+ bsr board_init_f_init_reserve
bsr cpu_init_f /* run low-level CPU init code (from flash) */
+ clr.l %sp@-
bsr board_init_f /* run low-level board init code (from flash) */
/* board_init_f() does not return */
diff --git a/arch/m68k/cpu/mcf523x/start.S b/arch/m68k/cpu/mcf523x/start.S
index 1702f98..3aa4dd6 100644
--- a/arch/m68k/cpu/mcf523x/start.S
+++ b/arch/m68k/cpu/mcf523x/start.S
@@ -134,17 +134,34 @@ _start:
move.l %d0, (%a1)
move.l %d0, (%a2)
- /* set stackpointer to end of internal ram to get some stackspace for the
- first c-code */
- move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
- clr.l %sp@-
+ /* put relocation table address to a5 */
+ move.l #__got_start, %a5
- move.l #__got_start, %a5 /* put relocation table address to a5 */
+ /* setup stack initially on top of internal static ram */
+ move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
+
+ /*
+ * if configured, malloc_f arena will be reserved first,
+ * then (and always) gd struct space will be reserved
+ */
+ move.l %sp, -(%sp)
+ move.l #board_init_f_alloc_reserve, %a1
+ jsr (%a1)
+
+ /* update stack and frame-pointers */
+ move.l %d0, %sp
+ move.l %sp, %fp
+
+ /* initialize reserved area */
+ move.l %d0, -(%sp)
+ move.l #board_init_f_init_reserve, %a1
+ jsr (%a1)
/* run low-level CPU init code (from flash) */
move.l #cpu_init_f, %a1
jsr (%a1)
/* run low-level board init code (from flash) */
+ clr.l %sp@-
move.l #board_init_f, %a1
jsr (%a1)
diff --git a/arch/m68k/cpu/mcf52x2/start.S b/arch/m68k/cpu/mcf52x2/start.S
index 4af691f..a048884 100644
--- a/arch/m68k/cpu/mcf52x2/start.S
+++ b/arch/m68k/cpu/mcf52x2/start.S
@@ -192,16 +192,34 @@ _after_flashbar_copy:
move.l %d0, (%a1)
move.l %d0, (%a2)
- /* set stackpointer to end of internal ram to get some stackspace for the first c-code */
- move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
- clr.l %sp@-
+ /* put relocation table address to a5 */
+ move.l #__got_start, %a5
- move.l #__got_start, %a5 /* put relocation table address to a5 */
+ /* setup stack initially on top of internal static ram */
+ move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
+
+ /*
+ * if configured, malloc_f arena will be reserved first,
+ * then (and always) gd struct space will be reserved
+ */
+ move.l %sp, -(%sp)
+ move.l #board_init_f_alloc_reserve, %a1
+ jsr (%a1)
+
+ /* update stack and frame-pointers */
+ move.l %d0, %sp
+ move.l %sp, %fp
+
+ /* initialize reserved area */
+ move.l %d0, -(%sp)
+ move.l #board_init_f_init_reserve, %a1
+ jsr (%a1)
/* run low-level CPU init code (from flash) */
move.l #cpu_init_f, %a1
jsr (%a1)
/* run low-level board init code (from flash) */
+ clr.l %sp@-
move.l #board_init_f, %a1
jsr (%a1)
diff --git a/arch/m68k/cpu/mcf530x/cpu_init.c b/arch/m68k/cpu/mcf530x/cpu_init.c
index 80dc239..b09eed8 100644
--- a/arch/m68k/cpu/mcf530x/cpu_init.c
+++ b/arch/m68k/cpu/mcf530x/cpu_init.c
@@ -142,7 +142,7 @@ int cpu_init_r(void)
return 0;
}
-void uart_port_conf(void)
+void uart_port_conf(int port)
{
}
diff --git a/arch/m68k/cpu/mcf530x/start.S b/arch/m68k/cpu/mcf530x/start.S
index 097958a..ca8bb32 100644
--- a/arch/m68k/cpu/mcf530x/start.S
+++ b/arch/m68k/cpu/mcf530x/start.S
@@ -126,21 +126,32 @@ _start:
move.l %d0, (%a1)
move.l %d0, (%a2)
+ /* put relocation table address to a5 */
+ move.l #__got_start, %a5
+
+ /* setup stack initially on top of internal static ram */
+ move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
+
/*
- * set stackpointer to internal sram end - 80
- * (global data struct size + some bytes)
- * get some stackspace for the first c-code,
+ * if configured, malloc_f arena will be reserved first,
+ * then (and always) gd struct space will be reserved
*/
- move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
- clr.l %sp@-
+ move.l %sp, -(%sp)
+ bsr board_init_f_alloc_reserve
- /* put relocation table address to a5 */
- move.l #__got_start, %a5
+ /* update stack and frame-pointers */
+ move.l %d0, %sp
+ move.l %sp, %fp
+
+ /* initialize reserved area */
+ move.l %d0, -(%sp)
+ bsr board_init_f_init_reserve
/* run low-level CPU init code (from flash) */
bsr cpu_init_f
/* run low-level board init code (from flash) */
+ clr.l %sp@-
bsr board_init_f
/* board_init_f() does not return */
diff --git a/arch/m68k/cpu/mcf532x/start.S b/arch/m68k/cpu/mcf532x/start.S
index 131ad6e..f25bc54 100644
--- a/arch/m68k/cpu/mcf532x/start.S
+++ b/arch/m68k/cpu/mcf532x/start.S
@@ -148,17 +148,34 @@ _start:
move.l %d0, (%a1)
move.l %d0, (%a2)
- /* set stackpointer to end of internal ram to get some stackspace for the
- first c-code */
- move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
- clr.l %sp@-
+ /* put relocation table address to a5 */
+ move.l #__got_start, %a5
- move.l #__got_start, %a5 /* put relocation table address to a5 */
+ /* setup stack initially on top of internal static ram */
+ move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
+
+ /*
+ * if configured, malloc_f arena will be reserved first,
+ * then (and always) gd struct space will be reserved
+ */
+ move.l %sp, -(%sp)
+ move.l #board_init_f_alloc_reserve, %a1
+ jsr (%a1)
+
+ /* update stack and frame-pointers */
+ move.l %d0, %sp
+ move.l %sp, %fp
+
+ /* initialize reserved area */
+ move.l %d0, -(%sp)
+ move.l #board_init_f_init_reserve, %a1
+ jsr (%a1)
/* run low-level CPU init code (from flash) */
move.l #cpu_init_f, %a1
jsr (%a1)
/* run low-level board init code (from flash) */
+ clr.l %sp@-
move.l #board_init_f, %a1
jsr (%a1)
diff --git a/arch/m68k/cpu/mcf5445x/start.S b/arch/m68k/cpu/mcf5445x/start.S
index f50f147..ba38678 100644
--- a/arch/m68k/cpu/mcf5445x/start.S
+++ b/arch/m68k/cpu/mcf5445x/start.S
@@ -657,17 +657,34 @@ _start:
movec %d0, %RAMBAR1
#endif
- /* set stackpointer to end of internal ram to get some stackspace for
- the first c-code */
- move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
- clr.l %sp@-
+ /* put relocation table address to a5 */
+ move.l #__got_start, %a5
+
+ /* setup stack initially on top of internal static ram */
+ move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
- move.l #__got_start, %a5 /* put relocation table address to a5 */
+ /*
+ * if configured, malloc_f arena will be reserved first,
+ * then (and always) gd struct space will be reserved
+ */
+ move.l %sp, -(%sp)
+ move.l #board_init_f_alloc_reserve, %a1
+ jsr (%a1)
+
+ /* update stack and frame-pointers */
+ move.l %d0, %sp
+ move.l %sp, %fp
+
+ /* initialize reserved area */
+ move.l %d0, -(%sp)
+ move.l #board_init_f_init_reserve, %a1
+ jsr (%a1)
/* run low-level CPU init code (from flash) */
move.l #cpu_init_f, %a1
jsr (%a1)
/* run low-level board init code (from flash) */
+ clr.l %sp@-
move.l #board_init_f, %a1
jsr (%a1)
diff --git a/arch/m68k/cpu/mcf547x_8x/start.S b/arch/m68k/cpu/mcf547x_8x/start.S
index 75de22d..9a87a0d 100644
--- a/arch/m68k/cpu/mcf547x_8x/start.S
+++ b/arch/m68k/cpu/mcf547x_8x/start.S
@@ -141,14 +141,29 @@ _start:
move.l %d0, (%a1)
move.l %d0, (%a2)
- /* set stackpointer to end of internal ram to get some stackspace for the
- first c-code */
- move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
- clr.l %sp@-
+ /* put relocation table address to a5 */
+ move.l #__got_start, %a5
- move.l #__got_start, %a5 /* put relocation table address to a5 */
+ /* setup stack initially on top of internal static ram */
+ move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
+
+ /*
+ * if configured, malloc_f arena will be reserved first,
+ * then (and always) gd struct space will be reserved
+ */
+ move.l %sp, -(%sp)
+ bsr board_init_f_alloc_reserve
+
+ /* update stack and frame-pointers */
+ move.l %d0, %sp
+ move.l %sp, %fp
+
+ /* initialize reserved area */
+ move.l %d0, -(%sp)
+ bsr board_init_f_init_reserve
jbsr cpu_init_f /* run low-level CPU init code (from flash) */
+ clr.l %sp@-
jbsr board_init_f /* run low-level board init code (from flash) */
/* board_init_f() does not return */
diff --git a/arch/m68k/include/asm/config.h b/arch/m68k/include/asm/config.h
index e1458ac..9c4d3fb 100644
--- a/arch/m68k/include/asm/config.h
+++ b/arch/m68k/include/asm/config.h
@@ -7,8 +7,6 @@
#ifndef _ASM_CONFIG_H_
#define _ASM_CONFIG_H_
-#define CONFIG_SYS_GENERIC_GLOBAL_DATA
-
#define CONFIG_NEEDS_MANUAL_RELOC
#define CONFIG_LMB
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index b87ee19..6919632 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -56,6 +56,21 @@ void outl(unsigned int value, unsigned int addr);
void outw(unsigned int value, unsigned int addr);
void outb(unsigned int value, unsigned int addr);
+static inline void _insw(volatile u16 *port, void *buf, int ns)
+{
+}
+
+static inline void _outsw(volatile u16 *port, const void *buf, int ns)
+{
+}
+
+#define insw(port, buf, ns) _insw((u16 *)port, buf, ns)
+#define outsw(port, buf, ns) _outsw((u16 *)port, buf, ns)
+
+/* For systemace.c */
+#define out16(addr, val)
+#define in16(addr) 0
+
#include <iotrace.h>
#include <asm/types.h>
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 4ef27dc..396023e 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -47,6 +47,9 @@ source "arch/x86/cpu/queensbay/Kconfig"
# architecture-specific options below
+config AHCI
+ default y
+
config SYS_MALLOC_F_LEN
default 0x800
diff --git a/arch/x86/cpu/broadwell/sata.c b/arch/x86/cpu/broadwell/sata.c
index dfb8486..2e47082 100644
--- a/arch/x86/cpu/broadwell/sata.c
+++ b/arch/x86/cpu/broadwell/sata.c
@@ -261,7 +261,7 @@ static const struct udevice_id broadwell_ahci_ids[] = {
U_BOOT_DRIVER(ahci_broadwell_drv) = {
.name = "ahci_broadwell",
- .id = UCLASS_DISK,
+ .id = UCLASS_AHCI,
.of_match = broadwell_ahci_ids,
.ofdata_to_platdata = broadwell_sata_ofdata_to_platdata,
.probe = broadwell_sata_probe,
diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c
index 93e4505..0fdef6f 100644
--- a/arch/x86/cpu/intel_common/cpu.c
+++ b/arch/x86/cpu/intel_common/cpu.c
@@ -58,7 +58,7 @@ int cpu_common_init(void)
return -ENODEV;
/* Cause the SATA device to do its early init */
- uclass_first_device(UCLASS_DISK, &dev);
+ uclass_first_device(UCLASS_AHCI, &dev);
return 0;
}
diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c
index 4c039ac..5b58d6c 100644
--- a/arch/x86/cpu/ivybridge/bd82x6x.c
+++ b/arch/x86/cpu/ivybridge/bd82x6x.c
@@ -162,7 +162,7 @@ static int bd82x6x_probe(struct udevice *dev)
return 0;
/* Cause the SATA device to do its init */
- uclass_first_device(UCLASS_DISK, &dev);
+ uclass_first_device(UCLASS_AHCI, &dev);
ret = syscon_get_by_driver_data(X86_SYSCON_GMA, &gma_dev);
if (ret)
diff --git a/arch/x86/cpu/ivybridge/sata.c b/arch/x86/cpu/ivybridge/sata.c
index c3d1057..1ce8195 100644
--- a/arch/x86/cpu/ivybridge/sata.c
+++ b/arch/x86/cpu/ivybridge/sata.c
@@ -233,7 +233,7 @@ static const struct udevice_id bd82x6x_ahci_ids[] = {
U_BOOT_DRIVER(ahci_ivybridge_drv) = {
.name = "ahci_ivybridge",
- .id = UCLASS_DISK,
+ .id = UCLASS_AHCI,
.of_match = bd82x6x_ahci_ids,
.probe = bd82x6x_sata_probe,
};
diff --git a/board/cm5200/fwupdate.c b/board/cm5200/fwupdate.c
index 2ed90de..4740c83 100644
--- a/board/cm5200/fwupdate.c
+++ b/board/cm5200/fwupdate.c
@@ -105,7 +105,7 @@ static int load_rescue_image(ulong addr)
/* Detect storage device */
for (devno = 0; devno < USB_MAX_STOR_DEV; devno++) {
- stor_dev = usb_stor_get_dev(devno);
+ stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, devno);
if (stor_dev->type != DEV_TYPE_UNKNOWN)
break;
}
diff --git a/board/mpl/pip405/README b/board/mpl/pip405/README
index e900c56..f039817 100644
--- a/board/mpl/pip405/README
+++ b/board/mpl/pip405/README
@@ -32,8 +32,8 @@ Changed files:
- include/cmd_bsp.h added PIP405 commands definitions
- include/cmd_condefs.h added Floppy and SCSI support
- include/cmd_disk.h changed to work with block device description
-- include/config_LANTEC.h excluded CONFIG_CMD_FDC and CONFIG_CMD_SCSI
-- include/config_hymod.h excluded CONFIG_CMD_FDC and CONFIG_CMD_SCSI
+- include/config_LANTEC.h excluded CONFIG_CMD_FDC and CONFIG_SCSI
+- include/config_hymod.h excluded CONFIG_CMD_FDC and CONFIG_SCSI
- include/flash.h added INTEL_ID_28F320C3T 0x88C488C4
- include/i2c.h added "defined(CONFIG_PIP405)"
- include/image.h added IH_OS_U_BOOT, IH_TYPE_FIRMWARE
@@ -86,7 +86,7 @@ section "Changes".
New Commands:
-------------
-CONFIG_CMD_SCSI SCSI Support
+CONFIG_SCSI SCSI Support
CONFIG_CMF_FDC Floppy disk support
IDE additions:
diff --git a/board/sandbox/MAINTAINERS b/board/sandbox/MAINTAINERS
index 10d88a2..f5db773 100644
--- a/board/sandbox/MAINTAINERS
+++ b/board/sandbox/MAINTAINERS
@@ -4,3 +4,10 @@ S: Maintained
F: board/sandbox/
F: include/configs/sandbox.h
F: configs/sandbox_defconfig
+
+SANDBOX_NOBLK BOARD
+M: Simon Glass <sjg@chromium.org>
+S: Maintained
+F: board/sandbox/
+F: include/configs/sandbox.h
+F: configs/sandbox_noblk_defconfig
diff --git a/cmd/Makefile b/cmd/Makefile
index f95759e..e3e0c74 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -112,7 +112,7 @@ obj-$(CONFIG_CMD_REMOTEPROC) += remoteproc.o
obj-$(CONFIG_SANDBOX) += host.o
obj-$(CONFIG_CMD_SATA) += sata.o
obj-$(CONFIG_CMD_SF) += sf.o
-obj-$(CONFIG_CMD_SCSI) += scsi.o
+obj-$(CONFIG_SCSI) += scsi.o
obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o
obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
obj-$(CONFIG_CMD_SOFTSWITCH) += softswitch.o
@@ -155,12 +155,6 @@ obj-$(CONFIG_CMD_PMIC) += pmic.o
obj-$(CONFIG_CMD_REGULATOR) += regulator.o
endif # !CONFIG_SPL_BUILD
-ifdef CONFIG_SPL_BUILD
-ifdef CONFIG_SPL_SATA_SUPPORT
-obj-$(CONFIG_CMD_SCSI) += scsi.o
-endif
-endif # CONFIG_SPL_BUILD
-
obj-$(CONFIG_CMD_BLOB) += blob.o
# core command
diff --git a/cmd/disk.c b/cmd/disk.c
index 2fd1717..fcc4123 100644
--- a/cmd/disk.c
+++ b/cmd/disk.c
@@ -8,7 +8,7 @@
#include <command.h>
#include <part.h>
-#if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \
+#if defined(CONFIG_CMD_IDE) || defined(CONFIG_SCSI) || \
defined(CONFIG_USB_STORAGE)
int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
char *const argv[])
diff --git a/cmd/ide.c b/cmd/ide.c
index c4c08c8..c942744 100644
--- a/cmd/ide.c
+++ b/cmd/ide.c
@@ -29,64 +29,9 @@
# include <status_led.h>
#endif
-#ifdef __PPC__
-# define EIEIO __asm__ volatile ("eieio")
-# define SYNC __asm__ volatile ("sync")
-#else
-# define EIEIO /* nothing */
-# define SYNC /* nothing */
-#endif
-
-/* ------------------------------------------------------------------------- */
-
/* Current I/O Device */
static int curr_device = -1;
-/* Current offset for IDE0 / IDE1 bus access */
-ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = {
-#if defined(CONFIG_SYS_ATA_IDE0_OFFSET)
- CONFIG_SYS_ATA_IDE0_OFFSET,
-#endif
-#if defined(CONFIG_SYS_ATA_IDE1_OFFSET) && (CONFIG_SYS_IDE_MAXBUS > 1)
- CONFIG_SYS_ATA_IDE1_OFFSET,
-#endif
-};
-
-static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS];
-
-struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE];
-/* ------------------------------------------------------------------------- */
-
-#ifdef CONFIG_IDE_RESET
-static void ide_reset (void);
-#else
-#define ide_reset() /* dummy */
-#endif
-
-static void ide_ident(struct blk_desc *dev_desc);
-static uchar ide_wait (int dev, ulong t);
-
-#define IDE_TIME_OUT 2000 /* 2 sec timeout */
-
-#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */
-
-#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */
-
-static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);
-
-#ifndef CONFIG_SYS_ATA_PORT_ADDR
-#define CONFIG_SYS_ATA_PORT_ADDR(port) (port)
-#endif
-
-#ifdef CONFIG_ATAPI
-static void atapi_inquiry(struct blk_desc *dev_desc);
-static ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr,
- lbaint_t blkcnt, void *buffer);
-#endif
-
-
-/* ------------------------------------------------------------------------- */
-
int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
int rcode = 0;
@@ -106,79 +51,41 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
ide_init();
return 0;
} else if (strncmp(argv[1], "inf", 3) == 0) {
- int i;
-
- putc('\n');
-
- for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) {
- if (ide_dev_desc[i].type == DEV_TYPE_UNKNOWN)
- continue; /* list only known devices */
- printf("IDE device %d: ", i);
- dev_print(&ide_dev_desc[i]);
- }
+ blk_list_devices(IF_TYPE_IDE);
return 0;
} else if (strncmp(argv[1], "dev", 3) == 0) {
- if ((curr_device < 0)
- || (curr_device >= CONFIG_SYS_IDE_MAXDEVICE)) {
- puts("\nno IDE devices available\n");
- return 1;
+ if (blk_print_device_num(IF_TYPE_IDE, curr_device)) {
+ printf("\nno IDE devices available\n");
+ return CMD_RET_FAILURE;
}
- printf("\nIDE device %d: ", curr_device);
- dev_print(&ide_dev_desc[curr_device]);
+
return 0;
} else if (strncmp(argv[1], "part", 4) == 0) {
- int dev, ok;
-
- for (ok = 0, dev = 0;
- dev < CONFIG_SYS_IDE_MAXDEVICE;
- ++dev) {
- if (ide_dev_desc[dev].part_type !=
- PART_TYPE_UNKNOWN) {
- ++ok;
- if (dev)
- putc('\n');
- part_print(&ide_dev_desc[dev]);
- }
- }
- if (!ok) {
- puts("\nno IDE devices available\n");
- rcode++;
- }
- return rcode;
+ if (blk_list_part(IF_TYPE_IDE))
+ printf("\nno IDE devices available\n");
+ return 1;
}
return CMD_RET_USAGE;
case 3:
if (strncmp(argv[1], "dev", 3) == 0) {
- int dev = (int) simple_strtoul(argv[2], NULL, 10);
+ int dev = (int)simple_strtoul(argv[2], NULL, 10);
- printf("\nIDE device %d: ", dev);
- if (dev >= CONFIG_SYS_IDE_MAXDEVICE) {
- puts("unknown device\n");
- return 1;
+ if (!blk_show_device(IF_TYPE_IDE, dev)) {
+ curr_device = dev;
+ printf("... is now current device\n");
+ } else {
+ return CMD_RET_FAILURE;
}
- dev_print(&ide_dev_desc[dev]);
- /*ide_print (dev); */
-
- if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN)
- return 1;
-
- curr_device = dev;
-
- puts("... is now current device\n");
-
return 0;
} else if (strncmp(argv[1], "part", 4) == 0) {
- int dev = (int) simple_strtoul(argv[2], NULL, 10);
+ int dev = (int)simple_strtoul(argv[2], NULL, 10);
- if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) {
- part_print(&ide_dev_desc[dev]);
- } else {
- printf("\nIDE device %d not available\n",
- dev);
- rcode = 1;
+ if (blk_print_part_devnum(IF_TYPE_IDE, dev)) {
+ printf("\nIDE device %d not available\n", dev);
+ return CMD_RET_FAILURE;
}
- return rcode;
+ return 1;
}
return CMD_RET_USAGE;
@@ -188,26 +95,22 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
if (strcmp(argv[1], "read") == 0) {
ulong addr = simple_strtoul(argv[2], NULL, 16);
ulong cnt = simple_strtoul(argv[4], NULL, 16);
- struct blk_desc *dev_desc;
ulong n;
#ifdef CONFIG_SYS_64BIT_LBA
lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
- printf("\nIDE read: device %d block # %lld, count %ld ... ",
- curr_device, blk, cnt);
+ printf("\nIDE read: device %d block # %lld, count %ld...",
+ curr_device, blk, cnt);
#else
lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
- printf("\nIDE read: device %d block # %ld, count %ld ... ",
- curr_device, blk, cnt);
+ printf("\nIDE read: device %d block # %ld, count %ld...",
+ curr_device, blk, cnt);
#endif
- dev_desc = &ide_dev_desc[curr_device];
- n = blk_dread(dev_desc, blk, cnt, (ulong *)addr);
- /* flush cache after read */
- flush_cache(addr,
- cnt * ide_dev_desc[curr_device].blksz);
+ n = blk_read_devnum(IF_TYPE_IDE, curr_device, blk, cnt,
+ (ulong *)addr);
printf("%ld blocks read: %s\n",
n, (n == cnt) ? "OK" : "ERROR");
@@ -223,19 +126,19 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
#ifdef CONFIG_SYS_64BIT_LBA
lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
- printf("\nIDE write: device %d block # %lld, count %ld ... ",
- curr_device, blk, cnt);
+ printf("\nIDE write: device %d block # %lld, count %ld...",
+ curr_device, blk, cnt);
#else
lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
- printf("\nIDE write: device %d block # %ld, count %ld ... ",
- curr_device, blk, cnt);
+ printf("\nIDE write: device %d block # %ld, count %ld...",
+ curr_device, blk, cnt);
#endif
- n = ide_write(&ide_dev_desc[curr_device], blk, cnt,
- (ulong *)addr);
+ n = blk_write_devnum(IF_TYPE_IDE, curr_device, blk, cnt,
+ (ulong *)addr);
- printf("%ld blocks written: %s\n",
- n, (n == cnt) ? "OK" : "ERROR");
+ printf("%ld blocks written: %s\n", n,
+ n == cnt ? "OK" : "ERROR");
if (n == cnt)
return 0;
else
@@ -253,1195 +156,6 @@ int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
return common_diskboot(cmdtp, "ide", argc, argv);
}
-/* ------------------------------------------------------------------------- */
-
-__weak void ide_led(uchar led, uchar status)
-{
-#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */
- static uchar led_buffer; /* Buffer for current LED status */
-
- uchar *led_port = LED_PORT;
-
- if (status) /* switch LED on */
- led_buffer |= led;
- else /* switch LED off */
- led_buffer &= ~led;
-
- *led_port = led_buffer;
-#endif
-}
-
-#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */
-# define DEVICE_LED(x) 0
-# define LED_IDE1 1
-# define LED_IDE2 2
-#endif
-
-/* ------------------------------------------------------------------------- */
-
-__weak void ide_outb(int dev, int port, unsigned char val)
-{
- debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n",
- dev, port, val,
- (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
-
-#if defined(CONFIG_IDE_AHB)
- if (port) {
- /* write command */
- ide_write_register(dev, port, val);
- } else {
- /* write data */
- outb(val, (ATA_CURR_BASE(dev)));
- }
-#else
- outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
-#endif
-}
-
-__weak unsigned char ide_inb(int dev, int port)
-{
- uchar val;
-
-#if defined(CONFIG_IDE_AHB)
- val = ide_read_register(dev, port);
-#else
- val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
-#endif
-
- debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n",
- dev, port,
- (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val);
- return val;
-}
-
-void ide_init(void)
-{
- unsigned char c;
- int i, bus;
-
-#ifdef CONFIG_IDE_8xx_PCCARD
- extern int ide_devices_found; /* Initialized in check_ide_device() */
-#endif /* CONFIG_IDE_8xx_PCCARD */
-
-#ifdef CONFIG_IDE_PREINIT
- WATCHDOG_RESET();
-
- if (ide_preinit()) {
- puts("ide_preinit failed\n");
- return;
- }
-#endif /* CONFIG_IDE_PREINIT */
-
- WATCHDOG_RESET();
-
- /*
- * Reset the IDE just to be sure.
- * Light LED's to show
- */
- ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */
-
- /* ATAPI Drives seems to need a proper IDE Reset */
- ide_reset();
-
-#ifdef CONFIG_IDE_INIT_POSTRESET
- WATCHDOG_RESET();
-
- if (ide_init_postreset()) {
- puts("ide_preinit_postreset failed\n");
- return;
- }
-#endif /* CONFIG_IDE_INIT_POSTRESET */
-
- /*
- * Wait for IDE to get ready.
- * According to spec, this can take up to 31 seconds!
- */
- for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) {
- int dev =
- bus * (CONFIG_SYS_IDE_MAXDEVICE /
- CONFIG_SYS_IDE_MAXBUS);
-
-#ifdef CONFIG_IDE_8xx_PCCARD
- /* Skip non-ide devices from probing */
- if ((ide_devices_found & (1 << bus)) == 0) {
- ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */
- continue;
- }
-#endif
- printf("Bus %d: ", bus);
-
- ide_bus_ok[bus] = 0;
-
- /* Select device
- */
- udelay(100000); /* 100 ms */
- ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
- udelay(100000); /* 100 ms */
- i = 0;
- do {
- udelay(10000); /* 10 ms */
-
- c = ide_inb(dev, ATA_STATUS);
- i++;
- if (i > (ATA_RESET_TIME * 100)) {
- puts("** Timeout **\n");
- /* LED's off */
- ide_led((LED_IDE1 | LED_IDE2), 0);
- return;
- }
- if ((i >= 100) && ((i % 100) == 0))
- putc('.');
-
- } while (c & ATA_STAT_BUSY);
-
- if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
- puts("not available ");
- debug("Status = 0x%02X ", c);
-#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */
- } else if ((c & ATA_STAT_READY) == 0) {
- puts("not available ");
- debug("Status = 0x%02X ", c);
-#endif
- } else {
- puts("OK ");
- ide_bus_ok[bus] = 1;
- }
- WATCHDOG_RESET();
- }
-
- putc('\n');
-
- ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */
-
- curr_device = -1;
- for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) {
- int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2;
- ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
- ide_dev_desc[i].if_type = IF_TYPE_IDE;
- ide_dev_desc[i].devnum = i;
- ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
- ide_dev_desc[i].blksz = 0;
- ide_dev_desc[i].log2blksz =
- LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz));
- ide_dev_desc[i].lba = 0;
- ide_dev_desc[i].block_read = ide_read;
- ide_dev_desc[i].block_write = ide_write;
- if (!ide_bus_ok[IDE_BUS(i)])
- continue;
- ide_led(led, 1); /* LED on */
- ide_ident(&ide_dev_desc[i]);
- ide_led(led, 0); /* LED off */
- dev_print(&ide_dev_desc[i]);
-
- if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) {
- /* initialize partition type */
- part_init(&ide_dev_desc[i]);
- if (curr_device < 0)
- curr_device = i;
- }
- }
- WATCHDOG_RESET();
-}
-
-/* ------------------------------------------------------------------------- */
-
-#ifdef CONFIG_PARTITIONS
-struct blk_desc *ide_get_dev(int dev)
-{
- return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL;
-}
-#endif
-
-/* ------------------------------------------------------------------------- */
-
-/* We only need to swap data if we are running on a big endian cpu. */
-#if defined(__LITTLE_ENDIAN)
-__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words)
-{
- ide_input_data(dev, sect_buf, words);
-}
-#else
-__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words)
-{
- volatile ushort *pbuf =
- (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
- ushort *dbuf = (ushort *) sect_buf;
-
- debug("in input swap data base for read is %lx\n",
- (unsigned long) pbuf);
-
- while (words--) {
-#ifdef __MIPS__
- *dbuf++ = swab16p((u16 *) pbuf);
- *dbuf++ = swab16p((u16 *) pbuf);
-#else
- *dbuf++ = ld_le16(pbuf);
- *dbuf++ = ld_le16(pbuf);
-#endif /* !MIPS */
- }
-}
-#endif /* __LITTLE_ENDIAN */
-
-
-#if defined(CONFIG_IDE_SWAP_IO)
-__weak void ide_output_data(int dev, const ulong *sect_buf, int words)
-{
- ushort *dbuf;
- volatile ushort *pbuf;
-
- pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
- dbuf = (ushort *) sect_buf;
- while (words--) {
- EIEIO;
- *pbuf = *dbuf++;
- EIEIO;
- *pbuf = *dbuf++;
- }
-}
-#else /* ! CONFIG_IDE_SWAP_IO */
-__weak void ide_output_data(int dev, const ulong *sect_buf, int words)
-{
-#if defined(CONFIG_IDE_AHB)
- ide_write_data(dev, sect_buf, words);
-#else
- outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1);
-#endif
-}
-#endif /* CONFIG_IDE_SWAP_IO */
-
-#if defined(CONFIG_IDE_SWAP_IO)
-__weak void ide_input_data(int dev, ulong *sect_buf, int words)
-{
- ushort *dbuf;
- volatile ushort *pbuf;
-
- pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
- dbuf = (ushort *) sect_buf;
-
- debug("in input data base for read is %lx\n", (unsigned long) pbuf);
-
- while (words--) {
- EIEIO;
- *dbuf++ = *pbuf;
- EIEIO;
- *dbuf++ = *pbuf;
- }
-}
-#else /* ! CONFIG_IDE_SWAP_IO */
-__weak void ide_input_data(int dev, ulong *sect_buf, int words)
-{
-#if defined(CONFIG_IDE_AHB)
- ide_read_data(dev, sect_buf, words);
-#else
- insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1);
-#endif
-}
-
-#endif /* CONFIG_IDE_SWAP_IO */
-
-/* -------------------------------------------------------------------------
- */
-static void ide_ident(struct blk_desc *dev_desc)
-{
- unsigned char c;
- hd_driveid_t iop;
-
-#ifdef CONFIG_ATAPI
- int retries = 0;
-#endif
- int device;
-
- device = dev_desc->devnum;
- printf(" Device %d: ", device);
-
- ide_led(DEVICE_LED(device), 1); /* LED on */
- /* Select device
- */
- ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
- dev_desc->if_type = IF_TYPE_IDE;
-#ifdef CONFIG_ATAPI
-
- retries = 0;
-
- /* Warning: This will be tricky to read */
- while (retries <= 1) {
- /* check signature */
- if ((ide_inb(device, ATA_SECT_CNT) == 0x01) &&
- (ide_inb(device, ATA_SECT_NUM) == 0x01) &&
- (ide_inb(device, ATA_CYL_LOW) == 0x14) &&
- (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) {
- /* ATAPI Signature found */
- dev_desc->if_type = IF_TYPE_ATAPI;
- /*
- * Start Ident Command
- */
- ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT);
- /*
- * Wait for completion - ATAPI devices need more time
- * to become ready
- */
- c = ide_wait(device, ATAPI_TIME_OUT);
- } else
-#endif
- {
- /*
- * Start Ident Command
- */
- ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT);
-
- /*
- * Wait for completion
- */
- c = ide_wait(device, IDE_TIME_OUT);
- }
- ide_led(DEVICE_LED(device), 0); /* LED off */
-
- if (((c & ATA_STAT_DRQ) == 0) ||
- ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) {
-#ifdef CONFIG_ATAPI
- {
- /*
- * Need to soft reset the device
- * in case it's an ATAPI...
- */
- debug("Retrying...\n");
- ide_outb(device, ATA_DEV_HD,
- ATA_LBA | ATA_DEVICE(device));
- udelay(100000);
- ide_outb(device, ATA_COMMAND, 0x08);
- udelay(500000); /* 500 ms */
- }
- /*
- * Select device
- */
- ide_outb(device, ATA_DEV_HD,
- ATA_LBA | ATA_DEVICE(device));
- retries++;
-#else
- return;
-#endif
- }
-#ifdef CONFIG_ATAPI
- else
- break;
- } /* see above - ugly to read */
-
- if (retries == 2) /* Not found */
- return;
-#endif
-
- ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS);
-
- ident_cpy((unsigned char *) dev_desc->revision, iop.fw_rev,
- sizeof(dev_desc->revision));
- ident_cpy((unsigned char *) dev_desc->vendor, iop.model,
- sizeof(dev_desc->vendor));
- ident_cpy((unsigned char *) dev_desc->product, iop.serial_no,
- sizeof(dev_desc->product));
-#ifdef __LITTLE_ENDIAN
- /*
- * firmware revision, model, and serial number have Big Endian Byte
- * order in Word. Convert all three to little endian.
- *
- * See CF+ and CompactFlash Specification Revision 2.0:
- * 6.2.1.6: Identify Drive, Table 39 for more details
- */
-
- strswab(dev_desc->revision);
- strswab(dev_desc->vendor);
- strswab(dev_desc->product);
-#endif /* __LITTLE_ENDIAN */
-
- if ((iop.config & 0x0080) == 0x0080)
- dev_desc->removable = 1;
- else
- dev_desc->removable = 0;
-
-#ifdef CONFIG_ATAPI
- if (dev_desc->if_type == IF_TYPE_ATAPI) {
- atapi_inquiry(dev_desc);
- return;
- }
-#endif /* CONFIG_ATAPI */
-
-#ifdef __BIG_ENDIAN
- /* swap shorts */
- dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16);
-#else /* ! __BIG_ENDIAN */
- /*
- * do not swap shorts on little endian
- *
- * See CF+ and CompactFlash Specification Revision 2.0:
- * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details.
- */
- dev_desc->lba = iop.lba_capacity;
-#endif /* __BIG_ENDIAN */
-
-#ifdef CONFIG_LBA48
- if (iop.command_set_2 & 0x0400) { /* LBA 48 support */
- dev_desc->lba48 = 1;
- dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] |
- ((unsigned long long) iop.lba48_capacity[1] << 16) |
- ((unsigned long long) iop.lba48_capacity[2] << 32) |
- ((unsigned long long) iop.lba48_capacity[3] << 48);
- } else {
- dev_desc->lba48 = 0;
- }
-#endif /* CONFIG_LBA48 */
- /* assuming HD */
- dev_desc->type = DEV_TYPE_HARDDISK;
- dev_desc->blksz = ATA_BLOCKSIZE;
- dev_desc->log2blksz = LOG2(dev_desc->blksz);
- dev_desc->lun = 0; /* just to fill something in... */
-
-#if 0 /* only used to test the powersaving mode,
- * if enabled, the drive goes after 5 sec
- * in standby mode */
- ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
- c = ide_wait(device, IDE_TIME_OUT);
- ide_outb(device, ATA_SECT_CNT, 1);
- ide_outb(device, ATA_LBA_LOW, 0);
- ide_outb(device, ATA_LBA_MID, 0);
- ide_outb(device, ATA_LBA_HIGH, 0);
- ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
- ide_outb(device, ATA_COMMAND, 0xe3);
- udelay(50);
- c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */
-#endif
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
- void *buffer)
-{
- int device = block_dev->devnum;
- ulong n = 0;
- unsigned char c;
- unsigned char pwrsave = 0; /* power save */
-
-#ifdef CONFIG_LBA48
- unsigned char lba48 = 0;
-
- if (blknr & 0x0000fffff0000000ULL) {
- /* more than 28 bits used, use 48bit mode */
- lba48 = 1;
- }
-#endif
- debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n",
- device, blknr, blkcnt, (ulong) buffer);
-
- ide_led(DEVICE_LED(device), 1); /* LED on */
-
- /* Select device
- */
- ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
- c = ide_wait(device, IDE_TIME_OUT);
-
- if (c & ATA_STAT_BUSY) {
- printf("IDE read: device %d not ready\n", device);
- goto IDE_READ_E;
- }
-
- /* first check if the drive is in Powersaving mode, if yes,
- * increase the timeout value */
- ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR);
- udelay(50);
-
- c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */
-
- if (c & ATA_STAT_BUSY) {
- printf("IDE read: device %d not ready\n", device);
- goto IDE_READ_E;
- }
- if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
- printf("No Powersaving mode %X\n", c);
- } else {
- c = ide_inb(device, ATA_SECT_CNT);
- debug("Powersaving %02X\n", c);
- if (c == 0)
- pwrsave = 1;
- }
-
-
- while (blkcnt-- > 0) {
-
- c = ide_wait(device, IDE_TIME_OUT);
-
- if (c & ATA_STAT_BUSY) {
- printf("IDE read: device %d not ready\n", device);
- break;
- }
-#ifdef CONFIG_LBA48
- if (lba48) {
- /* write high bits */
- ide_outb(device, ATA_SECT_CNT, 0);
- ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
-#ifdef CONFIG_SYS_64BIT_LBA
- ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
- ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
-#else
- ide_outb(device, ATA_LBA_MID, 0);
- ide_outb(device, ATA_LBA_HIGH, 0);
-#endif
- }
-#endif
- ide_outb(device, ATA_SECT_CNT, 1);
- ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
- ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
- ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
-
-#ifdef CONFIG_LBA48
- if (lba48) {
- ide_outb(device, ATA_DEV_HD,
- ATA_LBA | ATA_DEVICE(device));
- ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT);
-
- } else
-#endif
- {
- ide_outb(device, ATA_DEV_HD, ATA_LBA |
- ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
- ide_outb(device, ATA_COMMAND, ATA_CMD_READ);
- }
-
- udelay(50);
-
- if (pwrsave) {
- /* may take up to 4 sec */
- c = ide_wait(device, IDE_SPIN_UP_TIME_OUT);
- pwrsave = 0;
- } else {
- /* can't take over 500 ms */
- c = ide_wait(device, IDE_TIME_OUT);
- }
-
- if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
- ATA_STAT_DRQ) {
- printf("Error (no IRQ) dev %d blk " LBAF ": status "
- "%#02x\n", device, blknr, c);
- break;
- }
-
- ide_input_data(device, buffer, ATA_SECTORWORDS);
- (void) ide_inb(device, ATA_STATUS); /* clear IRQ */
-
- ++n;
- ++blknr;
- buffer += ATA_BLOCKSIZE;
- }
-IDE_READ_E:
- ide_led(DEVICE_LED(device), 0); /* LED off */
- return (n);
-}
-
-/* ------------------------------------------------------------------------- */
-
-
-ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
- const void *buffer)
-{
- int device = block_dev->devnum;
- ulong n = 0;
- unsigned char c;
-
-#ifdef CONFIG_LBA48
- unsigned char lba48 = 0;
-
- if (blknr & 0x0000fffff0000000ULL) {
- /* more than 28 bits used, use 48bit mode */
- lba48 = 1;
- }
-#endif
-
- ide_led(DEVICE_LED(device), 1); /* LED on */
-
- /* Select device
- */
- ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
-
- while (blkcnt-- > 0) {
-
- c = ide_wait(device, IDE_TIME_OUT);
-
- if (c & ATA_STAT_BUSY) {
- printf("IDE read: device %d not ready\n", device);
- goto WR_OUT;
- }
-#ifdef CONFIG_LBA48
- if (lba48) {
- /* write high bits */
- ide_outb(device, ATA_SECT_CNT, 0);
- ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
-#ifdef CONFIG_SYS_64BIT_LBA
- ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
- ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
-#else
- ide_outb(device, ATA_LBA_MID, 0);
- ide_outb(device, ATA_LBA_HIGH, 0);
-#endif
- }
-#endif
- ide_outb(device, ATA_SECT_CNT, 1);
- ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
- ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
- ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
-
-#ifdef CONFIG_LBA48
- if (lba48) {
- ide_outb(device, ATA_DEV_HD,
- ATA_LBA | ATA_DEVICE(device));
- ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT);
-
- } else
-#endif
- {
- ide_outb(device, ATA_DEV_HD, ATA_LBA |
- ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
- ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE);
- }
-
- udelay(50);
-
- /* can't take over 500 ms */
- c = ide_wait(device, IDE_TIME_OUT);
-
- if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
- ATA_STAT_DRQ) {
- printf("Error (no IRQ) dev %d blk " LBAF ": status "
- "%#02x\n", device, blknr, c);
- goto WR_OUT;
- }
-
- ide_output_data(device, buffer, ATA_SECTORWORDS);
- c = ide_inb(device, ATA_STATUS); /* clear IRQ */
- ++n;
- ++blknr;
- buffer += ATA_BLOCKSIZE;
- }
-WR_OUT:
- ide_led(DEVICE_LED(device), 0); /* LED off */
- return (n);
-}
-
-/* ------------------------------------------------------------------------- */
-
-/*
- * copy src to dest, skipping leading and trailing blanks and null
- * terminate the string
- * "len" is the size of available memory including the terminating '\0'
- */
-static void ident_cpy(unsigned char *dst, unsigned char *src,
- unsigned int len)
-{
- unsigned char *end, *last;
-
- last = dst;
- end = src + len - 1;
-
- /* reserve space for '\0' */
- if (len < 2)
- goto OUT;
-
- /* skip leading white space */
- while ((*src) && (src < end) && (*src == ' '))
- ++src;
-
- /* copy string, omitting trailing white space */
- while ((*src) && (src < end)) {
- *dst++ = *src;
- if (*src++ != ' ')
- last = dst;
- }
-OUT:
- *last = '\0';
-}
-
-/* ------------------------------------------------------------------------- */
-
-/*
- * Wait until Busy bit is off, or timeout (in ms)
- * Return last status
- */
-static uchar ide_wait(int dev, ulong t)
-{
- ulong delay = 10 * t; /* poll every 100 us */
- uchar c;
-
- while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
- udelay(100);
- if (delay-- == 0)
- break;
- }
- return (c);
-}
-
-/* ------------------------------------------------------------------------- */
-
-#ifdef CONFIG_IDE_RESET
-extern void ide_set_reset(int idereset);
-
-static void ide_reset(void)
-{
- int i;
-
- curr_device = -1;
- for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i)
- ide_bus_ok[i] = 0;
- for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i)
- ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
-
- ide_set_reset(1); /* assert reset */
-
- /* the reset signal shall be asserted for et least 25 us */
- udelay(25);
-
- WATCHDOG_RESET();
-
- /* de-assert RESET signal */
- ide_set_reset(0);
-
- /* wait 250 ms */
- for (i = 0; i < 250; ++i)
- udelay(1000);
-}
-
-#endif /* CONFIG_IDE_RESET */
-
-/* ------------------------------------------------------------------------- */
-
-#if defined(CONFIG_OF_IDE_FIXUP)
-int ide_device_present(int dev)
-{
- if (dev >= CONFIG_SYS_IDE_MAXBUS)
- return 0;
- return (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1);
-}
-#endif
-/* ------------------------------------------------------------------------- */
-
-#ifdef CONFIG_ATAPI
-/****************************************************************************
- * ATAPI Support
- */
-
-#if defined(CONFIG_IDE_SWAP_IO)
-/* since ATAPI may use commands with not 4 bytes alligned length
- * we have our own transfer functions, 2 bytes alligned */
-__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
-{
- ushort *dbuf;
- volatile ushort *pbuf;
-
- pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
- dbuf = (ushort *) sect_buf;
-
- debug("in output data shorts base for read is %lx\n",
- (unsigned long) pbuf);
-
- while (shorts--) {
- EIEIO;
- *pbuf = *dbuf++;
- }
-}
-
-__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
-{
- ushort *dbuf;
- volatile ushort *pbuf;
-
- pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
- dbuf = (ushort *) sect_buf;
-
- debug("in input data shorts base for read is %lx\n",
- (unsigned long) pbuf);
-
- while (shorts--) {
- EIEIO;
- *dbuf++ = *pbuf;
- }
-}
-
-#else /* ! CONFIG_IDE_SWAP_IO */
-__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
-{
- outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
-}
-
-__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
-{
- insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
-}
-
-#endif /* CONFIG_IDE_SWAP_IO */
-
-/*
- * Wait until (Status & mask) == res, or timeout (in ms)
- * Return last status
- * This is used since some ATAPI CD ROMs clears their Busy Bit first
- * and then they set their DRQ Bit
- */
-static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res)
-{
- ulong delay = 10 * t; /* poll every 100 us */
- uchar c;
-
- /* prevents to read the status before valid */
- c = ide_inb(dev, ATA_DEV_CTL);
-
- while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) {
- /* break if error occurs (doesn't make sense to wait more) */
- if ((c & ATA_STAT_ERR) == ATA_STAT_ERR)
- break;
- udelay(100);
- if (delay-- == 0)
- break;
- }
- return (c);
-}
-
-/*
- * issue an atapi command
- */
-unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen,
- unsigned char *buffer, int buflen)
-{
- unsigned char c, err, mask, res;
- int n;
-
- ide_led(DEVICE_LED(device), 1); /* LED on */
-
- /* Select device
- */
- mask = ATA_STAT_BUSY | ATA_STAT_DRQ;
- res = 0;
- ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
- c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
- if ((c & mask) != res) {
- printf("ATAPI_ISSUE: device %d not ready status %X\n", device,
- c);
- err = 0xFF;
- goto AI_OUT;
- }
- /* write taskfile */
- ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */
- ide_outb(device, ATA_SECT_CNT, 0);
- ide_outb(device, ATA_SECT_NUM, 0);
- ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF));
- ide_outb(device, ATA_CYL_HIGH,
- (unsigned char) ((buflen >> 8) & 0xFF));
- ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
-
- ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET);
- udelay(50);
-
- mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR;
- res = ATA_STAT_DRQ;
- c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
-
- if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */
- printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n",
- device, c);
- err = 0xFF;
- goto AI_OUT;
- }
-
- /* write command block */
- ide_output_data_shorts(device, (unsigned short *) ccb, ccblen / 2);
-
- /* ATAPI Command written wait for completition */
- udelay(5000); /* device must set bsy */
-
- mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR;
- /*
- * if no data wait for DRQ = 0 BSY = 0
- * if data wait for DRQ = 1 BSY = 0
- */
- res = 0;
- if (buflen)
- res = ATA_STAT_DRQ;
- c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
- if ((c & mask) != res) {
- if (c & ATA_STAT_ERR) {
- err = (ide_inb(device, ATA_ERROR_REG)) >> 4;
- debug("atapi_issue 1 returned sense key %X status %02X\n",
- err, c);
- } else {
- printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n",
- ccb[0], c);
- err = 0xFF;
- }
- goto AI_OUT;
- }
- n = ide_inb(device, ATA_CYL_HIGH);
- n <<= 8;
- n += ide_inb(device, ATA_CYL_LOW);
- if (n > buflen) {
- printf("ERROR, transfer bytes %d requested only %d\n", n,
- buflen);
- err = 0xff;
- goto AI_OUT;
- }
- if ((n == 0) && (buflen < 0)) {
- printf("ERROR, transfer bytes %d requested %d\n", n, buflen);
- err = 0xff;
- goto AI_OUT;
- }
- if (n != buflen) {
- debug("WARNING, transfer bytes %d not equal with requested %d\n",
- n, buflen);
- }
- if (n != 0) { /* data transfer */
- debug("ATAPI_ISSUE: %d Bytes to transfer\n", n);
- /* we transfer shorts */
- n >>= 1;
- /* ok now decide if it is an in or output */
- if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) {
- debug("Write to device\n");
- ide_output_data_shorts(device,
- (unsigned short *) buffer, n);
- } else {
- debug("Read from device @ %p shorts %d\n", buffer, n);
- ide_input_data_shorts(device,
- (unsigned short *) buffer, n);
- }
- }
- udelay(5000); /* seems that some CD ROMs need this... */
- mask = ATA_STAT_BUSY | ATA_STAT_ERR;
- res = 0;
- c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
- if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
- err = (ide_inb(device, ATA_ERROR_REG) >> 4);
- debug("atapi_issue 2 returned sense key %X status %X\n", err,
- c);
- } else {
- err = 0;
- }
-AI_OUT:
- ide_led(DEVICE_LED(device), 0); /* LED off */
- return (err);
-}
-
-/*
- * sending the command to atapi_issue. If an status other than good
- * returns, an request_sense will be issued
- */
-
-#define ATAPI_DRIVE_NOT_READY 100
-#define ATAPI_UNIT_ATTN 10
-
-unsigned char atapi_issue_autoreq(int device,
- unsigned char *ccb,
- int ccblen,
- unsigned char *buffer, int buflen)
-{
- unsigned char sense_data[18], sense_ccb[12];
- unsigned char res, key, asc, ascq;
- int notready, unitattn;
-
- unitattn = ATAPI_UNIT_ATTN;
- notready = ATAPI_DRIVE_NOT_READY;
-
-retry:
- res = atapi_issue(device, ccb, ccblen, buffer, buflen);
- if (res == 0)
- return 0; /* Ok */
-
- if (res == 0xFF)
- return 0xFF; /* error */
-
- debug("(auto_req)atapi_issue returned sense key %X\n", res);
-
- memset(sense_ccb, 0, sizeof(sense_ccb));
- memset(sense_data, 0, sizeof(sense_data));
- sense_ccb[0] = ATAPI_CMD_REQ_SENSE;
- sense_ccb[4] = 18; /* allocation Length */
-
- res = atapi_issue(device, sense_ccb, 12, sense_data, 18);
- key = (sense_data[2] & 0xF);
- asc = (sense_data[12]);
- ascq = (sense_data[13]);
-
- debug("ATAPI_CMD_REQ_SENSE returned %x\n", res);
- debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n",
- sense_data[0], key, asc, ascq);
-
- if ((key == 0))
- return 0; /* ok device ready */
-
- if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */
- if (unitattn-- > 0) {
- udelay(200 * 1000);
- goto retry;
- }
- printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN);
- goto error;
- }
- if ((asc == 0x4) && (ascq == 0x1)) {
- /* not ready, but will be ready soon */
- if (notready-- > 0) {
- udelay(200 * 1000);
- goto retry;
- }
- printf("Drive not ready, tried %d times\n",
- ATAPI_DRIVE_NOT_READY);
- goto error;
- }
- if (asc == 0x3a) {
- debug("Media not present\n");
- goto error;
- }
-
- printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc,
- ascq);
-error:
- debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq);
- return (0xFF);
-}
-
-
-static void atapi_inquiry(struct blk_desc *dev_desc)
-{
- unsigned char ccb[12]; /* Command descriptor block */
- unsigned char iobuf[64]; /* temp buf */
- unsigned char c;
- int device;
-
- device = dev_desc->devnum;
- dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */
- dev_desc->block_read = atapi_read;
-
- memset(ccb, 0, sizeof(ccb));
- memset(iobuf, 0, sizeof(iobuf));
-
- ccb[0] = ATAPI_CMD_INQUIRY;
- ccb[4] = 40; /* allocation Legnth */
- c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 40);
-
- debug("ATAPI_CMD_INQUIRY returned %x\n", c);
- if (c != 0)
- return;
-
- /* copy device ident strings */
- ident_cpy((unsigned char *) dev_desc->vendor, &iobuf[8], 8);
- ident_cpy((unsigned char *) dev_desc->product, &iobuf[16], 16);
- ident_cpy((unsigned char *) dev_desc->revision, &iobuf[32], 5);
-
- dev_desc->lun = 0;
- dev_desc->lba = 0;
- dev_desc->blksz = 0;
- dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz));
- dev_desc->type = iobuf[0] & 0x1f;
-
- if ((iobuf[1] & 0x80) == 0x80)
- dev_desc->removable = 1;
- else
- dev_desc->removable = 0;
-
- memset(ccb, 0, sizeof(ccb));
- memset(iobuf, 0, sizeof(iobuf));
- ccb[0] = ATAPI_CMD_START_STOP;
- ccb[4] = 0x03; /* start */
-
- c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0);
-
- debug("ATAPI_CMD_START_STOP returned %x\n", c);
- if (c != 0)
- return;
-
- memset(ccb, 0, sizeof(ccb));
- memset(iobuf, 0, sizeof(iobuf));
- c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0);
-
- debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c);
- if (c != 0)
- return;
-
- memset(ccb, 0, sizeof(ccb));
- memset(iobuf, 0, sizeof(iobuf));
- ccb[0] = ATAPI_CMD_READ_CAP;
- c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 8);
- debug("ATAPI_CMD_READ_CAP returned %x\n", c);
- if (c != 0)
- return;
-
- debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n",
- iobuf[0], iobuf[1], iobuf[2], iobuf[3],
- iobuf[4], iobuf[5], iobuf[6], iobuf[7]);
-
- dev_desc->lba = ((unsigned long) iobuf[0] << 24) +
- ((unsigned long) iobuf[1] << 16) +
- ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]);
- dev_desc->blksz = ((unsigned long) iobuf[4] << 24) +
- ((unsigned long) iobuf[5] << 16) +
- ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]);
- dev_desc->log2blksz = LOG2(dev_desc->blksz);
-#ifdef CONFIG_LBA48
- /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */
- dev_desc->lba48 = 0;
-#endif
- return;
-}
-
-
-/*
- * atapi_read:
- * we transfer only one block per command, since the multiple DRQ per
- * command is not yet implemented
- */
-#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */
-#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */
-#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE)
-
-ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
- void *buffer)
-{
- int device = block_dev->devnum;
- ulong n = 0;
- unsigned char ccb[12]; /* Command descriptor block */
- ulong cnt;
-
- debug("atapi_read dev %d start " LBAF " blocks " LBAF " buffer at %lX\n",
- device, blknr, blkcnt, (ulong) buffer);
-
- do {
- if (blkcnt > ATAPI_READ_MAX_BLOCK)
- cnt = ATAPI_READ_MAX_BLOCK;
- else
- cnt = blkcnt;
-
- ccb[0] = ATAPI_CMD_READ_12;
- ccb[1] = 0; /* reserved */
- ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */
- ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */
- ccb[4] = (unsigned char) (blknr >> 8) & 0xFF;
- ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */
- ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */
- ccb[7] = (unsigned char) (cnt >> 16) & 0xFF;
- ccb[8] = (unsigned char) (cnt >> 8) & 0xFF;
- ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */
- ccb[10] = 0; /* reserved */
- ccb[11] = 0; /* reserved */
-
- if (atapi_issue_autoreq(device, ccb, 12,
- (unsigned char *) buffer,
- cnt * ATAPI_READ_BLOCK_SIZE)
- == 0xFF) {
- return (n);
- }
- n += cnt;
- blkcnt -= cnt;
- blknr += cnt;
- buffer += (cnt * ATAPI_READ_BLOCK_SIZE);
- } while (blkcnt > 0);
- return (n);
-}
-
-/* ------------------------------------------------------------------------- */
-
-#endif /* CONFIG_ATAPI */
-
U_BOOT_CMD(ide, 5, 1, do_ide,
"IDE sub-system",
"reset - reset IDE controller\n"
diff --git a/cmd/mmc.c b/cmd/mmc.c
index c5454bf..eb4a547 100644
--- a/cmd/mmc.c
+++ b/cmd/mmc.c
@@ -314,12 +314,14 @@ static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag,
}
/* Switch to the RPMB partition */
original_part = mmc->block_dev.hwpart;
- if (mmc_select_hwpart(curr_device, MMC_PART_RPMB) != 0)
+ if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) !=
+ 0)
return CMD_RET_FAILURE;
ret = cp->cmd(cmdtp, flag, argc, argv);
/* Return to original partition */
- if (mmc_select_hwpart(curr_device, original_part) != 0)
+ if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part) !=
+ 0)
return CMD_RET_FAILURE;
return ret;
}
@@ -346,7 +348,7 @@ static int do_mmc_read(cmd_tbl_t *cmdtp, int flag,
printf("\nMMC read: dev # %d, block # %d, count %d ... ",
curr_device, blk, cnt);
- n = blk_dread(&mmc->block_dev, blk, cnt, addr);
+ n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
/* flush cache after read */
flush_cache((ulong)addr, cnt * 512); /* FIXME */
printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
@@ -378,7 +380,7 @@ static int do_mmc_write(cmd_tbl_t *cmdtp, int flag,
printf("Error: card is write protected!\n");
return CMD_RET_FAILURE;
}
- n = blk_dwrite(&mmc->block_dev, blk, cnt, addr);
+ n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
@@ -406,7 +408,7 @@ static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag,
printf("Error: card is write protected!\n");
return CMD_RET_FAILURE;
}
- n = blk_derase(&mmc->block_dev, blk, cnt);
+ n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR");
return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
@@ -432,7 +434,7 @@ static int do_mmc_part(cmd_tbl_t *cmdtp, int flag,
if (!mmc)
return CMD_RET_FAILURE;
- mmc_dev = mmc_get_dev(curr_device);
+ mmc_dev = blk_get_devnum_by_type(IF_TYPE_MMC, curr_device);
if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) {
part_print(mmc_dev);
return CMD_RET_SUCCESS;
@@ -467,7 +469,7 @@ static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag,
if (!mmc)
return CMD_RET_FAILURE;
- ret = mmc_select_hwpart(dev, part);
+ ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part);
printf("switch to partitions #%d, %s\n",
part, (!ret) ? "OK" : "ERROR");
if (ret)
@@ -478,7 +480,7 @@ static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag,
printf("mmc%d is current device\n", curr_device);
else
printf("mmc%d(part %d) is current device\n",
- curr_device, mmc->block_dev.hwpart);
+ curr_device, mmc_get_blk_desc(mmc)->hwpart);
return CMD_RET_SUCCESS;
}
diff --git a/cmd/sata.c b/cmd/sata.c
index 8748cce..d18b523 100644
--- a/cmd/sata.c
+++ b/cmd/sata.c
@@ -16,70 +16,6 @@
#include <sata.h>
static int sata_curr_device = -1;
-struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
-
-static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start,
- lbaint_t blkcnt, void *dst)
-{
- return sata_read(block_dev->devnum, start, blkcnt, dst);
-}
-
-static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start,
- lbaint_t blkcnt, const void *buffer)
-{
- return sata_write(block_dev->devnum, start, blkcnt, buffer);
-}
-
-int __sata_initialize(void)
-{
- int rc;
- int i;
-
- for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) {
- memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc));
- sata_dev_desc[i].if_type = IF_TYPE_SATA;
- sata_dev_desc[i].devnum = i;
- sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
- sata_dev_desc[i].type = DEV_TYPE_HARDDISK;
- sata_dev_desc[i].lba = 0;
- sata_dev_desc[i].blksz = 512;
- sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz);
- sata_dev_desc[i].block_read = sata_bread;
- sata_dev_desc[i].block_write = sata_bwrite;
-
- rc = init_sata(i);
- if (!rc) {
- rc = scan_sata(i);
- if (!rc && (sata_dev_desc[i].lba > 0) &&
- (sata_dev_desc[i].blksz > 0))
- part_init(&sata_dev_desc[i]);
- }
- }
- sata_curr_device = 0;
- return rc;
-}
-int sata_initialize(void) __attribute__((weak,alias("__sata_initialize")));
-
-__weak int __sata_stop(void)
-{
- int i, err = 0;
-
- for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++)
- err |= reset_sata(i);
-
- if (err)
- printf("Could not reset some SATA devices\n");
-
- return err;
-}
-int sata_stop(void) __attribute__((weak, alias("__sata_stop")));
-
-#ifdef CONFIG_PARTITIONS
-struct blk_desc *sata_get_dev(int dev)
-{
- return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL;
-}
-#endif
static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
@@ -105,69 +41,40 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
case 1:
return CMD_RET_USAGE;
case 2:
- if (strncmp(argv[1],"inf", 3) == 0) {
- int i;
- putc('\n');
- for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; ++i) {
- if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN)
- continue;
- printf ("SATA device %d: ", i);
- dev_print(&sata_dev_desc[i]);
- }
+ if (strncmp(argv[1], "inf", 3) == 0) {
+ blk_list_devices(IF_TYPE_SATA);
return 0;
- } else if (strncmp(argv[1],"dev", 3) == 0) {
- if ((sata_curr_device < 0) || (sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE)) {
- puts("\nno SATA devices available\n");
- return 1;
+ } else if (strncmp(argv[1], "dev", 3) == 0) {
+ if (blk_print_device_num(IF_TYPE_SATA,
+ sata_curr_device)) {
+ printf("\nno SATA devices available\n");
+ return CMD_RET_FAILURE;
}
- printf("\nSATA device %d: ", sata_curr_device);
- dev_print(&sata_dev_desc[sata_curr_device]);
return 0;
- } else if (strncmp(argv[1],"part",4) == 0) {
- int dev, ok;
-
- for (ok = 0, dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; ++dev) {
- if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) {
- ++ok;
- if (dev)
- putc ('\n');
- part_print(&sata_dev_desc[dev]);
- }
- }
- if (!ok) {
+ } else if (strncmp(argv[1], "part", 4) == 0) {
+ if (blk_list_part(IF_TYPE_SATA))
puts("\nno SATA devices available\n");
- rc ++;
- }
- return rc;
+ return 0;
}
return CMD_RET_USAGE;
case 3:
if (strncmp(argv[1], "dev", 3) == 0) {
int dev = (int)simple_strtoul(argv[2], NULL, 10);
- printf("\nSATA device %d: ", dev);
- if (dev >= CONFIG_SYS_SATA_MAX_DEVICE) {
- puts ("unknown device\n");
- return 1;
+ if (!blk_show_device(IF_TYPE_SATA, dev)) {
+ sata_curr_device = dev;
+ printf("... is now current device\n");
+ } else {
+ return CMD_RET_FAILURE;
}
- dev_print(&sata_dev_desc[dev]);
-
- if (sata_dev_desc[dev].type == DEV_TYPE_UNKNOWN)
- return 1;
-
- sata_curr_device = dev;
-
- puts("... is now current device\n");
-
return 0;
} else if (strncmp(argv[1], "part", 4) == 0) {
int dev = (int)simple_strtoul(argv[2], NULL, 10);
- if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) {
- part_print(&sata_dev_desc[dev]);
- } else {
- printf("\nSATA device %d not available\n", dev);
- rc = 1;
+ if (blk_print_part_devnum(IF_TYPE_SATA, dev)) {
+ printf("\nSATA device %d not available\n",
+ dev);
+ return CMD_RET_FAILURE;
}
return rc;
}
@@ -183,11 +90,8 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
printf("\nSATA read: device %d block # %ld, count %ld ... ",
sata_curr_device, blk, cnt);
- n = blk_dread(&sata_dev_desc[sata_curr_device],
- blk, cnt, (u32 *)addr);
-
- /* flush cache after read */
- flush_cache(addr, cnt * sata_dev_desc[sata_curr_device].blksz);
+ n = blk_read_devnum(IF_TYPE_SATA, sata_curr_device, blk,
+ cnt, (ulong *)addr);
printf("%ld blocks read: %s\n",
n, (n==cnt) ? "OK" : "ERROR");
@@ -202,8 +106,8 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
printf("\nSATA write: device %d block # %ld, count %ld ... ",
sata_curr_device, blk, cnt);
- n = blk_dwrite(&sata_dev_desc[sata_curr_device],
- blk, cnt, (u32 *)addr);
+ n = blk_write_devnum(IF_TYPE_SATA, sata_curr_device,
+ blk, cnt, (ulong *)addr);
printf("%ld blocks written: %s\n",
n, (n == cnt) ? "OK" : "ERROR");
diff --git a/cmd/scsi.c b/cmd/scsi.c
index 8991125..387ca1a 100644
--- a/cmd/scsi.c
+++ b/cmd/scsi.c
@@ -10,361 +10,108 @@
*/
#include <common.h>
#include <command.h>
-#include <inttypes.h>
-#include <asm/processor.h>
#include <scsi.h>
-#include <image.h>
-#include <pci.h>
-
-#ifdef CONFIG_SCSI_DEV_LIST
-#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST
-#else
-#ifdef CONFIG_SCSI_SYM53C8XX
-#define SCSI_VEND_ID 0x1000
-#ifndef CONFIG_SCSI_DEV_ID
-#define SCSI_DEV_ID 0x0001
-#else
-#define SCSI_DEV_ID CONFIG_SCSI_DEV_ID
-#endif
-#elif defined CONFIG_SATA_ULI5288
-
-#define SCSI_VEND_ID 0x10b9
-#define SCSI_DEV_ID 0x5288
-
-#elif !defined(CONFIG_SCSI_AHCI_PLAT)
-#error no scsi device defined
-#endif
-#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID}
-#endif
-
-#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
-const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
-#endif
-static ccb tempccb; /* temporary scsi command buffer */
-
-static unsigned char tempbuff[512]; /* temporary data buffer */
-
-static int scsi_max_devs; /* number of highest available scsi device */
static int scsi_curr_dev; /* current device */
-static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
-
-/********************************************************************************
- * forward declerations of some Setup Routines
- */
-void scsi_setup_test_unit_ready(ccb * pccb);
-void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks);
-void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks);
-void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks);
-
-static void scsi_setup_write_ext(ccb *pccb, lbaint_t start,
- unsigned short blocks);
-void scsi_setup_inquiry(ccb * pccb);
-void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);
-
-
-static int scsi_read_capacity(ccb *pccb, lbaint_t *capacity,
- unsigned long *blksz);
-static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr,
- lbaint_t blkcnt, void *buffer);
-static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr,
- lbaint_t blkcnt, const void *buffer);
-
-
-/*********************************************************************************
- * (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;
- ccb* pccb=(ccb *)&tempccb;
-
- 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;
- scsi_dev_desc[i].block_read=scsi_read;
- scsi_dev_desc[i].block_write = scsi_write;
- }
- 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++) {
- 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) {
- debug ("Selection timeout ID %d\n",pccb->target);
- continue; /* selection timeout => assuming no device present */
- }
- 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 == true) {
- 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);
- 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);
- dev_print(&scsi_dev_desc[scsi_max_devs]);
- } /* if mode */
- scsi_max_devs++;
- } /* next LUN */
- }
- if(scsi_max_devs>0)
- scsi_curr_dev=0;
- else
- scsi_curr_dev = -1;
-
- printf("Found %d device(s).\n", scsi_max_devs);
-#ifndef CONFIG_SPL_BUILD
- setenv_ulong("scsidevs", scsi_max_devs);
-#endif
-}
-
-int scsi_get_disk_count(void)
-{
- return scsi_max_devs;
-}
-
-#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
-void scsi_init(void)
-{
- int busdevfunc = -1;
- int i;
- /*
- * Find a device from the list, this driver will support a single
- * controller.
- */
- for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
- /* get PCI Device ID */
-#ifdef CONFIG_DM_PCI
- struct udevice *dev;
- int ret;
-
- ret = dm_pci_find_device(scsi_device_list[i].vendor,
- scsi_device_list[i].device, 0, &dev);
- if (!ret) {
- busdevfunc = dm_pci_get_bdf(dev);
- break;
- }
-#else
- busdevfunc = pci_find_device(scsi_device_list[i].vendor,
- scsi_device_list[i].device,
- 0);
-#endif
- if (busdevfunc != -1)
- break;
- }
-
- if (busdevfunc == -1) {
- printf("Error: SCSI Controller(s) ");
- for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
- printf("%04X:%04X ",
- scsi_device_list[i].vendor,
- scsi_device_list[i].device);
- }
- printf("not found\n");
- return;
- }
-#ifdef DEBUG
- else {
- printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",
- scsi_device_list[i].vendor,
- scsi_device_list[i].device,
- (busdevfunc >> 16) & 0xFF,
- (busdevfunc >> 11) & 0x1F,
- (busdevfunc >> 8) & 0x7);
- }
-#endif
- bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");
- scsi_low_level_init(busdevfunc);
- scsi_scan(1);
- bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
-}
-#endif
-
-#ifdef CONFIG_PARTITIONS
-struct blk_desc *scsi_get_dev(int dev)
-{
- return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL;
-}
-#endif
-
-#ifndef CONFIG_SPL_BUILD
-/******************************************************************************
+/*
* scsi boot command intepreter. Derived from diskboot
*/
-int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_scsiboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
return common_diskboot(cmdtp, "scsi", argc, argv);
}
-/*********************************************************************************
+/*
* scsi command intepreter
*/
-int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_scsi(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
switch (argc) {
case 0:
case 1:
return CMD_RET_USAGE;
-
case 2:
- if (strncmp(argv[1],"res",3) == 0) {
- printf("\nReset SCSI\n");
- scsi_bus_reset();
- scsi_scan(1);
- return 0;
- }
- if (strncmp(argv[1],"inf",3) == 0) {
- int i;
- for (i=0; i<CONFIG_SYS_SCSI_MAX_DEVICE; ++i) {
- if(scsi_dev_desc[i].type==DEV_TYPE_UNKNOWN)
- continue; /* list only known devices */
- printf ("SCSI dev. %d: ", i);
- dev_print(&scsi_dev_desc[i]);
- }
- return 0;
- }
- if (strncmp(argv[1],"dev",3) == 0) {
- if ((scsi_curr_dev < 0) || (scsi_curr_dev >= CONFIG_SYS_SCSI_MAX_DEVICE)) {
- printf("\nno SCSI devices available\n");
- return 1;
- }
- printf ("\n Device %d: ", scsi_curr_dev);
- dev_print(&scsi_dev_desc[scsi_curr_dev]);
- return 0;
- }
- if (strncmp(argv[1],"scan",4) == 0) {
- scsi_scan(1);
- return 0;
- }
- if (strncmp(argv[1],"part",4) == 0) {
- int dev, ok;
- for (ok=0, dev=0; dev<CONFIG_SYS_SCSI_MAX_DEVICE; ++dev) {
- if (scsi_dev_desc[dev].type!=DEV_TYPE_UNKNOWN) {
- ok++;
- if (dev)
- printf("\n");
- debug ("print_part of %x\n",dev);
- part_print(&scsi_dev_desc[dev]);
- }
- }
- if (!ok)
- printf("\nno SCSI devices available\n");
- return 1;
+ if (strncmp(argv[1], "res", 3) == 0) {
+ printf("\nReset SCSI\n");
+ scsi_bus_reset();
+ scsi_scan(1);
+ return 0;
+ }
+ if (strncmp(argv[1], "inf", 3) == 0) {
+ blk_list_devices(IF_TYPE_SCSI);
+ return 0;
+ }
+ if (strncmp(argv[1], "dev", 3) == 0) {
+ if (blk_print_device_num(IF_TYPE_SCSI, scsi_curr_dev)) {
+ printf("\nno SCSI devices available\n");
+ return CMD_RET_FAILURE;
}
- return CMD_RET_USAGE;
+
+ return 0;
+ }
+ if (strncmp(argv[1], "scan", 4) == 0) {
+ scsi_scan(1);
+ return 0;
+ }
+ if (strncmp(argv[1], "part", 4) == 0) {
+ if (blk_list_part(IF_TYPE_SCSI))
+ printf("\nno SCSI devices available\n");
+ return 0;
+ }
+ return CMD_RET_USAGE;
case 3:
- if (strncmp(argv[1],"dev",3) == 0) {
- int dev = (int)simple_strtoul(argv[2], NULL, 10);
- printf ("\nSCSI device %d: ", dev);
- if (dev >= CONFIG_SYS_SCSI_MAX_DEVICE) {
- printf("unknown device\n");
- return 1;
- }
- printf ("\n Device %d: ", dev);
- dev_print(&scsi_dev_desc[dev]);
- if(scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
- return 1;
- }
+ if (strncmp(argv[1], "dev", 3) == 0) {
+ int dev = (int)simple_strtoul(argv[2], NULL, 10);
+
+ if (!blk_show_device(IF_TYPE_SCSI, dev)) {
scsi_curr_dev = dev;
printf("... is now current device\n");
- return 0;
+ } else {
+ return CMD_RET_FAILURE;
}
- if (strncmp(argv[1],"part",4) == 0) {
- int dev = (int)simple_strtoul(argv[2], NULL, 10);
- if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) {
- part_print(&scsi_dev_desc[dev]);
- }
- else {
- printf ("\nSCSI device %d not available\n", dev);
- }
- return 1;
- }
- return CMD_RET_USAGE;
- default:
- /* at least 4 args */
- if (strcmp(argv[1],"read") == 0) {
- ulong addr = simple_strtoul(argv[2], NULL, 16);
- ulong blk = simple_strtoul(argv[3], NULL, 16);
- ulong cnt = simple_strtoul(argv[4], NULL, 16);
- ulong n;
- printf ("\nSCSI read: device %d block # %ld, count %ld ... ",
- scsi_curr_dev, blk, cnt);
- n = scsi_read(&scsi_dev_desc[scsi_curr_dev],
- blk, cnt, (ulong *)addr);
- printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR");
- return 0;
- } else if (strcmp(argv[1], "write") == 0) {
- ulong addr = simple_strtoul(argv[2], NULL, 16);
- ulong blk = simple_strtoul(argv[3], NULL, 16);
- ulong cnt = simple_strtoul(argv[4], NULL, 16);
- ulong n;
- printf("\nSCSI write: device %d block # %ld, "
- "count %ld ... ",
- scsi_curr_dev, blk, cnt);
- n = scsi_write(&scsi_dev_desc[scsi_curr_dev],
- blk, cnt, (ulong *)addr);
- printf("%ld blocks written: %s\n", n,
- (n == cnt) ? "OK" : "ERROR");
- return 0;
+ return 0;
+ }
+ if (strncmp(argv[1], "part", 4) == 0) {
+ int dev = (int)simple_strtoul(argv[2], NULL, 10);
+
+ if (blk_print_part_devnum(IF_TYPE_SCSI, dev)) {
+ printf("\nSCSI device %d not available\n",
+ dev);
+ return CMD_RET_FAILURE;
}
+ return 0;
+ }
+ return CMD_RET_USAGE;
+ default:
+ /* at least 4 args */
+ if (strcmp(argv[1], "read") == 0) {
+ ulong addr = simple_strtoul(argv[2], NULL, 16);
+ ulong blk = simple_strtoul(argv[3], NULL, 16);
+ ulong cnt = simple_strtoul(argv[4], NULL, 16);
+ ulong n;
+
+ printf("\nSCSI read: device %d block # %ld, count %ld ... ",
+ scsi_curr_dev, blk, cnt);
+ n = blk_read_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk,
+ cnt, (ulong *)addr);
+ printf("%ld blocks read: %s\n", n,
+ n == cnt ? "OK" : "ERROR");
+ return 0;
+ } else if (strcmp(argv[1], "write") == 0) {
+ ulong addr = simple_strtoul(argv[2], NULL, 16);
+ ulong blk = simple_strtoul(argv[3], NULL, 16);
+ ulong cnt = simple_strtoul(argv[4], NULL, 16);
+ ulong n;
+
+ printf("\nSCSI write: device %d block # %ld, count %ld ... ",
+ scsi_curr_dev, blk, cnt);
+ n = blk_write_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk,
+ cnt, (ulong *)addr);
+ printf("%ld blocks written: %s\n", n,
+ n == cnt ? "OK" : "ERROR");
+ return 0;
+ }
} /* switch */
return CMD_RET_USAGE;
}
@@ -388,347 +135,3 @@ U_BOOT_CMD(
"boot from SCSI device",
"loadAddr dev:part"
);
-#endif
-
-/****************************************************************************************
- * scsi_read
- */
-
-/* almost the maximum amount of the scsi_ext command.. */
-#define SCSI_MAX_READ_BLK 0xFFFF
-#define SCSI_LBA48_READ 0xFFFFFFF
-
-static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr,
- lbaint_t blkcnt, void *buffer)
-{
- 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;
- 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);
- 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;
- 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 * 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;
- smallblks=(unsigned short) blks;
- scsi_setup_read_ext(pccb,start,smallblks);
- start+=blks;
- blks=0;
- }
- debug("scsi_read_ext: startblk " LBAF
- ", blccnt %x buffer %" PRIXPTR "\n",
- start, smallblks, buf_addr);
- if (scsi_exec(pccb) != true) {
- scsi_print_error(pccb);
- blkcnt-=blks;
- break;
- }
- buf_addr+=pccb->datalen;
- } while(blks!=0);
- debug("scsi_read_ext: end startblk " LBAF
- ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr);
- return(blkcnt);
-}
-
-/*******************************************************************************
- * scsi_write
- */
-
-/* Almost the maximum amount of the scsi_ext command.. */
-#define SCSI_MAX_WRITE_BLK 0xFFFF
-
-static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr,
- lbaint_t blkcnt, const void *buffer)
-{
- 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;
- 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);
- do {
- pccb->pdata = (unsigned char *)buf_addr;
- if (blks > SCSI_MAX_WRITE_BLK) {
- pccb->datalen = (scsi_dev_desc[device].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;
- smallblks = (unsigned short)blks;
- scsi_setup_write_ext(pccb, start, smallblks);
- start += blks;
- blks = 0;
- }
- debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
- __func__, start, smallblks, buf_addr);
- if (scsi_exec(pccb) != true) {
- scsi_print_error(pccb);
- blkcnt -= blks;
- break;
- }
- buf_addr += pccb->datalen;
- } while (blks != 0);
- debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
- __func__, start, smallblks, buf_addr);
- return blkcnt;
-}
-
-/* copy src to dest, skipping leading and trailing blanks
- * and null terminate the string
- */
-void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len)
-{
- int start,end;
-
- start=0;
- while(start<len) {
- if(src[start]!=' ')
- break;
- start++;
- }
- end=len-1;
- while(end>start) {
- if(src[end]!=' ')
- break;
- end--;
- }
- for( ; start<=end; start++) {
- *dest++=src[start];
- }
- *dest='\0';
-}
-
-
-/* Trim trailing blanks, and NUL-terminate string
- */
-void scsi_trim_trail (unsigned char *str, unsigned int len)
-{
- unsigned char *p = str + len - 1;
-
- while (len-- > 0) {
- *p-- = '\0';
- if (*p != ' ') {
- return;
- }
- }
-}
-
-int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz)
-{
- *capacity = 0;
-
- memset(pccb->cmd, 0, sizeof(pccb->cmd));
- pccb->cmd[0] = SCSI_RD_CAPAC10;
- pccb->cmd[1] = pccb->lun << 5;
- pccb->cmdlen = 10;
- pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
-
- pccb->datalen = 8;
- if (scsi_exec(pccb) != true)
- return 1;
-
- *capacity = ((lbaint_t)pccb->pdata[0] << 24) |
- ((lbaint_t)pccb->pdata[1] << 16) |
- ((lbaint_t)pccb->pdata[2] << 8) |
- ((lbaint_t)pccb->pdata[3]);
-
- if (*capacity != 0xffffffff) {
- /* Read capacity (10) was sufficient for this drive. */
- *blksz = ((unsigned long)pccb->pdata[4] << 24) |
- ((unsigned long)pccb->pdata[5] << 16) |
- ((unsigned long)pccb->pdata[6] << 8) |
- ((unsigned long)pccb->pdata[7]);
- return 0;
- }
-
- /* Read capacity (10) was insufficient. Use read capacity (16). */
-
- memset(pccb->cmd, 0, sizeof(pccb->cmd));
- pccb->cmd[0] = SCSI_RD_CAPAC16;
- pccb->cmd[1] = 0x10;
- pccb->cmdlen = 16;
- pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
-
- pccb->datalen = 16;
- if (scsi_exec(pccb) != true)
- return 1;
-
- *capacity = ((uint64_t)pccb->pdata[0] << 56) |
- ((uint64_t)pccb->pdata[1] << 48) |
- ((uint64_t)pccb->pdata[2] << 40) |
- ((uint64_t)pccb->pdata[3] << 32) |
- ((uint64_t)pccb->pdata[4] << 24) |
- ((uint64_t)pccb->pdata[5] << 16) |
- ((uint64_t)pccb->pdata[6] << 8) |
- ((uint64_t)pccb->pdata[7]);
-
- *blksz = ((uint64_t)pccb->pdata[8] << 56) |
- ((uint64_t)pccb->pdata[9] << 48) |
- ((uint64_t)pccb->pdata[10] << 40) |
- ((uint64_t)pccb->pdata[11] << 32) |
- ((uint64_t)pccb->pdata[12] << 24) |
- ((uint64_t)pccb->pdata[13] << 16) |
- ((uint64_t)pccb->pdata[14] << 8) |
- ((uint64_t)pccb->pdata[15]);
-
- return 0;
-}
-
-
-/************************************************************************************
- * Some setup (fill-in) routines
- */
-void scsi_setup_test_unit_ready(ccb * pccb)
-{
- pccb->cmd[0]=SCSI_TST_U_RDY;
- pccb->cmd[1]=pccb->lun<<5;
- pccb->cmd[2]=0;
- pccb->cmd[3]=0;
- pccb->cmd[4]=0;
- pccb->cmd[5]=0;
- pccb->cmdlen=6;
- pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
-}
-
-#ifdef CONFIG_SYS_64BIT_LBA
-void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks)
-{
- pccb->cmd[0] = SCSI_READ16;
- pccb->cmd[1] = pccb->lun<<5;
- pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff;
- pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff;
- pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff;
- pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff;
- pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff;
- pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff;
- pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff;
- pccb->cmd[9] = ((unsigned char) (start)) & 0xff;
- pccb->cmd[10] = 0;
- pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff;
- pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff;
- pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff;
- pccb->cmd[14] = (unsigned char) blocks & 0xff;
- pccb->cmd[15] = 0;
- pccb->cmdlen = 16;
- pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
- debug ("scsi_setup_read16: cmd: %02X %02X "
- "startblk %02X%02X%02X%02X%02X%02X%02X%02X "
- "blccnt %02X%02X%02X%02X\n",
- pccb->cmd[0], pccb->cmd[1],
- pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
- pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9],
- pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]);
-}
-#endif
-
-void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks)
-{
- pccb->cmd[0]=SCSI_READ10;
- pccb->cmd[1]=pccb->lun<<5;
- pccb->cmd[2]=((unsigned char) (start>>24))&0xff;
- pccb->cmd[3]=((unsigned char) (start>>16))&0xff;
- pccb->cmd[4]=((unsigned char) (start>>8))&0xff;
- pccb->cmd[5]=((unsigned char) (start))&0xff;
- pccb->cmd[6]=0;
- pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff;
- pccb->cmd[8]=(unsigned char) blocks & 0xff;
- pccb->cmd[6]=0;
- pccb->cmdlen=10;
- pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
- debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
- pccb->cmd[0],pccb->cmd[1],
- pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5],
- pccb->cmd[7],pccb->cmd[8]);
-}
-
-void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks)
-{
- pccb->cmd[0] = SCSI_WRITE10;
- pccb->cmd[1] = pccb->lun << 5;
- pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff;
- pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff;
- pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff;
- pccb->cmd[5] = ((unsigned char) (start)) & 0xff;
- pccb->cmd[6] = 0;
- pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff;
- pccb->cmd[8] = (unsigned char)blocks & 0xff;
- pccb->cmd[9] = 0;
- pccb->cmdlen = 10;
- pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
- debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
- __func__,
- pccb->cmd[0], pccb->cmd[1],
- pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
- pccb->cmd[7], pccb->cmd[8]);
-}
-
-void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks)
-{
- pccb->cmd[0]=SCSI_READ6;
- pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f);
- pccb->cmd[2]=((unsigned char) (start>>8))&0xff;
- pccb->cmd[3]=((unsigned char) (start))&0xff;
- pccb->cmd[4]=(unsigned char) blocks & 0xff;
- pccb->cmd[5]=0;
- pccb->cmdlen=6;
- pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
- debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n",
- pccb->cmd[0],pccb->cmd[1],
- pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]);
-}
-
-
-void scsi_setup_inquiry(ccb * pccb)
-{
- pccb->cmd[0]=SCSI_INQUIRY;
- pccb->cmd[1]=pccb->lun<<5;
- pccb->cmd[2]=0;
- pccb->cmd[3]=0;
- if(pccb->datalen>255)
- pccb->cmd[4]=255;
- else
- pccb->cmd[4]=(unsigned char)pccb->datalen;
- pccb->cmd[5]=0;
- pccb->cmdlen=6;
- pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
-}
diff --git a/cmd/usb.c b/cmd/usb.c
index f1a7deb..b83d323 100644
--- a/cmd/usb.c
+++ b/cmd/usb.c
@@ -723,7 +723,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
int devno, ok = 0;
if (argc == 2) {
for (devno = 0; ; ++devno) {
- stor_dev = usb_stor_get_dev(devno);
+ stor_dev = blk_get_devnum_by_type(IF_TYPE_USB,
+ devno);
if (stor_dev == NULL)
break;
if (stor_dev->type != DEV_TYPE_UNKNOWN) {
@@ -736,7 +737,7 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
} else {
devno = simple_strtoul(argv[2], NULL, 16);
- stor_dev = usb_stor_get_dev(devno);
+ stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, devno);
if (stor_dev != NULL &&
stor_dev->type != DEV_TYPE_UNKNOWN) {
ok++;
@@ -762,7 +763,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
unsigned long n;
printf("\nUSB read: device %d block # %ld, count %ld"
" ... ", usb_stor_curr_dev, blk, cnt);
- stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
+ stor_dev = blk_get_devnum_by_type(IF_TYPE_USB,
+ usb_stor_curr_dev);
n = blk_dread(stor_dev, blk, cnt, (ulong *)addr);
printf("%ld blocks read: %s\n", n,
(n == cnt) ? "OK" : "ERROR");
@@ -783,7 +785,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
unsigned long n;
printf("\nUSB write: device %d block # %ld, count %ld"
" ... ", usb_stor_curr_dev, blk, cnt);
- stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
+ stor_dev = blk_get_devnum_by_type(IF_TYPE_USB,
+ usb_stor_curr_dev);
n = blk_dwrite(stor_dev, blk, cnt, (ulong *)addr);
printf("%ld blocks write: %s\n", n,
(n == cnt) ? "OK" : "ERROR");
@@ -796,7 +799,7 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (argc == 3) {
int dev = (int)simple_strtoul(argv[2], NULL, 10);
printf("\nUSB device %d: ", dev);
- stor_dev = usb_stor_get_dev(dev);
+ stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, dev);
if (stor_dev == NULL) {
printf("unknown device\n");
return 1;
@@ -810,7 +813,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return 0;
} else {
printf("\nUSB device %d: ", usb_stor_curr_dev);
- stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
+ stor_dev = blk_get_devnum_by_type(IF_TYPE_USB,
+ usb_stor_curr_dev);
dev_print(stor_dev);
if (stor_dev->type == DEV_TYPE_UNKNOWN)
return 1;
diff --git a/common/Makefile b/common/Makefile
index b23f312..f9b26b7 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -84,6 +84,8 @@ obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o
obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o
obj-$(CONFIG_LYNXKDI) += lynxkdi.o
obj-$(CONFIG_MENU) += menu.o
+obj-$(CONFIG_CMD_SATA) += sata.o
+obj-$(CONFIG_SCSI) += scsi.o
obj-$(CONFIG_UPDATE_TFTP) += update.o
obj-$(CONFIG_DFU_TFTP) += update.o
obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
@@ -112,6 +114,9 @@ obj-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
endif
+ifdef CONFIG_SPL_SATA_SUPPORT
+obj-$(CONFIG_SCSI) += scsi.o
+endif
endif
#environment
obj-y += env_common.o
@@ -130,6 +135,7 @@ obj-y += dlmalloc.o
ifdef CONFIG_SYS_MALLOC_F_LEN
obj-y += malloc_simple.o
endif
+obj-$(CONFIG_CMD_IDE) += ide.o
obj-y += image.o
obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
obj-$(CONFIG_$(SPL_)OF_LIBFDT) += image-fdt.o
diff --git a/common/board_r.c b/common/board_r.c
index ad02549..d959ad3 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_CMD_SCSI)
+#if defined(CONFIG_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_CMD_SCSI
+#ifdef CONFIG_SCSI
INIT_FUNC_WATCHDOG_RESET
initr_scsi,
#endif
diff --git a/common/env_mmc.c b/common/env_mmc.c
index bdb452e..c7fef18 100644
--- a/common/env_mmc.c
+++ b/common/env_mmc.c
@@ -86,8 +86,8 @@ static int mmc_set_env_part(struct mmc *mmc)
dev = 0;
#endif
- env_mmc_orig_hwpart = mmc->block_dev.hwpart;
- ret = mmc_select_hwpart(dev, part);
+ env_mmc_orig_hwpart = mmc_get_blk_desc(mmc)->hwpart;
+ ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part);
if (ret)
puts("MMC partition switch failed\n");
@@ -119,7 +119,7 @@ static void fini_mmc_for_env(struct mmc *mmc)
#ifdef CONFIG_SPL_BUILD
dev = 0;
#endif
- mmc_select_hwpart(dev, env_mmc_orig_hwpart);
+ blk_select_hwpart_devnum(IF_TYPE_MMC, dev, env_mmc_orig_hwpart);
#endif
}
diff --git a/common/ide.c b/common/ide.c
new file mode 100644
index 0000000..ac5b91c
--- /dev/null
+++ b/common/ide.c
@@ -0,0 +1,1231 @@
+/*
+ * (C) Copyright 2000-2011
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <ata.h>
+#include <dm.h>
+#include <ide.h>
+#include <watchdog.h>
+#include <asm/io.h>
+
+#ifdef __PPC__
+# define EIEIO __asm__ volatile ("eieio")
+# define SYNC __asm__ volatile ("sync")
+#else
+# define EIEIO /* nothing */
+# define SYNC /* nothing */
+#endif
+
+/* Current offset for IDE0 / IDE1 bus access */
+ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = {
+#if defined(CONFIG_SYS_ATA_IDE0_OFFSET)
+ CONFIG_SYS_ATA_IDE0_OFFSET,
+#endif
+#if defined(CONFIG_SYS_ATA_IDE1_OFFSET) && (CONFIG_SYS_IDE_MAXBUS > 1)
+ CONFIG_SYS_ATA_IDE1_OFFSET,
+#endif
+};
+
+static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS];
+
+struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE];
+
+#define IDE_TIME_OUT 2000 /* 2 sec timeout */
+
+#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */
+
+#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */
+
+#ifndef CONFIG_SYS_ATA_PORT_ADDR
+#define CONFIG_SYS_ATA_PORT_ADDR(port) (port)
+#endif
+
+#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */
+# define DEVICE_LED(x) 0
+# define LED_IDE1 1
+# define LED_IDE2 2
+#endif
+
+#ifdef CONFIG_IDE_RESET
+extern void ide_set_reset(int idereset);
+
+static void ide_reset(void)
+{
+ int i;
+
+ for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i)
+ ide_bus_ok[i] = 0;
+ for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i)
+ ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
+
+ ide_set_reset(1); /* assert reset */
+
+ /* the reset signal shall be asserted for et least 25 us */
+ udelay(25);
+
+ WATCHDOG_RESET();
+
+ /* de-assert RESET signal */
+ ide_set_reset(0);
+
+ /* wait 250 ms */
+ for (i = 0; i < 250; ++i)
+ udelay(1000);
+}
+#else
+#define ide_reset() /* dummy */
+#endif /* CONFIG_IDE_RESET */
+
+/*
+ * Wait until Busy bit is off, or timeout (in ms)
+ * Return last status
+ */
+static uchar ide_wait(int dev, ulong t)
+{
+ ulong delay = 10 * t; /* poll every 100 us */
+ uchar c;
+
+ while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
+ udelay(100);
+ if (delay-- == 0)
+ break;
+ }
+ return c;
+}
+
+/*
+ * copy src to dest, skipping leading and trailing blanks and null
+ * terminate the string
+ * "len" is the size of available memory including the terminating '\0'
+ */
+static void ident_cpy(unsigned char *dst, unsigned char *src,
+ unsigned int len)
+{
+ unsigned char *end, *last;
+
+ last = dst;
+ end = src + len - 1;
+
+ /* reserve space for '\0' */
+ if (len < 2)
+ goto OUT;
+
+ /* skip leading white space */
+ while ((*src) && (src < end) && (*src == ' '))
+ ++src;
+
+ /* copy string, omitting trailing white space */
+ while ((*src) && (src < end)) {
+ *dst++ = *src;
+ if (*src++ != ' ')
+ last = dst;
+ }
+OUT:
+ *last = '\0';
+}
+
+#ifdef CONFIG_ATAPI
+/****************************************************************************
+ * ATAPI Support
+ */
+
+#if defined(CONFIG_IDE_SWAP_IO)
+/* since ATAPI may use commands with not 4 bytes alligned length
+ * we have our own transfer functions, 2 bytes alligned */
+__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
+{
+ ushort *dbuf;
+ volatile ushort *pbuf;
+
+ pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
+ dbuf = (ushort *)sect_buf;
+
+ debug("in output data shorts base for read is %lx\n",
+ (unsigned long) pbuf);
+
+ while (shorts--) {
+ EIEIO;
+ *pbuf = *dbuf++;
+ }
+}
+
+__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
+{
+ ushort *dbuf;
+ volatile ushort *pbuf;
+
+ pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
+ dbuf = (ushort *)sect_buf;
+
+ debug("in input data shorts base for read is %lx\n",
+ (unsigned long) pbuf);
+
+ while (shorts--) {
+ EIEIO;
+ *dbuf++ = *pbuf;
+ }
+}
+
+#else /* ! CONFIG_IDE_SWAP_IO */
+__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
+{
+ outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
+}
+
+__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
+{
+ insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
+}
+
+#endif /* CONFIG_IDE_SWAP_IO */
+
+/*
+ * Wait until (Status & mask) == res, or timeout (in ms)
+ * Return last status
+ * This is used since some ATAPI CD ROMs clears their Busy Bit first
+ * and then they set their DRQ Bit
+ */
+static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res)
+{
+ ulong delay = 10 * t; /* poll every 100 us */
+ uchar c;
+
+ /* prevents to read the status before valid */
+ c = ide_inb(dev, ATA_DEV_CTL);
+
+ while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) {
+ /* break if error occurs (doesn't make sense to wait more) */
+ if ((c & ATA_STAT_ERR) == ATA_STAT_ERR)
+ break;
+ udelay(100);
+ if (delay-- == 0)
+ break;
+ }
+ return c;
+}
+
+/*
+ * issue an atapi command
+ */
+unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen,
+ unsigned char *buffer, int buflen)
+{
+ unsigned char c, err, mask, res;
+ int n;
+
+ ide_led(DEVICE_LED(device), 1); /* LED on */
+
+ /* Select device
+ */
+ mask = ATA_STAT_BUSY | ATA_STAT_DRQ;
+ res = 0;
+ ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+ c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
+ if ((c & mask) != res) {
+ printf("ATAPI_ISSUE: device %d not ready status %X\n", device,
+ c);
+ err = 0xFF;
+ goto AI_OUT;
+ }
+ /* write taskfile */
+ ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */
+ ide_outb(device, ATA_SECT_CNT, 0);
+ ide_outb(device, ATA_SECT_NUM, 0);
+ ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF));
+ ide_outb(device, ATA_CYL_HIGH,
+ (unsigned char) ((buflen >> 8) & 0xFF));
+ ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+
+ ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET);
+ udelay(50);
+
+ mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR;
+ res = ATA_STAT_DRQ;
+ c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
+
+ if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */
+ printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n",
+ device, c);
+ err = 0xFF;
+ goto AI_OUT;
+ }
+
+ /* write command block */
+ ide_output_data_shorts(device, (unsigned short *)ccb, ccblen / 2);
+
+ /* ATAPI Command written wait for completition */
+ udelay(5000); /* device must set bsy */
+
+ mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR;
+ /*
+ * if no data wait for DRQ = 0 BSY = 0
+ * if data wait for DRQ = 1 BSY = 0
+ */
+ res = 0;
+ if (buflen)
+ res = ATA_STAT_DRQ;
+ c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
+ if ((c & mask) != res) {
+ if (c & ATA_STAT_ERR) {
+ err = (ide_inb(device, ATA_ERROR_REG)) >> 4;
+ debug("atapi_issue 1 returned sense key %X status %02X\n",
+ err, c);
+ } else {
+ printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n",
+ ccb[0], c);
+ err = 0xFF;
+ }
+ goto AI_OUT;
+ }
+ n = ide_inb(device, ATA_CYL_HIGH);
+ n <<= 8;
+ n += ide_inb(device, ATA_CYL_LOW);
+ if (n > buflen) {
+ printf("ERROR, transfer bytes %d requested only %d\n", n,
+ buflen);
+ err = 0xff;
+ goto AI_OUT;
+ }
+ if ((n == 0) && (buflen < 0)) {
+ printf("ERROR, transfer bytes %d requested %d\n", n, buflen);
+ err = 0xff;
+ goto AI_OUT;
+ }
+ if (n != buflen) {
+ debug("WARNING, transfer bytes %d not equal with requested %d\n",
+ n, buflen);
+ }
+ if (n != 0) { /* data transfer */
+ debug("ATAPI_ISSUE: %d Bytes to transfer\n", n);
+ /* we transfer shorts */
+ n >>= 1;
+ /* ok now decide if it is an in or output */
+ if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) {
+ debug("Write to device\n");
+ ide_output_data_shorts(device, (unsigned short *)buffer,
+ n);
+ } else {
+ debug("Read from device @ %p shorts %d\n", buffer, n);
+ ide_input_data_shorts(device, (unsigned short *)buffer,
+ n);
+ }
+ }
+ udelay(5000); /* seems that some CD ROMs need this... */
+ mask = ATA_STAT_BUSY | ATA_STAT_ERR;
+ res = 0;
+ c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
+ if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
+ err = (ide_inb(device, ATA_ERROR_REG) >> 4);
+ debug("atapi_issue 2 returned sense key %X status %X\n", err,
+ c);
+ } else {
+ err = 0;
+ }
+AI_OUT:
+ ide_led(DEVICE_LED(device), 0); /* LED off */
+ return err;
+}
+
+/*
+ * sending the command to atapi_issue. If an status other than good
+ * returns, an request_sense will be issued
+ */
+
+#define ATAPI_DRIVE_NOT_READY 100
+#define ATAPI_UNIT_ATTN 10
+
+unsigned char atapi_issue_autoreq(int device,
+ unsigned char *ccb,
+ int ccblen,
+ unsigned char *buffer, int buflen)
+{
+ unsigned char sense_data[18], sense_ccb[12];
+ unsigned char res, key, asc, ascq;
+ int notready, unitattn;
+
+ unitattn = ATAPI_UNIT_ATTN;
+ notready = ATAPI_DRIVE_NOT_READY;
+
+retry:
+ res = atapi_issue(device, ccb, ccblen, buffer, buflen);
+ if (res == 0)
+ return 0; /* Ok */
+
+ if (res == 0xFF)
+ return 0xFF; /* error */
+
+ debug("(auto_req)atapi_issue returned sense key %X\n", res);
+
+ memset(sense_ccb, 0, sizeof(sense_ccb));
+ memset(sense_data, 0, sizeof(sense_data));
+ sense_ccb[0] = ATAPI_CMD_REQ_SENSE;
+ sense_ccb[4] = 18; /* allocation Length */
+
+ res = atapi_issue(device, sense_ccb, 12, sense_data, 18);
+ key = (sense_data[2] & 0xF);
+ asc = (sense_data[12]);
+ ascq = (sense_data[13]);
+
+ debug("ATAPI_CMD_REQ_SENSE returned %x\n", res);
+ debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n",
+ sense_data[0], key, asc, ascq);
+
+ if ((key == 0))
+ return 0; /* ok device ready */
+
+ if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */
+ if (unitattn-- > 0) {
+ udelay(200 * 1000);
+ goto retry;
+ }
+ printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN);
+ goto error;
+ }
+ if ((asc == 0x4) && (ascq == 0x1)) {
+ /* not ready, but will be ready soon */
+ if (notready-- > 0) {
+ udelay(200 * 1000);
+ goto retry;
+ }
+ printf("Drive not ready, tried %d times\n",
+ ATAPI_DRIVE_NOT_READY);
+ goto error;
+ }
+ if (asc == 0x3a) {
+ debug("Media not present\n");
+ goto error;
+ }
+
+ printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc,
+ ascq);
+error:
+ debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq);
+ return 0xFF;
+}
+
+/*
+ * atapi_read:
+ * we transfer only one block per command, since the multiple DRQ per
+ * command is not yet implemented
+ */
+#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */
+#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */
+#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE)
+
+ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *buffer)
+{
+ int device = block_dev->devnum;
+ ulong n = 0;
+ unsigned char ccb[12]; /* Command descriptor block */
+ ulong cnt;
+
+ debug("atapi_read dev %d start " LBAF " blocks " LBAF
+ " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer);
+
+ do {
+ if (blkcnt > ATAPI_READ_MAX_BLOCK)
+ cnt = ATAPI_READ_MAX_BLOCK;
+ else
+ cnt = blkcnt;
+
+ ccb[0] = ATAPI_CMD_READ_12;
+ ccb[1] = 0; /* reserved */
+ ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */
+ ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */
+ ccb[4] = (unsigned char) (blknr >> 8) & 0xFF;
+ ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */
+ ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */
+ ccb[7] = (unsigned char) (cnt >> 16) & 0xFF;
+ ccb[8] = (unsigned char) (cnt >> 8) & 0xFF;
+ ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */
+ ccb[10] = 0; /* reserved */
+ ccb[11] = 0; /* reserved */
+
+ if (atapi_issue_autoreq(device, ccb, 12,
+ (unsigned char *)buffer,
+ cnt * ATAPI_READ_BLOCK_SIZE)
+ == 0xFF) {
+ return n;
+ }
+ n += cnt;
+ blkcnt -= cnt;
+ blknr += cnt;
+ buffer += (cnt * ATAPI_READ_BLOCK_SIZE);
+ } while (blkcnt > 0);
+ return n;
+}
+
+static void atapi_inquiry(struct blk_desc *dev_desc)
+{
+ unsigned char ccb[12]; /* Command descriptor block */
+ unsigned char iobuf[64]; /* temp buf */
+ unsigned char c;
+ int device;
+
+ device = dev_desc->devnum;
+ dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */
+ dev_desc->block_read = atapi_read;
+
+ memset(ccb, 0, sizeof(ccb));
+ memset(iobuf, 0, sizeof(iobuf));
+
+ ccb[0] = ATAPI_CMD_INQUIRY;
+ ccb[4] = 40; /* allocation Legnth */
+ c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 40);
+
+ debug("ATAPI_CMD_INQUIRY returned %x\n", c);
+ if (c != 0)
+ return;
+
+ /* copy device ident strings */
+ ident_cpy((unsigned char *)dev_desc->vendor, &iobuf[8], 8);
+ ident_cpy((unsigned char *)dev_desc->product, &iobuf[16], 16);
+ ident_cpy((unsigned char *)dev_desc->revision, &iobuf[32], 5);
+
+ dev_desc->lun = 0;
+ dev_desc->lba = 0;
+ dev_desc->blksz = 0;
+ dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz));
+ dev_desc->type = iobuf[0] & 0x1f;
+
+ if ((iobuf[1] & 0x80) == 0x80)
+ dev_desc->removable = 1;
+ else
+ dev_desc->removable = 0;
+
+ memset(ccb, 0, sizeof(ccb));
+ memset(iobuf, 0, sizeof(iobuf));
+ ccb[0] = ATAPI_CMD_START_STOP;
+ ccb[4] = 0x03; /* start */
+
+ c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0);
+
+ debug("ATAPI_CMD_START_STOP returned %x\n", c);
+ if (c != 0)
+ return;
+
+ memset(ccb, 0, sizeof(ccb));
+ memset(iobuf, 0, sizeof(iobuf));
+ c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0);
+
+ debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c);
+ if (c != 0)
+ return;
+
+ memset(ccb, 0, sizeof(ccb));
+ memset(iobuf, 0, sizeof(iobuf));
+ ccb[0] = ATAPI_CMD_READ_CAP;
+ c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 8);
+ debug("ATAPI_CMD_READ_CAP returned %x\n", c);
+ if (c != 0)
+ return;
+
+ debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n",
+ iobuf[0], iobuf[1], iobuf[2], iobuf[3],
+ iobuf[4], iobuf[5], iobuf[6], iobuf[7]);
+
+ dev_desc->lba = ((unsigned long) iobuf[0] << 24) +
+ ((unsigned long) iobuf[1] << 16) +
+ ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]);
+ dev_desc->blksz = ((unsigned long) iobuf[4] << 24) +
+ ((unsigned long) iobuf[5] << 16) +
+ ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]);
+ dev_desc->log2blksz = LOG2(dev_desc->blksz);
+#ifdef CONFIG_LBA48
+ /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */
+ dev_desc->lba48 = 0;
+#endif
+ return;
+}
+
+#endif /* CONFIG_ATAPI */
+
+static void ide_ident(struct blk_desc *dev_desc)
+{
+ unsigned char c;
+ hd_driveid_t iop;
+
+#ifdef CONFIG_ATAPI
+ int retries = 0;
+#endif
+ int device;
+
+ device = dev_desc->devnum;
+ printf(" Device %d: ", device);
+
+ ide_led(DEVICE_LED(device), 1); /* LED on */
+ /* Select device
+ */
+ ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+ dev_desc->if_type = IF_TYPE_IDE;
+#ifdef CONFIG_ATAPI
+
+ retries = 0;
+
+ /* Warning: This will be tricky to read */
+ while (retries <= 1) {
+ /* check signature */
+ if ((ide_inb(device, ATA_SECT_CNT) == 0x01) &&
+ (ide_inb(device, ATA_SECT_NUM) == 0x01) &&
+ (ide_inb(device, ATA_CYL_LOW) == 0x14) &&
+ (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) {
+ /* ATAPI Signature found */
+ dev_desc->if_type = IF_TYPE_ATAPI;
+ /*
+ * Start Ident Command
+ */
+ ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT);
+ /*
+ * Wait for completion - ATAPI devices need more time
+ * to become ready
+ */
+ c = ide_wait(device, ATAPI_TIME_OUT);
+ } else
+#endif
+ {
+ /*
+ * Start Ident Command
+ */
+ ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT);
+
+ /*
+ * Wait for completion
+ */
+ c = ide_wait(device, IDE_TIME_OUT);
+ }
+ ide_led(DEVICE_LED(device), 0); /* LED off */
+
+ if (((c & ATA_STAT_DRQ) == 0) ||
+ ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) {
+#ifdef CONFIG_ATAPI
+ {
+ /*
+ * Need to soft reset the device
+ * in case it's an ATAPI...
+ */
+ debug("Retrying...\n");
+ ide_outb(device, ATA_DEV_HD,
+ ATA_LBA | ATA_DEVICE(device));
+ udelay(100000);
+ ide_outb(device, ATA_COMMAND, 0x08);
+ udelay(500000); /* 500 ms */
+ }
+ /*
+ * Select device
+ */
+ ide_outb(device, ATA_DEV_HD,
+ ATA_LBA | ATA_DEVICE(device));
+ retries++;
+#else
+ return;
+#endif
+ }
+#ifdef CONFIG_ATAPI
+ else
+ break;
+ } /* see above - ugly to read */
+
+ if (retries == 2) /* Not found */
+ return;
+#endif
+
+ ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS);
+
+ ident_cpy((unsigned char *)dev_desc->revision, iop.fw_rev,
+ sizeof(dev_desc->revision));
+ ident_cpy((unsigned char *)dev_desc->vendor, iop.model,
+ sizeof(dev_desc->vendor));
+ ident_cpy((unsigned char *)dev_desc->product, iop.serial_no,
+ sizeof(dev_desc->product));
+#ifdef __LITTLE_ENDIAN
+ /*
+ * firmware revision, model, and serial number have Big Endian Byte
+ * order in Word. Convert all three to little endian.
+ *
+ * See CF+ and CompactFlash Specification Revision 2.0:
+ * 6.2.1.6: Identify Drive, Table 39 for more details
+ */
+
+ strswab(dev_desc->revision);
+ strswab(dev_desc->vendor);
+ strswab(dev_desc->product);
+#endif /* __LITTLE_ENDIAN */
+
+ if ((iop.config & 0x0080) == 0x0080)
+ dev_desc->removable = 1;
+ else
+ dev_desc->removable = 0;
+
+#ifdef CONFIG_ATAPI
+ if (dev_desc->if_type == IF_TYPE_ATAPI) {
+ atapi_inquiry(dev_desc);
+ return;
+ }
+#endif /* CONFIG_ATAPI */
+
+#ifdef __BIG_ENDIAN
+ /* swap shorts */
+ dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16);
+#else /* ! __BIG_ENDIAN */
+ /*
+ * do not swap shorts on little endian
+ *
+ * See CF+ and CompactFlash Specification Revision 2.0:
+ * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details.
+ */
+ dev_desc->lba = iop.lba_capacity;
+#endif /* __BIG_ENDIAN */
+
+#ifdef CONFIG_LBA48
+ if (iop.command_set_2 & 0x0400) { /* LBA 48 support */
+ dev_desc->lba48 = 1;
+ dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] |
+ ((unsigned long long) iop.lba48_capacity[1] << 16) |
+ ((unsigned long long) iop.lba48_capacity[2] << 32) |
+ ((unsigned long long) iop.lba48_capacity[3] << 48);
+ } else {
+ dev_desc->lba48 = 0;
+ }
+#endif /* CONFIG_LBA48 */
+ /* assuming HD */
+ dev_desc->type = DEV_TYPE_HARDDISK;
+ dev_desc->blksz = ATA_BLOCKSIZE;
+ dev_desc->log2blksz = LOG2(dev_desc->blksz);
+ dev_desc->lun = 0; /* just to fill something in... */
+
+#if 0 /* only used to test the powersaving mode,
+ * if enabled, the drive goes after 5 sec
+ * in standby mode */
+ ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+ c = ide_wait(device, IDE_TIME_OUT);
+ ide_outb(device, ATA_SECT_CNT, 1);
+ ide_outb(device, ATA_LBA_LOW, 0);
+ ide_outb(device, ATA_LBA_MID, 0);
+ ide_outb(device, ATA_LBA_HIGH, 0);
+ ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+ ide_outb(device, ATA_COMMAND, 0xe3);
+ udelay(50);
+ c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */
+#endif
+}
+
+__weak void ide_led(uchar led, uchar status)
+{
+#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */
+ static uchar led_buffer; /* Buffer for current LED status */
+
+ uchar *led_port = LED_PORT;
+
+ if (status) /* switch LED on */
+ led_buffer |= led;
+ else /* switch LED off */
+ led_buffer &= ~led;
+
+ *led_port = led_buffer;
+#endif
+}
+
+__weak void ide_outb(int dev, int port, unsigned char val)
+{
+ debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n",
+ dev, port, val,
+ (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
+
+#if defined(CONFIG_IDE_AHB)
+ if (port) {
+ /* write command */
+ ide_write_register(dev, port, val);
+ } else {
+ /* write data */
+ outb(val, (ATA_CURR_BASE(dev)));
+ }
+#else
+ outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
+#endif
+}
+
+__weak unsigned char ide_inb(int dev, int port)
+{
+ uchar val;
+
+#if defined(CONFIG_IDE_AHB)
+ val = ide_read_register(dev, port);
+#else
+ val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
+#endif
+
+ debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n",
+ dev, port,
+ (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val);
+ return val;
+}
+
+void ide_init(void)
+{
+ unsigned char c;
+ int i, bus;
+
+#ifdef CONFIG_IDE_8xx_PCCARD
+ extern int ide_devices_found; /* Initialized in check_ide_device() */
+#endif /* CONFIG_IDE_8xx_PCCARD */
+
+#ifdef CONFIG_IDE_PREINIT
+ WATCHDOG_RESET();
+
+ if (ide_preinit()) {
+ puts("ide_preinit failed\n");
+ return;
+ }
+#endif /* CONFIG_IDE_PREINIT */
+
+ WATCHDOG_RESET();
+
+ /*
+ * Reset the IDE just to be sure.
+ * Light LED's to show
+ */
+ ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */
+
+ /* ATAPI Drives seems to need a proper IDE Reset */
+ ide_reset();
+
+#ifdef CONFIG_IDE_INIT_POSTRESET
+ WATCHDOG_RESET();
+
+ if (ide_init_postreset()) {
+ puts("ide_preinit_postreset failed\n");
+ return;
+ }
+#endif /* CONFIG_IDE_INIT_POSTRESET */
+
+ /*
+ * Wait for IDE to get ready.
+ * According to spec, this can take up to 31 seconds!
+ */
+ for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) {
+ int dev =
+ bus * (CONFIG_SYS_IDE_MAXDEVICE /
+ CONFIG_SYS_IDE_MAXBUS);
+
+#ifdef CONFIG_IDE_8xx_PCCARD
+ /* Skip non-ide devices from probing */
+ if ((ide_devices_found & (1 << bus)) == 0) {
+ ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */
+ continue;
+ }
+#endif
+ printf("Bus %d: ", bus);
+
+ ide_bus_ok[bus] = 0;
+
+ /* Select device
+ */
+ udelay(100000); /* 100 ms */
+ ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
+ udelay(100000); /* 100 ms */
+ i = 0;
+ do {
+ udelay(10000); /* 10 ms */
+
+ c = ide_inb(dev, ATA_STATUS);
+ i++;
+ if (i > (ATA_RESET_TIME * 100)) {
+ puts("** Timeout **\n");
+ /* LED's off */
+ ide_led((LED_IDE1 | LED_IDE2), 0);
+ return;
+ }
+ if ((i >= 100) && ((i % 100) == 0))
+ putc('.');
+
+ } while (c & ATA_STAT_BUSY);
+
+ if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
+ puts("not available ");
+ debug("Status = 0x%02X ", c);
+#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */
+ } else if ((c & ATA_STAT_READY) == 0) {
+ puts("not available ");
+ debug("Status = 0x%02X ", c);
+#endif
+ } else {
+ puts("OK ");
+ ide_bus_ok[bus] = 1;
+ }
+ WATCHDOG_RESET();
+ }
+
+ putc('\n');
+
+ ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */
+
+ for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) {
+ int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2;
+ ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
+ ide_dev_desc[i].if_type = IF_TYPE_IDE;
+ ide_dev_desc[i].devnum = i;
+ ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
+ ide_dev_desc[i].blksz = 0;
+ ide_dev_desc[i].log2blksz =
+ LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz));
+ ide_dev_desc[i].lba = 0;
+#ifndef CONFIG_BLK
+ ide_dev_desc[i].block_read = ide_read;
+ ide_dev_desc[i].block_write = ide_write;
+#endif
+ if (!ide_bus_ok[IDE_BUS(i)])
+ continue;
+ ide_led(led, 1); /* LED on */
+ ide_ident(&ide_dev_desc[i]);
+ ide_led(led, 0); /* LED off */
+ dev_print(&ide_dev_desc[i]);
+
+ if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) {
+ /* initialize partition type */
+ part_init(&ide_dev_desc[i]);
+ }
+ }
+ WATCHDOG_RESET();
+}
+
+/* We only need to swap data if we are running on a big endian cpu. */
+#if defined(__LITTLE_ENDIAN)
+__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words)
+{
+ ide_input_data(dev, sect_buf, words);
+}
+#else
+__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words)
+{
+ volatile ushort *pbuf =
+ (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
+ ushort *dbuf = (ushort *)sect_buf;
+
+ debug("in input swap data base for read is %lx\n",
+ (unsigned long) pbuf);
+
+ while (words--) {
+#ifdef __MIPS__
+ *dbuf++ = swab16p((u16 *)pbuf);
+ *dbuf++ = swab16p((u16 *)pbuf);
+#else
+ *dbuf++ = ld_le16(pbuf);
+ *dbuf++ = ld_le16(pbuf);
+#endif /* !MIPS */
+ }
+}
+#endif /* __LITTLE_ENDIAN */
+
+
+#if defined(CONFIG_IDE_SWAP_IO)
+__weak void ide_output_data(int dev, const ulong *sect_buf, int words)
+{
+ ushort *dbuf;
+ volatile ushort *pbuf;
+
+ pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
+ dbuf = (ushort *)sect_buf;
+ while (words--) {
+ EIEIO;
+ *pbuf = *dbuf++;
+ EIEIO;
+ *pbuf = *dbuf++;
+ }
+}
+#else /* ! CONFIG_IDE_SWAP_IO */
+__weak void ide_output_data(int dev, const ulong *sect_buf, int words)
+{
+#if defined(CONFIG_IDE_AHB)
+ ide_write_data(dev, sect_buf, words);
+#else
+ outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1);
+#endif
+}
+#endif /* CONFIG_IDE_SWAP_IO */
+
+#if defined(CONFIG_IDE_SWAP_IO)
+__weak void ide_input_data(int dev, ulong *sect_buf, int words)
+{
+ ushort *dbuf;
+ volatile ushort *pbuf;
+
+ pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
+ dbuf = (ushort *)sect_buf;
+
+ debug("in input data base for read is %lx\n", (unsigned long) pbuf);
+
+ while (words--) {
+ EIEIO;
+ *dbuf++ = *pbuf;
+ EIEIO;
+ *dbuf++ = *pbuf;
+ }
+}
+#else /* ! CONFIG_IDE_SWAP_IO */
+__weak void ide_input_data(int dev, ulong *sect_buf, int words)
+{
+#if defined(CONFIG_IDE_AHB)
+ ide_read_data(dev, sect_buf, words);
+#else
+ insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1);
+#endif
+}
+
+#endif /* CONFIG_IDE_SWAP_IO */
+
+#ifdef CONFIG_BLK
+ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *buffer)
+#else
+ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *buffer)
+#endif
+{
+#ifdef CONFIG_BLK
+ struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
+#endif
+ int device = block_dev->devnum;
+ ulong n = 0;
+ unsigned char c;
+ unsigned char pwrsave = 0; /* power save */
+
+#ifdef CONFIG_LBA48
+ unsigned char lba48 = 0;
+
+ if (blknr & 0x0000fffff0000000ULL) {
+ /* more than 28 bits used, use 48bit mode */
+ lba48 = 1;
+ }
+#endif
+ debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n",
+ device, blknr, blkcnt, (ulong) buffer);
+
+ ide_led(DEVICE_LED(device), 1); /* LED on */
+
+ /* Select device
+ */
+ ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+ c = ide_wait(device, IDE_TIME_OUT);
+
+ if (c & ATA_STAT_BUSY) {
+ printf("IDE read: device %d not ready\n", device);
+ goto IDE_READ_E;
+ }
+
+ /* first check if the drive is in Powersaving mode, if yes,
+ * increase the timeout value */
+ ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR);
+ udelay(50);
+
+ c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */
+
+ if (c & ATA_STAT_BUSY) {
+ printf("IDE read: device %d not ready\n", device);
+ goto IDE_READ_E;
+ }
+ if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
+ printf("No Powersaving mode %X\n", c);
+ } else {
+ c = ide_inb(device, ATA_SECT_CNT);
+ debug("Powersaving %02X\n", c);
+ if (c == 0)
+ pwrsave = 1;
+ }
+
+
+ while (blkcnt-- > 0) {
+ c = ide_wait(device, IDE_TIME_OUT);
+
+ if (c & ATA_STAT_BUSY) {
+ printf("IDE read: device %d not ready\n", device);
+ break;
+ }
+#ifdef CONFIG_LBA48
+ if (lba48) {
+ /* write high bits */
+ ide_outb(device, ATA_SECT_CNT, 0);
+ ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
+#ifdef CONFIG_SYS_64BIT_LBA
+ ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
+ ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
+#else
+ ide_outb(device, ATA_LBA_MID, 0);
+ ide_outb(device, ATA_LBA_HIGH, 0);
+#endif
+ }
+#endif
+ ide_outb(device, ATA_SECT_CNT, 1);
+ ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
+ ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
+ ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
+
+#ifdef CONFIG_LBA48
+ if (lba48) {
+ ide_outb(device, ATA_DEV_HD,
+ ATA_LBA | ATA_DEVICE(device));
+ ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT);
+
+ } else
+#endif
+ {
+ ide_outb(device, ATA_DEV_HD, ATA_LBA |
+ ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
+ ide_outb(device, ATA_COMMAND, ATA_CMD_READ);
+ }
+
+ udelay(50);
+
+ if (pwrsave) {
+ /* may take up to 4 sec */
+ c = ide_wait(device, IDE_SPIN_UP_TIME_OUT);
+ pwrsave = 0;
+ } else {
+ /* can't take over 500 ms */
+ c = ide_wait(device, IDE_TIME_OUT);
+ }
+
+ if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
+ ATA_STAT_DRQ) {
+ printf("Error (no IRQ) dev %d blk " LBAF
+ ": status %#02x\n", device, blknr, c);
+ break;
+ }
+
+ ide_input_data(device, buffer, ATA_SECTORWORDS);
+ (void) ide_inb(device, ATA_STATUS); /* clear IRQ */
+
+ ++n;
+ ++blknr;
+ buffer += ATA_BLOCKSIZE;
+ }
+IDE_READ_E:
+ ide_led(DEVICE_LED(device), 0); /* LED off */
+ return n;
+}
+
+#ifdef CONFIG_BLK
+ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer)
+#else
+ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer)
+#endif
+{
+#ifdef CONFIG_BLK
+ struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
+#endif
+ int device = block_dev->devnum;
+ ulong n = 0;
+ unsigned char c;
+
+#ifdef CONFIG_LBA48
+ unsigned char lba48 = 0;
+
+ if (blknr & 0x0000fffff0000000ULL) {
+ /* more than 28 bits used, use 48bit mode */
+ lba48 = 1;
+ }
+#endif
+
+ ide_led(DEVICE_LED(device), 1); /* LED on */
+
+ /* Select device
+ */
+ ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+
+ while (blkcnt-- > 0) {
+ c = ide_wait(device, IDE_TIME_OUT);
+
+ if (c & ATA_STAT_BUSY) {
+ printf("IDE read: device %d not ready\n", device);
+ goto WR_OUT;
+ }
+#ifdef CONFIG_LBA48
+ if (lba48) {
+ /* write high bits */
+ ide_outb(device, ATA_SECT_CNT, 0);
+ ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
+#ifdef CONFIG_SYS_64BIT_LBA
+ ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
+ ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
+#else
+ ide_outb(device, ATA_LBA_MID, 0);
+ ide_outb(device, ATA_LBA_HIGH, 0);
+#endif
+ }
+#endif
+ ide_outb(device, ATA_SECT_CNT, 1);
+ ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
+ ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
+ ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
+
+#ifdef CONFIG_LBA48
+ if (lba48) {
+ ide_outb(device, ATA_DEV_HD,
+ ATA_LBA | ATA_DEVICE(device));
+ ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT);
+
+ } else
+#endif
+ {
+ ide_outb(device, ATA_DEV_HD, ATA_LBA |
+ ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
+ ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE);
+ }
+
+ udelay(50);
+
+ /* can't take over 500 ms */
+ c = ide_wait(device, IDE_TIME_OUT);
+
+ if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
+ ATA_STAT_DRQ) {
+ printf("Error (no IRQ) dev %d blk " LBAF
+ ": status %#02x\n", device, blknr, c);
+ goto WR_OUT;
+ }
+
+ ide_output_data(device, buffer, ATA_SECTORWORDS);
+ c = ide_inb(device, ATA_STATUS); /* clear IRQ */
+ ++n;
+ ++blknr;
+ buffer += ATA_BLOCKSIZE;
+ }
+WR_OUT:
+ ide_led(DEVICE_LED(device), 0); /* LED off */
+ return n;
+}
+
+#if defined(CONFIG_OF_IDE_FIXUP)
+int ide_device_present(int dev)
+{
+ if (dev >= CONFIG_SYS_IDE_MAXBUS)
+ return 0;
+ return ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1;
+}
+#endif
+
+#ifdef CONFIG_BLK
+static const struct blk_ops ide_blk_ops = {
+ .read = ide_read,
+ .write = ide_write,
+};
+
+U_BOOT_DRIVER(ide_blk) = {
+ .name = "ide_blk",
+ .id = UCLASS_BLK,
+ .ops = &ide_blk_ops,
+};
+#else
+U_BOOT_LEGACY_BLK(ide) = {
+ .if_typename = "ide",
+ .if_type = IF_TYPE_IDE,
+ .max_devs = CONFIG_SYS_IDE_MAXDEVICE,
+ .desc = ide_dev_desc,
+};
+#endif
diff --git a/common/sata.c b/common/sata.c
new file mode 100644
index 0000000..88f08c9
--- /dev/null
+++ b/common/sata.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2000-2005, DENX Software Engineering
+ * Wolfgang Denk <wd@denx.de>
+ * Copyright (C) Procsys. All rights reserved.
+ * Mushtaq Khan <mushtaq_k@procsys.com>
+ * <mushtaqk_921@yahoo.co.in>
+ * Copyright (C) 2008 Freescale Semiconductor, Inc.
+ * Dave Liu <daveliu@freescale.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <sata.h>
+
+struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
+
+#ifdef CONFIG_PARTITIONS
+struct blk_desc *sata_get_dev(int dev)
+{
+ return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL;
+}
+#endif
+
+#ifdef CONFIG_BLK
+static unsigned long sata_bread(struct udevice *dev, lbaint_t start,
+ lbaint_t blkcnt, void *dst)
+{
+ return -ENOSYS;
+}
+
+static unsigned long sata_bwrite(struct udevice *dev, lbaint_t start,
+ lbaint_t blkcnt, const void *buffer)
+{
+ return -ENOSYS;
+}
+#else
+static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start,
+ lbaint_t blkcnt, void *dst)
+{
+ return sata_read(block_dev->devnum, start, blkcnt, dst);
+}
+
+static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start,
+ lbaint_t blkcnt, const void *buffer)
+{
+ return sata_write(block_dev->devnum, start, blkcnt, buffer);
+}
+#endif
+
+int __sata_initialize(void)
+{
+ int rc;
+ int i;
+
+ for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) {
+ memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc));
+ sata_dev_desc[i].if_type = IF_TYPE_SATA;
+ sata_dev_desc[i].devnum = i;
+ sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
+ sata_dev_desc[i].type = DEV_TYPE_HARDDISK;
+ sata_dev_desc[i].lba = 0;
+ sata_dev_desc[i].blksz = 512;
+ sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz);
+#ifndef CONFIG_BLK
+ sata_dev_desc[i].block_read = sata_bread;
+ sata_dev_desc[i].block_write = sata_bwrite;
+#endif
+ rc = init_sata(i);
+ if (!rc) {
+ rc = scan_sata(i);
+ if (!rc && sata_dev_desc[i].lba > 0 &&
+ sata_dev_desc[i].blksz > 0)
+ part_init(&sata_dev_desc[i]);
+ }
+ }
+
+ return rc;
+}
+int sata_initialize(void) __attribute__((weak, alias("__sata_initialize")));
+
+__weak int __sata_stop(void)
+{
+ int i, err = 0;
+
+ for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++)
+ err |= reset_sata(i);
+
+ if (err)
+ printf("Could not reset some SATA devices\n");
+
+ return err;
+}
+int sata_stop(void) __attribute__((weak, alias("__sata_stop")));
+
+#ifdef CONFIG_BLK
+static const struct blk_ops sata_blk_ops = {
+ .read = sata_bread,
+ .write = sata_bwrite,
+};
+
+U_BOOT_DRIVER(sata_blk) = {
+ .name = "sata_blk",
+ .id = UCLASS_BLK,
+ .ops = &sata_blk_ops,
+};
+#else
+U_BOOT_LEGACY_BLK(sata) = {
+ .if_typename = "sata",
+ .if_type = IF_TYPE_SATA,
+ .max_devs = CONFIG_SYS_SATA_MAX_DEVICE,
+ .desc = sata_dev_desc,
+};
+#endif
diff --git a/common/scsi.c b/common/scsi.c
new file mode 100644
index 0000000..8ac28dd
--- /dev/null
+++ b/common/scsi.c
@@ -0,0 +1,592 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <inttypes.h>
+#include <pci.h>
+#include <scsi.h>
+
+#ifdef CONFIG_SCSI_DEV_LIST
+#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST
+#else
+#ifdef CONFIG_SCSI_SYM53C8XX
+#define SCSI_VEND_ID 0x1000
+#ifndef CONFIG_SCSI_DEV_ID
+#define SCSI_DEV_ID 0x0001
+#else
+#define SCSI_DEV_ID CONFIG_SCSI_DEV_ID
+#endif
+#elif defined CONFIG_SATA_ULI5288
+
+#define SCSI_VEND_ID 0x10b9
+#define SCSI_DEV_ID 0x5288
+
+#elif !defined(CONFIG_SCSI_AHCI_PLAT)
+#error no scsi device defined
+#endif
+#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID}
+#endif
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
+const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
+#endif
+static ccb tempccb; /* temporary scsi command buffer */
+
+static unsigned char tempbuff[512]; /* temporary data buffer */
+
+static int scsi_max_devs; /* number of highest available scsi device */
+
+static int scsi_curr_dev; /* current device */
+
+static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
+
+/* almost the maximum amount of the scsi_ext command.. */
+#define SCSI_MAX_READ_BLK 0xFFFF
+#define SCSI_LBA48_READ 0xFFFFFFF
+
+#ifdef CONFIG_SYS_64BIT_LBA
+void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks)
+{
+ pccb->cmd[0] = SCSI_READ16;
+ pccb->cmd[1] = pccb->lun << 5;
+ pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff;
+ pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff;
+ pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff;
+ pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff;
+ pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff;
+ pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff;
+ pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff;
+ pccb->cmd[9] = (unsigned char)start & 0xff;
+ pccb->cmd[10] = 0;
+ pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff;
+ pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff;
+ pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff;
+ pccb->cmd[14] = (unsigned char)blocks & 0xff;
+ pccb->cmd[15] = 0;
+ pccb->cmdlen = 16;
+ pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
+ debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n",
+ pccb->cmd[0], pccb->cmd[1],
+ pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
+ pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9],
+ pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]);
+}
+#endif
+
+void scsi_setup_read_ext(ccb *pccb, lbaint_t start, unsigned short blocks)
+{
+ pccb->cmd[0] = SCSI_READ10;
+ pccb->cmd[1] = pccb->lun << 5;
+ pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
+ pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
+ pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
+ pccb->cmd[5] = (unsigned char)start & 0xff;
+ pccb->cmd[6] = 0;
+ pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff;
+ pccb->cmd[8] = (unsigned char)blocks & 0xff;
+ pccb->cmd[6] = 0;
+ pccb->cmdlen = 10;
+ pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
+ debug("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
+ pccb->cmd[0], pccb->cmd[1],
+ pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
+ pccb->cmd[7], pccb->cmd[8]);
+}
+
+void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks)
+{
+ pccb->cmd[0] = SCSI_WRITE10;
+ pccb->cmd[1] = pccb->lun << 5;
+ pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
+ pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
+ pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
+ pccb->cmd[5] = (unsigned char)start & 0xff;
+ pccb->cmd[6] = 0;
+ pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff;
+ pccb->cmd[8] = (unsigned char)blocks & 0xff;
+ pccb->cmd[9] = 0;
+ pccb->cmdlen = 10;
+ pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
+ debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
+ __func__,
+ pccb->cmd[0], pccb->cmd[1],
+ pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
+ pccb->cmd[7], pccb->cmd[8]);
+}
+
+void scsi_setup_read6(ccb *pccb, lbaint_t start, unsigned short blocks)
+{
+ pccb->cmd[0] = SCSI_READ6;
+ pccb->cmd[1] = pccb->lun << 5 | ((unsigned char)(start >> 16) & 0x1f);
+ pccb->cmd[2] = (unsigned char)(start >> 8) & 0xff;
+ pccb->cmd[3] = (unsigned char)start & 0xff;
+ pccb->cmd[4] = (unsigned char)blocks & 0xff;
+ pccb->cmd[5] = 0;
+ pccb->cmdlen = 6;
+ pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
+ debug("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n",
+ pccb->cmd[0], pccb->cmd[1],
+ pccb->cmd[2], pccb->cmd[3], pccb->cmd[4]);
+}
+
+
+void scsi_setup_inquiry(ccb *pccb)
+{
+ pccb->cmd[0] = SCSI_INQUIRY;
+ pccb->cmd[1] = pccb->lun << 5;
+ pccb->cmd[2] = 0;
+ pccb->cmd[3] = 0;
+ if (pccb->datalen > 255)
+ pccb->cmd[4] = 255;
+ else
+ pccb->cmd[4] = (unsigned char)pccb->datalen;
+ pccb->cmd[5] = 0;
+ pccb->cmdlen = 6;
+ pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
+}
+
+#ifdef CONFIG_BLK
+static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *buffer)
+#else
+static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr,
+ lbaint_t blkcnt, void *buffer)
+#endif
+{
+#ifdef CONFIG_BLK
+ struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
+#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;
+ 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);
+ 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;
+ 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 *
+ 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;
+ smallblks = (unsigned short)blks;
+ scsi_setup_read_ext(pccb, start, smallblks);
+ start += blks;
+ blks = 0;
+ }
+ debug("scsi_read_ext: startblk " LBAF
+ ", blccnt %x buffer %" PRIXPTR "\n",
+ start, smallblks, buf_addr);
+ if (scsi_exec(pccb) != true) {
+ scsi_print_error(pccb);
+ blkcnt -= blks;
+ break;
+ }
+ buf_addr += pccb->datalen;
+ } while (blks != 0);
+ debug("scsi_read_ext: end startblk " LBAF
+ ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr);
+ return blkcnt;
+}
+
+/*******************************************************************************
+ * scsi_write
+ */
+
+/* Almost the maximum amount of the scsi_ext command.. */
+#define SCSI_MAX_WRITE_BLK 0xFFFF
+
+#ifdef CONFIG_BLK
+static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer)
+#else
+static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr,
+ lbaint_t blkcnt, const void *buffer)
+#endif
+{
+#ifdef CONFIG_BLK
+ struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
+#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;
+ 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);
+ do {
+ pccb->pdata = (unsigned char *)buf_addr;
+ if (blks > SCSI_MAX_WRITE_BLK) {
+ pccb->datalen = (scsi_dev_desc[device].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;
+ smallblks = (unsigned short)blks;
+ scsi_setup_write_ext(pccb, start, smallblks);
+ start += blks;
+ blks = 0;
+ }
+ debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
+ __func__, start, smallblks, buf_addr);
+ if (scsi_exec(pccb) != true) {
+ scsi_print_error(pccb);
+ blkcnt -= blks;
+ break;
+ }
+ buf_addr += pccb->datalen;
+ } while (blks != 0);
+ debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
+ __func__, start, smallblks, buf_addr);
+ return blkcnt;
+}
+
+int scsi_get_disk_count(void)
+{
+ return scsi_max_devs;
+}
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
+void scsi_init(void)
+{
+ int busdevfunc = -1;
+ int i;
+ /*
+ * Find a device from the list, this driver will support a single
+ * controller.
+ */
+ for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
+ /* get PCI Device ID */
+#ifdef CONFIG_DM_PCI
+ struct udevice *dev;
+ int ret;
+
+ ret = dm_pci_find_device(scsi_device_list[i].vendor,
+ scsi_device_list[i].device, 0, &dev);
+ if (!ret) {
+ busdevfunc = dm_pci_get_bdf(dev);
+ break;
+ }
+#else
+ busdevfunc = pci_find_device(scsi_device_list[i].vendor,
+ scsi_device_list[i].device,
+ 0);
+#endif
+ if (busdevfunc != -1)
+ break;
+ }
+
+ if (busdevfunc == -1) {
+ printf("Error: SCSI Controller(s) ");
+ for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
+ printf("%04X:%04X ",
+ scsi_device_list[i].vendor,
+ scsi_device_list[i].device);
+ }
+ printf("not found\n");
+ return;
+ }
+#ifdef DEBUG
+ else {
+ printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",
+ scsi_device_list[i].vendor,
+ scsi_device_list[i].device,
+ (busdevfunc >> 16) & 0xFF,
+ (busdevfunc >> 11) & 0x1F,
+ (busdevfunc >> 8) & 0x7);
+ }
+#endif
+ bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");
+ scsi_low_level_init(busdevfunc);
+ scsi_scan(1);
+ bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
+}
+#endif
+
+/* copy src to dest, skipping leading and trailing blanks
+ * and null terminate the string
+ */
+void scsi_ident_cpy(unsigned char *dest, unsigned char *src, unsigned int len)
+{
+ int start, end;
+
+ start = 0;
+ while (start < len) {
+ if (src[start] != ' ')
+ break;
+ start++;
+ }
+ end = len-1;
+ while (end > start) {
+ if (src[end] != ' ')
+ break;
+ end--;
+ }
+ for (; start <= end; start++)
+ *dest ++= src[start];
+ *dest = '\0';
+}
+
+
+/* Trim trailing blanks, and NUL-terminate string
+ */
+void scsi_trim_trail(unsigned char *str, unsigned int len)
+{
+ unsigned char *p = str + len - 1;
+
+ while (len-- > 0) {
+ *p-- = '\0';
+ if (*p != ' ')
+ return;
+ }
+}
+
+int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz)
+{
+ *capacity = 0;
+
+ memset(pccb->cmd, '\0', sizeof(pccb->cmd));
+ pccb->cmd[0] = SCSI_RD_CAPAC10;
+ pccb->cmd[1] = pccb->lun << 5;
+ pccb->cmdlen = 10;
+ pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
+
+ pccb->datalen = 8;
+ if (scsi_exec(pccb) != true)
+ return 1;
+
+ *capacity = ((lbaint_t)pccb->pdata[0] << 24) |
+ ((lbaint_t)pccb->pdata[1] << 16) |
+ ((lbaint_t)pccb->pdata[2] << 8) |
+ ((lbaint_t)pccb->pdata[3]);
+
+ if (*capacity != 0xffffffff) {
+ /* Read capacity (10) was sufficient for this drive. */
+ *blksz = ((unsigned long)pccb->pdata[4] << 24) |
+ ((unsigned long)pccb->pdata[5] << 16) |
+ ((unsigned long)pccb->pdata[6] << 8) |
+ ((unsigned long)pccb->pdata[7]);
+ return 0;
+ }
+
+ /* Read capacity (10) was insufficient. Use read capacity (16). */
+ memset(pccb->cmd, '\0', sizeof(pccb->cmd));
+ pccb->cmd[0] = SCSI_RD_CAPAC16;
+ pccb->cmd[1] = 0x10;
+ pccb->cmdlen = 16;
+ pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
+
+ pccb->datalen = 16;
+ if (scsi_exec(pccb) != true)
+ return 1;
+
+ *capacity = ((uint64_t)pccb->pdata[0] << 56) |
+ ((uint64_t)pccb->pdata[1] << 48) |
+ ((uint64_t)pccb->pdata[2] << 40) |
+ ((uint64_t)pccb->pdata[3] << 32) |
+ ((uint64_t)pccb->pdata[4] << 24) |
+ ((uint64_t)pccb->pdata[5] << 16) |
+ ((uint64_t)pccb->pdata[6] << 8) |
+ ((uint64_t)pccb->pdata[7]);
+
+ *blksz = ((uint64_t)pccb->pdata[8] << 56) |
+ ((uint64_t)pccb->pdata[9] << 48) |
+ ((uint64_t)pccb->pdata[10] << 40) |
+ ((uint64_t)pccb->pdata[11] << 32) |
+ ((uint64_t)pccb->pdata[12] << 24) |
+ ((uint64_t)pccb->pdata[13] << 16) |
+ ((uint64_t)pccb->pdata[14] << 8) |
+ ((uint64_t)pccb->pdata[15]);
+
+ return 0;
+}
+
+
+/*
+ * Some setup (fill-in) routines
+ */
+void scsi_setup_test_unit_ready(ccb *pccb)
+{
+ pccb->cmd[0] = SCSI_TST_U_RDY;
+ pccb->cmd[1] = pccb->lun << 5;
+ pccb->cmd[2] = 0;
+ pccb->cmd[3] = 0;
+ pccb->cmd[4] = 0;
+ pccb->cmd[5] = 0;
+ pccb->cmdlen = 6;
+ pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
+}
+
+/*
+ * (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;
+ ccb *pccb = (ccb *)&tempccb;
+
+ 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
+ }
+ 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++) {
+ 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);
+ 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);
+ dev_print(&scsi_dev_desc[scsi_max_devs]);
+ } /* if mode */
+ scsi_max_devs++;
+ } /* next LUN */
+ }
+ if (scsi_max_devs > 0)
+ scsi_curr_dev = 0;
+ else
+ scsi_curr_dev = -1;
+
+ printf("Found %d device(s).\n", scsi_max_devs);
+#ifndef CONFIG_SPL_BUILD
+ setenv_ulong("scsidevs", scsi_max_devs);
+#endif
+}
+
+#ifdef CONFIG_BLK
+static const struct blk_ops scsi_blk_ops = {
+ .read = scsi_read,
+ .write = scsi_write,
+};
+
+U_BOOT_DRIVER(scsi_blk) = {
+ .name = "scsi_blk",
+ .id = UCLASS_BLK,
+ .ops = &scsi_blk_ops,
+};
+#else
+U_BOOT_LEGACY_BLK(scsi) = {
+ .if_typename = "sata",
+ .if_type = IF_TYPE_SCSI,
+ .max_devs = CONFIG_SYS_SCSI_MAX_DEVICE,
+ .desc = scsi_dev_desc,
+};
+#endif
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index 360c754..5676acd 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -300,7 +300,7 @@ int spl_mmc_load_image(u32 boot_device)
if (part == 7)
part = 0;
- err = mmc_switch_part(0, part);
+ err = blk_dselect_hwpart(mmc_get_blk_desc(mmc), part);
if (err) {
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
puts("spl: mmc partition switch failed\n");
diff --git a/common/spl/spl_sata.c b/common/spl/spl_sata.c
index 1719946..9d8cc7c 100644
--- a/common/spl/spl_sata.c
+++ b/common/spl/spl_sata.c
@@ -34,7 +34,7 @@ int spl_sata_load_image(void)
} else {
/* try to recognize storage devices immediately */
scsi_scan(0);
- stor_dev = scsi_get_dev(0);
+ stor_dev = blk_get_devnum_by_type(IF_TYPE_SCSI, 0);
if (!stor_dev)
return -ENODEV;
}
diff --git a/common/spl/spl_usb.c b/common/spl/spl_usb.c
index c42848e..04fa667 100644
--- a/common/spl/spl_usb.c
+++ b/common/spl/spl_usb.c
@@ -39,7 +39,7 @@ int spl_usb_load_image(void)
#ifdef CONFIG_USB_STORAGE
/* try to recognize storage devices immediately */
usb_stor_curr_dev = usb_stor_scan(1);
- stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
+ stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, usb_stor_curr_dev);
if (!stor_dev)
return -ENODEV;
#endif
diff --git a/common/usb_storage.c b/common/usb_storage.c
index 9285c95..7e6e52d 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -136,23 +136,6 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
#endif
void uhci_show_temp_int_td(void);
-#ifdef CONFIG_PARTITIONS
-struct blk_desc *usb_stor_get_dev(int index)
-{
-#ifdef CONFIG_BLK
- struct udevice *dev;
- int ret;
-
- ret = blk_get_device(IF_TYPE_USB, index, &dev);
- if (ret)
- return NULL;
- return dev_get_uclass_platdata(dev);
-#else
- return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
-#endif
-}
-#endif
-
static void usb_show_progress(void)
{
debug(".");
@@ -217,7 +200,6 @@ static int usb_stor_probe_device(struct usb_device *udev)
#ifdef CONFIG_BLK
struct us_data *data;
- char dev_name[30], *str;
int ret;
#else
int start;
@@ -240,14 +222,12 @@ static int usb_stor_probe_device(struct usb_device *udev)
for (lun = 0; lun <= max_lun; lun++) {
struct blk_desc *blkdev;
struct udevice *dev;
+ char str[10];
- snprintf(dev_name, sizeof(dev_name), "%s.lun%d",
- udev->dev->name, lun);
- str = strdup(dev_name);
- if (!str)
- return -ENOMEM;
- ret = blk_create_device(udev->dev, "usb_storage_blk", str,
- IF_TYPE_USB, usb_max_devs, 512, 0, &dev);
+ snprintf(str, sizeof(str), "lun%d", lun);
+ ret = blk_create_devicef(udev->dev, "usb_storage_blk", str,
+ IF_TYPE_USB, usb_max_devs, 512, 0,
+ &dev);
if (ret) {
debug("Cannot bind driver\n");
return ret;
@@ -1555,4 +1535,11 @@ U_BOOT_DRIVER(usb_storage_blk) = {
.id = UCLASS_BLK,
.ops = &usb_storage_ops,
};
+#else
+U_BOOT_LEGACY_BLK(usb) = {
+ .if_typename = "usb",
+ .if_type = IF_TYPE_USB,
+ .max_devs = USB_MAX_STOR_DEV,
+ .desc = usb_dev_desc,
+};
#endif
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index afdf4a3..aec2e53 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -1,4 +1,5 @@
CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_MMC=y
CONFIG_PCI=y
CONFIG_DEFAULT_DEVICE_TREE="sandbox"
CONFIG_I8042_KEYB=y
@@ -97,6 +98,7 @@ CONFIG_PWRSEQ=y
CONFIG_SPL_PWRSEQ=y
CONFIG_RESET=y
CONFIG_DM_MMC=y
+CONFIG_SANDBOX_MMC=y
CONFIG_SPI_FLASH_SANDBOX=y
CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_ATMEL=y
diff --git a/configs/sandbox_noblk_defconfig b/configs/sandbox_noblk_defconfig
new file mode 100644
index 0000000..93167c2
--- /dev/null
+++ b/configs/sandbox_noblk_defconfig
@@ -0,0 +1,168 @@
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_PCI=y
+CONFIG_DEFAULT_DEVICE_TREE="sandbox"
+CONFIG_I8042_KEYB=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_BOOTSTAGE_USER_COUNT=0x20
+CONFIG_BOOTSTAGE_FDT=y
+CONFIG_BOOTSTAGE_STASH=y
+CONFIG_BOOTSTAGE_STASH_ADDR=0x0
+CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
+CONFIG_CONSOLE_RECORD=y
+CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CPU=y
+CONFIG_CMD_LICENSE=y
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_ASKENV=y
+CONFIG_CMD_GREPENV=y
+CONFIG_LOOPW=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MX_CYCLIC=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_DEMO=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_REMOTEPROC=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_TFTPSRV=y
+CONFIG_CMD_RARP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CDP=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_SOUND=y
+CONFIG_CMD_BOOTSTAGE=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_TPM=y
+CONFIG_CMD_TPM_TEST=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_HOSTFILE=y
+CONFIG_NETCONSOLE=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_DEVRES=y
+CONFIG_DEBUG_DEVRES=y
+CONFIG_ADC=y
+CONFIG_ADC_SANDBOX=y
+CONFIG_CLK=y
+CONFIG_CPU=y
+CONFIG_DM_DEMO=y
+CONFIG_DM_DEMO_SIMPLE=y
+CONFIG_DM_DEMO_SHAPE=y
+CONFIG_PM8916_GPIO=y
+CONFIG_SANDBOX_GPIO=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_I2C_CROS_EC_TUNNEL=y
+CONFIG_I2C_CROS_EC_LDO=y
+CONFIG_DM_I2C_GPIO=y
+CONFIG_SYS_I2C_SANDBOX=y
+CONFIG_I2C_MUX=y
+CONFIG_SPL_I2C_MUX=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=y
+CONFIG_CROS_EC_KEYB=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_CMD_CROS_EC=y
+CONFIG_CROS_EC=y
+CONFIG_CROS_EC_I2C=y
+CONFIG_CROS_EC_LPC=y
+CONFIG_CROS_EC_SANDBOX=y
+CONFIG_CROS_EC_SPI=y
+CONFIG_PWRSEQ=y
+CONFIG_SPL_PWRSEQ=y
+CONFIG_RESET=y
+CONFIG_DM_MMC=y
+CONFIG_SPI_FLASH_SANDBOX=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_ETH=y
+CONFIG_DM_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCI_SANDBOX=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_ROCKCHIP_PINCTRL=y
+CONFIG_ROCKCHIP_3036_PINCTRL=y
+CONFIG_PINCTRL_SANDBOX=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_ACT8846=y
+CONFIG_DM_PMIC_PFUZE100=y
+CONFIG_DM_PMIC_MAX77686=y
+CONFIG_PMIC_PM8916=y
+CONFIG_PMIC_RK808=y
+CONFIG_PMIC_S2MPS11=y
+CONFIG_DM_PMIC_SANDBOX=y
+CONFIG_PMIC_S5M8767=y
+CONFIG_PMIC_TPS65090=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_ACT8846=y
+CONFIG_DM_REGULATOR_PFUZE100=y
+CONFIG_DM_REGULATOR_MAX77686=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_S5M8767=y
+CONFIG_DM_REGULATOR_SANDBOX=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_RAM=y
+CONFIG_REMOTEPROC_SANDBOX=y
+CONFIG_DM_RTC=y
+CONFIG_SANDBOX_SERIAL=y
+CONFIG_SOUND=y
+CONFIG_SOUND_SANDBOX=y
+CONFIG_SANDBOX_SPI=y
+CONFIG_SPMI=y
+CONFIG_SPMI_SANDBOX=y
+CONFIG_TIMER=y
+CONFIG_TIMER_EARLY=y
+CONFIG_SANDBOX_TIMER=y
+CONFIG_TPM_TIS_SANDBOX=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EMUL=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_SYS_USB_EVENT_POLL=y
+CONFIG_DM_VIDEO=y
+CONFIG_CONSOLE_ROTATION=y
+CONFIG_CONSOLE_TRUETYPE=y
+CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
+CONFIG_VIDEO_SANDBOX_SDL=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_TPM=y
+CONFIG_LZ4=y
+CONFIG_ERRNO_STR=y
+CONFIG_UNIT_TEST=y
+CONFIG_UT_TIME=y
+CONFIG_UT_DM=y
+CONFIG_UT_ENV=y
diff --git a/disk/part.c b/disk/part.c
index 543cab8..6a1c02d 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -21,35 +21,6 @@
#define PRINTF(fmt,args...)
#endif
-const struct block_drvr block_drvr[] = {
-#if defined(CONFIG_CMD_IDE)
- { .name = "ide", .get_dev = ide_get_dev, },
-#endif
-#if defined(CONFIG_CMD_SATA)
- {.name = "sata", .get_dev = sata_get_dev, },
-#endif
-#if defined(CONFIG_CMD_SCSI)
- { .name = "scsi", .get_dev = scsi_get_dev, },
-#endif
-#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
- { .name = "usb", .get_dev = usb_stor_get_dev, },
-#endif
-#if defined(CONFIG_MMC)
- {
- .name = "mmc",
- .get_dev = mmc_get_dev,
- .select_hwpart = mmc_select_hwpart,
- },
-#endif
-#if defined(CONFIG_SYSTEMACE)
- { .name = "ace", .get_dev = systemace_get_dev, },
-#endif
-#if defined(CONFIG_SANDBOX)
- { .name = "host", .get_dev = host_get_dev, },
-#endif
- { },
-};
-
DECLARE_GLOBAL_DATA_PTR;
#ifdef HAVE_BLOCK_DEVICE
@@ -71,45 +42,23 @@ static struct part_driver *part_driver_lookup_type(int part_type)
static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart)
{
- const struct block_drvr *drvr = block_drvr;
- struct blk_desc* (*reloc_get_dev)(int dev);
- int (*select_hwpart)(int dev_num, int hwpart);
- char *name;
+ struct blk_desc *dev_desc;
int ret;
- if (!ifname)
+ dev_desc = blk_get_devnum_by_typename(ifname, dev);
+ if (!dev_desc) {
+ debug("%s: No device for iface '%s', dev %d\n", __func__,
+ ifname, dev);
return NULL;
-
- name = drvr->name;
-#ifdef CONFIG_NEEDS_MANUAL_RELOC
- name += gd->reloc_off;
-#endif
- while (drvr->name) {
- name = drvr->name;
- reloc_get_dev = drvr->get_dev;
- select_hwpart = drvr->select_hwpart;
-#ifdef CONFIG_NEEDS_MANUAL_RELOC
- name += gd->reloc_off;
- reloc_get_dev += gd->reloc_off;
- if (select_hwpart)
- select_hwpart += gd->reloc_off;
-#endif
- if (strncmp(ifname, name, strlen(name)) == 0) {
- struct blk_desc *dev_desc = reloc_get_dev(dev);
- if (!dev_desc)
- return NULL;
- if (hwpart == 0 && !select_hwpart)
- return dev_desc;
- if (!select_hwpart)
- return NULL;
- ret = select_hwpart(dev_desc->devnum, hwpart);
- if (ret < 0)
- return NULL;
- return dev_desc;
- }
- drvr++;
}
- return NULL;
+ ret = blk_dselect_hwpart(dev_desc, hwpart);
+ if (ret) {
+ debug("%s: Failed to select h/w partition: err-%d\n", __func__,
+ ret);
+ return NULL;
+ }
+
+ return dev_desc;
}
struct blk_desc *blk_get_dev(const char *ifname, int dev)
@@ -401,7 +350,7 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str,
if (*ep) {
printf("** Bad device specification %s %s **\n",
ifname, dev_str);
- dev = -1;
+ dev = -EINVAL;
goto cleanup;
}
@@ -410,7 +359,7 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str,
if (*ep) {
printf("** Bad HW partition specification %s %s **\n",
ifname, hwpart_str);
- dev = -1;
+ dev = -EINVAL;
goto cleanup;
}
}
@@ -418,7 +367,7 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str,
*dev_desc = get_dev_hwpart(ifname, dev, hwpart);
if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
printf("** Bad device %s %s **\n", ifname, dev_hwpart_str);
- dev = -1;
+ dev = -ENOENT;
goto cleanup;
}
diff --git a/drivers/Makefile b/drivers/Makefile
index 6900097..99dd07f 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -36,6 +36,8 @@ obj-$(CONFIG_SPL_WATCHDOG_SUPPORT) += watchdog/
obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += usb/host/
obj-$(CONFIG_OMAP_USB_PHY) += usb/phy/
obj-$(CONFIG_SPL_SATA_SUPPORT) += block/
+obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += block/
+obj-$(CONFIG_SPL_MMC_SUPPORT) += block/
else
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index fcc9ccd..80eea84 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -9,10 +9,9 @@ config BLK
be partitioned into several areas, called 'partitions' in U-Boot.
A filesystem can be placed in each partition.
-config DISK
- bool "Support disk controllers with driver model"
+config AHCI
+ bool "Support SATA controllers with driver model"
depends on DM
- default y if DM
help
This enables a uclass for disk controllers in U-Boot. Various driver
types can use this, such as AHCI/SATA. It does not provide any standard
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index a43492f..436b79f 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -7,7 +7,11 @@
obj-$(CONFIG_BLK) += blk-uclass.o
-obj-$(CONFIG_DISK) += disk-uclass.o
+ifndef CONFIG_BLK
+obj-y += blk_legacy.o
+endif
+
+obj-$(CONFIG_AHCI) += ahci-uclass.o
obj-$(CONFIG_SCSI_AHCI) += ahci.o
obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o
obj-$(CONFIG_FSL_SATA) += fsl_sata.o
@@ -22,7 +26,7 @@ obj-$(CONFIG_SATA_MV) += sata_mv.o
obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o
obj-$(CONFIG_SATA_SIL) += sata_sil.o
obj-$(CONFIG_IDE_SIL680) += sil680.o
-obj-$(CONFIG_SANDBOX) += sandbox.o
+obj-$(CONFIG_SANDBOX) += sandbox.o sandbox_scsi.o sata_sandbox.o
obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
obj-$(CONFIG_SYSTEMACE) += systemace.o
obj-$(CONFIG_BLOCK_CACHE) += blkcache.o
diff --git a/drivers/block/disk-uclass.c b/drivers/block/ahci-uclass.c
index d665b35..7b8c326 100644
--- a/drivers/block/disk-uclass.c
+++ b/drivers/block/ahci-uclass.c
@@ -8,7 +8,7 @@
#include <common.h>
#include <dm.h>
-UCLASS_DRIVER(disk) = {
- .id = UCLASS_DISK,
- .name = "disk",
+UCLASS_DRIVER(ahci) = {
+ .id = UCLASS_AHCI,
+ .name = "ahci",
};
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index 617db22..6ba1026 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -11,6 +11,315 @@
#include <dm/device-internal.h>
#include <dm/lists.h>
+static const char *if_typename_str[IF_TYPE_COUNT] = {
+ [IF_TYPE_IDE] = "ide",
+ [IF_TYPE_SCSI] = "scsi",
+ [IF_TYPE_ATAPI] = "atapi",
+ [IF_TYPE_USB] = "usb",
+ [IF_TYPE_DOC] = "doc",
+ [IF_TYPE_MMC] = "mmc",
+ [IF_TYPE_SD] = "sd",
+ [IF_TYPE_SATA] = "sata",
+ [IF_TYPE_HOST] = "host",
+ [IF_TYPE_SYSTEMACE] = "ace",
+};
+
+static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
+ [IF_TYPE_IDE] = UCLASS_INVALID,
+ [IF_TYPE_SCSI] = UCLASS_INVALID,
+ [IF_TYPE_ATAPI] = UCLASS_INVALID,
+ [IF_TYPE_USB] = UCLASS_MASS_STORAGE,
+ [IF_TYPE_DOC] = UCLASS_INVALID,
+ [IF_TYPE_MMC] = UCLASS_MMC,
+ [IF_TYPE_SD] = UCLASS_INVALID,
+ [IF_TYPE_SATA] = UCLASS_AHCI,
+ [IF_TYPE_HOST] = UCLASS_ROOT,
+ [IF_TYPE_SYSTEMACE] = UCLASS_INVALID,
+};
+
+static enum if_type if_typename_to_iftype(const char *if_typename)
+{
+ int i;
+
+ for (i = 0; i < IF_TYPE_COUNT; i++) {
+ if (if_typename_str[i] &&
+ !strcmp(if_typename, if_typename_str[i]))
+ return i;
+ }
+
+ return IF_TYPE_UNKNOWN;
+}
+
+static enum uclass_id if_type_to_uclass_id(enum if_type if_type)
+{
+ return if_type_uclass_id[if_type];
+}
+
+struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
+{
+ struct blk_desc *desc;
+ struct udevice *dev;
+ int ret;
+
+ ret = blk_get_device(if_type, devnum, &dev);
+ if (ret)
+ return NULL;
+ desc = dev_get_uclass_platdata(dev);
+
+ return desc;
+}
+
+/*
+ * This function is complicated with driver model. We look up the interface
+ * name in a local table. This gives us an interface type which we can match
+ * against the uclass of the block device's parent.
+ */
+struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum)
+{
+ enum uclass_id uclass_id;
+ enum if_type if_type;
+ struct udevice *dev;
+ struct uclass *uc;
+ int ret;
+
+ if_type = if_typename_to_iftype(if_typename);
+ if (if_type == IF_TYPE_UNKNOWN) {
+ debug("%s: Unknown interface type '%s'\n", __func__,
+ if_typename);
+ return NULL;
+ }
+ uclass_id = if_type_to_uclass_id(if_type);
+ if (uclass_id == UCLASS_INVALID) {
+ debug("%s: Unknown uclass for interface type'\n",
+ if_typename_str[if_type]);
+ return NULL;
+ }
+
+ ret = uclass_get(UCLASS_BLK, &uc);
+ if (ret)
+ return NULL;
+ uclass_foreach_dev(dev, uc) {
+ struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+ debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
+ if_type, devnum, dev->name, desc->if_type, desc->devnum);
+ if (desc->devnum != devnum)
+ continue;
+
+ /* Find out the parent device uclass */
+ if (device_get_uclass_id(dev->parent) != uclass_id) {
+ debug("%s: parent uclass %d, this dev %d\n", __func__,
+ device_get_uclass_id(dev->parent), uclass_id);
+ continue;
+ }
+
+ if (device_probe(dev))
+ return NULL;
+
+ debug("%s: Device desc %p\n", __func__, desc);
+ return desc;
+ }
+ debug("%s: No device found\n", __func__);
+
+ return NULL;
+}
+
+/**
+ * get_desc() - Get the block device descriptor for the given device number
+ *
+ * @if_type: Interface type
+ * @devnum: Device number (0 = first)
+ * @descp: Returns block device descriptor on success
+ * @return 0 on success, -ENODEV if there is no such device and no device
+ * with a higher device number, -ENOENT if there is no such device but there
+ * is one with a higher number, or other -ve on other error.
+ */
+static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp)
+{
+ bool found_more = false;
+ struct udevice *dev;
+ struct uclass *uc;
+ int ret;
+
+ *descp = NULL;
+ ret = uclass_get(UCLASS_BLK, &uc);
+ if (ret)
+ return ret;
+ uclass_foreach_dev(dev, uc) {
+ struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+ debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
+ if_type, devnum, dev->name, desc->if_type, desc->devnum);
+ if (desc->if_type == if_type) {
+ if (desc->devnum == devnum) {
+ ret = device_probe(dev);
+ if (ret)
+ return ret;
+
+ } else if (desc->devnum > devnum) {
+ found_more = true;
+ }
+ }
+ }
+
+ return found_more ? -ENOENT : -ENODEV;
+}
+
+int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart)
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = blk_get_device(if_type, devnum, &dev);
+ if (ret)
+ return ret;
+
+ return blk_select_hwpart(dev, hwpart);
+}
+
+int blk_list_part(enum if_type if_type)
+{
+ struct blk_desc *desc;
+ int devnum, ok;
+ int ret;
+
+ for (ok = 0, devnum = 0;; ++devnum) {
+ ret = get_desc(if_type, devnum, &desc);
+ if (ret == -ENODEV)
+ break;
+ else if (ret)
+ continue;
+ if (desc->part_type != PART_TYPE_UNKNOWN) {
+ ++ok;
+ if (devnum)
+ putc('\n');
+ part_print(desc);
+ }
+ }
+ if (!ok)
+ return -ENODEV;
+
+ return 0;
+}
+
+int blk_print_part_devnum(enum if_type if_type, int devnum)
+{
+ struct blk_desc *desc;
+ int ret;
+
+ ret = get_desc(if_type, devnum, &desc);
+ if (ret)
+ return ret;
+ if (desc->type == DEV_TYPE_UNKNOWN)
+ return -ENOENT;
+ part_print(desc);
+
+ return 0;
+}
+
+void blk_list_devices(enum if_type if_type)
+{
+ struct blk_desc *desc;
+ int ret;
+ int i;
+
+ for (i = 0;; ++i) {
+ ret = get_desc(if_type, i, &desc);
+ if (ret == -ENODEV)
+ break;
+ else if (ret)
+ continue;
+ if (desc->type == DEV_TYPE_UNKNOWN)
+ continue; /* list only known devices */
+ printf("Device %d: ", i);
+ dev_print(desc);
+ }
+}
+
+int blk_print_device_num(enum if_type if_type, int devnum)
+{
+ struct blk_desc *desc;
+ int ret;
+
+ ret = get_desc(if_type, devnum, &desc);
+ if (ret)
+ return ret;
+ printf("\nIDE device %d: ", devnum);
+ dev_print(desc);
+
+ return 0;
+}
+
+int blk_show_device(enum if_type if_type, int devnum)
+{
+ struct blk_desc *desc;
+ int ret;
+
+ printf("\nDevice %d: ", devnum);
+ ret = get_desc(if_type, devnum, &desc);
+ if (ret == -ENODEV || ret == -ENOENT) {
+ printf("unknown device\n");
+ return -ENODEV;
+ }
+ if (ret)
+ return ret;
+ dev_print(desc);
+
+ if (desc->type == DEV_TYPE_UNKNOWN)
+ return -ENOENT;
+
+ return 0;
+}
+
+ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
+ lbaint_t blkcnt, void *buffer)
+{
+ struct blk_desc *desc;
+ ulong n;
+ int ret;
+
+ ret = get_desc(if_type, devnum, &desc);
+ if (ret)
+ return ret;
+ n = blk_dread(desc, start, blkcnt, buffer);
+ if (IS_ERR_VALUE(n))
+ return n;
+
+ /* flush cache after read */
+ flush_cache((ulong)buffer, blkcnt * desc->blksz);
+
+ return n;
+}
+
+ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
+ lbaint_t blkcnt, const void *buffer)
+{
+ struct blk_desc *desc;
+ int ret;
+
+ ret = get_desc(if_type, devnum, &desc);
+ if (ret)
+ return ret;
+ return blk_dwrite(desc, start, blkcnt, buffer);
+}
+
+int blk_select_hwpart(struct udevice *dev, int hwpart)
+{
+ const struct blk_ops *ops = blk_get_ops(dev);
+
+ if (!ops)
+ return -ENOSYS;
+ if (!ops->select_hwpart)
+ return 0;
+
+ return ops->select_hwpart(dev, hwpart);
+}
+
+int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
+{
+ return blk_select_hwpart(desc->bdev, hwpart);
+}
+
int blk_first_device(int if_type, struct udevice **devp)
{
struct blk_desc *desc;
@@ -131,6 +440,26 @@ int blk_prepare_device(struct udevice *dev)
return 0;
}
+int blk_find_max_devnum(enum if_type if_type)
+{
+ struct udevice *dev;
+ int max_devnum = -ENODEV;
+ struct uclass *uc;
+ int ret;
+
+ ret = uclass_get(UCLASS_BLK, &uc);
+ if (ret)
+ return ret;
+ uclass_foreach_dev(dev, uc) {
+ struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+ if (desc->if_type == if_type && desc->devnum > max_devnum)
+ max_devnum = desc->devnum;
+ }
+
+ return max_devnum;
+}
+
int blk_create_device(struct udevice *parent, const char *drv_name,
const char *name, int if_type, int devnum, int blksz,
lbaint_t size, struct udevice **devp)
@@ -139,6 +468,15 @@ int blk_create_device(struct udevice *parent, const char *drv_name,
struct udevice *dev;
int ret;
+ if (devnum == -1) {
+ ret = blk_find_max_devnum(if_type);
+ if (ret == -ENODEV)
+ devnum = 0;
+ else if (ret < 0)
+ return ret;
+ else
+ devnum = ret + 1;
+ }
ret = device_bind_driver(parent, drv_name, name, &dev);
if (ret)
return ret;
@@ -154,6 +492,29 @@ int blk_create_device(struct udevice *parent, const char *drv_name,
return 0;
}
+int blk_create_devicef(struct udevice *parent, const char *drv_name,
+ const char *name, int if_type, int devnum, int blksz,
+ lbaint_t size, struct udevice **devp)
+{
+ char dev_name[30], *str;
+ int ret;
+
+ snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name);
+ str = strdup(dev_name);
+ if (!str)
+ return -ENOMEM;
+
+ ret = blk_create_device(parent, drv_name, str, if_type, devnum,
+ blksz, size, devp);
+ if (ret) {
+ free(str);
+ return ret;
+ }
+ device_set_name_alloced(*devp);
+
+ return ret;
+}
+
int blk_unbind_all(int if_type)
{
struct uclass *uc;
diff --git a/drivers/block/blk_legacy.c b/drivers/block/blk_legacy.c
new file mode 100644
index 0000000..7b90a8a
--- /dev/null
+++ b/drivers/block/blk_legacy.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/err.h>
+
+struct blk_driver *blk_driver_lookup_type(int if_type)
+{
+ struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver);
+ const int n_ents = ll_entry_count(struct blk_driver, blk_driver);
+ struct blk_driver *entry;
+
+ for (entry = drv; entry != drv + n_ents; entry++) {
+ if (if_type == entry->if_type)
+ return entry;
+ }
+
+ /* Not found */
+ return NULL;
+}
+
+static struct blk_driver *blk_driver_lookup_typename(const char *if_typename)
+{
+ struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver);
+ const int n_ents = ll_entry_count(struct blk_driver, blk_driver);
+ struct blk_driver *entry;
+
+ for (entry = drv; entry != drv + n_ents; entry++) {
+ if (!strcmp(if_typename, entry->if_typename))
+ return entry;
+ }
+
+ /* Not found */
+ return NULL;
+}
+
+/**
+ * get_desc() - Get the block device descriptor for the given device number
+ *
+ * @drv: Legacy block driver
+ * @devnum: Device number (0 = first)
+ * @descp: Returns block device descriptor on success
+ * @return 0 on success, -ENODEV if there is no such device, -ENOSYS if the
+ * driver does not provide a way to find a device, or other -ve on other
+ * error.
+ */
+static int get_desc(struct blk_driver *drv, int devnum, struct blk_desc **descp)
+{
+ if (drv->desc) {
+ if (devnum < 0 || devnum >= drv->max_devs)
+ return -ENODEV;
+ *descp = &drv->desc[devnum];
+ return 0;
+ }
+ if (!drv->get_dev)
+ return -ENOSYS;
+
+ return drv->get_dev(devnum, descp);
+}
+
+#ifdef HAVE_BLOCK_DEVICE
+int blk_list_part(enum if_type if_type)
+{
+ struct blk_driver *drv;
+ struct blk_desc *desc;
+ int devnum, ok;
+ bool first = true;
+
+ drv = blk_driver_lookup_type(if_type);
+ if (!drv)
+ return -ENOSYS;
+ for (ok = 0, devnum = 0; devnum < drv->max_devs; ++devnum) {
+ if (get_desc(drv, devnum, &desc))
+ continue;
+ if (desc->part_type != PART_TYPE_UNKNOWN) {
+ ++ok;
+ if (!first)
+ putc('\n');
+ part_print(desc);
+ first = false;
+ }
+ }
+ if (!ok)
+ return -ENODEV;
+
+ return 0;
+}
+
+int blk_print_part_devnum(enum if_type if_type, int devnum)
+{
+ struct blk_driver *drv = blk_driver_lookup_type(if_type);
+ struct blk_desc *desc;
+ int ret;
+
+ if (!drv)
+ return -ENOSYS;
+ ret = get_desc(drv, devnum, &desc);
+ if (ret)
+ return ret;
+ if (desc->type == DEV_TYPE_UNKNOWN)
+ return -ENOENT;
+ part_print(desc);
+
+ return 0;
+}
+
+void blk_list_devices(enum if_type if_type)
+{
+ struct blk_driver *drv = blk_driver_lookup_type(if_type);
+ struct blk_desc *desc;
+ int i;
+
+ if (!drv)
+ return;
+ for (i = 0; i < drv->max_devs; ++i) {
+ if (get_desc(drv, i, &desc))
+ continue;
+ if (desc->type == DEV_TYPE_UNKNOWN)
+ continue; /* list only known devices */
+ printf("Device %d: ", i);
+ dev_print(desc);
+ }
+}
+
+int blk_print_device_num(enum if_type if_type, int devnum)
+{
+ struct blk_driver *drv = blk_driver_lookup_type(if_type);
+ struct blk_desc *desc;
+ int ret;
+
+ if (!drv)
+ return -ENOSYS;
+ ret = get_desc(drv, devnum, &desc);
+ if (ret)
+ return ret;
+ printf("\n%s device %d: ", drv->if_typename, devnum);
+ dev_print(desc);
+
+ return 0;
+}
+
+int blk_show_device(enum if_type if_type, int devnum)
+{
+ struct blk_driver *drv = blk_driver_lookup_type(if_type);
+ struct blk_desc *desc;
+ int ret;
+
+ if (!drv)
+ return -ENOSYS;
+ printf("\nDevice %d: ", devnum);
+ if (devnum >= drv->max_devs) {
+ puts("unknown device\n");
+ return -ENODEV;
+ }
+ ret = get_desc(drv, devnum, &desc);
+ if (ret)
+ return ret;
+ dev_print(desc);
+
+ if (desc->type == DEV_TYPE_UNKNOWN)
+ return -ENOENT;
+
+ return 0;
+}
+#endif /* HAVE_BLOCK_DEVICE */
+
+struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
+{
+ struct blk_driver *drv = blk_driver_lookup_type(if_type);
+ struct blk_desc *desc;
+
+ if (!drv)
+ return NULL;
+
+ if (get_desc(drv, devnum, &desc))
+ return NULL;
+
+ return desc;
+}
+
+int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
+{
+ struct blk_driver *drv = blk_driver_lookup_type(desc->if_type);
+
+ if (!drv)
+ return -ENOSYS;
+ if (drv->select_hwpart)
+ return drv->select_hwpart(desc, hwpart);
+
+ return 0;
+}
+
+struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum)
+{
+ struct blk_driver *drv = blk_driver_lookup_typename(if_typename);
+ struct blk_desc *desc;
+
+ if (!drv)
+ return NULL;
+
+ if (get_desc(drv, devnum, &desc))
+ return NULL;
+
+ return desc;
+}
+
+ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
+ lbaint_t blkcnt, void *buffer)
+{
+ struct blk_driver *drv = blk_driver_lookup_type(if_type);
+ struct blk_desc *desc;
+ ulong n;
+ int ret;
+
+ if (!drv)
+ return -ENOSYS;
+ ret = get_desc(drv, devnum, &desc);
+ if (ret)
+ return ret;
+ n = desc->block_read(desc, start, blkcnt, buffer);
+ if (IS_ERR_VALUE(n))
+ return n;
+
+ /* flush cache after read */
+ flush_cache((ulong)buffer, blkcnt * desc->blksz);
+
+ return n;
+}
+
+ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
+ lbaint_t blkcnt, const void *buffer)
+{
+ struct blk_driver *drv = blk_driver_lookup_type(if_type);
+ struct blk_desc *desc;
+ int ret;
+
+ if (!drv)
+ return -ENOSYS;
+ ret = get_desc(drv, devnum, &desc);
+ if (ret)
+ return ret;
+ return desc->block_write(desc, start, blkcnt, buffer);
+}
+
+int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart)
+{
+ struct blk_driver *drv = blk_driver_lookup_type(if_type);
+ struct blk_desc *desc;
+ int ret;
+
+ if (!drv)
+ return -ENOSYS;
+ ret = get_desc(drv, devnum, &desc);
+ if (ret)
+ return ret;
+ return drv->select_hwpart(desc, hwpart);
+}
diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c
index 2d340ef..ac28f83 100644
--- a/drivers/block/sandbox.c
+++ b/drivers/block/sandbox.c
@@ -17,6 +17,19 @@
DECLARE_GLOBAL_DATA_PTR;
+#ifndef CONFIG_BLK
+static struct host_block_dev host_devices[CONFIG_HOST_MAX_DEVICES];
+
+static struct host_block_dev *find_host_device(int dev)
+{
+ if (dev >= 0 && dev < CONFIG_HOST_MAX_DEVICES)
+ return &host_devices[dev];
+
+ return NULL;
+}
+#endif
+
+#ifdef CONFIG_BLK
static unsigned long host_block_read(struct udevice *dev,
unsigned long start, lbaint_t blkcnt,
void *buffer)
@@ -24,6 +37,18 @@ static unsigned long host_block_read(struct udevice *dev,
struct host_block_dev *host_dev = dev_get_priv(dev);
struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
+#else
+static unsigned long host_block_read(struct blk_desc *block_dev,
+ unsigned long start, lbaint_t blkcnt,
+ void *buffer)
+{
+ int dev = block_dev->devnum;
+ struct host_block_dev *host_dev = find_host_device(dev);
+
+ if (!host_dev)
+ return -1;
+#endif
+
if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) ==
-1) {
printf("ERROR: Invalid block %lx\n", start);
@@ -35,12 +60,21 @@ static unsigned long host_block_read(struct udevice *dev,
return -1;
}
+#ifdef CONFIG_BLK
static unsigned long host_block_write(struct udevice *dev,
unsigned long start, lbaint_t blkcnt,
const void *buffer)
{
struct host_block_dev *host_dev = dev_get_priv(dev);
struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
+#else
+static unsigned long host_block_write(struct blk_desc *block_dev,
+ unsigned long start, lbaint_t blkcnt,
+ const void *buffer)
+{
+ int dev = block_dev->devnum;
+ struct host_block_dev *host_dev = find_host_device(dev);
+#endif
if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) ==
-1) {
@@ -53,6 +87,7 @@ static unsigned long host_block_write(struct udevice *dev,
return -1;
}
+#ifdef CONFIG_BLK
int host_dev_bind(int devnum, char *filename)
{
struct host_block_dev *host_dev;
@@ -115,9 +150,51 @@ err:
free(str);
return ret;
}
+#else
+int host_dev_bind(int dev, char *filename)
+{
+ struct host_block_dev *host_dev = find_host_device(dev);
+
+ if (!host_dev)
+ return -1;
+ if (host_dev->blk_dev.priv) {
+ os_close(host_dev->fd);
+ host_dev->blk_dev.priv = NULL;
+ }
+ if (host_dev->filename)
+ free(host_dev->filename);
+ if (filename && *filename) {
+ host_dev->filename = strdup(filename);
+ } else {
+ host_dev->filename = NULL;
+ return 0;
+ }
+
+ host_dev->fd = os_open(host_dev->filename, OS_O_RDWR);
+ if (host_dev->fd == -1) {
+ printf("Failed to access host backing file '%s'\n",
+ host_dev->filename);
+ return 1;
+ }
+
+ struct blk_desc *blk_dev = &host_dev->blk_dev;
+ blk_dev->if_type = IF_TYPE_HOST;
+ blk_dev->priv = host_dev;
+ blk_dev->blksz = 512;
+ blk_dev->lba = os_lseek(host_dev->fd, 0, OS_SEEK_END) / blk_dev->blksz;
+ blk_dev->block_read = host_block_read;
+ blk_dev->block_write = host_block_write;
+ blk_dev->devnum = dev;
+ blk_dev->part_type = PART_TYPE_UNKNOWN;
+ part_init(blk_dev);
+
+ return 0;
+}
+#endif
int host_get_dev_err(int devnum, struct blk_desc **blk_devp)
{
+#ifdef CONFIG_BLK
struct udevice *dev;
int ret;
@@ -125,20 +202,22 @@ int host_get_dev_err(int devnum, struct blk_desc **blk_devp)
if (ret)
return ret;
*blk_devp = dev_get_uclass_platdata(dev);
+#else
+ struct host_block_dev *host_dev = find_host_device(devnum);
- return 0;
-}
+ if (!host_dev)
+ return -ENODEV;
-struct blk_desc *host_get_dev(int dev)
-{
- struct blk_desc *blk_dev;
+ if (!host_dev->blk_dev.priv)
+ return -ENOENT;
- if (host_get_dev_err(dev, &blk_dev))
- return NULL;
+ *blk_devp = &host_dev->blk_dev;
+#endif
- return blk_dev;
+ return 0;
}
+#ifdef CONFIG_BLK
static const struct blk_ops sandbox_host_blk_ops = {
.read = host_block_read,
.write = host_block_write,
@@ -150,3 +229,11 @@ U_BOOT_DRIVER(sandbox_host_blk) = {
.ops = &sandbox_host_blk_ops,
.priv_auto_alloc_size = sizeof(struct host_block_dev),
};
+#else
+U_BOOT_LEGACY_BLK(sandbox_host) = {
+ .if_typename = "host",
+ .if_type = IF_TYPE_HOST,
+ .max_devs = CONFIG_HOST_MAX_DEVICES,
+ .get_dev = host_get_dev_err,
+};
+#endif
diff --git a/drivers/block/sandbox_scsi.c b/drivers/block/sandbox_scsi.c
new file mode 100644
index 0000000..ad961bd
--- /dev/null
+++ b/drivers/block/sandbox_scsi.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This file contains dummy implementations of SCSI functions requried so
+ * that CONFIG_SCSI can be enabled for sandbox.
+ */
+
+#include <common.h>
+#include <scsi.h>
+
+void scsi_bus_reset(void)
+{
+}
+
+void scsi_init(void)
+{
+}
+
+int scsi_exec(ccb *pccb)
+{
+ return 0;
+}
+
+void scsi_print_error(ccb *pccb)
+{
+}
diff --git a/drivers/block/sata_sandbox.c b/drivers/block/sata_sandbox.c
new file mode 100644
index 0000000..bd967d2
--- /dev/null
+++ b/drivers/block/sata_sandbox.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+
+int init_sata(int dev)
+{
+ return 0;
+}
+
+int reset_sata(int dev)
+{
+ return 0;
+}
+
+int scan_sata(int dev)
+{
+ return 0;
+}
+
+ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer)
+{
+ return 0;
+}
+
+ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer)
+{
+ return 0;
+}
diff --git a/drivers/block/sym53c8xx.c b/drivers/block/sym53c8xx.c
index c7c40af..5daede7 100644
--- a/drivers/block/sym53c8xx.c
+++ b/drivers/block/sym53c8xx.c
@@ -33,7 +33,7 @@
#define PRINTF(fmt,args...)
#endif
-#if defined(CONFIG_CMD_SCSI) && defined(CONFIG_SCSI_SYM53C8XX)
+#if defined(CONFIG_SCSI) && defined(CONFIG_SCSI_SYM53C8XX)
#undef SCSI_SINGLE_STEP
/*
diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c
index 09fe834..9392bea 100644
--- a/drivers/block/systemace.c
+++ b/drivers/block/systemace.c
@@ -27,7 +27,7 @@
#include <common.h>
#include <command.h>
-#include <systemace.h>
+#include <dm.h>
#include <part.h>
#include <asm/io.h>
@@ -69,11 +69,9 @@ static u16 ace_readw(unsigned off)
return in16(base + off);
}
-static unsigned long systemace_read(struct blk_desc *block_dev,
- unsigned long start, lbaint_t blkcnt,
- void *buffer);
-
+#ifndef CONFIG_BLK
static struct blk_desc systemace_dev = { 0 };
+#endif
static int get_cf_lock(void)
{
@@ -104,42 +102,19 @@ static void release_cf_lock(void)
ace_writew((val & 0xffff), 0x18);
}
-#ifdef CONFIG_PARTITIONS
-struct blk_desc *systemace_get_dev(int dev)
-{
- /* The first time through this, the systemace_dev object is
- not yet initialized. In that case, fill it in. */
- if (systemace_dev.blksz == 0) {
- systemace_dev.if_type = IF_TYPE_UNKNOWN;
- systemace_dev.devnum = 0;
- systemace_dev.part_type = PART_TYPE_UNKNOWN;
- systemace_dev.type = DEV_TYPE_HARDDISK;
- systemace_dev.blksz = 512;
- systemace_dev.log2blksz = LOG2(systemace_dev.blksz);
- systemace_dev.removable = 1;
- systemace_dev.block_read = systemace_read;
-
- /*
- * Ensure the correct bus mode (8/16 bits) gets enabled
- */
- ace_writew(width == 8 ? 0 : 0x0001, 0);
-
- part_init(&systemace_dev);
-
- }
-
- return &systemace_dev;
-}
-#endif
-
/*
* This function is called (by dereferencing the block_read pointer in
* the dev_desc) to read blocks of data. The return value is the
* number of blocks read. A zero return indicates an error.
*/
+#ifdef CONFIG_BLK
+static unsigned long systemace_read(struct udevice *dev, unsigned long start,
+ lbaint_t blkcnt, void *buffer)
+#else
static unsigned long systemace_read(struct blk_desc *block_dev,
unsigned long start, lbaint_t blkcnt,
void *buffer)
+#endif
{
int retry;
unsigned blk_countdown;
@@ -257,3 +232,72 @@ static unsigned long systemace_read(struct blk_desc *block_dev,
return blkcnt;
}
+
+#ifdef CONFIG_BLK
+static int systemace_bind(struct udevice *dev)
+{
+ struct blk_desc *bdesc;
+ struct udevice *bdev;
+ int ret;
+
+ ret = blk_create_devicef(dev, "systemace_blk", "blk", IF_TYPE_SYSTEMACE,
+ -1, 512, 0, &bdev);
+ if (ret) {
+ debug("Cannot create block device\n");
+ return ret;
+ }
+ bdesc = dev_get_uclass_platdata(bdev);
+ bdesc->removable = 1;
+ bdesc->part_type = PART_TYPE_UNKNOWN;
+ bdesc->log2blksz = LOG2(bdesc->blksz);
+
+ /* Ensure the correct bus mode (8/16 bits) gets enabled */
+ ace_writew(width == 8 ? 0 : 0x0001, 0);
+
+ return 0;
+}
+
+static const struct blk_ops systemace_blk_ops = {
+ .read = systemace_read,
+};
+
+U_BOOT_DRIVER(systemace_blk) = {
+ .name = "systemace_blk",
+ .id = UCLASS_BLK,
+ .ops = &systemace_blk_ops,
+ .bind = systemace_bind,
+};
+#else
+static int systemace_get_dev(int dev, struct blk_desc **descp)
+{
+ /* The first time through this, the systemace_dev object is
+ not yet initialized. In that case, fill it in. */
+ if (systemace_dev.blksz == 0) {
+ systemace_dev.if_type = IF_TYPE_UNKNOWN;
+ systemace_dev.devnum = 0;
+ systemace_dev.part_type = PART_TYPE_UNKNOWN;
+ systemace_dev.type = DEV_TYPE_HARDDISK;
+ systemace_dev.blksz = 512;
+ systemace_dev.log2blksz = LOG2(systemace_dev.blksz);
+ systemace_dev.removable = 1;
+ systemace_dev.block_read = systemace_read;
+
+ /*
+ * Ensure the correct bus mode (8/16 bits) gets enabled
+ */
+ ace_writew(width == 8 ? 0 : 0x0001, 0);
+
+ part_init(&systemace_dev);
+ }
+ *descp = &systemace_dev;
+
+ return 0;
+}
+
+U_BOOT_LEGACY_BLK(systemace) = {
+ .if_typename = "ace",
+ .if_type = IF_TYPE_SYSTEMACE,
+ .max_devs = 1,
+ .get_dev = systemace_get_dev,
+};
+#endif
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index e1714b2..0e56b23 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -112,6 +112,8 @@ int device_unbind(struct udevice *dev)
devres_release_all(dev);
+ if (dev->flags & DM_NAME_ALLOCED)
+ free((char *)dev->name);
free(dev);
return 0;
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 1322991..5c2dc70 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -657,8 +657,8 @@ fdt_addr_t dev_get_addr_name(struct udevice *dev, const char *name)
#if CONFIG_IS_ENABLED(OF_CONTROL)
int index;
- index = fdt_find_string(gd->fdt_blob, dev->parent->of_offset,
- "reg-names", name);
+ index = fdt_find_string(gd->fdt_blob, dev->of_offset, "reg-names",
+ name);
if (index < 0)
return index;
@@ -706,12 +706,18 @@ bool device_is_last_sibling(struct udevice *dev)
return list_is_last(&dev->sibling_node, &parent->child_head);
}
+void device_set_name_alloced(struct udevice *dev)
+{
+ dev->flags |= DM_NAME_ALLOCED;
+}
+
int device_set_name(struct udevice *dev, const char *name)
{
name = strdup(name);
if (!name)
return -ENOMEM;
dev->name = name;
+ device_set_name_alloced(dev);
return 0;
}
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index c4fc216..a72db13 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -171,6 +171,10 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
dm_dbg(" - found match at '%s'\n", entry->name);
ret = device_bind(parent, entry, name, NULL, offset, &dev);
+ if (ret == -ENODEV) {
+ dm_dbg("Driver '%s' refuses to bind\n", entry->name);
+ continue;
+ }
if (ret) {
dm_warn("Error binding driver '%s': %d\n", entry->name,
ret);
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index faece88..78724e4 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -50,8 +50,9 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
if (dfu->data.mmc.hw_partition >= 0) {
part_num_bkp = mmc->block_dev.hwpart;
- ret = mmc_select_hwpart(dfu->data.mmc.dev_num,
- dfu->data.mmc.hw_partition);
+ ret = blk_select_hwpart_devnum(IF_TYPE_MMC,
+ dfu->data.mmc.dev_num,
+ dfu->data.mmc.hw_partition);
if (ret)
return ret;
}
@@ -75,12 +76,16 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
if (n != blk_count) {
error("MMC operation failed");
if (dfu->data.mmc.hw_partition >= 0)
- mmc_select_hwpart(dfu->data.mmc.dev_num, part_num_bkp);
+ blk_select_hwpart_devnum(IF_TYPE_MMC,
+ dfu->data.mmc.dev_num,
+ part_num_bkp);
return -EIO;
}
if (dfu->data.mmc.hw_partition >= 0) {
- ret = mmc_select_hwpart(dfu->data.mmc.dev_num, part_num_bkp);
+ ret = blk_select_hwpart_devnum(IF_TYPE_MMC,
+ dfu->data.mmc.dev_num,
+ part_num_bkp);
if (ret)
return ret;
}
diff --git a/drivers/gpio/74x164_gpio.c b/drivers/gpio/74x164_gpio.c
new file mode 100644
index 0000000..9ac10a7
--- /dev/null
+++ b/drivers/gpio/74x164_gpio.c
@@ -0,0 +1,193 @@
+/*
+ * Take drivers/gpio/gpio-74x164.c as reference.
+ *
+ * 74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver
+ *
+ * Copyright (C) 2016 Peng Fan <van.freenix@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <spi.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * struct gen_74x164_chip - Data for 74Hx164
+ *
+ * @oe: OE pin
+ * @nregs: number of registers
+ * @buffer: buffer for chained chips
+ */
+#define GEN_74X164_NUMBER_GPIOS 8
+
+struct gen_74x164_priv {
+ struct gpio_desc oe;
+ u32 nregs;
+ /*
+ * Since the nregs are chained, every byte sent will make
+ * the previous byte shift to the next register in the
+ * chain. Thus, the first byte sent will end up in the last
+ * register at the end of the transfer. So, to have a logical
+ * numbering, store the bytes in reverse order.
+ */
+ u8 *buffer;
+};
+
+static int gen_74x164_write_conf(struct udevice *dev)
+{
+ struct gen_74x164_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = dm_spi_claim_bus(dev);
+ if (ret)
+ return ret;
+
+ ret = dm_spi_xfer(dev, priv->nregs * 8, priv->buffer, NULL,
+ SPI_XFER_BEGIN | SPI_XFER_END);
+
+ dm_spi_release_bus(dev);
+
+ return ret;
+}
+
+static int gen_74x164_get_value(struct udevice *dev, unsigned offset)
+{
+ struct gen_74x164_priv *priv = dev_get_priv(dev);
+ uint bank = priv->nregs - 1 - offset / 8;
+ uint pin = offset % 8;
+
+ return (priv->buffer[bank] >> pin) & 0x1;
+}
+
+static int gen_74x164_set_value(struct udevice *dev, unsigned offset,
+ int value)
+{
+ struct gen_74x164_priv *priv = dev_get_priv(dev);
+ uint bank = priv->nregs - 1 - offset / 8;
+ uint pin = offset % 8;
+ int ret;
+
+ if (value)
+ priv->buffer[bank] |= 1 << pin;
+ else
+ priv->buffer[bank] &= ~(1 << pin);
+
+ ret = gen_74x164_write_conf(dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int gen_74x164_direction_input(struct udevice *dev, unsigned offset)
+{
+ return -ENOSYS;
+}
+
+static int gen_74x164_direction_output(struct udevice *dev, unsigned offset,
+ int value)
+{
+ return gen_74x164_set_value(dev, offset, value);
+}
+
+static int gen_74x164_get_function(struct udevice *dev, unsigned offset)
+{
+ return GPIOF_OUTPUT;
+}
+
+static int gen_74x164_xlate(struct udevice *dev, struct gpio_desc *desc,
+ struct fdtdec_phandle_args *args)
+{
+ desc->offset = args->args[0];
+ desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
+
+ return 0;
+}
+
+static const struct dm_gpio_ops gen_74x164_ops = {
+ .direction_input = gen_74x164_direction_input,
+ .direction_output = gen_74x164_direction_output,
+ .get_value = gen_74x164_get_value,
+ .set_value = gen_74x164_set_value,
+ .get_function = gen_74x164_get_function,
+ .xlate = gen_74x164_xlate,
+};
+
+static int gen_74x164_probe(struct udevice *dev)
+{
+ struct gen_74x164_priv *priv = dev_get_priv(dev);
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ char *str, name[32];
+ int ret;
+ const void *fdt = gd->fdt_blob;
+ int node = dev->of_offset;
+
+ snprintf(name, sizeof(name), "%s_", dev->name);
+ str = strdup(name);
+ if (!str)
+ return -ENOMEM;
+
+ /*
+ * See Linux kernel:
+ * Documentation/devicetree/bindings/gpio/gpio-74x164.txt
+ */
+ priv->nregs = fdtdec_get_int(fdt, node, "registers-number", 1);
+ priv->buffer = calloc(priv->nregs, sizeof(u8));
+ if (!priv->buffer) {
+ ret = -ENOMEM;
+ goto free_str;
+ }
+
+ ret = fdtdec_get_byte_array(fdt, node, "registers-default",
+ priv->buffer, priv->nregs);
+ if (ret)
+ dev_dbg(dev, "No registers-default property\n");
+
+ ret = gpio_request_by_name(dev, "oe-gpios", 0, &priv->oe,
+ GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+ if (ret) {
+ dev_err(dev, "No oe-pins property\n");
+ goto free_buf;
+ }
+
+ uc_priv->bank_name = str;
+ uc_priv->gpio_count = priv->nregs * 8;
+
+ ret = gen_74x164_write_conf(dev);
+ if (ret)
+ goto free_buf;
+
+ dev_dbg(dev, "%s is ready\n", dev->name);
+
+ return 0;
+
+free_buf:
+ free(priv->buffer);
+free_str:
+ free(str);
+ return ret;
+}
+
+static const struct udevice_id gen_74x164_ids[] = {
+ { .compatible = "fairchild,74hc595" },
+ { }
+};
+
+U_BOOT_DRIVER(74x164) = {
+ .name = "74x164",
+ .id = UCLASS_GPIO,
+ .ops = &gen_74x164_ops,
+ .probe = gen_74x164_probe,
+ .priv_auto_alloc_size = sizeof(struct gen_74x164_priv),
+ .of_match = gen_74x164_ids,
+};
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 2b4624d..93a7e8c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -143,4 +143,34 @@ config ZYNQ_GPIO
help
Supports GPIO access on Zynq SoC.
+config DM_74X164
+ bool "74x164 serial-in/parallel-out 8-bits shift register"
+ depends on DM_GPIO
+ help
+ Driver for 74x164 compatible serial-in/parallel-out 8-outputs
+ shift registers, such as 74lv165, 74hc595.
+ This driver can be used to provide access to more gpio outputs.
+
+config DM_PCA953X
+ bool "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports"
+ depends on DM_GPIO
+ help
+ Say yes here to provide access to several register-oriented
+ SMBus I/O expanders, made mostly by NXP or TI. Compatible
+ models include:
+
+ 4 bits: pca9536, pca9537
+
+ 8 bits: max7310, max7315, pca6107, pca9534, pca9538, pca9554,
+ pca9556, pca9557, pca9574, tca6408, xra1202
+
+ 16 bits: max7312, max7313, pca9535, pca9539, pca9555, pca9575,
+ tca6416
+
+ 24 bits: tca6424
+
+ 40 bits: pca9505, pca9698
+
+ Now, max 24 bits chips and PCA953X compatible chips are
+ supported
endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 4f071c4..ddec1ef 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -11,6 +11,9 @@ obj-$(CONFIG_AXP_GPIO) += axp_gpio.o
endif
obj-$(CONFIG_DM_GPIO) += gpio-uclass.o
+obj-$(CONFIG_DM_PCA953X) += pca953x_gpio.o
+obj-$(CONFIG_DM_74X164) += 74x164_gpio.o
+
obj-$(CONFIG_AT91_GPIO) += at91_gpio.o
obj-$(CONFIG_ATMEL_PIO4) += atmel_pio4.o
obj-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index b58d4e6..732b6c2 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <dm.h>
+#include <dt-bindings/gpio/gpio.h>
#include <errno.h>
#include <fdtdec.h>
#include <malloc.h>
@@ -113,19 +114,33 @@ int gpio_lookup_name(const char *name, struct udevice **devp,
return 0;
}
+int gpio_xlate_offs_flags(struct udevice *dev,
+ struct gpio_desc *desc,
+ struct fdtdec_phandle_args *args)
+{
+ if (args->args_count < 1)
+ return -EINVAL;
+
+ desc->offset = args->args[0];
+
+ if (args->args_count < 2)
+ return 0;
+
+ if (args->args[1] & GPIO_ACTIVE_LOW)
+ desc->flags = GPIOD_ACTIVE_LOW;
+
+ return 0;
+}
+
static int gpio_find_and_xlate(struct gpio_desc *desc,
struct fdtdec_phandle_args *args)
{
struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
- /* Use the first argument as the offset by default */
- if (args->args_count > 0)
- desc->offset = args->args[0];
+ if (ops->xlate)
+ return ops->xlate(desc->dev, desc, args);
else
- desc->offset = -1;
- desc->flags = 0;
-
- return ops->xlate ? ops->xlate(desc->dev, desc, args) : 0;
+ return gpio_xlate_offs_flags(desc->dev, desc, args);
}
int dm_gpio_request(struct gpio_desc *desc, const char *label)
@@ -605,6 +620,7 @@ static int _gpio_request_by_name_nodev(const void *blob, int node,
desc->dev = NULL;
desc->offset = 0;
+ desc->flags = 0;
ret = fdtdec_parse_phandle_with_args(blob, node, list_name,
"#gpio-cells", 0, index, &args);
if (ret) {
diff --git a/drivers/gpio/intel_broadwell_gpio.c b/drivers/gpio/intel_broadwell_gpio.c
index 8cf76f9..81ce446 100644
--- a/drivers/gpio/intel_broadwell_gpio.c
+++ b/drivers/gpio/intel_broadwell_gpio.c
@@ -162,15 +162,6 @@ static int broadwell_gpio_ofdata_to_platdata(struct udevice *dev)
return 0;
}
-static int broadwell_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
- struct fdtdec_phandle_args *args)
-{
- desc->offset = args->args[0];
- desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
-
- return 0;
-}
-
static const struct dm_gpio_ops gpio_broadwell_ops = {
.request = broadwell_gpio_request,
.direction_input = broadwell_gpio_direction_input,
@@ -178,7 +169,6 @@ static const struct dm_gpio_ops gpio_broadwell_ops = {
.get_value = broadwell_gpio_get_value,
.set_value = broadwell_gpio_set_value,
.get_function = broadwell_gpio_get_function,
- .xlate = broadwell_gpio_xlate,
};
static const struct udevice_id intel_broadwell_gpio_ids[] = {
diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c
index 93d18e4..cd960dc 100644
--- a/drivers/gpio/omap_gpio.c
+++ b/drivers/gpio/omap_gpio.c
@@ -25,7 +25,6 @@
#include <asm/io.h>
#include <asm/errno.h>
#include <malloc.h>
-#include <dt-bindings/gpio/gpio.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -277,22 +276,12 @@ static int omap_gpio_get_function(struct udevice *dev, unsigned offset)
return GPIOF_INPUT;
}
-static int omap_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
- struct fdtdec_phandle_args *args)
-{
- desc->offset = args->args[0];
- desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
-
- return 0;
-}
-
static const struct dm_gpio_ops gpio_omap_ops = {
.direction_input = omap_gpio_direction_input,
.direction_output = omap_gpio_direction_output,
.get_value = omap_gpio_get_value,
.set_value = omap_gpio_set_value,
.get_function = omap_gpio_get_function,
- .xlate = omap_gpio_xlate,
};
static int omap_gpio_probe(struct udevice *dev)
diff --git a/drivers/gpio/pca953x_gpio.c b/drivers/gpio/pca953x_gpio.c
new file mode 100644
index 0000000..987d10e
--- /dev/null
+++ b/drivers/gpio/pca953x_gpio.c
@@ -0,0 +1,351 @@
+/*
+ * Take linux kernel driver drivers/gpio/gpio-pca953x.c for reference.
+ *
+ * Copyright (C) 2016 Peng Fan <van.freenix@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ */
+
+/*
+ * Note:
+ * The driver's compatible table is borrowed from Linux Kernel,
+ * but now max supported gpio pins is 24 and only PCA953X_TYPE
+ * is supported. PCA957X_TYPE is not supported now.
+ * Also the Polarity Inversion feature is not supported now.
+ *
+ * TODO:
+ * 1. Support PCA957X_TYPE
+ * 2. Support max 40 gpio pins
+ * 3. Support Plolarity Inversion
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <malloc.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <dt-bindings/gpio/gpio.h>
+
+#define PCA953X_INPUT 0
+#define PCA953X_OUTPUT 1
+#define PCA953X_INVERT 2
+#define PCA953X_DIRECTION 3
+
+#define PCA_GPIO_MASK 0x00FF
+#define PCA_INT 0x0100
+#define PCA953X_TYPE 0x1000
+#define PCA957X_TYPE 0x2000
+#define PCA_TYPE_MASK 0xF000
+#define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK)
+
+enum {
+ PCA953X_DIRECTION_IN,
+ PCA953X_DIRECTION_OUT,
+};
+
+#define MAX_BANK 3
+#define BANK_SZ 8
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * struct pca953x_info - Data for pca953x
+ *
+ * @dev: udevice structure for the device
+ * @addr: i2c slave address
+ * @invert: Polarity inversion or not
+ * @gpio_count: the number of gpio pins that the device supports
+ * @chip_type: indicate the chip type,PCA953X or PCA957X
+ * @bank_count: the number of banks that the device supports
+ * @reg_output: array to hold the value of output registers
+ * @reg_direction: array to hold the value of direction registers
+ */
+struct pca953x_info {
+ struct udevice *dev;
+ int addr;
+ int invert;
+ int gpio_count;
+ int chip_type;
+ int bank_count;
+ u8 reg_output[MAX_BANK];
+ u8 reg_direction[MAX_BANK];
+};
+
+static int pca953x_write_single(struct udevice *dev, int reg, u8 val,
+ int offset)
+{
+ struct pca953x_info *info = dev_get_platdata(dev);
+ int bank_shift = fls((info->gpio_count - 1) / BANK_SZ);
+ int off = offset / BANK_SZ;
+ int ret = 0;
+
+ ret = dm_i2c_write(dev, (reg << bank_shift) + off, &val, 1);
+ if (ret) {
+ dev_err(dev, "%s error\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pca953x_read_single(struct udevice *dev, int reg, u8 *val,
+ int offset)
+{
+ struct pca953x_info *info = dev_get_platdata(dev);
+ int bank_shift = fls((info->gpio_count - 1) / BANK_SZ);
+ int off = offset / BANK_SZ;
+ int ret;
+ u8 byte;
+
+ ret = dm_i2c_read(dev, (reg << bank_shift) + off, &byte, 1);
+ if (ret) {
+ dev_err(dev, "%s error\n", __func__);
+ return ret;
+ }
+
+ *val = byte;
+
+ return 0;
+}
+
+static int pca953x_read_regs(struct udevice *dev, int reg, u8 *val)
+{
+ struct pca953x_info *info = dev_get_platdata(dev);
+ int ret = 0;
+
+ if (info->gpio_count <= 8) {
+ ret = dm_i2c_read(dev, reg, val, 1);
+ } else if (info->gpio_count <= 16) {
+ ret = dm_i2c_read(dev, reg << 1, val, info->bank_count);
+ } else {
+ dev_err(dev, "Unsupported now\n");
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int pca953x_is_output(struct udevice *dev, int offset)
+{
+ struct pca953x_info *info = dev_get_platdata(dev);
+
+ int bank = offset / BANK_SZ;
+ int off = offset % BANK_SZ;
+
+ /*0: output; 1: input */
+ return !(info->reg_direction[bank] & (1 << off));
+}
+
+static int pca953x_get_value(struct udevice *dev, unsigned offset)
+{
+ int ret;
+ u8 val = 0;
+
+ ret = pca953x_read_single(dev, PCA953X_INPUT, &val, offset);
+ if (ret)
+ return ret;
+
+ return (val >> offset) & 0x1;
+}
+
+static int pca953x_set_value(struct udevice *dev, unsigned offset,
+ int value)
+{
+ struct pca953x_info *info = dev_get_platdata(dev);
+ int bank = offset / BANK_SZ;
+ int off = offset % BANK_SZ;
+ u8 val;
+ int ret;
+
+ if (value)
+ val = info->reg_output[bank] | (1 << off);
+ else
+ val = info->reg_output[bank] & ~(1 << off);
+
+ ret = pca953x_write_single(dev, PCA953X_OUTPUT, val, offset);
+ if (ret)
+ return ret;
+
+ info->reg_output[bank] = val;
+
+ return 0;
+}
+
+static int pca953x_set_direction(struct udevice *dev, unsigned offset, int dir)
+{
+ struct pca953x_info *info = dev_get_platdata(dev);
+ int bank = offset / BANK_SZ;
+ int off = offset % BANK_SZ;
+ u8 val;
+ int ret;
+
+ if (dir == PCA953X_DIRECTION_IN)
+ val = info->reg_direction[bank] | (1 << off);
+ else
+ val = info->reg_direction[bank] & ~(1 << off);
+
+ ret = pca953x_write_single(dev, PCA953X_DIRECTION, val, offset);
+ if (ret)
+ return ret;
+
+ info->reg_direction[bank] = val;
+
+ return 0;
+}
+
+static int pca953x_direction_input(struct udevice *dev, unsigned offset)
+{
+ return pca953x_set_direction(dev, offset, PCA953X_DIRECTION_IN);
+}
+
+static int pca953x_direction_output(struct udevice *dev, unsigned offset,
+ int value)
+{
+ /* Configure output value. */
+ pca953x_set_value(dev, offset, value);
+
+ /* Configure direction as output. */
+ pca953x_set_direction(dev, offset, PCA953X_DIRECTION_OUT);
+
+ return 0;
+}
+
+static int pca953x_get_function(struct udevice *dev, unsigned offset)
+{
+ if (pca953x_is_output(dev, offset))
+ return GPIOF_OUTPUT;
+ else
+ return GPIOF_INPUT;
+}
+
+static int pca953x_xlate(struct udevice *dev, struct gpio_desc *desc,
+ struct fdtdec_phandle_args *args)
+{
+ desc->offset = args->args[0];
+ desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
+
+ return 0;
+}
+
+static const struct dm_gpio_ops pca953x_ops = {
+ .direction_input = pca953x_direction_input,
+ .direction_output = pca953x_direction_output,
+ .get_value = pca953x_get_value,
+ .set_value = pca953x_set_value,
+ .get_function = pca953x_get_function,
+ .xlate = pca953x_xlate,
+};
+
+static int pca953x_probe(struct udevice *dev)
+{
+ struct pca953x_info *info = dev_get_platdata(dev);
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
+ char name[32], *str;
+ int addr;
+ ulong driver_data;
+ int ret;
+
+ if (!info) {
+ dev_err(dev, "platdata not ready\n");
+ return -ENOMEM;
+ }
+
+ if (!chip) {
+ dev_err(dev, "i2c not ready\n");
+ return -ENODEV;
+ }
+
+ addr = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", 0);
+ if (addr == 0)
+ return -ENODEV;
+
+ info->addr = addr;
+
+ driver_data = dev_get_driver_data(dev);
+
+ info->gpio_count = driver_data & PCA_GPIO_MASK;
+ if (info->gpio_count > MAX_BANK * BANK_SZ) {
+ dev_err(dev, "Max support %d pins now\n", MAX_BANK * BANK_SZ);
+ return -EINVAL;
+ }
+
+ info->chip_type = PCA_CHIP_TYPE(driver_data);
+ if (info->chip_type != PCA953X_TYPE) {
+ dev_err(dev, "Only support PCA953X chip type now.\n");
+ return -EINVAL;
+ }
+
+ info->bank_count = DIV_ROUND_UP(info->gpio_count, BANK_SZ);
+
+ ret = pca953x_read_regs(dev, PCA953X_OUTPUT, info->reg_output);
+ if (ret) {
+ dev_err(dev, "Error reading output register\n");
+ return ret;
+ }
+
+ ret = pca953x_read_regs(dev, PCA953X_DIRECTION, info->reg_direction);
+ if (ret) {
+ dev_err(dev, "Error reading direction register\n");
+ return ret;
+ }
+
+ snprintf(name, sizeof(name), "gpio@%x_", info->addr);
+ str = strdup(name);
+ if (!str)
+ return -ENOMEM;
+ uc_priv->bank_name = str;
+ uc_priv->gpio_count = info->gpio_count;
+
+ dev_dbg(dev, "%s is ready\n", str);
+
+ return 0;
+}
+
+#define OF_953X(__nrgpio, __int) (ulong)(__nrgpio | PCA953X_TYPE | __int)
+#define OF_957X(__nrgpio, __int) (ulong)(__nrgpio | PCA957X_TYPE | __int)
+
+static const struct udevice_id pca953x_ids[] = {
+ { .compatible = "nxp,pca9505", .data = OF_953X(40, PCA_INT), },
+ { .compatible = "nxp,pca9534", .data = OF_953X(8, PCA_INT), },
+ { .compatible = "nxp,pca9535", .data = OF_953X(16, PCA_INT), },
+ { .compatible = "nxp,pca9536", .data = OF_953X(4, 0), },
+ { .compatible = "nxp,pca9537", .data = OF_953X(4, PCA_INT), },
+ { .compatible = "nxp,pca9538", .data = OF_953X(8, PCA_INT), },
+ { .compatible = "nxp,pca9539", .data = OF_953X(16, PCA_INT), },
+ { .compatible = "nxp,pca9554", .data = OF_953X(8, PCA_INT), },
+ { .compatible = "nxp,pca9555", .data = OF_953X(16, PCA_INT), },
+ { .compatible = "nxp,pca9556", .data = OF_953X(8, 0), },
+ { .compatible = "nxp,pca9557", .data = OF_953X(8, 0), },
+ { .compatible = "nxp,pca9574", .data = OF_957X(8, PCA_INT), },
+ { .compatible = "nxp,pca9575", .data = OF_957X(16, PCA_INT), },
+ { .compatible = "nxp,pca9698", .data = OF_953X(40, 0), },
+
+ { .compatible = "maxim,max7310", .data = OF_953X(8, 0), },
+ { .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), },
+ { .compatible = "maxim,max7313", .data = OF_953X(16, PCA_INT), },
+ { .compatible = "maxim,max7315", .data = OF_953X(8, PCA_INT), },
+
+ { .compatible = "ti,pca6107", .data = OF_953X(8, PCA_INT), },
+ { .compatible = "ti,tca6408", .data = OF_953X(8, PCA_INT), },
+ { .compatible = "ti,tca6416", .data = OF_953X(16, PCA_INT), },
+ { .compatible = "ti,tca6424", .data = OF_953X(24, PCA_INT), },
+
+ { .compatible = "onsemi,pca9654", .data = OF_953X(8, PCA_INT), },
+
+ { .compatible = "exar,xra1202", .data = OF_953X(8, 0), },
+ { }
+};
+
+U_BOOT_DRIVER(pca953x) = {
+ .name = "pca953x",
+ .id = UCLASS_GPIO,
+ .ops = &pca953x_ops,
+ .probe = pca953x_probe,
+ .platdata_auto_alloc_size = sizeof(struct pca953x_info),
+ .of_match = pca953x_ids,
+};
diff --git a/drivers/gpio/pic32_gpio.c b/drivers/gpio/pic32_gpio.c
index 499b4fa..7a037f3 100644
--- a/drivers/gpio/pic32_gpio.c
+++ b/drivers/gpio/pic32_gpio.c
@@ -12,7 +12,6 @@
#include <asm/io.h>
#include <asm/gpio.h>
#include <linux/compat.h>
-#include <dt-bindings/gpio/gpio.h>
#include <mach/pic32.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -99,14 +98,6 @@ static int pic32_gpio_direction_output(struct udevice *dev,
return 0;
}
-static int pic32_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
- struct fdtdec_phandle_args *args)
-{
- desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
-
- return 0;
-}
-
static int pic32_gpio_get_function(struct udevice *dev, unsigned offset)
{
int ret = GPIOF_UNUSED;
@@ -131,7 +122,6 @@ static const struct dm_gpio_ops gpio_pic32_ops = {
.get_value = pic32_gpio_get_value,
.set_value = pic32_gpio_set_value,
.get_function = pic32_gpio_get_function,
- .xlate = pic32_gpio_xlate,
};
static int pic32_gpio_probe(struct udevice *dev)
diff --git a/drivers/gpio/rk_gpio.c b/drivers/gpio/rk_gpio.c
index 40e87bd..fefe3ca 100644
--- a/drivers/gpio/rk_gpio.c
+++ b/drivers/gpio/rk_gpio.c
@@ -16,7 +16,6 @@
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <dm/pinctrl.h>
-#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/clock/rk3288-cru.h>
enum {
@@ -98,15 +97,6 @@ static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset)
#endif
}
-static int rockchip_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
- struct fdtdec_phandle_args *args)
-{
- desc->offset = args->args[0];
- desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
-
- return 0;
-}
-
static int rockchip_gpio_probe(struct udevice *dev)
{
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
@@ -135,7 +125,6 @@ static const struct dm_gpio_ops gpio_rockchip_ops = {
.get_value = rockchip_gpio_get_value,
.set_value = rockchip_gpio_set_value,
.get_function = rockchip_gpio_get_function,
- .xlate = rockchip_gpio_xlate,
};
static const struct udevice_id rockchip_gpio_ids[] = {
diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c
index 0f22b23..377fed4 100644
--- a/drivers/gpio/s5p_gpio.c
+++ b/drivers/gpio/s5p_gpio.c
@@ -13,7 +13,6 @@
#include <asm/io.h>
#include <asm/gpio.h>
#include <dm/device-internal.h>
-#include <dt-bindings/gpio/gpio.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -276,22 +275,12 @@ static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
return GPIOF_FUNC;
}
-static int exynos_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
- struct fdtdec_phandle_args *args)
-{
- desc->offset = args->args[0];
- desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
-
- return 0;
-}
-
static const struct dm_gpio_ops gpio_exynos_ops = {
.direction_input = exynos_gpio_direction_input,
.direction_output = exynos_gpio_direction_output,
.get_value = exynos_gpio_get_value,
.set_value = exynos_gpio_set_value,
.get_function = exynos_gpio_get_function,
- .xlate = exynos_gpio_xlate,
};
static int gpio_exynos_probe(struct udevice *dev)
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 4d3df11..c80efc3 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -2,7 +2,7 @@ menu "MMC Host controller Support"
config MMC
bool "Enable MMC support"
- depends on ARCH_SUNXI
+ depends on ARCH_SUNXI || SANDBOX
help
TODO: Move all architectures to use this option
@@ -58,4 +58,13 @@ config MMC_UNIPHIER
help
This selects support for the SD/MMC Host Controller on UniPhier SoCs.
+config SANDBOX_MMC
+ bool "Sandbox MMC support"
+ depends on MMC && SANDBOX
+ help
+ This select a dummy sandbox MMC driver. At present this does nothing
+ other than allow sandbox to be build with MMC support. This
+ improves build coverage for sandbox and makes it easier to detect
+ MMC build errors with sandbox.
+
endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 585aaf3..3da4817 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -5,7 +5,13 @@
# SPDX-License-Identifier: GPL-2.0+
#
-obj-$(CONFIG_DM_MMC) += mmc-uclass.o
+ifdef CONFIG_DM_MMC
+obj-$(CONFIG_GENERIC_MMC) += mmc-uclass.o
+endif
+
+ifndef CONFIG_BLK
+obj-$(CONFIG_GENERIC_MMC) += mmc_legacy.o
+endif
obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o
obj-$(CONFIG_ATMEL_SDHCI) += atmel_sdhci.o
@@ -34,7 +40,11 @@ obj-$(CONFIG_ROCKCHIP_DWMMC) += rockchip_dw_mmc.o
obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
obj-$(CONFIG_S3C_SDI) += s3c_sdi.o
obj-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
+ifdef CONFIG_BLK
+ifdef CONFIG_GENERIC_MMC
obj-$(CONFIG_SANDBOX) += sandbox_mmc.o
+endif
+endif
obj-$(CONFIG_SDHCI) += sdhci.o
obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 777489f..1b967d9 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -21,6 +21,112 @@ struct mmc *mmc_get_mmc_dev(struct udevice *dev)
return upriv->mmc;
}
+#ifdef CONFIG_BLK
+struct mmc *find_mmc_device(int dev_num)
+{
+ struct udevice *dev, *mmc_dev;
+ int ret;
+
+ ret = blk_get_device(IF_TYPE_MMC, dev_num, &dev);
+
+ if (ret) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
+ printf("MMC Device %d not found\n", dev_num);
+#endif
+ return NULL;
+ }
+
+ mmc_dev = dev_get_parent(dev);
+
+ return mmc_get_mmc_dev(mmc_dev);
+}
+
+int get_mmc_num(void)
+{
+ return max(blk_find_max_devnum(IF_TYPE_MMC), 0);
+}
+
+int mmc_get_next_devnum(void)
+{
+ int ret;
+
+ ret = get_mmc_num();
+ if (ret < 0)
+ return ret;
+
+ return ret + 1;
+}
+
+struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
+{
+ struct blk_desc *desc;
+ struct udevice *dev;
+
+ device_find_first_child(mmc->dev, &dev);
+ if (!dev)
+ return NULL;
+ desc = dev_get_uclass_platdata(dev);
+
+ return desc;
+}
+
+void mmc_do_preinit(void)
+{
+ struct udevice *dev;
+ struct uclass *uc;
+ int ret;
+
+ ret = uclass_get(UCLASS_MMC, &uc);
+ if (ret)
+ return;
+ uclass_foreach_dev(dev, uc) {
+ struct mmc *m = mmc_get_mmc_dev(dev);
+
+ if (!m)
+ continue;
+#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
+ mmc_set_preinit(m, 1);
+#endif
+ if (m->preinit)
+ mmc_start_init(m);
+ }
+}
+
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
+void print_mmc_devices(char separator)
+{
+ struct udevice *dev;
+ char *mmc_type;
+ bool first = true;
+
+ for (uclass_first_device(UCLASS_MMC, &dev);
+ dev;
+ uclass_next_device(&dev)) {
+ struct mmc *m = mmc_get_mmc_dev(dev);
+
+ if (!first) {
+ printf("%c", separator);
+ if (separator != '\n')
+ puts(" ");
+ }
+ if (m->has_init)
+ mmc_type = IS_SD(m) ? "SD" : "eMMC";
+ else
+ mmc_type = NULL;
+
+ printf("%s: %d", m->cfg->name, mmc_get_blk_desc(m)->devnum);
+ if (mmc_type)
+ printf(" (%s)", mmc_type);
+ }
+
+ printf("\n");
+}
+
+#else
+void print_mmc_devices(char separator) { }
+#endif
+#endif /* CONFIG_BLK */
+
U_BOOT_DRIVER(mmc) = {
.name = "mmc",
.id = UCLASS_MMC,
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index d3c22ab..74b3d68 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -21,9 +21,6 @@
#include <div64.h>
#include "mmc_private.h"
-static struct list_head mmc_devices;
-static int cur_dev_num = -1;
-
__weak int board_mmc_getwp(struct mmc *mmc)
{
return -1;
@@ -178,25 +175,6 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
return mmc_send_cmd(mmc, &cmd, NULL);
}
-struct mmc *find_mmc_device(int dev_num)
-{
- struct mmc *m;
- struct list_head *entry;
-
- list_for_each(entry, &mmc_devices) {
- m = list_entry(entry, struct mmc, link);
-
- if (m->block_dev.devnum == dev_num)
- return m;
- }
-
-#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
- printf("MMC Device %d not found\n", dev_num);
-#endif
-
- return NULL;
-}
-
static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
lbaint_t blkcnt)
{
@@ -238,9 +216,17 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
return blkcnt;
}
+#ifdef CONFIG_BLK
+static ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
+ void *dst)
+#else
static ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start,
lbaint_t blkcnt, void *dst)
+#endif
{
+#ifdef CONFIG_BLK
+ struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
+#endif
int dev_num = block_dev->devnum;
int err;
lbaint_t cur, blocks_todo = blkcnt;
@@ -252,14 +238,14 @@ static ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start,
if (!mmc)
return 0;
- err = mmc_select_hwpart(dev_num, block_dev->hwpart);
+ err = blk_dselect_hwpart(block_dev, block_dev->hwpart);
if (err < 0)
return 0;
- if ((start + blkcnt) > mmc->block_dev.lba) {
+ if ((start + blkcnt) > block_dev->lba) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
- start + blkcnt, mmc->block_dev.lba);
+ start + blkcnt, block_dev->lba);
#endif
return 0;
}
@@ -577,58 +563,73 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num)
return -1;
}
- mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
+ mmc_get_blk_desc(mmc)->lba = lldiv(mmc->capacity, mmc->read_bl_len);
return 0;
}
-int mmc_select_hwpart(int dev_num, int hwpart)
+static int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
{
- struct mmc *mmc = find_mmc_device(dev_num);
int ret;
- if (!mmc)
- return -ENODEV;
+ ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
+ (mmc->part_config & ~PART_ACCESS_MASK)
+ | (part_num & PART_ACCESS_MASK));
- if (mmc->block_dev.hwpart == hwpart)
+ /*
+ * Set the capacity if the switch succeeded or was intended
+ * to return to representing the raw device.
+ */
+ if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0))) {
+ ret = mmc_set_capacity(mmc, part_num);
+ mmc_get_blk_desc(mmc)->hwpart = part_num;
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_BLK
+static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
+{
+ struct udevice *mmc_dev = dev_get_parent(bdev);
+ struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
+ struct blk_desc *desc = dev_get_uclass_platdata(bdev);
+ int ret;
+
+ if (desc->hwpart == hwpart)
return 0;
- if (mmc->part_config == MMCPART_NOAVAILABLE) {
- printf("Card doesn't support part_switch\n");
+ if (mmc->part_config == MMCPART_NOAVAILABLE)
return -EMEDIUMTYPE;
- }
- ret = mmc_switch_part(dev_num, hwpart);
+ ret = mmc_switch_part(mmc, hwpart);
if (ret)
return ret;
return 0;
}
-
-
-int mmc_switch_part(int dev_num, unsigned int part_num)
+#else
+static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
{
- struct mmc *mmc = find_mmc_device(dev_num);
+ struct mmc *mmc = find_mmc_device(desc->devnum);
int ret;
if (!mmc)
- return -1;
+ return -ENODEV;
- ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
- (mmc->part_config & ~PART_ACCESS_MASK)
- | (part_num & PART_ACCESS_MASK));
+ if (mmc->block_dev.hwpart == hwpart)
+ return 0;
- /*
- * Set the capacity if the switch succeeded or was intended
- * to return to representing the raw device.
- */
- if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0))) {
- ret = mmc_set_capacity(mmc, part_num);
- mmc->block_dev.hwpart = part_num;
- }
+ if (mmc->part_config == MMCPART_NOAVAILABLE)
+ return -EMEDIUMTYPE;
- return ret;
+ ret = mmc_switch_part(mmc, hwpart);
+ if (ret)
+ return ret;
+
+ return 0;
}
+#endif
int mmc_hwpart_config(struct mmc *mmc,
const struct mmc_hwpart_conf *conf,
@@ -1039,6 +1040,7 @@ static int mmc_startup(struct mmc *mmc)
int timeout = 1000;
bool has_parts = false;
bool part_completed;
+ struct blk_desc *bdesc;
#ifdef CONFIG_MMC_SPI_CRC_ON
if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
@@ -1335,7 +1337,7 @@ static int mmc_startup(struct mmc *mmc)
mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
}
- err = mmc_set_capacity(mmc, mmc->block_dev.hwpart);
+ err = mmc_set_capacity(mmc, mmc_get_blk_desc(mmc)->hwpart);
if (err)
return err;
@@ -1475,31 +1477,32 @@ static int mmc_startup(struct mmc *mmc)
}
/* fill in device description */
- mmc->block_dev.lun = 0;
- mmc->block_dev.hwpart = 0;
- mmc->block_dev.type = 0;
- mmc->block_dev.blksz = mmc->read_bl_len;
- mmc->block_dev.log2blksz = LOG2(mmc->block_dev.blksz);
- mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
+ bdesc = mmc_get_blk_desc(mmc);
+ bdesc->lun = 0;
+ bdesc->hwpart = 0;
+ bdesc->type = 0;
+ bdesc->blksz = mmc->read_bl_len;
+ bdesc->log2blksz = LOG2(bdesc->blksz);
+ bdesc->lba = lldiv(mmc->capacity, mmc->read_bl_len);
#if !defined(CONFIG_SPL_BUILD) || \
(defined(CONFIG_SPL_LIBCOMMON_SUPPORT) && \
!defined(CONFIG_USE_TINY_PRINTF))
- sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x",
+ sprintf(bdesc->vendor, "Man %06x Snr %04x%04x",
mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
(mmc->cid[3] >> 16) & 0xffff);
- sprintf(mmc->block_dev.product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff,
+ sprintf(bdesc->product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff,
(mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
(mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff,
(mmc->cid[2] >> 24) & 0xff);
- sprintf(mmc->block_dev.revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
+ sprintf(bdesc->revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
(mmc->cid[2] >> 16) & 0xf);
#else
- mmc->block_dev.vendor[0] = 0;
- mmc->block_dev.product[0] = 0;
- mmc->block_dev.revision[0] = 0;
+ bdesc->vendor[0] = 0;
+ bdesc->product[0] = 0;
+ bdesc->revision[0] = 0;
#endif
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
- part_init(&mmc->block_dev);
+ part_init(bdesc);
#endif
return 0;
@@ -1537,8 +1540,55 @@ int __deprecated mmc_register(struct mmc *mmc)
return -1;
}
+#ifdef CONFIG_BLK
+int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
+{
+ struct blk_desc *bdesc;
+ struct udevice *bdev;
+ int ret;
+
+ ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512,
+ 0, &bdev);
+ if (ret) {
+ debug("Cannot create block device\n");
+ return ret;
+ }
+ bdesc = dev_get_uclass_platdata(bdev);
+ mmc->cfg = cfg;
+ mmc->priv = dev;
+
+ /* the following chunk was from mmc_register() */
+
+ /* Setup dsr related values */
+ mmc->dsr_imp = 0;
+ mmc->dsr = 0xffffffff;
+ /* Setup the universal parts of the block interface just once */
+ bdesc->removable = 1;
+
+ /* setup initial part type */
+ bdesc->part_type = mmc->cfg->part_type;
+ mmc->dev = dev;
+
+ return 0;
+}
+
+int mmc_unbind(struct udevice *dev)
+{
+ struct udevice *bdev;
+
+ device_find_first_child(dev, &bdev);
+ if (bdev) {
+ device_remove(bdev);
+ device_unbind(bdev);
+ }
+
+ return 0;
+}
+
+#else
struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
{
+ struct blk_desc *bdesc;
struct mmc *mmc;
/* quick validation */
@@ -1559,19 +1609,17 @@ struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
mmc->dsr_imp = 0;
mmc->dsr = 0xffffffff;
/* Setup the universal parts of the block interface just once */
- mmc->block_dev.if_type = IF_TYPE_MMC;
- mmc->block_dev.devnum = cur_dev_num++;
- mmc->block_dev.removable = 1;
- mmc->block_dev.block_read = mmc_bread;
- mmc->block_dev.block_write = mmc_bwrite;
- mmc->block_dev.block_erase = mmc_berase;
+ bdesc = mmc_get_blk_desc(mmc);
+ bdesc->if_type = IF_TYPE_MMC;
+ bdesc->removable = 1;
+ bdesc->devnum = mmc_get_next_devnum();
+ bdesc->block_read = mmc_bread;
+ bdesc->block_write = mmc_bwrite;
+ bdesc->block_erase = mmc_berase;
/* setup initial part type */
- mmc->block_dev.part_type = mmc->cfg->part_type;
-
- INIT_LIST_HEAD(&mmc->link);
-
- list_add_tail(&mmc->link, &mmc_devices);
+ bdesc->part_type = mmc->cfg->part_type;
+ mmc_list_add(mmc);
return mmc;
}
@@ -1581,15 +1629,23 @@ void mmc_destroy(struct mmc *mmc)
/* only freeing memory for now */
free(mmc);
}
+#endif
-#ifdef CONFIG_PARTITIONS
-struct blk_desc *mmc_get_dev(int dev)
+#ifndef CONFIG_BLK
+static int mmc_get_dev(int dev, struct blk_desc **descp)
{
struct mmc *mmc = find_mmc_device(dev);
- if (!mmc || mmc_init(mmc))
- return NULL;
+ int ret;
- return &mmc->block_dev;
+ if (!mmc)
+ return -ENODEV;
+ ret = mmc_init(mmc);
+ if (ret)
+ return ret;
+
+ *descp = &mmc->block_dev;
+
+ return 0;
}
#endif
@@ -1636,7 +1692,7 @@ int mmc_start_init(struct mmc *mmc)
return err;
/* The internal partition reset to user partition(0) at every CMD0*/
- mmc->block_dev.hwpart = 0;
+ mmc_get_blk_desc(mmc)->hwpart = 0;
/* Test for SD version 2 */
err = mmc_send_if_cond(mmc);
@@ -1683,7 +1739,11 @@ int mmc_init(struct mmc *mmc)
{
int err = 0;
unsigned start;
+#ifdef CONFIG_DM_MMC
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc->dev);
+ upriv->mmc = mmc;
+#endif
if (mmc->has_init)
return 0;
@@ -1716,66 +1776,11 @@ __weak int board_mmc_init(bd_t *bis)
return -1;
}
-#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
-
-void print_mmc_devices(char separator)
-{
- struct mmc *m;
- struct list_head *entry;
- char *mmc_type;
-
- list_for_each(entry, &mmc_devices) {
- m = list_entry(entry, struct mmc, link);
-
- if (m->has_init)
- mmc_type = IS_SD(m) ? "SD" : "eMMC";
- else
- mmc_type = NULL;
-
- printf("%s: %d", m->cfg->name, m->block_dev.devnum);
- if (mmc_type)
- printf(" (%s)", mmc_type);
-
- if (entry->next != &mmc_devices) {
- printf("%c", separator);
- if (separator != '\n')
- puts (" ");
- }
- }
-
- printf("\n");
-}
-
-#else
-void print_mmc_devices(char separator) { }
-#endif
-
-int get_mmc_num(void)
-{
- return cur_dev_num;
-}
-
void mmc_set_preinit(struct mmc *mmc, int preinit)
{
mmc->preinit = preinit;
}
-static void do_preinit(void)
-{
- struct mmc *m;
- struct list_head *entry;
-
- list_for_each(entry, &mmc_devices) {
- m = list_entry(entry, struct mmc, link);
-
-#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
- mmc_set_preinit(m, 1);
-#endif
- if (m->preinit)
- mmc_start_init(m);
- }
-}
-
#if defined(CONFIG_DM_MMC) && defined(CONFIG_SPL_BUILD)
static int mmc_probe(bd_t *bis)
{
@@ -1828,9 +1833,9 @@ int mmc_initialize(bd_t *bis)
return 0;
initialized = 1;
- INIT_LIST_HEAD (&mmc_devices);
- cur_dev_num = 0;
-
+#ifndef CONFIG_BLK
+ mmc_list_init();
+#endif
ret = mmc_probe(bis);
if (ret)
return ret;
@@ -1839,7 +1844,7 @@ int mmc_initialize(bd_t *bis)
print_mmc_devices(',');
#endif
- do_preinit();
+ mmc_do_preinit();
return 0;
}
@@ -1965,3 +1970,25 @@ int mmc_set_rst_n_function(struct mmc *mmc, u8 enable)
enable);
}
#endif
+
+#ifdef CONFIG_BLK
+static const struct blk_ops mmc_blk_ops = {
+ .read = mmc_bread,
+ .write = mmc_bwrite,
+ .select_hwpart = mmc_select_hwpart,
+};
+
+U_BOOT_DRIVER(mmc_blk) = {
+ .name = "mmc_blk",
+ .id = UCLASS_BLK,
+ .ops = &mmc_blk_ops,
+};
+#else
+U_BOOT_LEGACY_BLK(mmc) = {
+ .if_typename = "mmc",
+ .if_type = IF_TYPE_MMC,
+ .max_devs = -1,
+ .get_dev = mmc_get_dev,
+ .select_hwpart = mmc_select_hwpartp,
+};
+#endif
diff --git a/drivers/mmc/mmc_legacy.c b/drivers/mmc/mmc_legacy.c
new file mode 100644
index 0000000..3ec649f
--- /dev/null
+++ b/drivers/mmc/mmc_legacy.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+
+static struct list_head mmc_devices;
+static int cur_dev_num = -1;
+
+struct mmc *find_mmc_device(int dev_num)
+{
+ struct mmc *m;
+ struct list_head *entry;
+
+ list_for_each(entry, &mmc_devices) {
+ m = list_entry(entry, struct mmc, link);
+
+ if (m->block_dev.devnum == dev_num)
+ return m;
+ }
+
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
+ printf("MMC Device %d not found\n", dev_num);
+#endif
+
+ return NULL;
+}
+
+int mmc_get_next_devnum(void)
+{
+ return cur_dev_num++;
+}
+
+struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
+{
+ return &mmc->block_dev;
+}
+
+int get_mmc_num(void)
+{
+ return cur_dev_num;
+}
+
+void mmc_do_preinit(void)
+{
+ struct mmc *m;
+ struct list_head *entry;
+
+ list_for_each(entry, &mmc_devices) {
+ m = list_entry(entry, struct mmc, link);
+
+#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
+ mmc_set_preinit(m, 1);
+#endif
+ if (m->preinit)
+ mmc_start_init(m);
+ }
+}
+
+void mmc_list_init(void)
+{
+ INIT_LIST_HEAD(&mmc_devices);
+ cur_dev_num = 0;
+}
+
+void mmc_list_add(struct mmc *mmc)
+{
+ INIT_LIST_HEAD(&mmc->link);
+
+ list_add_tail(&mmc->link, &mmc_devices);
+}
+
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
+void print_mmc_devices(char separator)
+{
+ struct mmc *m;
+ struct list_head *entry;
+ char *mmc_type;
+
+ list_for_each(entry, &mmc_devices) {
+ m = list_entry(entry, struct mmc, link);
+
+ if (m->has_init)
+ mmc_type = IS_SD(m) ? "SD" : "eMMC";
+ else
+ mmc_type = NULL;
+
+ printf("%s: %d", m->cfg->name, m->block_dev.devnum);
+ if (mmc_type)
+ printf(" (%s)", mmc_type);
+
+ if (entry->next != &mmc_devices) {
+ printf("%c", separator);
+ if (separator != '\n')
+ puts(" ");
+ }
+ }
+
+ printf("\n");
+}
+
+#else
+void print_mmc_devices(char separator) { }
+#endif
diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h
index d3f6bfe..27b9e5f 100644
--- a/drivers/mmc/mmc_private.h
+++ b/drivers/mmc/mmc_private.h
@@ -25,8 +25,13 @@ void mmc_adapter_card_type_ident(void);
unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start,
lbaint_t blkcnt);
-unsigned long mmc_bwrite(struct blk_desc *block_dev, lbaint_t start,
- lbaint_t blkcnt, const void *src);
+#ifdef CONFIG_BLK
+ulong mmc_bwrite(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
+ const void *src);
+#else
+ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
+ const void *src);
+#endif
#else /* CONFIG_SPL_BUILD */
@@ -46,4 +51,28 @@ static inline ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start,
#endif /* CONFIG_SPL_BUILD */
+/**
+ * mmc_get_next_devnum() - Get the next available MMC device number
+ *
+ * @return next available device number (0 = first), or -ve on error
+ */
+int mmc_get_next_devnum(void);
+
+/**
+ * mmc_do_preinit() - Get an MMC device ready for use
+ */
+void mmc_do_preinit(void);
+
+/**
+ * mmc_list_init() - Set up the list of MMC devices
+ */
+void mmc_list_init(void);
+
+/**
+ * mmc_list_add() - Add a new MMC device to the list of devices
+ *
+ * @mmc: Device to add
+ */
+void mmc_list_add(struct mmc *mmc);
+
#endif /* _MMC_PRIVATE_H_ */
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index 7b186f8..0f8b5c7 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -9,6 +9,7 @@
#include <config.h>
#include <common.h>
+#include <dm.h>
#include <part.h>
#include <div64.h>
#include <linux/math64.h>
@@ -78,7 +79,8 @@ unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start,
if (!mmc)
return -1;
- err = mmc_select_hwpart(dev_num, block_dev->hwpart);
+ err = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_num,
+ block_dev->hwpart);
if (err < 0)
return -1;
@@ -121,9 +123,9 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
struct mmc_data data;
int timeout = 1000;
- if ((start + blkcnt) > mmc->block_dev.lba) {
+ if ((start + blkcnt) > mmc_get_blk_desc(mmc)->lba) {
printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
- start + blkcnt, mmc->block_dev.lba);
+ start + blkcnt, mmc_get_blk_desc(mmc)->lba);
return 0;
}
@@ -171,9 +173,17 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
return blkcnt;
}
+#ifdef CONFIG_BLK
+ulong mmc_bwrite(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
+ const void *src)
+#else
ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
const void *src)
+#endif
{
+#ifdef CONFIG_BLK
+ struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
+#endif
int dev_num = block_dev->devnum;
lbaint_t cur, blocks_todo = blkcnt;
int err;
@@ -182,7 +192,7 @@ ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
if (!mmc)
return 0;
- err = mmc_select_hwpart(dev_num, block_dev->hwpart);
+ err = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_num, block_dev->hwpart);
if (err < 0)
return 0;
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 85a832b..be34057 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -825,6 +825,7 @@ static int omap_hsmmc_probe(struct udevice *dev)
gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, GPIOD_IS_IN);
#endif
+ mmc->dev = dev;
upriv->mmc = mmc;
return 0;
diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c
index e03d6dd..abe7429 100644
--- a/drivers/mmc/pic32_sdhci.c
+++ b/drivers/mmc/pic32_sdhci.c
@@ -41,7 +41,12 @@ static int pic32_sdhci_probe(struct udevice *dev)
return ret;
}
- return add_sdhci(host, f_min_max[1], f_min_max[0]);
+ ret = add_sdhci(host, f_min_max[1], f_min_max[0]);
+ if (ret)
+ return ret;
+ host->mmc->dev = dev;
+
+ return 0;
}
static const struct udevice_id pic32_sdhci_ids[] = {
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index cb9e104..0a261c5 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -104,6 +104,7 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
if (ret)
return ret;
+ host->mmc->dev = dev;
upriv->mmc = host->mmc;
return 0;
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c
index f4646a8..7da059c 100644
--- a/drivers/mmc/sandbox_mmc.c
+++ b/drivers/mmc/sandbox_mmc.c
@@ -8,18 +8,150 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
+#include <fdtdec.h>
#include <mmc.h>
#include <asm/test.h>
DECLARE_GLOBAL_DATA_PTR;
+struct sandbox_mmc_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+};
+
+/**
+ * sandbox_mmc_send_cmd() - Emulate SD commands
+ *
+ * This emulate an SD card version 2. Single-block reads result in zero data.
+ * Multiple-block reads return a test string.
+ */
+static int sandbox_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ switch (cmd->cmdidx) {
+ case MMC_CMD_ALL_SEND_CID:
+ break;
+ case SD_CMD_SEND_RELATIVE_ADDR:
+ cmd->response[0] = 0 << 16; /* mmc->rca */
+ case MMC_CMD_GO_IDLE_STATE:
+ break;
+ case SD_CMD_SEND_IF_COND:
+ cmd->response[0] = 0xaa;
+ break;
+ case MMC_CMD_SEND_STATUS:
+ cmd->response[0] = MMC_STATUS_RDY_FOR_DATA;
+ break;
+ case MMC_CMD_SELECT_CARD:
+ break;
+ case MMC_CMD_SEND_CSD:
+ cmd->response[0] = 0;
+ cmd->response[1] = 10 << 16; /* 1 << block_len */
+ break;
+ case SD_CMD_SWITCH_FUNC: {
+ u32 *resp = (u32 *)data->dest;
+
+ resp[7] = cpu_to_be32(SD_HIGHSPEED_BUSY);
+ break;
+ }
+ case MMC_CMD_READ_SINGLE_BLOCK:
+ memset(data->dest, '\0', data->blocksize);
+ break;
+ case MMC_CMD_READ_MULTIPLE_BLOCK:
+ strcpy(data->dest, "this is a test");
+ break;
+ case MMC_CMD_STOP_TRANSMISSION:
+ break;
+ case SD_CMD_APP_SEND_OP_COND:
+ cmd->response[0] = OCR_BUSY | OCR_HCS;
+ cmd->response[1] = 0;
+ cmd->response[2] = 0;
+ break;
+ case MMC_CMD_APP_CMD:
+ break;
+ case MMC_CMD_SET_BLOCKLEN:
+ debug("block len %d\n", cmd->cmdarg);
+ break;
+ case SD_CMD_APP_SEND_SCR: {
+ u32 *scr = (u32 *)data->dest;
+
+ scr[0] = cpu_to_be32(2 << 24 | 1 << 15); /* SD version 3 */
+ break;
+ }
+ default:
+ debug("%s: Unknown command %d\n", __func__, cmd->cmdidx);
+ break;
+ }
+
+ return 0;
+}
+
+static void sandbox_mmc_set_ios(struct mmc *mmc)
+{
+}
+
+static int sandbox_mmc_init(struct mmc *mmc)
+{
+ return 0;
+}
+
+static int sandbox_mmc_getcd(struct mmc *mmc)
+{
+ return 1;
+}
+
+static const struct mmc_ops sandbox_mmc_ops = {
+ .send_cmd = sandbox_mmc_send_cmd,
+ .set_ios = sandbox_mmc_set_ios,
+ .init = sandbox_mmc_init,
+ .getcd = sandbox_mmc_getcd,
+};
+
+int sandbox_mmc_probe(struct udevice *dev)
+{
+ struct sandbox_mmc_plat *plat = dev_get_platdata(dev);
+
+ return mmc_init(&plat->mmc);
+}
+
+int sandbox_mmc_bind(struct udevice *dev)
+{
+ struct sandbox_mmc_plat *plat = dev_get_platdata(dev);
+ struct mmc_config *cfg = &plat->cfg;
+ int ret;
+
+ cfg->name = dev->name;
+ cfg->ops = &sandbox_mmc_ops;
+ cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_8BIT;
+ cfg->voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
+ cfg->f_min = 1000000;
+ cfg->f_max = 52000000;
+ cfg->b_max = U32_MAX;
+
+ ret = mmc_bind(dev, &plat->mmc, cfg);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int sandbox_mmc_unbind(struct udevice *dev)
+{
+ mmc_unbind(dev);
+
+ return 0;
+}
+
static const struct udevice_id sandbox_mmc_ids[] = {
{ .compatible = "sandbox,mmc" },
{ }
};
-U_BOOT_DRIVER(warm_mmc_sandbox) = {
+U_BOOT_DRIVER(mmc_sandbox) = {
.name = "mmc_sandbox",
.id = UCLASS_MMC,
.of_match = sandbox_mmc_ids,
+ .bind = sandbox_mmc_bind,
+ .unbind = sandbox_mmc_unbind,
+ .probe = sandbox_mmc_probe,
+ .platdata_auto_alloc_size = sizeof(struct sandbox_mmc_plat),
};
diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c
index 097db81..6a0e971 100644
--- a/drivers/mmc/socfpga_dw_mmc.c
+++ b/drivers/mmc/socfpga_dw_mmc.c
@@ -108,6 +108,7 @@ static int socfpga_dwmmc_probe(struct udevice *dev)
return ret;
upriv->mmc = host->mmc;
+ host->mmc->dev = dev;
return 0;
}
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
index 81a80cd..4978cca 100644
--- a/drivers/mmc/uniphier-sd.c
+++ b/drivers/mmc/uniphier-sd.c
@@ -725,6 +725,7 @@ int uniphier_sd_probe(struct udevice *dev)
return -EIO;
upriv->mmc = priv->mmc;
+ priv->mmc->dev = dev;
return 0;
}
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index b59feca..d405929 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -35,6 +35,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
CONFIG_ZYNQ_SDHCI_MIN_FREQ);
upriv->mmc = host->mmc;
+ host->mmc->dev = dev;
return 0;
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 4619089..4b73a0f 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -175,11 +175,7 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
int bus;
for (hose = pci_get_hose_head(); hose; hose = hose->next) {
-#ifdef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE
- for (bus = hose->last_busno; bus >= hose->first_busno; bus--) {
-#else
for (bus = hose->first_busno; bus <= hose->last_busno; bus++) {
-#endif
bdf = pci_hose_find_devices(hose, bus, ids, &index);
if (bdf != -1)
return bdf;
diff --git a/drivers/serial/mcfuart.c b/drivers/serial/mcfuart.c
index 407354f..059cb0f 100644
--- a/drivers/serial/mcfuart.c
+++ b/drivers/serial/mcfuart.c
@@ -2,6 +2,9 @@
* (C) Copyright 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew, Tsi-Chung.Liew@freescale.com.
*
+ * Modified to add device model (DM) support
+ * (C) Copyright 2015 Angelo Dureghello <angelo@sysam.it>
+ *
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -11,9 +14,10 @@
*/
#include <common.h>
+#include <dm.h>
+#include <dm/platform_data/serial_coldfire.h>
#include <serial.h>
#include <linux/compiler.h>
-
#include <asm/immap.h>
#include <asm/uart.h>
@@ -21,91 +25,110 @@ DECLARE_GLOBAL_DATA_PTR;
extern void uart_port_conf(int port);
-static int mcf_serial_init(void)
+static int mcf_serial_init_common(uart_t *uart, int port_idx, int baudrate)
{
- volatile uart_t *uart;
u32 counter;
- uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
-
- uart_port_conf(CONFIG_SYS_UART_PORT);
+ uart_port_conf(port_idx);
/* write to SICR: SIM2 = uart mode,dcd does not affect rx */
- uart->ucr = UART_UCR_RESET_RX;
- uart->ucr = UART_UCR_RESET_TX;
- uart->ucr = UART_UCR_RESET_ERROR;
- uart->ucr = UART_UCR_RESET_MR;
+ writeb(UART_UCR_RESET_RX, &uart->ucr);
+ writeb(UART_UCR_RESET_TX, &uart->ucr);
+ writeb(UART_UCR_RESET_ERROR, &uart->ucr);
+ writeb(UART_UCR_RESET_MR, &uart->ucr);
__asm__("nop");
- uart->uimr = 0;
+ writeb(0, &uart->uimr);
/* write to CSR: RX/TX baud rate from timers */
- uart->ucsr = (UART_UCSR_RCS_SYS_CLK | UART_UCSR_TCS_SYS_CLK);
+ writeb(UART_UCSR_RCS_SYS_CLK | UART_UCSR_TCS_SYS_CLK, &uart->ucsr);
- uart->umr = (UART_UMR_BC_8 | UART_UMR_PM_NONE);
- uart->umr = UART_UMR_SB_STOP_BITS_1;
+ writeb(UART_UMR_BC_8 | UART_UMR_PM_NONE, &uart->umr);
+ writeb(UART_UMR_SB_STOP_BITS_1, &uart->umr);
/* Setting up BaudRate */
- counter = (u32) ((gd->bus_clk / 32) + (gd->baudrate / 2));
- counter = counter / gd->baudrate;
+ counter = (u32) ((gd->bus_clk / 32) + (baudrate / 2));
+ counter = counter / baudrate;
/* write to CTUR: divide counter upper byte */
- uart->ubg1 = (u8) ((counter & 0xff00) >> 8);
+ writeb((u8)((counter & 0xff00) >> 8), &uart->ubg1);
/* write to CTLR: divide counter lower byte */
- uart->ubg2 = (u8) (counter & 0x00ff);
+ writeb((u8)(counter & 0x00ff), &uart->ubg2);
- uart->ucr = (UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED);
+ writeb(UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED, &uart->ucr);
return (0);
}
+static void mcf_serial_setbrg_common(uart_t *uart, int baudrate)
+{
+ u32 counter;
+
+ /* Setting up BaudRate */
+ counter = (u32) ((gd->bus_clk / 32) + (baudrate / 2));
+ counter = counter / baudrate;
+
+ /* write to CTUR: divide counter upper byte */
+ writeb(((counter & 0xff00) >> 8), &uart->ubg1);
+ /* write to CTLR: divide counter lower byte */
+ writeb((counter & 0x00ff), &uart->ubg2);
+
+ writeb(UART_UCR_RESET_RX, &uart->ucr);
+ writeb(UART_UCR_RESET_TX, &uart->ucr);
+
+ writeb(UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED, &uart->ucr);
+}
+
+#ifndef CONFIG_DM_SERIAL
+
+static int mcf_serial_init(void)
+{
+ uart_t *uart_base;
+ int port_idx;
+
+ uart_base = (uart_t *)CONFIG_SYS_UART_BASE;
+ port_idx = CONFIG_SYS_UART_PORT;
+
+ return mcf_serial_init_common(uart_base, port_idx, gd->baudrate);
+}
+
static void mcf_serial_putc(const char c)
{
- volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
+ uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
if (c == '\n')
serial_putc('\r');
/* Wait for last character to go. */
- while (!(uart->usr & UART_USR_TXRDY)) ;
+ while (!(readb(&uart->usr) & UART_USR_TXRDY))
+ ;
- uart->utb = c;
+ writeb(c, &uart->utb);
}
static int mcf_serial_getc(void)
{
- volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
+ uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
/* Wait for a character to arrive. */
- while (!(uart->usr & UART_USR_RXRDY)) ;
- return uart->urb;
-}
-
-static int mcf_serial_tstc(void)
-{
- volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
+ while (!(readb(&uart->usr) & UART_USR_RXRDY))
+ ;
- return (uart->usr & UART_USR_RXRDY);
+ return readb(&uart->urb);
}
static void mcf_serial_setbrg(void)
{
- volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
- u32 counter;
-
- /* Setting up BaudRate */
- counter = (u32) ((gd->bus_clk / 32) + (gd->baudrate / 2));
- counter = counter / gd->baudrate;
+ uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
- /* write to CTUR: divide counter upper byte */
- uart->ubg1 = ((counter & 0xff00) >> 8);
- /* write to CTLR: divide counter lower byte */
- uart->ubg2 = (counter & 0x00ff);
+ mcf_serial_setbrg_common(uart, gd->baudrate);
+}
- uart->ucr = UART_UCR_RESET_RX;
- uart->ucr = UART_UCR_RESET_TX;
+static int mcf_serial_tstc(void)
+{
+ uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
- uart->ucr = UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED;
+ return readb(&uart->usr) & UART_USR_RXRDY;
}
static struct serial_device mcf_serial_drv = {
@@ -128,3 +151,80 @@ __weak struct serial_device *default_serial_console(void)
{
return &mcf_serial_drv;
}
+
+#endif
+
+#ifdef CONFIG_DM_SERIAL
+
+static int coldfire_serial_probe(struct udevice *dev)
+{
+ struct coldfire_serial_platdata *plat = dev->platdata;
+
+ return mcf_serial_init_common((uart_t *)plat->base,
+ plat->port, plat->baudrate);
+}
+
+static int coldfire_serial_putc(struct udevice *dev, const char ch)
+{
+ struct coldfire_serial_platdata *plat = dev->platdata;
+ uart_t *uart = (uart_t *)plat->base;
+
+ /* Wait for last character to go. */
+ if (!(readb(&uart->usr) & UART_USR_TXRDY))
+ return -EAGAIN;
+
+ writeb(ch, &uart->utb);
+
+ return 0;
+}
+
+static int coldfire_serial_getc(struct udevice *dev)
+{
+ struct coldfire_serial_platdata *plat = dev->platdata;
+ uart_t *uart = (uart_t *)(plat->base);
+
+ /* Wait for a character to arrive. */
+ if (!(readb(&uart->usr) & UART_USR_RXRDY))
+ return -EAGAIN;
+
+ return readb(&uart->urb);
+}
+
+int coldfire_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct coldfire_serial_platdata *plat = dev->platdata;
+ uart_t *uart = (uart_t *)(plat->base);
+
+ mcf_serial_setbrg_common(uart, baudrate);
+
+ return 0;
+}
+
+static int coldfire_serial_pending(struct udevice *dev, bool input)
+{
+ struct coldfire_serial_platdata *plat = dev->platdata;
+ uart_t *uart = (uart_t *)(plat->base);
+
+ if (input)
+ return readb(&uart->usr) & UART_USR_RXRDY ? 1 : 0;
+ else
+ return readb(&uart->usr) & UART_USR_TXRDY ? 0 : 1;
+
+ return 0;
+}
+
+static const struct dm_serial_ops coldfire_serial_ops = {
+ .putc = coldfire_serial_putc,
+ .pending = coldfire_serial_pending,
+ .getc = coldfire_serial_getc,
+ .setbrg = coldfire_serial_setbrg,
+};
+
+U_BOOT_DRIVER(serial_coldfire) = {
+ .name = "serial_coldfire",
+ .id = UCLASS_SERIAL,
+ .probe = coldfire_serial_probe,
+ .ops = &coldfire_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+#endif
diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c
index aa4abcc..d23dc81 100644
--- a/drivers/spi/soft_spi.c
+++ b/drivers/spi/soft_spi.c
@@ -26,15 +26,20 @@ struct soft_spi_platdata {
struct gpio_desc mosi;
struct gpio_desc miso;
int spi_delay_us;
+ int flags;
};
+#define SPI_MASTER_NO_RX BIT(0)
+#define SPI_MASTER_NO_TX BIT(1)
+
struct soft_spi_priv {
unsigned int mode;
};
static int soft_spi_scl(struct udevice *dev, int bit)
{
- struct soft_spi_platdata *plat = dev->platdata;
+ struct udevice *bus = dev_get_parent(dev);
+ struct soft_spi_platdata *plat = dev_get_platdata(bus);
dm_gpio_set_value(&plat->sclk, bit);
@@ -43,7 +48,8 @@ static int soft_spi_scl(struct udevice *dev, int bit)
static int soft_spi_sda(struct udevice *dev, int bit)
{
- struct soft_spi_platdata *plat = dev->platdata;
+ struct udevice *bus = dev_get_parent(dev);
+ struct soft_spi_platdata *plat = dev_get_platdata(bus);
dm_gpio_set_value(&plat->mosi, bit);
@@ -52,7 +58,8 @@ static int soft_spi_sda(struct udevice *dev, int bit)
static int soft_spi_cs_activate(struct udevice *dev)
{
- struct soft_spi_platdata *plat = dev->platdata;
+ struct udevice *bus = dev_get_parent(dev);
+ struct soft_spi_platdata *plat = dev_get_platdata(bus);
dm_gpio_set_value(&plat->cs, 0);
dm_gpio_set_value(&plat->sclk, 0);
@@ -63,7 +70,8 @@ static int soft_spi_cs_activate(struct udevice *dev)
static int soft_spi_cs_deactivate(struct udevice *dev)
{
- struct soft_spi_platdata *plat = dev->platdata;
+ struct udevice *bus = dev_get_parent(dev);
+ struct soft_spi_platdata *plat = dev_get_platdata(bus);
dm_gpio_set_value(&plat->cs, 0);
@@ -100,8 +108,9 @@ static int soft_spi_release_bus(struct udevice *dev)
static int soft_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
{
- struct soft_spi_priv *priv = dev_get_priv(dev);
- struct soft_spi_platdata *plat = dev->platdata;
+ struct udevice *bus = dev_get_parent(dev);
+ struct soft_spi_priv *priv = dev_get_priv(bus);
+ struct soft_spi_platdata *plat = dev_get_platdata(bus);
uchar tmpdin = 0;
uchar tmpdout = 0;
const u8 *txd = dout;
@@ -134,14 +143,16 @@ static int soft_spi_xfer(struct udevice *dev, unsigned int bitlen,
if (!cpha)
soft_spi_scl(dev, 0);
- soft_spi_sda(dev, tmpdout & 0x80);
+ if ((plat->flags & SPI_MASTER_NO_TX) == 0)
+ soft_spi_sda(dev, !!(tmpdout & 0x80));
udelay(plat->spi_delay_us);
if (cpha)
soft_spi_scl(dev, 0);
else
soft_spi_scl(dev, 1);
tmpdin <<= 1;
- tmpdin |= dm_gpio_get_value(&plat->miso);
+ if ((plat->flags & SPI_MASTER_NO_RX) == 0)
+ tmpdin |= dm_gpio_get_value(&plat->miso);
tmpdout <<= 1;
udelay(plat->spi_delay_us);
if (cpha)
@@ -203,24 +214,36 @@ static int soft_spi_probe(struct udevice *dev)
struct spi_slave *slave = dev_get_parent_priv(dev);
struct soft_spi_platdata *plat = dev->platdata;
int cs_flags, clk_flags;
+ int ret;
cs_flags = (slave->mode & SPI_CS_HIGH) ? 0 : GPIOD_ACTIVE_LOW;
clk_flags = (slave->mode & SPI_CPOL) ? GPIOD_ACTIVE_LOW : 0;
- if (gpio_request_by_name(dev, "cs-gpio", 0, &plat->cs,
+
+ if (gpio_request_by_name(dev, "cs-gpios", 0, &plat->cs,
GPIOD_IS_OUT | cs_flags) ||
- gpio_request_by_name(dev, "sclk-gpio", 0, &plat->sclk,
- GPIOD_IS_OUT | clk_flags) ||
- gpio_request_by_name(dev, "mosi-gpio", 0, &plat->mosi,
- GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE) ||
- gpio_request_by_name(dev, "miso-gpio", 0, &plat->miso,
- GPIOD_IS_IN))
+ gpio_request_by_name(dev, "gpio-sck", 0, &plat->sclk,
+ GPIOD_IS_OUT | clk_flags))
+ return -EINVAL;
+
+ ret = gpio_request_by_name(dev, "gpio-mosi", 0, &plat->mosi,
+ GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+ if (ret)
+ plat->flags |= SPI_MASTER_NO_TX;
+
+ ret = gpio_request_by_name(dev, "gpio-miso", 0, &plat->miso,
+ GPIOD_IS_IN);
+ if (ret)
+ plat->flags |= SPI_MASTER_NO_RX;
+
+ if ((plat->flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_TX)) ==
+ (SPI_MASTER_NO_RX | SPI_MASTER_NO_TX))
return -EINVAL;
return 0;
}
static const struct udevice_id soft_spi_ids[] = {
- { .compatible = "u-boot,soft-spi" },
+ { .compatible = "spi-gpio" },
{ }
};
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 5561f36..84b6786 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -45,12 +45,12 @@ static int spi_set_speed_mode(struct udevice *bus, int speed, int mode)
return 0;
}
-int spi_claim_bus(struct spi_slave *slave)
+int dm_spi_claim_bus(struct udevice *dev)
{
- struct udevice *dev = slave->dev;
struct udevice *bus = dev->parent;
struct dm_spi_ops *ops = spi_get_ops(bus);
struct dm_spi_bus *spi = dev_get_uclass_priv(bus);
+ struct spi_slave *slave = dev_get_parent_priv(dev);
int speed;
int ret;
@@ -73,9 +73,8 @@ int spi_claim_bus(struct spi_slave *slave)
return ops->claim_bus ? ops->claim_bus(dev) : 0;
}
-void spi_release_bus(struct spi_slave *slave)
+void dm_spi_release_bus(struct udevice *dev)
{
- struct udevice *dev = slave->dev;
struct udevice *bus = dev->parent;
struct dm_spi_ops *ops = spi_get_ops(bus);
@@ -83,10 +82,9 @@ void spi_release_bus(struct spi_slave *slave)
ops->release_bus(dev);
}
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
- const void *dout, void *din, unsigned long flags)
+int dm_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
{
- struct udevice *dev = slave->dev;
struct udevice *bus = dev->parent;
if (bus->uclass->uc_drv->id != UCLASS_SPI)
@@ -95,6 +93,22 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
return spi_get_ops(bus)->xfer(dev, bitlen, dout, din, flags);
}
+int spi_claim_bus(struct spi_slave *slave)
+{
+ return dm_spi_claim_bus(slave->dev);
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ dm_spi_release_bus(slave->dev);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+ return dm_spi_xfer(slave->dev, bitlen, dout, din, flags);
+}
+
static int spi_post_bind(struct udevice *dev)
{
/* Scan the bus for devices */
diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile
index 2f3d43d..2f46d38 100644
--- a/drivers/usb/common/Makefile
+++ b/drivers/usb/common/Makefile
@@ -3,5 +3,6 @@
# SPDX-License-Identifier: GPL-2.0+
#
+obj-$(CONFIG_DM_USB) += common.o
obj-$(CONFIG_USB_EHCI_FSL) += fsl-dt-fixup.o
obj-$(CONFIG_USB_XHCI_FSL) += fsl-dt-fixup.o
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
new file mode 100644
index 0000000..35c2dc1
--- /dev/null
+++ b/drivers/usb/common/common.c
@@ -0,0 +1,40 @@
+/*
+ * Provides code common for host and device side USB.
+ *
+ * (C) Copyright 2016
+ * Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <linux/usb/otg.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const char *const usb_dr_modes[] = {
+ [USB_DR_MODE_UNKNOWN] = "",
+ [USB_DR_MODE_HOST] = "host",
+ [USB_DR_MODE_PERIPHERAL] = "peripheral",
+ [USB_DR_MODE_OTG] = "otg",
+};
+
+enum usb_dr_mode usb_get_dr_mode(int node)
+{
+ const void *fdt = gd->fdt_blob;
+ const char *dr_mode;
+ int i;
+
+ dr_mode = fdt_getprop(fdt, node, "dr_mode", NULL);
+ if (!dr_mode) {
+ error("usb dr_mode not found\n");
+ return USB_DR_MODE_UNKNOWN;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(usb_dr_modes); i++)
+ if (!strcmp(dr_mode, usb_dr_modes[i]))
+ return i;
+
+ return USB_DR_MODE_UNKNOWN;
+}
diff --git a/drivers/video/tegra.c b/drivers/video/tegra.c
index 7fd10e6..c01809e 100644
--- a/drivers/video/tegra.c
+++ b/drivers/video/tegra.c
@@ -620,6 +620,13 @@ static int tegra_lcd_ofdata_to_platdata(struct udevice *dev)
static int tegra_lcd_bind(struct udevice *dev)
{
struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+ const void *blob = gd->fdt_blob;
+ int node = dev->of_offset;
+ int rgb;
+
+ rgb = fdt_subnode_offset(blob, node, "rgb");
+ if ((rgb < 0) || !fdtdec_get_is_enabled(blob, rgb))
+ return -ENODEV;
plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
(1 << LCD_MAX_LOG2_BPP) / 8;
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 600a90e..826bd85 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -1254,7 +1254,7 @@ int file_fat_detectfs(void)
#if defined(CONFIG_CMD_IDE) || \
defined(CONFIG_CMD_SATA) || \
- defined(CONFIG_CMD_SCSI) || \
+ defined(CONFIG_SCSI) || \
defined(CONFIG_CMD_USB) || \
defined(CONFIG_MMC)
printf("Interface: ");
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 68b5f0b..2500c10 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -207,6 +207,16 @@ int gpio_requestf(unsigned gpio, const char *fmt, ...)
struct fdtdec_phandle_args;
/**
+ * gpio_xlate_offs_flags() - implementation for common use of dm_gpio_ops.xlate
+ *
+ * This routine sets the offset field to args[0] and the flags field to
+ * GPIOD_ACTIVE_LOW if the GPIO_ACTIVE_LOW flag is present in args[1].
+ *
+ */
+int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc,
+ struct fdtdec_phandle_args *args);
+
+/**
* struct struct dm_gpio_ops - Driver model GPIO operations
*
* Refer to functions above for description. These function largely copy
@@ -258,12 +268,11 @@ struct dm_gpio_ops {
*
* @desc->dev to @dev
* @desc->flags to 0
- * @desc->offset to the value of the first argument in args, if any,
- * otherwise -1 (which is invalid)
+ * @desc->offset to 0
*
- * This method is optional so if the above defaults suit it can be
- * omitted. Typical behaviour is to set up the GPIOD_ACTIVE_LOW flag
- * in desc->flags.
+ * This method is optional and defaults to gpio_xlate_offs_flags,
+ * which will parse offset and the GPIO_ACTIVE_LOW flag in the first
+ * two arguments.
*
* Note that @dev is passed in as a parameter to follow driver model
* uclass conventions, even though it is already available as
diff --git a/include/blk.h b/include/blk.h
index f624671..66a1c55 100644
--- a/include/blk.h
+++ b/include/blk.h
@@ -30,6 +30,7 @@ enum if_type {
IF_TYPE_SD,
IF_TYPE_SATA,
IF_TYPE_HOST,
+ IF_TYPE_SYSTEMACE,
IF_TYPE_COUNT, /* Number of interface types */
};
@@ -62,6 +63,11 @@ struct blk_desc {
char product[20+1]; /* IDE Serial no, SCSI product */
char revision[8+1]; /* firmware revision */
#ifdef CONFIG_BLK
+ /*
+ * For now we have a few functions which take struct blk_desc as a
+ * parameter. This field allows them to look up the associated
+ * device. Once these functions are removed we can drop this field.
+ */
struct udevice *bdev;
#else
unsigned long (*block_read)(struct blk_desc *block_dev,
@@ -210,6 +216,25 @@ struct blk_ops {
*/
unsigned long (*erase)(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt);
+
+ /**
+ * select_hwpart() - select a particular hardware partition
+ *
+ * Some devices (e.g. MMC) can support partitioning at the hardware
+ * level. This is quite separate from the normal idea of
+ * software-based partitions. MMC hardware partitions must be
+ * explicitly selected. Once selected only the region of the device
+ * covered by that partition is accessible.
+ *
+ * The MMC standard provides for two boot partitions (numbered 1 and 2),
+ * rpmb (3), and up to 4 addition general-purpose partitions (4-7).
+ *
+ * @desc: Block device to update
+ * @hwpart: Hardware partition number to select. 0 means the raw
+ * device, 1 is the first partition, 2 is the second, etc.
+ * @return 0 if OK, -ve on error
+ */
+ int (*select_hwpart)(struct udevice *dev, int hwpart);
};
#define blk_get_ops(dev) ((struct blk_ops *)(dev)->driver->ops)
@@ -269,7 +294,8 @@ int blk_next_device(struct udevice **devp);
* @drv_name: Driver name to use for the block device
* @name: Name for the device
* @if_type: Interface type (enum if_type_t)
- * @devnum: Device number, specific to the interface type
+ * @devnum: Device number, specific to the interface type, or -1 to
+ * allocate the next available number
* @blksz: Block size of the device in bytes (typically 512)
* @size: Total size of the device in bytes
* @devp: the new device (which has not been probed)
@@ -279,6 +305,23 @@ int blk_create_device(struct udevice *parent, const char *drv_name,
lbaint_t size, struct udevice **devp);
/**
+ * blk_create_devicef() - Create a new named block device
+ *
+ * @parent: Parent of the new device
+ * @drv_name: Driver name to use for the block device
+ * @name: Name for the device (parent name is prepended)
+ * @if_type: Interface type (enum if_type_t)
+ * @devnum: Device number, specific to the interface type, or -1 to
+ * allocate the next available number
+ * @blksz: Block size of the device in bytes (typically 512)
+ * @size: Total size of the device in bytes
+ * @devp: the new device (which has not been probed)
+ */
+int blk_create_devicef(struct udevice *parent, const char *drv_name,
+ const char *name, int if_type, int devnum, int blksz,
+ lbaint_t size, struct udevice **devp);
+
+/**
* blk_prepare_device() - Prepare a block device for use
*
* This reads partition information from the device if supported.
@@ -298,6 +341,29 @@ int blk_prepare_device(struct udevice *dev);
*/
int blk_unbind_all(int if_type);
+/**
+ * blk_find_max_devnum() - find the maximum device number for an interface type
+ *
+ * Finds the last allocated device number for an interface type @if_type. The
+ * next number is safe to use for a newly allocated device.
+ *
+ * @if_type: Interface type to scan
+ * @return maximum device number found, or -ENODEV if none, or other -ve on
+ * error
+ */
+int blk_find_max_devnum(enum if_type if_type);
+
+/**
+ * blk_select_hwpart() - select a hardware partition
+ *
+ * Select a hardware partition if the device supports it (typically MMC does)
+ *
+ * @dev: Device to update
+ * @hwpart: Partition number to select
+ * @return 0 if OK, -ve on error
+ */
+int blk_select_hwpart(struct udevice *dev, int hwpart);
+
#else
#include <errno.h>
/*
@@ -340,6 +406,201 @@ static inline ulong blk_derase(struct blk_desc *block_dev, lbaint_t start,
blkcache_invalidate(block_dev->if_type, block_dev->devnum);
return block_dev->block_erase(block_dev, start, blkcnt);
}
+
+/**
+ * struct blk_driver - Driver for block interface types
+ *
+ * This provides access to the block devices for each interface type. One
+ * driver should be provided using U_BOOT_LEGACY_BLK() for each interface
+ * type that is to be supported.
+ *
+ * @if_typename: Interface type name
+ * @if_type: Interface type
+ * @max_devs: Maximum number of devices supported
+ * @desc: Pointer to list of devices for this interface type,
+ * or NULL to use @get_dev() instead
+ */
+struct blk_driver {
+ const char *if_typename;
+ enum if_type if_type;
+ int max_devs;
+ struct blk_desc *desc;
+ /**
+ * get_dev() - get a pointer to a block device given its number
+ *
+ * Each interface allocates its own devices and typically
+ * struct blk_desc is contained with the interface's data structure.
+ * There is no global numbering for block devices. This method allows
+ * the device for an interface type to be obtained when @desc is NULL.
+ *
+ * @devnum: Device number (0 for first device on that interface,
+ * 1 for second, etc.
+ * @descp: Returns pointer to the block device on success
+ * @return 0 if OK, -ve on error
+ */
+ int (*get_dev)(int devnum, struct blk_desc **descp);
+
+ /**
+ * select_hwpart() - Select a hardware partition
+ *
+ * Some devices (e.g. MMC) can support partitioning at the hardware
+ * level. This is quite separate from the normal idea of
+ * software-based partitions. MMC hardware partitions must be
+ * explicitly selected. Once selected only the region of the device
+ * covered by that partition is accessible.
+ *
+ * The MMC standard provides for two boot partitions (numbered 1 and 2),
+ * rpmb (3), and up to 4 addition general-purpose partitions (4-7).
+ * Partition 0 is the main user-data partition.
+ *
+ * @desc: Block device descriptor
+ * @hwpart: Hardware partition number to select. 0 means the main
+ * user-data partition, 1 is the first partition, 2 is
+ * the second, etc.
+ * @return 0 if OK, other value for an error
+ */
+ int (*select_hwpart)(struct blk_desc *desc, int hwpart);
+};
+
+/*
+ * Declare a new U-Boot legacy block driver. New drivers should use driver
+ * model (UCLASS_BLK).
+ */
+#define U_BOOT_LEGACY_BLK(__name) \
+ ll_entry_declare(struct blk_driver, __name, blk_driver)
+
+struct blk_driver *blk_driver_lookup_type(int if_type);
+
#endif /* !CONFIG_BLK */
+/**
+ * blk_get_devnum_by_typename() - Get a block device by type and number
+ *
+ * This looks through the available block devices of the given type, returning
+ * the one with the given @devnum.
+ *
+ * @if_type: Block device type
+ * @devnum: Device number
+ * @return point to block device descriptor, or NULL if not found
+ */
+struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum);
+
+/**
+ * blk_get_devnum_by_type() - Get a block device by type name, and number
+ *
+ * This looks up the block device type based on @if_typename, then calls
+ * blk_get_devnum_by_type().
+ *
+ * @if_typename: Block device type name
+ * @devnum: Device number
+ * @return point to block device descriptor, or NULL if not found
+ */
+struct blk_desc *blk_get_devnum_by_typename(const char *if_typename,
+ int devnum);
+
+/**
+ * blk_dselect_hwpart() - select a hardware partition
+ *
+ * This selects a hardware partition (such as is supported by MMC). The block
+ * device size may change as this effectively points the block device to a
+ * partition at the hardware level. See the select_hwpart() method above.
+ *
+ * @desc: Block device descriptor for the device to select
+ * @hwpart: Partition number to select
+ * @return 0 if OK, -ve on error
+ */
+int blk_dselect_hwpart(struct blk_desc *desc, int hwpart);
+
+/**
+ * blk_list_part() - list the partitions for block devices of a given type
+ *
+ * This looks up the partition type for each block device of type @if_type,
+ * then displays a list of partitions.
+ *
+ * @if_type: Block device type
+ * @return 0 if OK, -ENODEV if there is none of that type
+ */
+int blk_list_part(enum if_type if_type);
+
+/**
+ * blk_list_devices() - list the block devices of a given type
+ *
+ * This lists each block device of the type @if_type, showing the capacity
+ * as well as type-specific information.
+ *
+ * @if_type: Block device type
+ */
+void blk_list_devices(enum if_type if_type);
+
+/**
+ * blk_show_device() - show information about a given block device
+ *
+ * This shows the block device capacity as well as type-specific information.
+ *
+ * @if_type: Block device type
+ * @devnum: Device number
+ * @return 0 if OK, -ENODEV for invalid device number
+ */
+int blk_show_device(enum if_type if_type, int devnum);
+
+/**
+ * blk_print_device_num() - show information about a given block device
+ *
+ * This is similar to blk_show_device() but returns an error if the block
+ * device type is unknown.
+ *
+ * @if_type: Block device type
+ * @devnum: Device number
+ * @return 0 if OK, -ENODEV for invalid device number, -ENOENT if the block
+ * device is not connected
+ */
+int blk_print_device_num(enum if_type if_type, int devnum);
+
+/**
+ * blk_print_part_devnum() - print the partition information for a device
+ *
+ * @if_type: Block device type
+ * @devnum: Device number
+ * @return 0 if OK, -ENOENT if the block device is not connected, -ENOSYS if
+ * the interface type is not supported, other -ve on other error
+ */
+int blk_print_part_devnum(enum if_type if_type, int devnum);
+
+/**
+ * blk_read_devnum() - read blocks from a device
+ *
+ * @if_type: Block device type
+ * @devnum: Device number
+ * @blkcnt: Number of blocks to read
+ * @buffer: Address to write data to
+ * @return number of blocks read, or -ve error number on error
+ */
+ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
+ lbaint_t blkcnt, void *buffer);
+
+/**
+ * blk_write_devnum() - write blocks to a device
+ *
+ * @if_type: Block device type
+ * @devnum: Device number
+ * @blkcnt: Number of blocks to write
+ * @buffer: Address to read data from
+ * @return number of blocks written, or -ve error number on error
+ */
+ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
+ lbaint_t blkcnt, const void *buffer);
+
+/**
+ * blk_select_hwpart_devnum() - select a hardware partition
+ *
+ * This is similar to blk_dselect_hwpart() but it looks up the interface and
+ * device number.
+ *
+ * @if_type: Block device type
+ * @devnum: Device number
+ * @hwpart: Partition number to select
+ * @return 0 if OK, -ve on error
+ */
+int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart);
+
#endif
diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
index ed502a1..b5fd6c6 100644
--- a/include/config_cmd_all.h
+++ b/include/config_cmd_all.h
@@ -45,7 +45,7 @@
#define CONFIG_CMD_READ /* Read data from partition */
#define CONFIG_CMD_SANDBOX /* sb command to access sandbox features */
#define CONFIG_CMD_SAVES /* save S record dump */
-#define CONFIG_CMD_SCSI /* SCSI Support */
+#define CONFIG_SCSI /* SCSI Support */
#define CONFIG_CMD_SDRAM /* SDRAM DIMM SPD info printout */
#define CONFIG_CMD_TERMINAL /* built-in Serial Terminal */
#define CONFIG_CMD_UBI /* UBI Support */
diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
index 7f67344..5a8d7f2 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -165,7 +165,7 @@
BOOT_TARGET_DEVICES_references_SATA_without_CONFIG_CMD_SATA
#endif
-#ifdef CONFIG_CMD_SCSI
+#ifdef CONFIG_SCSI
#define BOOTENV_RUN_SCSI_INIT "run scsi_init; "
#define BOOTENV_SET_SCSI_NEED_INIT "setenv scsi_need_init; "
#define BOOTENV_SHARED_SCSI \
@@ -185,9 +185,9 @@
#define BOOTENV_SET_SCSI_NEED_INIT
#define BOOTENV_SHARED_SCSI
#define BOOTENV_DEV_SCSI \
- BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_CMD_SCSI
+ BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_SCSI
#define BOOTENV_DEV_NAME_SCSI \
- BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_CMD_SCSI
+ BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_SCSI
#endif
#ifdef CONFIG_CMD_IDE
diff --git a/include/config_fallbacks.h b/include/config_fallbacks.h
index 2666191..2ad54b7 100644
--- a/include/config_fallbacks.h
+++ b/include/config_fallbacks.h
@@ -45,7 +45,7 @@
/* Rather than repeat this expression each time, add a define for it */
#if defined(CONFIG_CMD_IDE) || \
defined(CONFIG_CMD_SATA) || \
- defined(CONFIG_CMD_SCSI) || \
+ defined(CONFIG_SCSI) || \
defined(CONFIG_CMD_USB) || \
defined(CONFIG_CMD_PART) || \
defined(CONFIG_CMD_GPT) || \
diff --git a/include/configs/MPC8544DS.h b/include/configs/MPC8544DS.h
index 26d92da..f3036c1 100644
--- a/include/configs/MPC8544DS.h
+++ b/include/configs/MPC8544DS.h
@@ -373,7 +373,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
#if defined(CONFIG_PCI)
#define CONFIG_CMD_PCI
- #define CONFIG_CMD_SCSI
+ #define CONFIG_SCSI
#endif
/*
diff --git a/include/configs/MPC8572DS.h b/include/configs/MPC8572DS.h
index 8c4e5e2..bb7f38e 100644
--- a/include/configs/MPC8572DS.h
+++ b/include/configs/MPC8572DS.h
@@ -576,7 +576,7 @@
#if defined(CONFIG_PCI)
#define CONFIG_CMD_PCI
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#endif
/*
diff --git a/include/configs/MPC8610HPCD.h b/include/configs/MPC8610HPCD.h
index e7f01d0..f6d45a9 100644
--- a/include/configs/MPC8610HPCD.h
+++ b/include/configs/MPC8610HPCD.h
@@ -449,7 +449,7 @@
#if defined(CONFIG_PCI)
#define CONFIG_CMD_PCI
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#endif
#define CONFIG_WATCHDOG /* watchdog enabled */
diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h
index 2f94c82..9b2623c 100644
--- a/include/configs/MPC8641HPCN.h
+++ b/include/configs/MPC8641HPCN.h
@@ -354,8 +354,6 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
#define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */
-#undef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE
-
#define CONFIG_PCI_PNP /* do pci plug-and-play */
#undef CONFIG_EEPRO100
@@ -612,7 +610,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
#if defined(CONFIG_PCI)
#define CONFIG_CMD_PCI
- #define CONFIG_CMD_SCSI
+ #define CONFIG_SCSI
#endif
#undef CONFIG_WATCHDOG /* watchdog disabled */
diff --git a/include/configs/PIP405.h b/include/configs/PIP405.h
index 4bd06a4..4506d86 100644
--- a/include/configs/PIP405.h
+++ b/include/configs/PIP405.h
@@ -43,7 +43,7 @@
#define CONFIG_CMD_EEPROM
#define CONFIG_CMD_REGINFO
#define CONFIG_CMD_FDC
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#define CONFIG_CMD_DATE
#define CONFIG_CMD_SDRAM
#define CONFIG_CMD_SAVES
diff --git a/include/configs/am57xx_evm.h b/include/configs/am57xx_evm.h
index 32d7d4d..d53b0fd 100644
--- a/include/configs/am57xx_evm.h
+++ b/include/configs/am57xx_evm.h
@@ -75,7 +75,7 @@
/* SATA */
#define CONFIG_BOARD_LATE_INIT
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#define CONFIG_LIBATA
#define CONFIG_SCSI_AHCI
#define CONFIG_SCSI_AHCI_PLAT
diff --git a/include/configs/cm_t54.h b/include/configs/cm_t54.h
index 9b13aa6..ac6103c 100644
--- a/include/configs/cm_t54.h
+++ b/include/configs/cm_t54.h
@@ -60,7 +60,7 @@
#define CONFIG_SPL_SATA_BOOT_DEVICE 0
#define CONFIG_SYS_SATA_FAT_BOOT_PARTITION 1
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#define CONFIG_LIBATA
#define CONFIG_SCSI_AHCI
#define CONFIG_SCSI_AHCI_PLAT
diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h
index d84dde3..3539a62 100644
--- a/include/configs/db-88f6820-gp.h
+++ b/include/configs/db-88f6820-gp.h
@@ -27,7 +27,7 @@
#define CONFIG_SYS_NO_FLASH /* Declare no flash (NOR/SPI) */
#define CONFIG_CMD_ENV
#define CONFIG_CMD_PCI
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
/* I2C */
#define CONFIG_SYS_I2C
diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h
index 79b6c09..8a0cd66 100644
--- a/include/configs/dra7xx_evm.h
+++ b/include/configs/dra7xx_evm.h
@@ -230,7 +230,7 @@
/* SATA */
#define CONFIG_BOARD_LATE_INIT
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#define CONFIG_LIBATA
#define CONFIG_SCSI_AHCI
#define CONFIG_SCSI_AHCI_PLAT
diff --git a/include/configs/efi-x86.h b/include/configs/efi-x86.h
index 6dd0b32..95e46c5 100644
--- a/include/configs/efi-x86.h
+++ b/include/configs/efi-x86.h
@@ -18,7 +18,7 @@
#undef CONFIG_VIDEO
#undef CONFIG_CFB_CONSOLE
#undef CONFIG_SCSI_AHCI
-#undef CONFIG_CMD_SCSI
+#undef CONFIG_SCSI
#undef CONFIG_INTEL_ICH6_GPIO
#undef CONFIG_USB_EHCI_PCI
diff --git a/include/configs/galileo.h b/include/configs/galileo.h
index 2f1f6d4..40f7fba 100644
--- a/include/configs/galileo.h
+++ b/include/configs/galileo.h
@@ -29,7 +29,7 @@
/* SATA is not supported in Quark SoC */
#undef CONFIG_SCSI_AHCI
-#undef CONFIG_CMD_SCSI
+#undef CONFIG_SCSI
/* Video is not supported in Quark SoC */
#undef CONFIG_VIDEO
diff --git a/include/configs/highbank.h b/include/configs/highbank.h
index 3bce12b..5cefddc 100644
--- a/include/configs/highbank.h
+++ b/include/configs/highbank.h
@@ -51,7 +51,7 @@
/*
* Command line configuration.
*/
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#define CONFIG_BOOT_RETRY_TIME -1
#define CONFIG_RESET_TO_RETRY
diff --git a/include/configs/ls1043aqds.h b/include/configs/ls1043aqds.h
index d71a229..af1f73d 100644
--- a/include/configs/ls1043aqds.h
+++ b/include/configs/ls1043aqds.h
@@ -108,7 +108,7 @@ unsigned long get_board_ddr_clk(void);
#define CONFIG_LIBATA
#define CONFIG_SCSI_AHCI
#define CONFIG_SCSI_AHCI_PLAT
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#define CONFIG_DOS_PARTITION
#define CONFIG_BOARD_LATE_INIT
diff --git a/include/configs/ls2080aqds.h b/include/configs/ls2080aqds.h
index 2d7567f..f8c9e51 100644
--- a/include/configs/ls2080aqds.h
+++ b/include/configs/ls2080aqds.h
@@ -44,7 +44,7 @@ unsigned long get_board_ddr_clk(void);
#define CONFIG_LIBATA
#define CONFIG_SCSI_AHCI
#define CONFIG_SCSI_AHCI_PLAT
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#define CONFIG_DOS_PARTITION
#define CONFIG_BOARD_LATE_INIT
diff --git a/include/configs/ls2080ardb.h b/include/configs/ls2080ardb.h
index 5bec509..4577919 100644
--- a/include/configs/ls2080ardb.h
+++ b/include/configs/ls2080ardb.h
@@ -62,7 +62,7 @@ unsigned long get_board_sys_clk(void);
#define CONFIG_LIBATA
#define CONFIG_SCSI_AHCI
#define CONFIG_SCSI_AHCI_PLAT
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#define CONFIG_DOS_PARTITION
#define CONFIG_BOARD_LATE_INIT
diff --git a/include/configs/omap5_uevm.h b/include/configs/omap5_uevm.h
index 86cefa3..4ddc492 100644
--- a/include/configs/omap5_uevm.h
+++ b/include/configs/omap5_uevm.h
@@ -115,7 +115,7 @@
/* Max time to hold reset on this board, see doc/README.omap-reset-time */
#define CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC 16296
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#define CONFIG_LIBATA
#define CONFIG_SCSI_AHCI
#define CONFIG_SCSI_AHCI_PLAT
diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h
index b0d2ffe..476d37d 100644
--- a/include/configs/qemu-x86.h
+++ b/include/configs/qemu-x86.h
@@ -43,7 +43,7 @@
#define CONFIG_ATAPI
#undef CONFIG_SCSI_AHCI
-#undef CONFIG_CMD_SCSI
+#undef CONFIG_SCSI
#else
#define CONFIG_SCSI_DEV_LIST \
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_AHCI}
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 9790a14..23a0c40 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -192,4 +192,29 @@
#define CONFIG_CMD_LZMADEC
#define CONFIG_CMD_DATE
+#define CONFIG_CMD_IDE
+#define CONFIG_SYS_IDE_MAXBUS 1
+#define CONFIG_SYS_ATA_IDE0_OFFSET 0
+#define CONFIG_SYS_IDE_MAXDEVICE 2
+#define CONFIG_SYS_ATA_BASE_ADDR 0x100
+#define CONFIG_SYS_ATA_DATA_OFFSET 0
+#define CONFIG_SYS_ATA_REG_OFFSET 1
+#define CONFIG_SYS_ATA_ALT_OFFSET 2
+#define CONFIG_SYS_ATA_STRIDE 4
+
+#define CONFIG_SCSI
+#define CONFIG_SCSI_AHCI_PLAT
+#define CONFIG_SYS_SCSI_MAX_DEVICE 2
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID 8
+#define CONFIG_SYS_SCSI_MAX_LUN 4
+
+#define CONFIG_CMD_SATA
+#define CONFIG_SYS_SATA_MAX_DEVICE 2
+
+#define CONFIG_SYSTEMACE
+#define CONFIG_SYS_SYSTEMACE_WIDTH 16
+#define CONFIG_SYS_SYSTEMACE_BASE 0
+
+#define CONFIG_GENERIC_MMC
+
#endif
diff --git a/include/configs/sbc8641d.h b/include/configs/sbc8641d.h
index a7c7aef..c9970f1 100644
--- a/include/configs/sbc8641d.h
+++ b/include/configs/sbc8641d.h
@@ -297,8 +297,6 @@
#define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */
-#undef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE
-
#define CONFIG_PCI_PNP /* do pci plug-and-play */
#undef CONFIG_EEPRO100
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 2406115..ac2d931 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -125,7 +125,7 @@
#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_CMD_SCSI
+#define CONFIG_SCSI
#endif
#define CONFIG_SETUP_MEMORY_TAGS
diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h
index a2822e0..b79f47b 100644
--- a/include/configs/x86-common.h
+++ b/include/configs/x86-common.h
@@ -100,7 +100,7 @@
#define CONFIG_CMD_IRQ
#define CONFIG_CMD_PCI
#define CONFIG_CMD_GETTIME
-#define CONFIG_CMD_SCSI
+#define CONFIG_SCSI
#define CONFIG_CMD_ZBOOT
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index 060bca9..6b8e3ea 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -201,7 +201,7 @@
#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_CMD_SCSI
+#define CONFIG_SCSI
#endif
#define CONFIG_SYS_BOOTM_LEN (60 * 1024 * 1024)
diff --git a/include/dm/device.h b/include/dm/device.h
index 8970fc0..e9a8ec7 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -41,6 +41,9 @@ struct driver_info;
/* Device is bound */
#define DM_FLAG_BOUND (1 << 6)
+/* Device name is allocated and should be freed on unbind() */
+#define DM_NAME_ALLOCED (1 << 7)
+
/**
* struct udevice - An instance of a driver
*
@@ -523,6 +526,9 @@ bool device_is_last_sibling(struct udevice *dev);
* this is unnecessary but for probed devices which don't get a useful name
* this function can be helpful.
*
+ * The name is allocated and will be freed automatically when the device is
+ * unbound.
+ *
* @dev: Device to update
* @name: New name (this string is allocated new memory and attached to
* the device)
@@ -532,6 +538,16 @@ bool device_is_last_sibling(struct udevice *dev);
int device_set_name(struct udevice *dev, const char *name);
/**
+ * device_set_name_alloced() - note that a device name is allocated
+ *
+ * This sets the DM_NAME_ALLOCED flag for the device, so that when it is
+ * unbound the name will be freed. This avoids memory leaks.
+ *
+ * @dev: Device to update
+ */
+void device_set_name_alloced(struct udevice *dev);
+
+/**
* device_is_on_pci_bus - Test if a device is on a PCI bus
*
* @dev: device to test
diff --git a/include/dm/platform_data/serial_coldfire.h b/include/dm/platform_data/serial_coldfire.h
new file mode 100644
index 0000000..5d86456
--- /dev/null
+++ b/include/dm/platform_data/serial_coldfire.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 Angelo Dureghello <angelo@sysam.it>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __serial_coldfire_h
+#define __serial_coldfire_h
+
+/*
+ * struct coldfire_serial_platdata - information about a coldfire port
+ *
+ * @base: Uart port base register address
+ * @port: Uart port index, for cpu with pinmux for uart / gpio
+ * baudrtatre: Uart port baudrate
+ */
+struct coldfire_serial_platdata {
+ unsigned long base;
+ int port;
+ int baudrate;
+};
+
+#endif /* __serial_coldfire_h */
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index cbf9b2c..a5cf6e2 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -26,11 +26,11 @@ enum uclass_id {
/* U-Boot uclasses start here - in alphabetical order */
UCLASS_ADC, /* Analog-to-digital converter */
+ UCLASS_AHCI, /* SATA disk controller */
UCLASS_BLK, /* Block device */
UCLASS_CLK, /* Clock source, e.g. used by peripherals */
UCLASS_CPU, /* CPU, typically part of an SoC */
UCLASS_CROS_EC, /* Chrome OS EC */
- UCLASS_DISK, /* Disk controller, e.g. SATA */
UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */
UCLASS_DMA, /* Direct Memory Access */
UCLASS_RAM, /* RAM controller */
diff --git a/include/ide.h b/include/ide.h
index a4e65cf..9b0a4a9 100644
--- a/include/ide.h
+++ b/include/ide.h
@@ -34,10 +34,18 @@ void ide_led(uchar led, uchar status);
void ide_init(void);
struct blk_desc;
+struct udevice;
+#ifdef CONFIG_BLK
+ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *buffer);
+ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer);
+#else
ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
void *buffer);
ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
const void *buffer);
+#endif
#ifdef CONFIG_IDE_PREINIT
int ide_preinit(void);
diff --git a/include/iotrace.h b/include/iotrace.h
index 9bd1f16..e4ceb61 100644
--- a/include/iotrace.h
+++ b/include/iotrace.h
@@ -31,10 +31,11 @@
#define writew(val, addr) iotrace_writew(val, (const void *)(addr))
#undef readb
-#define readb(addr) iotrace_readb((const void *)(addr))
+#define readb(addr) iotrace_readb((const void *)(uintptr_t)addr)
#undef writeb
-#define writeb(val, addr) iotrace_writeb(val, (const void *)(addr))
+#define writeb(val, addr) \
+ iotrace_writeb(val, (const void *)(uintptr_t)addr)
#endif
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 7ec5550..8f8ac6a 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -17,4 +17,13 @@ enum usb_dr_mode {
USB_DR_MODE_OTG,
};
+/**
+ * usb_get_dr_mode() - Get dual role mode for given device
+ * @node: Node offset to the given device
+ *
+ * The function gets phy interface string from property 'dr_mode',
+ * and returns the correspondig enum usb_dr_mode
+ */
+enum usb_dr_mode usb_get_dr_mode(int node);
+
#endif /* __LINUX_USB_OTG_H */
diff --git a/include/mmc.h b/include/mmc.h
index cdb56e7..a5c6573 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -344,7 +344,9 @@ struct mmc_config {
/* TODO struct mmc should be in mmc_private but it's hard to fix right now */
struct mmc {
+#ifndef CONFIG_BLK
struct list_head link;
+#endif
const struct mmc_config *cfg; /* provided configuration */
uint version;
void *priv;
@@ -376,11 +378,16 @@ struct mmc {
u64 capacity_gp[4];
u64 enh_user_start;
u64 enh_user_size;
+#ifndef CONFIG_BLK
struct blk_desc block_dev;
+#endif
char op_cond_pending; /* 1 if we are waiting on an op_cond command */
char init_in_progress; /* 1 if we have done mmc_start_init() */
char preinit; /* start init as early as possible */
int ddr_mode;
+#ifdef CONFIG_DM_MMC
+ struct udevice *dev; /* Device for this MMC controller */
+#endif
};
struct mmc_hwpart_conf {
@@ -406,7 +413,29 @@ enum mmc_hwpart_conf_mode {
int mmc_register(struct mmc *mmc);
struct mmc *mmc_create(const struct mmc_config *cfg, void *priv);
+
+/**
+ * mmc_bind() - Set up a new MMC device ready for probing
+ *
+ * A child block device is bound with the IF_TYPE_MMC interface type. This
+ * allows the device to be used with CONFIG_BLK
+ *
+ * @dev: MMC device to set up
+ * @mmc: MMC struct
+ * @cfg: MMC configuration
+ * @return 0 if OK, -ve on error
+ */
+int mmc_bind(struct udevice *dev, struct mmc *mmc,
+ const struct mmc_config *cfg);
void mmc_destroy(struct mmc *mmc);
+
+/**
+ * mmc_unbind() - Unbind a MMC device's child block device
+ *
+ * @dev: MMC device
+ * @return 0 if OK, -ve on error
+ */
+int mmc_unbind(struct udevice *dev);
int mmc_initialize(bd_t *bis);
int mmc_init(struct mmc *mmc);
int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
@@ -415,7 +444,6 @@ struct mmc *find_mmc_device(int dev_num);
int mmc_set_dev(int dev_num);
void print_mmc_devices(char separator);
int get_mmc_num(void);
-int mmc_switch_part(int dev_num, unsigned int part_num);
int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf,
enum mmc_hwpart_conf_mode mode);
int mmc_getcd(struct mmc *mmc);
@@ -498,4 +526,12 @@ int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported);
#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
#endif
+/**
+ * mmc_get_blk_desc() - Get the block descriptor for an MMC device
+ *
+ * @mmc: MMC device
+ * @return block device if found, else NULL
+ */
+struct blk_desc *mmc_get_blk_desc(struct mmc *mmc);
+
#endif /* _MMC_H_ */
diff --git a/include/part.h b/include/part.h
index e3811c6..226b5be 100644
--- a/include/part.h
+++ b/include/part.h
@@ -12,7 +12,6 @@
struct block_drvr {
char *name;
- struct blk_desc* (*get_dev)(int dev);
int (*select_hwpart)(int dev_num, int hwpart);
};
@@ -73,32 +72,8 @@ typedef struct disk_partition {
* error occurred.
*/
struct blk_desc *blk_get_dev(const char *ifname, int dev);
-struct blk_desc *ide_get_dev(int dev);
-struct blk_desc *sata_get_dev(int dev);
-struct blk_desc *scsi_get_dev(int dev);
-struct blk_desc *usb_stor_get_dev(int dev);
-struct blk_desc *mmc_get_dev(int dev);
-/**
- * mmc_select_hwpart() - Select the MMC hardware partiion on an MMC device
- *
- * MMC devices can support partitioning at the hardware level. This is quite
- * separate from the normal idea of software-based partitions. MMC hardware
- * partitions must be explicitly selected. Once selected only the region of
- * the device covered by that partition is accessible.
- *
- * The MMC standard provides for two boot partitions (numbered 1 and 2),
- * rpmb (3), and up to 4 addition general-purpose partitions (4-7).
- *
- * @dev_num: Block device number (struct blk_desc->dev value)
- * @hwpart: Hardware partition number to select. 0 means the raw device,
- * 1 is the first partition, 2 is the second, etc.
- * @return 0 if OK, other value for an error
- */
-int mmc_select_hwpart(int dev_num, int hwpart);
-struct blk_desc *systemace_get_dev(int dev);
struct blk_desc *mg_disk_get_dev(int dev);
-struct blk_desc *host_get_dev(int dev);
int host_get_dev_err(int dev, struct blk_desc **blk_devp);
/* disk/part.c */
@@ -175,15 +150,7 @@ extern const struct block_drvr block_drvr[];
#else
static inline struct blk_desc *blk_get_dev(const char *ifname, int dev)
{ return NULL; }
-static inline struct blk_desc *ide_get_dev(int dev) { return NULL; }
-static inline struct blk_desc *sata_get_dev(int dev) { return NULL; }
-static inline struct blk_desc *scsi_get_dev(int dev) { return NULL; }
-static inline struct blk_desc *usb_stor_get_dev(int dev) { return NULL; }
-static inline struct blk_desc *mmc_get_dev(int dev) { return NULL; }
-static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; }
-static inline struct blk_desc *systemace_get_dev(int dev) { return NULL; }
static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; }
-static inline struct blk_desc *host_get_dev(int dev) { return NULL; }
static inline int part_get_info(struct blk_desc *dev_desc, int part,
disk_partition_t *info) { return -1; }
diff --git a/include/spi.h b/include/spi.h
index 4b88d39..ca96fa4 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -612,6 +612,58 @@ int sandbox_spi_get_emul(struct sandbox_state *state,
struct udevice *bus, struct udevice *slave,
struct udevice **emulp);
+/**
+ * Claim the bus and prepare it for communication with a given slave.
+ *
+ * This must be called before doing any transfers with a SPI slave. It
+ * will enable and initialize any SPI hardware as necessary, and make
+ * sure that the SCK line is in the correct idle state. It is not
+ * allowed to claim the same bus for several slaves without releasing
+ * the bus in between.
+ *
+ * @dev: The SPI slave device
+ *
+ * Returns: 0 if the bus was claimed successfully, or a negative value
+ * if it wasn't.
+ */
+int dm_spi_claim_bus(struct udevice *dev);
+
+/**
+ * Release the SPI bus
+ *
+ * This must be called once for every call to dm_spi_claim_bus() after
+ * all transfers have finished. It may disable any SPI hardware as
+ * appropriate.
+ *
+ * @slave: The SPI slave device
+ */
+void dm_spi_release_bus(struct udevice *dev);
+
+/**
+ * SPI transfer
+ *
+ * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks
+ * "bitlen" bits in the SPI MISO port. That's just the way SPI works.
+ *
+ * The source of the outgoing bits is the "dout" parameter and the
+ * destination of the input bits is the "din" parameter. Note that "dout"
+ * and "din" can point to the same memory location, in which case the
+ * input data overwrites the output data (since both are buffered by
+ * temporary variables, this is OK).
+ *
+ * dm_spi_xfer() interface:
+ * @dev: The SPI slave device which will be sending/receiving the data.
+ * @bitlen: How many bits to write and read.
+ * @dout: Pointer to a string of bits to send out. The bits are
+ * held in a byte array and are sent MSB first.
+ * @din: Pointer to a string of bits that will be filled in.
+ * @flags: A bitwise combination of SPI_XFER_* flags.
+ *
+ * Returns: 0 on success, not 0 on failure
+ */
+int dm_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags);
+
/* Access the operations for a SPI device */
#define spi_get_ops(dev) ((struct dm_spi_ops *)(dev)->driver->ops)
#define spi_emul_get_ops(dev) ((struct dm_spi_emul_ops *)(dev)->driver->ops)
diff --git a/include/systemace.h b/include/systemace.h
deleted file mode 100644
index 3b6ec7d..0000000
--- a/include/systemace.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __SYSTEMACE_H
-#define __SYSTEMACE_H
-/*
- * Copyright (c) 2004 Picture Elements, Inc.
- * Stephen Williams (steve@picturel.com)
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifdef CONFIG_SYSTEMACE
-
-# include <part.h>
-
-struct blk_desc *systemace_get_dev(int dev);
-
-#endif /* CONFIG_SYSTEMACE */
-#endif /* __SYSTEMACE_H */
diff --git a/include/usb.h b/include/usb.h
index 5adad36..02a0ccd 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -228,7 +228,6 @@ int board_usb_cleanup(int index, enum usb_init_type init);
#ifdef CONFIG_USB_STORAGE
#define USB_MAX_STOR_DEV 7
-struct blk_desc *usb_stor_get_dev(int index);
int usb_stor_scan(int mode);
int usb_stor_info(void);
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 28e5b7f..075fd34 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -7,6 +7,7 @@
*/
#include <common.h>
+#include <blk.h>
#include <efi_loader.h>
#include <inttypes.h>
#include <part.h>
@@ -142,7 +143,7 @@ static const struct efi_block_io block_io_disk_template = {
};
static void efi_disk_add_dev(char *name,
- const struct block_drvr *cur_drvr,
+ const struct blk_driver *cur_drvr,
const struct blk_desc *desc,
int dev_index,
lbaint_t offset)
@@ -160,7 +161,7 @@ static void efi_disk_add_dev(char *name,
diskobj->parent.protocols[1].open = efi_disk_open_dp;
diskobj->parent.handle = diskobj;
diskobj->ops = block_io_disk_template;
- diskobj->ifname = cur_drvr->name;
+ diskobj->ifname = cur_drvr->if_typename;
diskobj->dev_index = dev_index;
diskobj->offset = offset;
@@ -189,7 +190,7 @@ static void efi_disk_add_dev(char *name,
}
static int efi_disk_create_eltorito(struct blk_desc *desc,
- const struct block_drvr *cur_drvr,
+ const struct blk_driver *cur_drvr,
int diskid)
{
int disks = 0;
@@ -202,8 +203,8 @@ static int efi_disk_create_eltorito(struct blk_desc *desc,
return 0;
while (!part_get_info(desc, part, &info)) {
- snprintf(devname, sizeof(devname), "%s%d:%d", cur_drvr->name,
- diskid, part);
+ snprintf(devname, sizeof(devname), "%s%d:%d",
+ cur_drvr->if_typename, diskid, part);
efi_disk_add_dev(devname, cur_drvr, desc, diskid, info.start);
part++;
disks++;
@@ -222,25 +223,29 @@ static int efi_disk_create_eltorito(struct blk_desc *desc,
*/
int efi_disk_register(void)
{
- const struct block_drvr *cur_drvr;
- int i;
+ const struct blk_driver *cur_drvr;
+ int i, if_type;
int disks = 0;
/* Search for all available disk devices */
- for (cur_drvr = block_drvr; cur_drvr->name; cur_drvr++) {
- printf("Scanning disks on %s...\n", cur_drvr->name);
+ for (if_type = 0; if_type < IF_TYPE_COUNT; if_type++) {
+ cur_drvr = blk_driver_lookup_type(if_type);
+ if (!cur_drvr)
+ continue;
+
+ printf("Scanning disks on %s...\n", cur_drvr->if_typename);
for (i = 0; i < 4; i++) {
struct blk_desc *desc;
char devname[32] = { 0 }; /* dp->str is u16[32] long */
- desc = blk_get_dev(cur_drvr->name, i);
+ desc = blk_get_devnum_by_type(if_type, i);
if (!desc)
continue;
if (desc->type == DEV_TYPE_UNKNOWN)
continue;
snprintf(devname, sizeof(devname), "%s%d",
- cur_drvr->name, i);
+ cur_drvr->if_typename, i);
efi_disk_add_dev(devname, cur_drvr, desc, i, 0);
disks++;
diff --git a/test/dm/blk.c b/test/dm/blk.c
index f4ea32e..012bf4c 100644
--- a/test/dm/blk.c
+++ b/test/dm/blk.c
@@ -83,12 +83,12 @@ static int dm_test_blk_usb(struct unit_test_state *uts)
ut_asserteq_ptr(usb_dev, dev_get_parent(dev));
/* Check we have one block device for each mass storage device */
- ut_asserteq(3, count_blk_devices());
+ ut_asserteq(4, count_blk_devices());
/* Now go around again, making sure the old devices were unbound */
ut_assertok(usb_stop());
ut_assertok(usb_init());
- ut_asserteq(3, count_blk_devices());
+ ut_asserteq(4, count_blk_devices());
ut_assertok(usb_stop());
return 0;
diff --git a/test/dm/mmc.c b/test/dm/mmc.c
index 0461423..5bca4b7 100644
--- a/test/dm/mmc.c
+++ b/test/dm/mmc.c
@@ -25,3 +25,22 @@ static int dm_test_mmc_base(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_mmc_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_mmc_blk(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct blk_desc *dev_desc;
+ char cmp[1024];
+
+ ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev));
+ ut_assertok(blk_get_device_by_str("mmc", "0", &dev_desc));
+
+ /* Read a few blocks and look for the string we expect */
+ ut_asserteq(512, dev_desc->blksz);
+ memset(cmp, '\0', sizeof(cmp));
+ ut_asserteq(2, blk_dread(dev_desc, 0, 2, cmp));
+ ut_assertok(strcmp(cmp, "this is a test"));
+
+ return 0;
+}
+DM_TEST(dm_test_mmc_blk, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/tools/buildman/README b/tools/buildman/README
index 4705d26..26755c5 100644
--- a/tools/buildman/README
+++ b/tools/buildman/README
@@ -898,6 +898,48 @@ when using the -b flag. For example:
will build commits in us-buildman that are not in upstream/master.
+Building Faster
+===============
+
+By default, buildman executes 'make mrproper' prior to building the first
+commit for each board. This causes everything to be built from scratch. If you
+trust the build system's incremental build capabilities, you can pass the -I
+flag to skip the 'make mproper' invocation, which will reduce the amount of
+work 'make' does, and hence speed up the build. This flag will speed up any
+buildman invocation, since it reduces the amount of work done on any build.
+
+One possible application of buildman is as part of a continual edit, build,
+edit, build, ... cycle; repeatedly applying buildman to the same change or
+series of changes while making small incremental modifications to the source
+each time. This provides quick feedback regarding the correctness of recent
+modifications. In this scenario, buildman's default choice of build directory
+causes more build work to be performed than strictly necessary.
+
+By default, each buildman thread uses a single directory for all builds. When a
+thread builds multiple boards, the configuration built in this directory will
+cycle through various different configurations, one per board built by the
+thread. Variations in the configuration will force a rebuild of affected source
+files when a thread switches between boards. Ideally, such buildman-induced
+rebuilds would not happen, thus allowing the build to operate as efficiently as
+the build system and source changes allow. buildman's -P flag may be used to
+enable this; -P causes each board to be built in a separate (board-specific)
+directory, thus avoiding any buildman-induced configuration changes in any
+build directory.
+
+U-Boot's build system embeds information such as a build timestamp into the
+final binary. This information varies each time U-Boot is built. This causes
+various files to be rebuilt even if no source changes are made, which in turn
+requires that the final U-Boot binary be re-linked. This unnecessary work can
+be avoided by turning off the timestamp feature. This can be achieved by
+setting the SOURCE_DATE_EPOCH environment variable to 0.
+
+Combining all of these options together yields the command-line shown below.
+This will provide the quickest possible feedback regarding the current content
+of the source tree, thus allowing rapid tested evolution of the code.
+
+ SOURCE_DATE_EPOCH=0 ./tools/buildman/buildman -I -P tegra
+
+
Other options
=============
diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py
index 141bf64..8ec3551 100644
--- a/tools/buildman/builder.py
+++ b/tools/buildman/builder.py
@@ -205,7 +205,8 @@ class Builder:
def __init__(self, toolchains, base_dir, git_dir, num_threads, num_jobs,
gnu_make='make', checkout=True, show_unknown=True, step=1,
- no_subdirs=False, full_path=False, verbose_build=False):
+ no_subdirs=False, full_path=False, verbose_build=False,
+ incremental=False, per_board_out_dir=False):
"""Create a new Builder object
Args:
@@ -224,6 +225,10 @@ class Builder:
full_path: Return the full path in CROSS_COMPILE and don't set
PATH
verbose_build: Run build with V=1 and don't use 'make -s'
+ incremental: Always perform incremental builds; don't run make
+ mrproper when configuring
+ per_board_out_dir: Build in a separate persistent directory per
+ board rather than a thread-specific directory
"""
self.toolchains = toolchains
self.base_dir = base_dir
@@ -263,7 +268,8 @@ class Builder:
self.queue = Queue.Queue()
self.out_queue = Queue.Queue()
for i in range(self.num_threads):
- t = builderthread.BuilderThread(self, i)
+ t = builderthread.BuilderThread(self, i, incremental,
+ per_board_out_dir)
t.setDaemon(True)
t.start()
self.threads.append(t)
diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py
index cf25bb8..c512d3b 100644
--- a/tools/buildman/builderthread.py
+++ b/tools/buildman/builderthread.py
@@ -80,11 +80,13 @@ class BuilderThread(threading.Thread):
thread_num: Our thread number (0-n-1), used to decide on a
temporary directory
"""
- def __init__(self, builder, thread_num):
+ def __init__(self, builder, thread_num, incremental, per_board_out_dir):
"""Set up a new builder thread"""
threading.Thread.__init__(self)
self.builder = builder
self.thread_num = thread_num
+ self.incremental = incremental
+ self.per_board_out_dir = per_board_out_dir
def Make(self, commit, brd, stage, cwd, *args, **kwargs):
"""Run 'make' on a particular commit and board.
@@ -136,7 +138,11 @@ class BuilderThread(threading.Thread):
if self.builder.in_tree:
out_dir = work_dir
else:
- out_dir = os.path.join(work_dir, 'build')
+ if self.per_board_out_dir:
+ out_rel_dir = os.path.join('..', brd.target)
+ else:
+ out_rel_dir = 'build'
+ out_dir = os.path.join(work_dir, out_rel_dir)
# Check if the job was already completed last time
done_file = self.builder.GetDoneFile(commit_upto, brd.target)
@@ -197,12 +203,12 @@ class BuilderThread(threading.Thread):
#
# Symlinks can confuse U-Boot's Makefile since
# we may use '..' in our path, so remove them.
- work_dir = os.path.realpath(work_dir)
- args.append('O=%s/build' % work_dir)
+ out_dir = os.path.realpath(out_dir)
+ args.append('O=%s' % out_dir)
cwd = None
src_dir = os.getcwd()
else:
- args.append('O=build')
+ args.append('O=%s' % out_rel_dir)
if self.builder.verbose_build:
args.append('V=1')
else:
@@ -215,9 +221,11 @@ class BuilderThread(threading.Thread):
# If we need to reconfigure, do that now
if do_config:
- result = self.Make(commit, brd, 'mrproper', cwd,
- 'mrproper', *args, env=env)
- config_out = result.combined
+ config_out = ''
+ if not self.incremental:
+ result = self.Make(commit, brd, 'mrproper', cwd,
+ 'mrproper', *args, env=env)
+ config_out += result.combined
result = self.Make(commit, brd, 'config', cwd,
*(args + config_args), env=env)
config_out += result.combined
diff --git a/tools/buildman/cmdline.py b/tools/buildman/cmdline.py
index 8341ab1..3e3bd63 100644
--- a/tools/buildman/cmdline.py
+++ b/tools/buildman/cmdline.py
@@ -49,6 +49,8 @@ def ParseArgs():
parser.add_option('-i', '--in-tree', dest='in_tree',
action='store_true', default=False,
help='Build in the source tree instead of a separate directory')
+ parser.add_option('-I', '--incremental', action='store_true',
+ default=False, help='Do not run make mrproper (when reconfiguring)')
parser.add_option('-j', '--jobs', dest='jobs', type='int',
default=None, help='Number of jobs to run at once (passed to make)')
parser.add_option('-k', '--keep-outputs', action='store_true',
@@ -70,6 +72,8 @@ def ParseArgs():
default=False, help='Do a rough build, with limited warning resolution')
parser.add_option('-p', '--full-path', action='store_true',
default=False, help="Use full toolchain path in CROSS_COMPILE")
+ parser.add_option('-P', '--per-board-out-dir', action='store_true',
+ default=False, help="Use an O= (output) directory per board rather than per thread")
parser.add_option('-s', '--summary', action='store_true',
default=False, help='Show a build summary')
parser.add_option('-S', '--show-sizes', action='store_true',
diff --git a/tools/buildman/control.py b/tools/buildman/control.py
index c2c54bf..aeb128a 100644
--- a/tools/buildman/control.py
+++ b/tools/buildman/control.py
@@ -250,7 +250,9 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
options.threads, options.jobs, gnu_make=gnu_make, checkout=True,
show_unknown=options.show_unknown, step=options.step,
no_subdirs=options.no_subdirs, full_path=options.full_path,
- verbose_build=options.verbose_build)
+ verbose_build=options.verbose_build,
+ incremental=options.incremental,
+ per_board_out_dir=options.per_board_out_dir,)
builder.force_config_on_failure = not options.quick
if make_func:
builder.do_make = make_func