mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
Merge git://git.denx.de/u-boot-dm
This commit is contained in:
commit
4b6e1fda10
136 changed files with 5426 additions and 2756 deletions
4
README
4
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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
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
|
||||
|
||||
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 */
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ int cpu_init_r(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void uart_port_conf(void)
|
||||
void uart_port_conf(int port)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -126,21 +126,32 @@ _start:
|
|||
move.l %d0, (%a1)
|
||||
move.l %d0, (%a2)
|
||||
|
||||
/*
|
||||
* set stackpointer to internal sram end - 80
|
||||
* (global data struct size + some bytes)
|
||||
* 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
|
||||
|
||||
/* 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 */
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
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)
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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[])
|
||||
|
|
18
cmd/mmc.c
18
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;
|
||||
}
|
||||
|
|
142
cmd/sata.c
142
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 (blk_print_device_num(IF_TYPE_SATA,
|
||||
sata_curr_device)) {
|
||||
printf("\nno SATA devices available\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
return 0;
|
||||
} else if (strncmp(argv[1],"dev", 3) == 0) {
|
||||
if ((sata_curr_device < 0) || (sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE)) {
|
||||
} else if (strncmp(argv[1], "part", 4) == 0) {
|
||||
if (blk_list_part(IF_TYPE_SATA))
|
||||
puts("\nno SATA devices available\n");
|
||||
return 1;
|
||||
}
|
||||
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) {
|
||||
puts("\nno SATA devices available\n");
|
||||
rc ++;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
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");
|
||||
|
|
753
cmd/scsi.c
753
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], "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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 */
|
||||
}
|
||||
|
|
16
cmd/usb.c
16
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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
1231
common/ide.c
Normal file
1231
common/ide.c
Normal file
File diff suppressed because it is too large
Load diff
115
common/sata.c
Normal file
115
common/sata.c
Normal file
|
@ -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
|
592
common/scsi.c
Normal file
592
common/scsi.c
Normal file
|
@ -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
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
168
configs/sandbox_noblk_defconfig
Normal file
168
configs/sandbox_noblk_defconfig
Normal file
|
@ -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
|
83
disk/part.c
83
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
};
|
|
@ -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;
|
||||
|
|
261
drivers/block/blk_legacy.c
Normal file
261
drivers/block/blk_legacy.c
Normal file
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
||||
if (!host_dev)
|
||||
return -ENODEV;
|
||||
|
||||
if (!host_dev->blk_dev.priv)
|
||||
return -ENOENT;
|
||||
|
||||
*blk_devp = &host_dev->blk_dev;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct blk_desc *host_get_dev(int dev)
|
||||
{
|
||||
struct blk_desc *blk_dev;
|
||||
|
||||
if (host_get_dev_err(dev, &blk_dev))
|
||||
return NULL;
|
||||
|
||||
return blk_dev;
|
||||
}
|
||||
|
||||
#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
|
||||
|
|
29
drivers/block/sandbox_scsi.c
Normal file
29
drivers/block/sandbox_scsi.c
Normal file
|
@ -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)
|
||||
{
|
||||
}
|
33
drivers/block/sata_sandbox.c
Normal file
33
drivers/block/sata_sandbox.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
193
drivers/gpio/74x164_gpio.c
Normal file
193
drivers/gpio/74x164_gpio.c
Normal file
|
@ -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,
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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)
|
||||
|
|
351
drivers/gpio/pca953x_gpio.c
Normal file
351
drivers/gpio/pca953x_gpio.c
Normal file
|
@ -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,
|
||||
};
|
|
@ -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)
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,43 +563,15 @@ 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;
|
||||
|
||||
if (mmc->block_dev.hwpart == hwpart)
|
||||
return 0;
|
||||
|
||||
if (mmc->part_config == MMCPART_NOAVAILABLE) {
|
||||
printf("Card doesn't support part_switch\n");
|
||||
return -EMEDIUMTYPE;
|
||||
}
|
||||
|
||||
ret = mmc_switch_part(dev_num, hwpart);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int mmc_switch_part(int dev_num, unsigned int part_num)
|
||||
{
|
||||
struct mmc *mmc = find_mmc_device(dev_num);
|
||||
int ret;
|
||||
|
||||
if (!mmc)
|
||||
return -1;
|
||||
|
||||
ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
|
||||
(mmc->part_config & ~PART_ACCESS_MASK)
|
||||
| (part_num & PART_ACCESS_MASK));
|
||||
|
@ -624,12 +582,55 @@ int mmc_switch_part(int dev_num, unsigned int part_num)
|
|||
*/
|
||||
if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0))) {
|
||||
ret = mmc_set_capacity(mmc, part_num);
|
||||
mmc->block_dev.hwpart = 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)
|
||||
return -EMEDIUMTYPE;
|
||||
|
||||
ret = mmc_switch_part(mmc, hwpart);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
|
||||
{
|
||||
struct mmc *mmc = find_mmc_device(desc->devnum);
|
||||
int ret;
|
||||
|
||||
if (!mmc)
|
||||
return -ENODEV;
|
||||
|
||||
if (mmc->block_dev.hwpart == hwpart)
|
||||
return 0;
|
||||
|
||||
if (mmc->part_config == MMCPART_NOAVAILABLE)
|
||||
return -EMEDIUMTYPE;
|
||||
|
||||
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,
|
||||
enum mmc_hwpart_conf_mode mode)
|
||||
|
@ -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
|
||||
|
|
108
drivers/mmc/mmc_legacy.c
Normal file
108
drivers/mmc/mmc_legacy.c
Normal file
|
@ -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
|
|
@ -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_ */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
|
|
|
@ -108,6 +108,7 @@ static int socfpga_dwmmc_probe(struct udevice *dev)
|
|||
return ret;
|
||||
|
||||
upriv->mmc = host->mmc;
|
||||
host->mmc->dev = dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -725,6 +725,7 @@ int uniphier_sd_probe(struct udevice *dev)
|
|||
return -EIO;
|
||||
|
||||
upriv->mmc = priv->mmc;
|
||||
priv->mmc->dev = dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
while (!(readb(&uart->usr) & UART_USR_RXRDY))
|
||||
;
|
||||
|
||||
static int mcf_serial_tstc(void)
|
||||
{
|
||||
volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
|
||||
|
||||
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;
|
||||
uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
|
||||
|
||||
/* Setting up BaudRate */
|
||||
counter = (u32) ((gd->bus_clk / 32) + (gd->baudrate / 2));
|
||||
counter = counter / gd->baudrate;
|
||||
mcf_serial_setbrg_common(uart, gd->baudrate);
|
||||
}
|
||||
|
||||
/* write to CTUR: divide counter upper byte */
|
||||
uart->ubg1 = ((counter & 0xff00) >> 8);
|
||||
/* write to CTLR: divide counter lower byte */
|
||||
uart->ubg2 = (counter & 0x00ff);
|
||||
static int mcf_serial_tstc(void)
|
||||
{
|
||||
uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
|
||||
|
||||
uart->ucr = UART_UCR_RESET_RX;
|
||||
uart->ucr = UART_UCR_RESET_TX;
|
||||
|
||||
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
|
||||
|
|
|
@ -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" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
40
drivers/usb/common/common.c
Normal file
40
drivers/usb/common/common.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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: ");
|
||||
|
|
|
@ -206,6 +206,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
|
||||
*
|
||||
|
@ -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
|
||||
|
|
263
include/blk.h
263
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)
|
||||
|
@ -278,6 +304,23 @@ 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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) || \
|
||||
|
|
|
@ -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
|
||||
|
||||
/*
|
||||
|
|
|
@ -576,7 +576,7 @@
|
|||
|
||||
#if defined(CONFIG_PCI)
|
||||
#define CONFIG_CMD_PCI
|
||||
#define CONFIG_CMD_SCSI
|
||||
#define CONFIG_SCSI
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue