diff options
Diffstat (limited to 'common')
41 files changed, 1243 insertions, 652 deletions
diff --git a/common/Kconfig b/common/Kconfig index 4cde4b0048..17930a4ff3 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -339,6 +339,122 @@ config CMD_SETGETDCR getidcr - Get a register value via indirect DCR addressing setidcr - Set a register value via indirect DCR addressing +config CMD_SOUND + bool "sound" + depends on SOUND + help + This provides basic access to the U-Boot's sound support. The main + feature is to play a beep. + + sound init - set up sound system + sound play - play a sound + +endmenu + +menu "Boot timing" + +config BOOTSTAGE + bool "Boot timing and reporting" + help + Enable recording of boot time while booting. To use it, insert + calls to bootstage_mark() with a suitable BOOTSTAGE_ID from + bootstage.h. Only a single entry is recorded for each ID. You can + give the entry a name with bootstage_mark_name(). You can also + record elapsed time in a particular stage using bootstage_start() + before starting and bootstage_accum() when finished. Bootstage will + add up all the accumated time and report it. + + Normally, IDs are defined in bootstage.h but a small number of + additional 'user' IDs can be used but passing BOOTSTAGE_ID_ALLOC + as the ID. + + Calls to show_boot_progress() wil also result in log entries but + these will not have names. + +config BOOTSTAGE_REPORT + bool "Display a detailed boot timing report before booting the OS" + depends on BOOTSTAGE + help + Enable output of a boot time report just before the OS is booted. + This shows how long it took U-Boot to go through each stage of the + boot process. The report looks something like this: + + Timer summary in microseconds: + Mark Elapsed Stage + 0 0 reset + 3,575,678 3,575,678 board_init_f start + 3,575,695 17 arch_cpu_init A9 + 3,575,777 82 arch_cpu_init done + 3,659,598 83,821 board_init_r start + 3,910,375 250,777 main_loop + 29,916,167 26,005,792 bootm_start + 30,361,327 445,160 start_kernel + +config BOOTSTAGE_USER_COUNT + hex "Number of boot ID numbers available for user use" + default 20 + help + This is the number of available user bootstage records. + Each time you call bootstage_mark(BOOTSTAGE_ID_ALLOC, ...) + a new ID will be allocated from this stash. If you exceed + the limit, recording will stop. + +config CMD_BOOTSTAGE + bool "Enable the 'bootstage' command" + depends on BOOTSTAGE + help + Add a 'bootstage' command which supports printing a report + and un/stashing of bootstage data. + +config BOOTSTAGE_FDT + bool "Store boot timing information in the OS device tree" + depends on BOOTSTAGE + help + Stash the bootstage information in the FDT. A root 'bootstage' + node is created with each bootstage id as a child. Each child + has a 'name' property and either 'mark' containing the + mark time in microsecond, or 'accum' containing the + accumulated time for that bootstage id in microseconds. + For example: + + bootstage { + 154 { + name = "board_init_f"; + mark = <3575678>; + }; + 170 { + name = "lcd"; + accum = <33482>; + }; + }; + + Code in the Linux kernel can find this in /proc/devicetree. + +config BOOTSTAGE_STASH + bool "Stash the boot timing information in memory before booting OS" + depends on BOOTSTAGE + help + Some OSes do not support device tree. Bootstage can instead write + the boot timing information in a binary format at a given address. + This happens through a call to bootstage_stash(), typically in + the CPU's cleanup_before_linux() function. You can use the + 'bootstage stash' and 'bootstage unstash' commands to do this on + the command line. + +config BOOTSTAGE_STASH_ADDR + hex "Address to stash boot timing information" + default 0 + help + Provide an address which will not be overwritten by the OS when it + starts, so that it can read this information when ready. + +config BOOTSTAGE_STASH_SIZE + hex "Size of boot timing stash region" + default 4096 + help + This should be large enough to hold the bootstage stash. A value of + 4096 (4KiB) is normally plenty. + endmenu endmenu diff --git a/common/Makefile b/common/Makefile index e545458578..fba3830f1d 100644 --- a/common/Makefile +++ b/common/Makefile @@ -152,7 +152,7 @@ obj-$(CONFIG_CMD_PXE) += cmd_pxe.o obj-$(CONFIG_CMD_READ) += cmd_read.o obj-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o obj-$(CONFIG_CMD_REISER) += cmd_reiser.o -obj-$(CONFIG_SANDBOX) += cmd_sandbox.o +obj-$(CONFIG_SANDBOX) += cmd_host.o obj-$(CONFIG_CMD_SATA) += cmd_sata.o obj-$(CONFIG_CMD_SF) += cmd_sf.o obj-$(CONFIG_CMD_SCSI) += cmd_scsi.o diff --git a/common/board_f.c b/common/board_f.c index cb956b853c..775df1419e 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -23,6 +23,7 @@ #include <i2c.h> #include <initcall.h> #include <logbuff.h> +#include <mapmem.h> /* TODO: Can we move these into arch/ headers? */ #ifdef CONFIG_8xx @@ -815,6 +816,11 @@ __weak int reserve_arch(void) return 0; } +__weak int arch_cpu_init_dm(void) +{ + return 0; +} + static init_fnc_t init_sequence_f[] = { #ifdef CONFIG_SANDBOX setup_ram_buf, @@ -835,6 +841,7 @@ static init_fnc_t init_sequence_f[] = { fdtdec_check_fdt, #endif initf_dm, + arch_cpu_init_dm, #if defined(CONFIG_BOARD_EARLY_INIT_F) board_early_init_f, #endif diff --git a/common/board_r.c b/common/board_r.c index 0335f6bde6..42ff18c219 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -33,6 +33,7 @@ #endif #include <logbuff.h> #include <malloc.h> +#include <mapmem.h> #ifdef CONFIG_BITBANGMII #include <miiphy.h> #endif @@ -230,7 +231,9 @@ static int initr_unlock_ram_in_cache(void) #ifdef CONFIG_PCI static int initr_pci(void) { +#ifndef CONFIG_DM_PCI pci_init(); +#endif return 0; } @@ -587,7 +590,7 @@ static int initr_bbmii(void) static int initr_net(void) { puts("Net: "); - eth_initialize(gd->bd); + eth_initialize(); #if defined(CONFIG_RESET_PHY_R) debug("Reset Ethernet PHY\n"); reset_phy(); @@ -777,9 +780,6 @@ init_fnc_t init_sequence_r[] = { #ifdef CONFIG_PPC initr_spi, #endif -#if defined(CONFIG_X86) && defined(CONFIG_SPI) - init_func_spi, -#endif #ifdef CONFIG_CMD_NAND initr_nand, #endif diff --git a/common/bootm.c b/common/bootm.c index 34f60bbb53..6842029dfb 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -13,6 +13,7 @@ #include <fdt_support.h> #include <lmb.h> #include <malloc.h> +#include <mapmem.h> #include <asm/io.h> #include <linux/lzo.h> #include <lzma/LzmaTypes.h> diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index aa81da227b..f16d5c719f 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -34,6 +34,7 @@ static void print_eth(int idx) printf("%-12s= %s\n", name, val); } +#ifndef CONFIG_DM_ETH __maybe_unused static void print_eths(void) { @@ -52,6 +53,7 @@ static void print_eths(void) printf("current eth = %s\n", eth_get_name()); printf("ip_addr = %s\n", getenv("ipaddr")); } +#endif __maybe_unused static void print_lnum(const char *name, unsigned long long value) @@ -375,7 +377,7 @@ static int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, print_num("-> size", bd->bi_dram[i].size); } -#if defined(CONFIG_CMD_NET) +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH) print_eths(); #endif printf("baudrate = %u bps\n", gd->baudrate); diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 4f77f22f94..6b6aca66fd 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -16,6 +16,7 @@ #include <image.h> #include <lmb.h> #include <malloc.h> +#include <mapmem.h> #include <nand.h> #include <asm/byteorder.h> #include <linux/compiler.h> diff --git a/common/cmd_bootstage.c b/common/cmd_bootstage.c index 106894aa51..788ab16436 100644 --- a/common/cmd_bootstage.c +++ b/common/cmd_bootstage.c @@ -6,11 +6,6 @@ #include <common.h> -#ifndef CONFIG_BOOTSTAGE_STASH -#define CONFIG_BOOTSTAGE_STASH -1UL -#define CONFIG_BOOTSTAGE_STASH_SIZE -1 -#endif - static int do_bootstage_report(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -24,7 +19,7 @@ static int get_base_size(int argc, char * const argv[], ulong *basep, { char *endp; - *basep = CONFIG_BOOTSTAGE_STASH; + *basep = CONFIG_BOOTSTAGE_STASH_ADDR; *sizep = CONFIG_BOOTSTAGE_STASH_SIZE; if (argc < 2) return 0; diff --git a/common/cmd_demo.c b/common/cmd_demo.c index 8a10bdf42a..209dc4a57c 100644 --- a/common/cmd_demo.c +++ b/common/cmd_demo.c @@ -9,6 +9,7 @@ #include <common.h> #include <dm-demo.h> +#include <mapmem.h> #include <asm/io.h> struct udevice *demo_dev; diff --git a/common/cmd_elf.c b/common/cmd_elf.c index c745371506..22475dc3cb 100644 --- a/common/cmd_elf.c +++ b/common/cmd_elf.c @@ -170,7 +170,7 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * Check to see if we need to tftp the image ourselves before starting */ if ((argc == 2) && (strcmp(argv[1], "tftp") == 0)) { - if (NetLoop(TFTPGET) <= 0) + if (net_loop(TFTPGET) <= 0) return 1; printf("Automatic boot of VxWorks image at address 0x%08lx ...\n", addr); diff --git a/common/cmd_fat.c b/common/cmd_fat.c index c00fb28b62..aae993d2b9 100644 --- a/common/cmd_fat.c +++ b/common/cmd_fat.c @@ -14,6 +14,7 @@ #include <net.h> #include <ata.h> #include <asm/io.h> +#include <mapmem.h> #include <part.h> #include <fat.h> #include <fs.h> diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 48b3e70415..682b655395 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -15,6 +15,7 @@ #include <asm/global_data.h> #include <libfdt.h> #include <fdt_support.h> +#include <mapmem.h> #include <asm/io.h> #define MAX_LEVEL 32 /* how deeply nested we will go */ diff --git a/common/cmd_host.c b/common/cmd_host.c new file mode 100644 index 0000000000..ba1460ea1c --- /dev/null +++ b/common/cmd_host.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2012, Google Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <fs.h> +#include <part.h> +#include <sandboxblockdev.h> +#include <asm/errno.h> + +static int host_curr_device = -1; + +static int do_host_load(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return do_load(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); +} + +static int do_host_ls(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return do_ls(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); +} + +static int do_host_save(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return do_save(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); +} + +static int do_host_bind(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + if (argc < 2 || argc > 3) + return CMD_RET_USAGE; + char *ep; + char *dev_str = argv[1]; + char *file = argc >= 3 ? argv[2] : NULL; + int dev = simple_strtoul(dev_str, &ep, 16); + if (*ep) { + printf("** Bad device specification %s **\n", dev_str); + return CMD_RET_USAGE; + } + return host_dev_bind(dev, file); +} + +static int do_host_info(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + if (argc < 1 || argc > 2) + return CMD_RET_USAGE; + int min_dev = 0; + int max_dev = CONFIG_HOST_MAX_DEVICES - 1; + if (argc >= 2) { + char *ep; + char *dev_str = argv[1]; + int dev = simple_strtoul(dev_str, &ep, 16); + if (*ep) { + printf("** Bad device specification %s **\n", dev_str); + return CMD_RET_USAGE; + } + min_dev = dev; + max_dev = dev; + } + int dev; + printf("%3s %12s %s\n", "dev", "blocks", "path"); + for (dev = min_dev; dev <= max_dev; dev++) { + block_dev_desc_t *blk_dev; + int ret; + + printf("%3d ", dev); + ret = host_get_dev_err(dev, &blk_dev); + if (ret) { + if (ret == -ENOENT) + puts("Not bound to a backing file\n"); + else if (ret == -ENODEV) + puts("Invalid host device number\n"); + + continue; + } + struct host_block_dev *host_dev = blk_dev->priv; + printf("%12lu %s\n", (unsigned long)blk_dev->lba, + host_dev->filename); + } + return 0; +} + +static int do_host_dev(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int dev; + char *ep; + block_dev_desc_t *blk_dev; + int ret; + + if (argc < 1 || argc > 3) + return CMD_RET_USAGE; + + if (argc == 1) { + if (host_curr_device < 0) { + printf("No current host device\n"); + return 1; + } + printf("Current host device %d\n", host_curr_device); + return 0; + } + + dev = simple_strtoul(argv[1], &ep, 16); + if (*ep) { + printf("** Bad device specification %s **\n", argv[2]); + return CMD_RET_USAGE; + } + + ret = host_get_dev_err(dev, &blk_dev); + if (ret) { + if (ret == -ENOENT) + puts("Not bound to a backing file\n"); + else if (ret == -ENODEV) + puts("Invalid host device number\n"); + + return 1; + } + + host_curr_device = dev; + return 0; +} + +static cmd_tbl_t cmd_host_sub[] = { + U_BOOT_CMD_MKENT(load, 7, 0, do_host_load, "", ""), + U_BOOT_CMD_MKENT(ls, 3, 0, do_host_ls, "", ""), + U_BOOT_CMD_MKENT(save, 6, 0, do_host_save, "", ""), + U_BOOT_CMD_MKENT(bind, 3, 0, do_host_bind, "", ""), + U_BOOT_CMD_MKENT(info, 3, 0, do_host_info, "", ""), + U_BOOT_CMD_MKENT(dev, 0, 1, do_host_dev, "", ""), +}; + +static int do_host(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + cmd_tbl_t *c; + + /* Skip past 'host' */ + argc--; + argv++; + + c = find_cmd_tbl(argv[0], cmd_host_sub, + ARRAY_SIZE(cmd_host_sub)); + + if (c) + return c->cmd(cmdtp, flag, argc, argv); + else + return CMD_RET_USAGE; +} + +U_BOOT_CMD( + sb, 8, 1, do_host, + "Deprecated: use 'host' command instead.", "" +); + +U_BOOT_CMD( + host, 8, 1, do_host, + "Miscellaneous host commands", + "load hostfs - <addr> <filename> [<bytes> <offset>] - " + "load a file from host\n" + "host ls hostfs - <filename> - list files on host\n" + "host save hostfs - <addr> <filename> <bytes> [<offset>] - " + "save a file to host\n" + "host bind <dev> [<filename>] - bind \"host\" device to file\n" + "host info [<dev>] - show device binding & info\n" + "host dev [<dev>] - Set or retrieve the current host device\n" + "host commands use the \"hostfs\" device. The \"host\" device is used\n" + "with standard IO commands such as fatls or ext2load" +); diff --git a/common/cmd_lzmadec.c b/common/cmd_lzmadec.c index 7b0b3fdd90..1ad9ed6ce9 100644 --- a/common/cmd_lzmadec.c +++ b/common/cmd_lzmadec.c @@ -12,6 +12,7 @@ #include <common.h> #include <command.h> +#include <mapmem.h> #include <asm/io.h> #include <lzma/LzmaTools.h> diff --git a/common/cmd_md5sum.c b/common/cmd_md5sum.c index d22ace5220..23bb81e88c 100644 --- a/common/cmd_md5sum.c +++ b/common/cmd_md5sum.c @@ -10,6 +10,7 @@ #include <common.h> #include <command.h> +#include <mapmem.h> #include <u-boot/md5.h> #include <asm/io.h> diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 3f85c1aa85..45e471ca82 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -20,6 +20,7 @@ #endif #include <hash.h> #include <inttypes.h> +#include <mapmem.h> #include <watchdog.h> #include <asm/io.h> #include <linux/compiler.h> @@ -165,7 +166,7 @@ static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #endif ulong addr, count; int size; - void *buf; + void *buf, *start; ulong bytes; if ((argc < 3) || (argc > 4)) @@ -197,7 +198,8 @@ static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } bytes = size * count; - buf = map_sysmem(addr, bytes); + start = map_sysmem(addr, bytes); + buf = start; while (count-- > 0) { if (size == 4) *((u32 *)buf) = (u32)writeval; @@ -211,7 +213,7 @@ static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) *((u8 *)buf) = (u8)writeval; buf += size; } - unmap_sysmem(buf); + unmap_sysmem(start); return 0; } diff --git a/common/cmd_net.c b/common/cmd_net.c index 09489d404e..b2f3c7b709 100644 --- a/common/cmd_net.c +++ b/common/cmd_net.c @@ -44,10 +44,7 @@ U_BOOT_CMD( #ifdef CONFIG_CMD_TFTPPUT int do_tftpput(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - int ret; - - ret = netboot_common(TFTPPUT, cmdtp, argc, argv); - return ret; + return netboot_common(TFTPPUT, cmdtp, argc, argv); } U_BOOT_CMD( @@ -117,24 +114,24 @@ static void netboot_update_env(void) { char tmp[22]; - if (NetOurGatewayIP) { - ip_to_string(NetOurGatewayIP, tmp); + if (net_gateway.s_addr) { + ip_to_string(net_gateway, tmp); setenv("gatewayip", tmp); } - if (NetOurSubnetMask) { - ip_to_string(NetOurSubnetMask, tmp); + if (net_netmask.s_addr) { + ip_to_string(net_netmask, tmp); setenv("netmask", tmp); } - if (NetOurHostName[0]) - setenv("hostname", NetOurHostName); + if (net_hostname[0]) + setenv("hostname", net_hostname); - if (NetOurRootPath[0]) - setenv("rootpath", NetOurRootPath); + if (net_root_path[0]) + setenv("rootpath", net_root_path); - if (NetOurIP) { - ip_to_string(NetOurIP, tmp); + if (net_ip.s_addr) { + ip_to_string(net_ip, tmp); setenv("ipaddr", tmp); } #if !defined(CONFIG_BOOTP_SERVERIP) @@ -142,35 +139,33 @@ static void netboot_update_env(void) * Only attempt to change serverip if net/bootp.c:BootpCopyNetParams() * could have set it */ - if (NetServerIP) { - ip_to_string(NetServerIP, tmp); + if (net_server_ip.s_addr) { + ip_to_string(net_server_ip, tmp); setenv("serverip", tmp); } #endif - if (NetOurDNSIP) { - ip_to_string(NetOurDNSIP, tmp); + if (net_dns_server.s_addr) { + ip_to_string(net_dns_server, tmp); setenv("dnsip", tmp); } #if defined(CONFIG_BOOTP_DNS2) - if (NetOurDNS2IP) { - ip_to_string(NetOurDNS2IP, tmp); + if (net_dns_server2.s_addr) { + ip_to_string(net_dns_server2, tmp); setenv("dnsip2", tmp); } #endif - if (NetOurNISDomain[0]) - setenv("domain", NetOurNISDomain); + if (net_nis_domain[0]) + setenv("domain", net_nis_domain); -#if defined(CONFIG_CMD_SNTP) \ - && defined(CONFIG_BOOTP_TIMEOFFSET) - if (NetTimeOffset) { - sprintf(tmp, "%d", NetTimeOffset); +#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET) + if (net_ntp_time_offset) { + sprintf(tmp, "%d", net_ntp_time_offset); setenv("timeoffset", tmp); } #endif -#if defined(CONFIG_CMD_SNTP) \ - && defined(CONFIG_BOOTP_NTPSERVER) - if (NetNtpServerIP) { - ip_to_string(NetNtpServerIP, tmp); +#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER) + if (net_ntp_server.s_addr) { + ip_to_string(net_ntp_server, tmp); setenv("ntpserverip", tmp); } #endif @@ -186,9 +181,9 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc, ulong addr; /* pre-set load_addr */ - if ((s = getenv("loadaddr")) != NULL) { + s = getenv("loadaddr"); + if (s != NULL) load_addr = simple_strtoul(s, NULL, 16); - } switch (argc) { case 1: @@ -204,22 +199,26 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc, if (end == (argv[1] + strlen(argv[1]))) load_addr = addr; else - copy_filename(BootFile, argv[1], sizeof(BootFile)); + copy_filename(net_boot_file_name, argv[1], + sizeof(net_boot_file_name)); break; - case 3: load_addr = simple_strtoul(argv[1], NULL, 16); - copy_filename(BootFile, argv[2], sizeof(BootFile)); + case 3: + load_addr = simple_strtoul(argv[1], NULL, 16); + copy_filename(net_boot_file_name, argv[2], + sizeof(net_boot_file_name)); break; #ifdef CONFIG_CMD_TFTPPUT case 4: if (strict_strtoul(argv[1], 16, &save_addr) < 0 || - strict_strtoul(argv[2], 16, &save_size) < 0) { + strict_strtoul(argv[2], 16, &save_size) < 0) { printf("Invalid address/size\n"); - return cmd_usage(cmdtp); + return CMD_RET_USAGE; } - copy_filename(BootFile, argv[3], sizeof(BootFile)); + copy_filename(net_boot_file_name, argv[3], + sizeof(net_boot_file_name)); break; #endif default: @@ -228,19 +227,20 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc, } bootstage_mark(BOOTSTAGE_ID_NET_START); - if ((size = NetLoop(proto)) < 0) { + size = net_loop(proto); + if (size < 0) { bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK); - return 1; + return CMD_RET_FAILURE; } bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK); - /* NetLoop ok, update environment */ + /* net_loop ok, update environment */ netboot_update_env(); /* done if no file was loaded (no errors though) */ if (size == 0) { bootstage_error(BOOTSTAGE_ID_NET_LOADED); - return 0; + return CMD_RET_SUCCESS; } /* flush cache */ @@ -250,10 +250,10 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc, rcode = bootm_maybe_autostart(cmdtp, argv[0]); - if (rcode < 0) - bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR); - else + if (rcode == CMD_RET_SUCCESS) bootstage_mark(BOOTSTAGE_ID_NET_DONE); + else + bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR); return rcode; } @@ -261,20 +261,20 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc, static int do_ping(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { if (argc < 2) - return -1; + return CMD_RET_USAGE; - NetPingIP = string_to_ip(argv[1]); - if (NetPingIP == 0) + net_ping_ip = string_to_ip(argv[1]); + if (net_ping_ip.s_addr == 0) return CMD_RET_USAGE; - if (NetLoop(PING) < 0) { + if (net_loop(PING) < 0) { printf("ping failed; host %s is not alive\n", argv[1]); - return 1; + return CMD_RET_FAILURE; } printf("host %s is alive\n", argv[1]); - return 0; + return CMD_RET_SUCCESS; } U_BOOT_CMD( @@ -290,35 +290,35 @@ static void cdp_update_env(void) { char tmp[16]; - if (CDPApplianceVLAN != htons(-1)) { - printf("CDP offered appliance VLAN %d\n", ntohs(CDPApplianceVLAN)); - VLAN_to_string(CDPApplianceVLAN, tmp); + if (cdp_appliance_vlan != htons(-1)) { + printf("CDP offered appliance VLAN %d\n", + ntohs(cdp_appliance_vlan)); + vlan_to_string(cdp_appliance_vlan, tmp); setenv("vlan", tmp); - NetOurVLAN = CDPApplianceVLAN; + net_our_vlan = cdp_appliance_vlan; } - if (CDPNativeVLAN != htons(-1)) { - printf("CDP offered native VLAN %d\n", ntohs(CDPNativeVLAN)); - VLAN_to_string(CDPNativeVLAN, tmp); + if (cdp_native_vlan != htons(-1)) { + printf("CDP offered native VLAN %d\n", ntohs(cdp_native_vlan)); + vlan_to_string(cdp_native_vlan, tmp); setenv("nvlan", tmp); - NetOurNativeVLAN = CDPNativeVLAN; + net_native_vlan = cdp_native_vlan; } - } int do_cdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int r; - r = NetLoop(CDP); + r = net_loop(CDP); if (r < 0) { printf("cdp failed; perhaps not a CISCO switch?\n"); - return 1; + return CMD_RET_FAILURE; } cdp_update_env(); - return 0; + return CMD_RET_SUCCESS; } U_BOOT_CMD( @@ -334,32 +334,32 @@ int do_sntp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) char *toff; if (argc < 2) { - NetNtpServerIP = getenv_IPaddr("ntpserverip"); - if (NetNtpServerIP == 0) { + net_ntp_server = getenv_ip("ntpserverip"); + if (net_ntp_server.s_addr == 0) { printf("ntpserverip not set\n"); - return (1); + return CMD_RET_FAILURE; } } else { - NetNtpServerIP = string_to_ip(argv[1]); - if (NetNtpServerIP == 0) { + net_ntp_server = string_to_ip(argv[1]); + if (net_ntp_server.s_addr == 0) { printf("Bad NTP server IP address\n"); - return (1); + return CMD_RET_FAILURE; } } toff = getenv("timeoffset"); if (toff == NULL) - NetTimeOffset = 0; + net_ntp_time_offset = 0; else - NetTimeOffset = simple_strtol(toff, NULL, 10); + net_ntp_time_offset = simple_strtol(toff, NULL, 10); - if (NetLoop(SNTP) < 0) { + if (net_loop(SNTP) < 0) { printf("SNTP failed: host %pI4 not responding\n", - &NetNtpServerIP); - return 1; + &net_ntp_server); + return CMD_RET_FAILURE; } - return 0; + return CMD_RET_SUCCESS; } U_BOOT_CMD( @@ -389,22 +389,22 @@ int do_dns(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) */ if (strlen(argv[1]) >= 255) { printf("dns error: hostname too long\n"); - return 1; + return CMD_RET_FAILURE; } - NetDNSResolve = argv[1]; + net_dns_resolve = argv[1]; if (argc == 3) - NetDNSenvvar = argv[2]; + net_dns_env_var = argv[2]; else - NetDNSenvvar = NULL; + net_dns_env_var = NULL; - if (NetLoop(DNS) < 0) { + if (net_loop(DNS) < 0) { printf("dns lookup of %s failed, check setup\n", argv[1]); - return 1; + return CMD_RET_FAILURE; } - return 0; + return CMD_RET_SUCCESS; } U_BOOT_CMD( @@ -421,21 +421,21 @@ static int do_link_local(cmd_tbl_t *cmdtp, int flag, int argc, { char tmp[22]; - if (NetLoop(LINKLOCAL) < 0) - return 1; + if (net_loop(LINKLOCAL) < 0) + return CMD_RET_FAILURE; - NetOurGatewayIP = 0; - ip_to_string(NetOurGatewayIP, tmp); + net_gateway.s_addr = 0; + ip_to_string(net_gateway, tmp); setenv("gatewayip", tmp); - ip_to_string(NetOurSubnetMask, tmp); + ip_to_string(net_netmask, tmp); setenv("netmask", tmp); - ip_to_string(NetOurIP, tmp); + ip_to_string(net_ip, tmp); setenv("ipaddr", tmp); setenv("llipaddr", tmp); /* store this for next time */ - return 0; + return CMD_RET_SUCCESS; } U_BOOT_CMD( diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 855808c3e4..be792ae746 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -31,6 +31,7 @@ #include <search.h> #include <errno.h> #include <malloc.h> +#include <mapmem.h> #include <watchdog.h> #include <linux/stddef.h> #include <asm/byteorder.h> diff --git a/common/cmd_pci.c b/common/cmd_pci.c index e3a77e3582..dcecef8da8 100644 --- a/common/cmd_pci.c +++ b/common/cmd_pci.c @@ -48,6 +48,7 @@ void pciinfo(int BusNum, int ShortPCIListing) unsigned char HeaderType; unsigned short VendorID; pci_dev_t dev; + int ret; if (!hose) return; @@ -74,7 +75,10 @@ void pciinfo(int BusNum, int ShortPCIListing) if (pci_skip_dev(hose, dev)) continue; - pci_read_config_word(dev, PCI_VENDOR_ID, &VendorID); + ret = pci_read_config_word(dev, PCI_VENDOR_ID, + &VendorID); + if (ret) + goto error; if ((VendorID == 0xFFFF) || (VendorID == 0x0000)) continue; @@ -91,8 +95,12 @@ void pciinfo(int BusNum, int ShortPCIListing) BusNum, Device, Function); pci_header_show(dev); } - } - } + } + } + + return; +error: + printf("Cannot read bus configuration: %d\n", ret); } diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c index 7e32c95df3..4cbb2b1173 100644 --- a/common/cmd_pxe.c +++ b/common/cmd_pxe.c @@ -8,11 +8,13 @@ #include <common.h> #include <command.h> #include <malloc.h> +#include <mapmem.h> #include <linux/string.h> #include <linux/ctype.h> #include <errno.h> #include <linux/list.h> #include <fs.h> +#include <asm/io.h> #include "menu.h" #include "cli.h" @@ -188,11 +190,12 @@ static int do_get_any(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr) * * Returns 1 for success, or < 0 on error. */ -static int get_relfile(cmd_tbl_t *cmdtp, const char *file_path, void *file_addr) +static int get_relfile(cmd_tbl_t *cmdtp, const char *file_path, + unsigned long file_addr) { size_t path_len; char relfile[MAX_TFTP_PATH_LEN+1]; - char addr_buf[10]; + char addr_buf[18]; int err; err = get_bootfile_path(file_path, relfile, sizeof(relfile)); @@ -215,7 +218,7 @@ static int get_relfile(cmd_tbl_t *cmdtp, const char *file_path, void *file_addr) printf("Retrieving file: %s\n", relfile); - sprintf(addr_buf, "%p", file_addr); + sprintf(addr_buf, "%lx", file_addr); return do_getfile(cmdtp, relfile, addr_buf); } @@ -227,11 +230,13 @@ static int get_relfile(cmd_tbl_t *cmdtp, const char *file_path, void *file_addr) * * Returns 1 on success, or < 0 for error. */ -static int get_pxe_file(cmd_tbl_t *cmdtp, const char *file_path, void *file_addr) +static int get_pxe_file(cmd_tbl_t *cmdtp, const char *file_path, + unsigned long file_addr) { unsigned long config_file_size; char *tftp_filesize; int err; + char *buf; err = get_relfile(cmdtp, file_path, file_addr); @@ -250,7 +255,9 @@ static int get_pxe_file(cmd_tbl_t *cmdtp, const char *file_path, void *file_addr if (strict_strtoul(tftp_filesize, 16, &config_file_size) < 0) return -EINVAL; - *(char *)(file_addr + config_file_size) = '\0'; + buf = map_sysmem(file_addr + config_file_size, 1); + *buf = '\0'; + unmap_sysmem(buf); return 1; } @@ -266,7 +273,8 @@ static int get_pxe_file(cmd_tbl_t *cmdtp, const char *file_path, void *file_addr * * Returns 1 on success or < 0 on error. */ -static int get_pxelinux_path(cmd_tbl_t *cmdtp, const char *file, void *pxefile_addr_r) +static int get_pxelinux_path(cmd_tbl_t *cmdtp, const char *file, + unsigned long pxefile_addr_r) { size_t base_len = strlen(PXELINUX_DIR); char path[MAX_TFTP_PATH_LEN+1]; @@ -287,7 +295,7 @@ static int get_pxelinux_path(cmd_tbl_t *cmdtp, const char *file, void *pxefile_a * * Returns 1 on success or < 0 on error. */ -static int pxe_uuid_path(cmd_tbl_t *cmdtp, void *pxefile_addr_r) +static int pxe_uuid_path(cmd_tbl_t *cmdtp, unsigned long pxefile_addr_r) { char *uuid_str; @@ -305,7 +313,7 @@ static int pxe_uuid_path(cmd_tbl_t *cmdtp, void *pxefile_addr_r) * * Returns 1 on success or < 0 on error. */ -static int pxe_mac_path(cmd_tbl_t *cmdtp, void *pxefile_addr_r) +static int pxe_mac_path(cmd_tbl_t *cmdtp, unsigned long pxefile_addr_r) { char mac_str[21]; int err; @@ -325,12 +333,12 @@ static int pxe_mac_path(cmd_tbl_t *cmdtp, void *pxefile_addr_r) * * Returns 1 on success or < 0 on error. */ -static int pxe_ipaddr_paths(cmd_tbl_t *cmdtp, void *pxefile_addr_r) +static int pxe_ipaddr_paths(cmd_tbl_t *cmdtp, unsigned long pxefile_addr_r) { char ip_addr[9]; int mask_pos, err; - sprintf(ip_addr, "%08X", ntohl(NetOurIP)); + sprintf(ip_addr, "%08X", ntohl(net_ip.s_addr)); for (mask_pos = 7; mask_pos >= 0; mask_pos--) { err = get_pxelinux_path(cmdtp, ip_addr, pxefile_addr_r); @@ -384,9 +392,9 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * Keep trying paths until we successfully get a file we're looking * for. */ - if (pxe_uuid_path(cmdtp, (void *)pxefile_addr_r) > 0 || - pxe_mac_path(cmdtp, (void *)pxefile_addr_r) > 0 || - pxe_ipaddr_paths(cmdtp, (void *)pxefile_addr_r) > 0) { + if (pxe_uuid_path(cmdtp, pxefile_addr_r) > 0 || + pxe_mac_path(cmdtp, pxefile_addr_r) > 0 || + pxe_ipaddr_paths(cmdtp, pxefile_addr_r) > 0) { printf("Config file found\n"); return 0; @@ -394,7 +402,7 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) while (pxe_default_paths[i]) { if (get_pxelinux_path(cmdtp, pxe_default_paths[i], - (void *)pxefile_addr_r) > 0) { + pxefile_addr_r) > 0) { printf("Config file found\n"); return 0; } @@ -427,7 +435,7 @@ static int get_relfile_envaddr(cmd_tbl_t *cmdtp, const char *file_path, const ch if (strict_strtoul(envaddr, 16, &file_addr) < 0) return -EINVAL; - return get_relfile(cmdtp, file_path, (void *)file_addr); + return get_relfile(cmdtp, file_path, file_addr); } /* @@ -790,6 +798,7 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label) else do_bootz(cmdtp, 0, bootm_argc, bootm_argv); #endif + unmap_sysmem(buf); return 1; } @@ -1054,7 +1063,8 @@ static int parse_integer(char **c, int *dst) return 1; } -static int parse_pxefile_top(cmd_tbl_t *cmdtp, char *p, struct pxe_menu *cfg, int nest_level); +static int parse_pxefile_top(cmd_tbl_t *cmdtp, char *p, unsigned long base, + struct pxe_menu *cfg, int nest_level); /* * Parse an include statement, and retrieve and parse the file it mentions. @@ -1064,12 +1074,14 @@ static int parse_pxefile_top(cmd_tbl_t *cmdtp, char *p, struct pxe_menu *cfg, in * include, nest_level has already been incremented and doesn't need to be * incremented here. */ -static int handle_include(cmd_tbl_t *cmdtp, char **c, char *base, +static int handle_include(cmd_tbl_t *cmdtp, char **c, unsigned long base, struct pxe_menu *cfg, int nest_level) { char *include_path; char *s = *c; int err; + char *buf; + int ret; err = parse_sliteral(c, &include_path); @@ -1086,20 +1098,25 @@ static int handle_include(cmd_tbl_t *cmdtp, char **c, char *base, return err; } - return parse_pxefile_top(cmdtp, base, cfg, nest_level); + buf = map_sysmem(base, 0); + ret = parse_pxefile_top(cmdtp, buf, base, cfg, nest_level); + unmap_sysmem(buf); + + return ret; } /* * Parse lines that begin with 'menu'. * - * b and nest are provided to handle the 'menu include' case. + * base and nest are provided to handle the 'menu include' case. * - * b should be the address where the file currently being parsed is stored. + * base should point to a location where it's safe to store the included file. * * nest_level should be 1 when parsing the top level pxe file, 2 when parsing * a file it includes, 3 when parsing a file included by that file, and so on. */ -static int parse_menu(cmd_tbl_t *cmdtp, char **c, struct pxe_menu *cfg, char *b, int nest_level) +static int parse_menu(cmd_tbl_t *cmdtp, char **c, struct pxe_menu *cfg, + unsigned long base, int nest_level) { struct token t; char *s = *c; @@ -1114,7 +1131,7 @@ static int parse_menu(cmd_tbl_t *cmdtp, char **c, struct pxe_menu *cfg, char *b, break; case T_INCLUDE: - err = handle_include(cmdtp, c, b + strlen(b) + 1, cfg, + err = handle_include(cmdtp, c, base, cfg, nest_level + 1); break; @@ -1281,7 +1298,8 @@ static int parse_label(char **c, struct pxe_menu *cfg) * * Returns 1 on success, < 0 on error. */ -static int parse_pxefile_top(cmd_tbl_t *cmdtp, char *p, struct pxe_menu *cfg, int nest_level) +static int parse_pxefile_top(cmd_tbl_t *cmdtp, char *p, unsigned long base, + struct pxe_menu *cfg, int nest_level) { struct token t; char *s, *b, *label_name; @@ -1303,7 +1321,9 @@ static int parse_pxefile_top(cmd_tbl_t *cmdtp, char *p, struct pxe_menu *cfg, in switch (t.type) { case T_MENU: cfg->prompt = 1; - err = parse_menu(cmdtp, &p, cfg, b, nest_level); + err = parse_menu(cmdtp, &p, cfg, + base + ALIGN(strlen(b) + 1, 4), + nest_level); break; case T_TIMEOUT: @@ -1328,8 +1348,9 @@ static int parse_pxefile_top(cmd_tbl_t *cmdtp, char *p, struct pxe_menu *cfg, in break; case T_INCLUDE: - err = handle_include(cmdtp, &p, b + ALIGN(strlen(b), 4), cfg, - nest_level + 1); + err = handle_include(cmdtp, &p, + base + ALIGN(strlen(b), 4), cfg, + nest_level + 1); break; case T_PROMPT: @@ -1385,9 +1406,11 @@ static void destroy_pxe_menu(struct pxe_menu *cfg) * files it includes). The resulting pxe_menu struct can be free()'d by using * the destroy_pxe_menu() function. */ -static struct pxe_menu *parse_pxefile(cmd_tbl_t *cmdtp, char *menucfg) +static struct pxe_menu *parse_pxefile(cmd_tbl_t *cmdtp, unsigned long menucfg) { struct pxe_menu *cfg; + char *buf; + int r; cfg = malloc(sizeof(struct pxe_menu)); @@ -1398,7 +1421,11 @@ static struct pxe_menu *parse_pxefile(cmd_tbl_t *cmdtp, char *menucfg) INIT_LIST_HEAD(&cfg->labels); - if (parse_pxefile_top(cmdtp, menucfg, cfg, 1) < 0) { + buf = map_sysmem(menucfg, 0); + r = parse_pxefile_top(cmdtp, buf, menucfg, cfg, 1); + unmap_sysmem(buf); + + if (r < 0) { destroy_pxe_menu(cfg); return NULL; } @@ -1556,7 +1583,7 @@ do_pxe_boot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; } - cfg = parse_pxefile(cmdtp, (char *)(pxefile_addr_r)); + cfg = parse_pxefile(cmdtp, pxefile_addr_r); if (cfg == NULL) { printf("Error parsing config file\n"); @@ -1567,7 +1594,7 @@ do_pxe_boot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) destroy_pxe_menu(cfg); - copy_filename(BootFile, "", sizeof(BootFile)); + copy_filename(net_boot_file_name, "", sizeof(net_boot_file_name)); return 0; } @@ -1663,12 +1690,12 @@ static int do_sysboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; } - if (get_pxe_file(cmdtp, filename, (void *)pxefile_addr_r) < 0) { + if (get_pxe_file(cmdtp, filename, pxefile_addr_r) < 0) { printf("Error reading config file\n"); return 1; } - cfg = parse_pxefile(cmdtp, (char *)(pxefile_addr_r)); + cfg = parse_pxefile(cmdtp, pxefile_addr_r); if (cfg == NULL) { printf("Error parsing config file\n"); diff --git a/common/cmd_sandbox.c b/common/cmd_sandbox.c deleted file mode 100644 index 428696982e..0000000000 --- a/common/cmd_sandbox.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2012, Google Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <fs.h> -#include <part.h> -#include <sandboxblockdev.h> -#include <asm/errno.h> - -static int do_sandbox_load(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - return do_load(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); -} - -static int do_sandbox_ls(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - return do_ls(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); -} - -static int do_sandbox_save(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - return do_save(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); -} - -static int do_sandbox_bind(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - if (argc < 2 || argc > 3) - return CMD_RET_USAGE; - char *ep; - char *dev_str = argv[1]; - char *file = argc >= 3 ? argv[2] : NULL; - int dev = simple_strtoul(dev_str, &ep, 16); - if (*ep) { - printf("** Bad device specification %s **\n", dev_str); - return CMD_RET_USAGE; - } - return host_dev_bind(dev, file); -} - -static int do_sandbox_info(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - if (argc < 1 || argc > 2) - return CMD_RET_USAGE; - int min_dev = 0; - int max_dev = CONFIG_HOST_MAX_DEVICES - 1; - if (argc >= 2) { - char *ep; - char *dev_str = argv[1]; - int dev = simple_strtoul(dev_str, &ep, 16); - if (*ep) { - printf("** Bad device specification %s **\n", dev_str); - return CMD_RET_USAGE; - } - min_dev = dev; - max_dev = dev; - } - int dev; - printf("%3s %12s %s\n", "dev", "blocks", "path"); - for (dev = min_dev; dev <= max_dev; dev++) { - block_dev_desc_t *blk_dev; - int ret; - - printf("%3d ", dev); - ret = host_get_dev_err(dev, &blk_dev); - if (ret) { - if (ret == -ENOENT) - puts("Not bound to a backing file\n"); - else if (ret == -ENODEV) - puts("Invalid host device number\n"); - - continue; - } - struct host_block_dev *host_dev = blk_dev->priv; - printf("%12lu %s\n", (unsigned long)blk_dev->lba, - host_dev->filename); - } - return 0; -} - -static cmd_tbl_t cmd_sandbox_sub[] = { - U_BOOT_CMD_MKENT(load, 7, 0, do_sandbox_load, "", ""), - U_BOOT_CMD_MKENT(ls, 3, 0, do_sandbox_ls, "", ""), - U_BOOT_CMD_MKENT(save, 6, 0, do_sandbox_save, "", ""), - U_BOOT_CMD_MKENT(bind, 3, 0, do_sandbox_bind, "", ""), - U_BOOT_CMD_MKENT(info, 3, 0, do_sandbox_info, "", ""), -}; - -static int do_sandbox(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - cmd_tbl_t *c; - - /* Skip past 'sandbox' */ - argc--; - argv++; - - c = find_cmd_tbl(argv[0], cmd_sandbox_sub, - ARRAY_SIZE(cmd_sandbox_sub)); - - if (c) - return c->cmd(cmdtp, flag, argc, argv); - else - return CMD_RET_USAGE; -} - -U_BOOT_CMD( - sb, 8, 1, do_sandbox, - "Miscellaneous sandbox commands", - "load hostfs - <addr> <filename> [<bytes> <offset>] - " - "load a file from host\n" - "sb ls hostfs - <filename> - list files on host\n" - "sb save hostfs - <addr> <filename> <bytes> [<offset>] - " - "save a file to host\n" - "sb bind <dev> [<filename>] - bind \"host\" device to file\n" - "sb info [<dev>] - show device binding & info\n" - "sb commands use the \"hostfs\" device. The \"host\" device is used\n" - "with standard IO commands such as fatls or ext2load" -); diff --git a/common/cmd_sf.c b/common/cmd_sf.c index 5c788e96bd..6aabf39302 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -10,6 +10,7 @@ #include <div64.h> #include <dm.h> #include <malloc.h> +#include <mapmem.h> #include <spi.h> #include <spi_flash.h> @@ -130,7 +131,7 @@ static int do_spi_flash_probe(int argc, char * const argv[]) return 1; } - flash = new->uclass_priv; + flash = dev_get_uclass_priv(new); #else new = spi_flash_probe(bus, cs, speed, mode); if (!new) { diff --git a/common/cmd_source.c b/common/cmd_source.c index 6881bc9ddd..d2a881ddc7 100644 --- a/common/cmd_source.c +++ b/common/cmd_source.c @@ -19,6 +19,7 @@ #include <command.h> #include <image.h> #include <malloc.h> +#include <mapmem.h> #include <asm/byteorder.h> #include <asm/io.h> #if defined(CONFIG_8xx) diff --git a/common/cmd_trace.c b/common/cmd_trace.c index 8c630e6a84..1e62a1a199 100644 --- a/common/cmd_trace.c +++ b/common/cmd_trace.c @@ -6,6 +6,7 @@ #include <common.h> #include <command.h> +#include <mapmem.h> #include <trace.h> #include <asm/io.h> diff --git a/common/cmd_usb.c b/common/cmd_usb.c index 27813f0d7a..eab55cd674 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -2,6 +2,9 @@ * (C) Copyright 2001 * Denis Peter, MPL AG Switzerland * + * Adapted for U-Boot driver model + * (C) Copyright 2015 Google, Inc + * * Most of this source has been derived from the Linux USB * project. * @@ -10,6 +13,7 @@ #include <common.h> #include <command.h> +#include <dm.h> #include <asm/byteorder.h> #include <asm/unaligned.h> #include <part.h> @@ -252,18 +256,57 @@ static void usb_display_config(struct usb_device *dev) printf("\n"); } +/* + * With driver model this isn't right since we can have multiple controllers + * and the device numbering starts at 1 on each bus. + * TODO(sjg@chromium.org): Add a way to specify the controller/bus. + */ static struct usb_device *usb_find_device(int devnum) { - struct usb_device *dev; +#ifdef CONFIG_DM_USB + struct usb_device *udev; + struct udevice *hub; + struct uclass *uc; + int ret; + + /* Device addresses start at 1 */ + devnum++; + ret = uclass_get(UCLASS_USB_HUB, &uc); + if (ret) + return NULL; + + uclass_foreach_dev(hub, uc) { + struct udevice *dev; + + if (!device_active(hub)) + continue; + udev = dev_get_parentdata(hub); + if (udev->devnum == devnum) + return udev; + + for (device_find_first_child(hub, &dev); + dev; + device_find_next_child(&dev)) { + if (!device_active(hub)) + continue; + + udev = dev_get_parentdata(dev); + if (udev->devnum == devnum) + return udev; + } + } +#else + struct usb_device *udev; int d; for (d = 0; d < USB_MAX_DEVICE; d++) { - dev = usb_get_dev_index(d); - if (dev == NULL) + udev = usb_get_dev_index(d); + if (udev == NULL) return NULL; - if (dev->devnum == devnum) - return dev; + if (udev->devnum == devnum) + return udev; } +#endif return NULL; } @@ -293,20 +336,31 @@ static inline char *portspeed(int speed) /* shows the device tree recursively */ static void usb_show_tree_graph(struct usb_device *dev, char *pre) { - int i, index; + int index; int has_child, last_child; index = strlen(pre); printf(" %s", pre); +#ifdef CONFIG_DM_USB + has_child = device_has_active_children(dev->dev); +#else /* check if the device has connected children */ + int i; + has_child = 0; for (i = 0; i < dev->maxchild; i++) { if (dev->children[i] != NULL) has_child = 1; } +#endif /* check if we are the last one */ - last_child = 1; - if (dev->parent != NULL) { +#ifdef CONFIG_DM_USB + last_child = device_is_last_sibling(dev->dev); +#else + last_child = (dev->parent != NULL); +#endif + if (last_child) { +#ifndef CONFIG_DM_USB for (i = 0; i < dev->parent->maxchild; i++) { /* search for children */ if (dev->parent->children[i] == dev) { @@ -322,9 +376,10 @@ static void usb_show_tree_graph(struct usb_device *dev, char *pre) } /* while */ } /* device found */ } /* for all children of the parent */ +#endif printf("\b+-"); /* correct last child */ - if (last_child) + if (last_child && index) pre[index-1] = ' '; } /* if not root hub */ else @@ -340,6 +395,26 @@ static void usb_show_tree_graph(struct usb_device *dev, char *pre) if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial)) printf(" %s %s %s %s\n", pre, dev->mf, dev->prod, dev->serial); printf(" %s\n", pre); +#ifdef CONFIG_DM_USB + struct udevice *child; + + for (device_find_first_child(dev->dev, &child); + child; + device_find_next_child(&child)) { + struct usb_device *udev; + + if (!device_active(child)) + continue; + + udev = dev_get_parentdata(child); + + /* Ignore emulators, we only want real devices */ + if (device_get_uclass_id(child) != UCLASS_USB_EMUL) { + usb_show_tree_graph(udev, pre); + pre[index] = 0; + } + } +#else if (dev->maxchild > 0) { for (i = 0; i < dev->maxchild; i++) { if (dev->children[i] != NULL) { @@ -348,6 +423,7 @@ static void usb_show_tree_graph(struct usb_device *dev, char *pre) } } } +#endif } /* main routine for the tree command */ @@ -355,7 +431,7 @@ static void usb_show_tree(struct usb_device *dev) { char preamble[32]; - memset(preamble, 0, 32); + memset(preamble, '\0', sizeof(preamble)); usb_show_tree_graph(dev, &preamble[0]); } @@ -448,10 +524,13 @@ static void do_usb_start(void) if (usb_init() < 0) return; + /* Driver model will probe the devices as they are found */ +#ifndef CONFIG_DM_USB #ifdef CONFIG_USB_STORAGE /* try to recognize storage devices immediately */ usb_stor_curr_dev = usb_stor_scan(1); #endif +#endif #ifdef CONFIG_USB_HOST_ETHER /* try to recognize ethernet devices immediately */ usb_ether_curr_dev = usb_host_eth_scan(1); @@ -461,14 +540,50 @@ static void do_usb_start(void) #endif } +#ifdef CONFIG_DM_USB +static void show_info(struct udevice *dev) +{ + struct udevice *child; + struct usb_device *udev; + + udev = dev_get_parentdata(dev); + usb_display_desc(udev); + usb_display_config(udev); + for (device_find_first_child(dev, &child); + child; + device_find_next_child(&child)) { + if (device_active(child)) + show_info(child); + } +} + +static int usb_device_info(void) +{ + struct udevice *bus; + + for (uclass_first_device(UCLASS_USB, &bus); + bus; + uclass_next_device(&bus)) { + struct udevice *hub; + + device_find_first_child(bus, &hub); + if (device_get_uclass_id(hub) == UCLASS_USB_HUB && + device_active(hub)) { + show_info(hub); + } + } + + return 0; +} +#endif + /****************************************************************************** * usb command intepreter */ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - + struct usb_device *udev = NULL; int i; - struct usb_device *dev = NULL; extern char usb_started; #ifdef CONFIG_USB_STORAGE block_dev_desc_t *stor_dev; @@ -508,36 +623,63 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } if (strncmp(argv[1], "tree", 4) == 0) { puts("USB device tree:\n"); +#ifdef CONFIG_DM_USB + struct udevice *bus; + + for (uclass_first_device(UCLASS_USB, &bus); + bus; + uclass_next_device(&bus)) { + struct usb_device *udev; + struct udevice *hub; + + device_find_first_child(bus, &hub); + if (device_get_uclass_id(hub) == UCLASS_USB_HUB && + device_active(hub)) { + udev = dev_get_parentdata(hub); + usb_show_tree(udev); + } + } +#else for (i = 0; i < USB_MAX_DEVICE; i++) { - dev = usb_get_dev_index(i); - if (dev == NULL) + udev = usb_get_dev_index(i); + if (udev == NULL) break; - if (dev->parent == NULL) - usb_show_tree(dev); + if (udev->parent == NULL) + usb_show_tree(udev); } +#endif return 0; } if (strncmp(argv[1], "inf", 3) == 0) { - int d; if (argc == 2) { +#ifdef CONFIG_DM_USB + usb_device_info(); +#else + int d; for (d = 0; d < USB_MAX_DEVICE; d++) { - dev = usb_get_dev_index(d); - if (dev == NULL) + udev = usb_get_dev_index(d); + if (udev == NULL) break; - usb_display_desc(dev); - usb_display_config(dev); + usb_display_desc(udev); + usb_display_config(udev); } +#endif return 0; } else { + /* + * With driver model this isn't right since we can + * have multiple controllers and the device numbering + * starts at 1 on each bus. + */ i = simple_strtoul(argv[2], NULL, 10); printf("config for device %d\n", i); - dev = usb_find_device(i); - if (dev == NULL) { + udev = usb_find_device(i); + if (udev == NULL) { printf("*** No device available ***\n"); return 0; } else { - usb_display_desc(dev); - usb_display_config(dev); + usb_display_desc(udev); + usb_display_config(udev); } } return 0; @@ -546,13 +688,13 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc < 5) return CMD_RET_USAGE; i = simple_strtoul(argv[2], NULL, 10); - dev = usb_find_device(i); - if (dev == NULL) { + udev = usb_find_device(i); + if (udev == NULL) { printf("Device %d does not exist.\n", i); return 1; } i = simple_strtoul(argv[3], NULL, 10); - return usb_test(dev, i, argv[4]); + return usb_test(udev, i, argv[4]); } #ifdef CONFIG_USB_STORAGE if (strncmp(argv[1], "stor", 4) == 0) diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c index 64b9186d73..8b8645c9e1 100644 --- a/common/cmd_ximg.c +++ b/common/cmd_ximg.c @@ -15,6 +15,7 @@ #include <common.h> #include <command.h> #include <image.h> +#include <mapmem.h> #include <watchdog.h> #if defined(CONFIG_BZIP2) #include <bzlib.h> diff --git a/common/cros_ec.c b/common/cros_ec.c index bb299bccff..7a4f785bc8 100644 --- a/common/cros_ec.c +++ b/common/cros_ec.c @@ -15,18 +15,8 @@ DECLARE_GLOBAL_DATA_PTR; -#ifndef CONFIG_DM_CROS_EC -struct local_info { - struct cros_ec_dev *cros_ec_dev; /* Pointer to cros_ec device */ - int cros_ec_err; /* Error for cros_ec, 0 if ok */ -}; - -static struct local_info local; -#endif - struct cros_ec_dev *board_get_cros_ec_dev(void) { -#ifdef CONFIG_DM_CROS_EC struct udevice *dev; int ret; @@ -35,31 +25,11 @@ struct cros_ec_dev *board_get_cros_ec_dev(void) debug("%s: Error %d\n", __func__, ret); return NULL; } - return dev->uclass_priv; -#else - return local.cros_ec_dev; -#endif -} - -static int board_init_cros_ec_devices(const void *blob) -{ -#ifndef CONFIG_DM_CROS_EC - local.cros_ec_err = cros_ec_init(blob, &local.cros_ec_dev); - if (local.cros_ec_err) - return -1; /* Will report in board_late_init() */ -#endif - - return 0; -} - -int cros_ec_board_init(void) -{ - return board_init_cros_ec_devices(gd->fdt_blob); + return dev_get_uclass_priv(dev); } int cros_ec_get_error(void) { -#ifdef CONFIG_DM_CROS_EC struct udevice *dev; int ret; @@ -68,7 +38,4 @@ int cros_ec_get_error(void) return ret; return 0; -#else - return local.cros_ec_err; -#endif } diff --git a/common/hash.c b/common/hash.c index 9e9f84b9fb..c94c98be9e 100644 --- a/common/hash.c +++ b/common/hash.c @@ -14,6 +14,7 @@ #include <common.h> #include <command.h> #include <malloc.h> +#include <mapmem.h> #include <hw_sha.h> #include <asm/io.h> #include <asm/errno.h> diff --git a/common/image-fdt.c b/common/image-fdt.c index d9e47283c7..7e2da7b3b7 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -14,6 +14,7 @@ #include <errno.h> #include <image.h> #include <libfdt.h> +#include <mapmem.h> #include <asm/io.h> #ifndef CONFIG_SYS_FDT_PAD diff --git a/common/image-fit.c b/common/image-fit.c index 778d2a148b..4eb4d42655 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -16,6 +16,7 @@ #else #include <common.h> #include <errno.h> +#include <mapmem.h> #include <asm/io.h> DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ diff --git a/common/image.c b/common/image.c index 162b68269d..abc0d890f2 100644 --- a/common/image.c +++ b/common/image.c @@ -27,6 +27,7 @@ #include <environment.h> #include <image.h> +#include <mapmem.h> #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) #include <libfdt.h> diff --git a/common/iotrace.c b/common/iotrace.c index ced426ea5c..2725563e8f 100644 --- a/common/iotrace.c +++ b/common/iotrace.c @@ -7,6 +7,7 @@ #define IOTRACE_IMPL #include <common.h> +#include <mapmem.h> #include <asm/io.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/common/lcd.c b/common/lcd.c index aab73d8a61..055c366b19 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -15,6 +15,7 @@ #include <linux/types.h> #include <stdio_dev.h> #include <lcd.h> +#include <mapmem.h> #include <watchdog.h> #include <asm/unaligned.h> #include <splash.h> diff --git a/common/malloc_simple.c b/common/malloc_simple.c index 64ae0365af..d445199c58 100644 --- a/common/malloc_simple.c +++ b/common/malloc_simple.c @@ -8,6 +8,7 @@ #include <common.h> #include <malloc.h> +#include <mapmem.h> #include <asm/io.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/common/miiphyutil.c b/common/miiphyutil.c index 74812e6e1b..c88c28adbf 100644 --- a/common/miiphyutil.c +++ b/common/miiphyutil.c @@ -11,6 +11,7 @@ */ #include <common.h> +#include <dm.h> #include <miiphy.h> #include <phy.h> diff --git a/common/spl/spl_net.c b/common/spl/spl_net.c index ff53705926..217a435c73 100644 --- a/common/spl/spl_net.c +++ b/common/spl/spl_net.c @@ -21,14 +21,14 @@ void spl_net_load_image(const char *device) env_relocate(); setenv("autoload", "yes"); load_addr = CONFIG_SYS_TEXT_BASE - sizeof(struct image_header); - rv = eth_initialize(gd->bd); + rv = eth_initialize(); if (rv == 0) { printf("No Ethernet devices found\n"); hang(); } if (device) setenv("ethact", device); - rv = NetLoop(BOOTP); + rv = net_loop(BOOTP); if (rv < 0) { printf("Problem booting with BOOTP\n"); hang(); diff --git a/common/update.c b/common/update.c index cc830a7865..1c6aa186d0 100644 --- a/common/update.c +++ b/common/update.c @@ -39,8 +39,8 @@ #define CONFIG_UPDATE_TFTP_CNT_MAX 0 #endif -extern ulong TftpRRQTimeoutMSecs; -extern int TftpRRQTimeoutCountMax; +extern ulong tftp_timeout_ms; +extern int tftp_timeout_count_max; extern flash_info_t flash_info[]; extern ulong load_addr; @@ -55,22 +55,22 @@ static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr) rv = 0; /* save used globals and env variable */ - saved_timeout_msecs = TftpRRQTimeoutMSecs; - saved_timeout_count = TftpRRQTimeoutCountMax; + saved_timeout_msecs = tftp_timeout_ms; + saved_timeout_count = tftp_timeout_count_max; saved_netretry = strdup(getenv("netretry")); - saved_bootfile = strdup(BootFile); + saved_bootfile = strdup(net_boot_file_name); /* set timeouts for auto-update */ - TftpRRQTimeoutMSecs = msec_max; - TftpRRQTimeoutCountMax = cnt_max; + tftp_timeout_ms = msec_max; + tftp_timeout_count_max = cnt_max; /* we don't want to retry the connection if errors occur */ setenv("netretry", "no"); /* download the update file */ load_addr = addr; - copy_filename(BootFile, filename, sizeof(BootFile)); - size = NetLoop(TFTPGET); + copy_filename(net_boot_file_name, filename, sizeof(net_boot_file_name)); + size = net_loop(TFTPGET); if (size < 0) rv = 1; @@ -78,15 +78,16 @@ static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr) flush_cache(addr, size); /* restore changed globals and env variable */ - TftpRRQTimeoutMSecs = saved_timeout_msecs; - TftpRRQTimeoutCountMax = saved_timeout_count; + tftp_timeout_ms = saved_timeout_msecs; + tftp_timeout_count_max = saved_timeout_count; setenv("netretry", saved_netretry); if (saved_netretry != NULL) free(saved_netretry); if (saved_bootfile != NULL) { - copy_filename(BootFile, saved_bootfile, sizeof(BootFile)); + copy_filename(net_boot_file_name, saved_bootfile, + sizeof(net_boot_file_name)); free(saved_bootfile); } diff --git a/common/usb.c b/common/usb.c index d94640a99e..a4820d3e94 100644 --- a/common/usb.c +++ b/common/usb.c @@ -28,6 +28,7 @@ */ #include <common.h> #include <command.h> +#include <dm.h> #include <asm/processor.h> #include <linux/compiler.h> #include <linux/ctype.h> @@ -41,12 +42,13 @@ #define USB_BUFSIZ 512 -static struct usb_device usb_dev[USB_MAX_DEVICE]; -static int dev_index; static int asynch_allowed; - char usb_started; /* flag for the started/stopped USB status */ +#ifndef CONFIG_DM_USB +static struct usb_device usb_dev[USB_MAX_DEVICE]; +static int dev_index; + #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 #endif @@ -94,8 +96,8 @@ int usb_init(void) controllers_initialized++; start_index = dev_index; printf("scanning bus %d for devices... ", i); - dev = usb_alloc_new_device(ctrl); - if (!dev) + ret = usb_alloc_new_device(ctrl, &dev); + if (ret) break; /* @@ -104,7 +106,7 @@ int usb_init(void) */ ret = usb_new_device(dev); if (ret) - usb_free_device(); + usb_free_device(dev->controller); if (start_index == dev_index) { puts("No USB Device found\n"); @@ -158,6 +160,7 @@ int usb_disable_asynch(int disable) asynch_allowed = !disable; return old_value; } +#endif /* !CONFIG_DM_USB */ /*------------------------------------------------------------------- @@ -821,6 +824,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) * the USB device are static allocated [USB_MAX_DEVICE]. */ +#ifndef CONFIG_DM_USB /* returns a pointer to the device with the index [index]. * if the device is not assigned (dev->devnum==-1) returns NULL @@ -833,16 +837,13 @@ struct usb_device *usb_get_dev_index(int index) return &usb_dev[index]; } -/* returns a pointer of a new device structure or NULL, if - * no device struct is available - */ -struct usb_device *usb_alloc_new_device(void *controller) +int usb_alloc_new_device(struct udevice *controller, struct usb_device **devp) { int i; debug("New Device %d\n", dev_index); if (dev_index == USB_MAX_DEVICE) { printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE); - return NULL; + return -ENOSPC; } /* default Address is 0, real addresses start with 1 */ usb_dev[dev_index].devnum = dev_index + 1; @@ -852,7 +853,9 @@ struct usb_device *usb_alloc_new_device(void *controller) usb_dev[dev_index].parent = NULL; usb_dev[dev_index].controller = controller; dev_index++; - return &usb_dev[dev_index - 1]; + *devp = &usb_dev[dev_index - 1]; + + return 0; } /* @@ -860,7 +863,7 @@ struct usb_device *usb_alloc_new_device(void *controller) * Called in error cases where configuring a newly attached * device fails for some reason. */ -void usb_free_device(void) +void usb_free_device(struct udevice *controller) { dev_index--; debug("Freeing device node: %d\n", dev_index); @@ -878,123 +881,101 @@ __weak int usb_alloc_device(struct usb_device *udev) { return 0; } -/* - * By the time we get here, the device has gotten a new device ID - * and is in the default state. We need to identify the thing and - * get the ball rolling.. - * - * Returns 0 for success, != 0 for error. - */ -int usb_new_device(struct usb_device *dev) +#endif /* !CONFIG_DM_USB */ + +#ifndef CONFIG_DM_USB +int usb_legacy_port_reset(struct usb_device *hub, int portnr) { - int addr, err; - int tmp; - ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); + if (hub) { + unsigned short portstatus; + int err; - /* - * Allocate usb 3.0 device context. - * USB 3.0 (xHCI) protocol tries to allocate device slot - * and related data structures first. This call does that. - * Refer to sec 4.3.2 in xHCI spec rev1.0 - */ - if (usb_alloc_device(dev)) { - printf("Cannot allocate device context to get SLOT_ID\n"); - return -EINVAL; + /* reset the port for the second time */ + err = legacy_hub_port_reset(hub, portnr - 1, &portstatus); + if (err < 0) { + printf("\n Couldn't reset port %i\n", portnr); + return err; + } + } else { + usb_reset_root_port(); } - /* We still haven't set the Address yet */ - addr = dev->devnum; - dev->devnum = 0; + return 0; +} +#endif -#ifdef CONFIG_LEGACY_USB_INIT_SEQ - /* this is the old and known way of initializing devices, it is - * different than what Windows and Linux are doing. Windows and Linux - * both retrieve 64 bytes while reading the device descriptor - * Several USB stick devices report ERR: CTL_TIMEOUT, caused by an - * invalid header while reading 8 bytes as device descriptor. */ - dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ - dev->maxpacketsize = PACKET_SIZE_8; - dev->epmaxpacketin[0] = 8; - dev->epmaxpacketout[0] = 8; - - err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, tmpbuf, 8); - if (err < 8) { - printf("\n USB device not responding, " \ - "giving up (status=%lX)\n", dev->status); - return -EIO; +static int get_descriptor_len(struct usb_device *dev, int len, int expect_len) +{ + __maybe_unused struct usb_device_descriptor *desc; + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); + int err; + + desc = (struct usb_device_descriptor *)tmpbuf; + + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, len); + if (err < expect_len) { + if (err < 0) { + printf("unable to get device descriptor (error=%d)\n", + err); + return err; + } else { + printf("USB device descriptor short read (expected %i, got %i)\n", + expect_len, err); + return -EIO; + } } - memcpy(&dev->descriptor, tmpbuf, 8); -#else - /* This is a Windows scheme of initialization sequence, with double + memcpy(&dev->descriptor, tmpbuf, sizeof(dev->descriptor)); + + return 0; +} + +static int usb_setup_descriptor(struct usb_device *dev, bool do_read) +{ + __maybe_unused struct usb_device_descriptor *desc; + + /* + * This is a Windows scheme of initialization sequence, with double * reset of the device (Linux uses the same sequence) * Some equipment is said to work only with such init sequence; this * patch is based on the work by Alan Stern: * http://sourceforge.net/mailarchive/forum.php? * thread_id=5729457&forum_id=5398 */ - __maybe_unused struct usb_device_descriptor *desc; - struct usb_device *parent = dev->parent; - unsigned short portstatus; - /* send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is + /* + * send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is * only 18 bytes long, this will terminate with a short packet. But if * the maxpacket size is 8 or 16 the device may be waiting to transmit * some more, or keeps on retransmitting the 8 byte header. */ - desc = (struct usb_device_descriptor *)tmpbuf; dev->descriptor.bMaxPacketSize0 = 64; /* Start off at 64 bytes */ /* Default to 64 byte max packet size */ dev->maxpacketsize = PACKET_SIZE_64; dev->epmaxpacketin[0] = 64; dev->epmaxpacketout[0] = 64; - /* - * XHCI needs to issue a Address device command to setup - * proper device context structures, before it can interact - * with the device. So a get_descriptor will fail before any - * of that is done for XHCI unlike EHCI. - */ -#ifndef CONFIG_USB_XHCI - err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64); - /* - * Validate we've received only at least 8 bytes, not that we've - * received the entire descriptor. The reasoning is: - * - The code only uses fields in the first 8 bytes, so that's all we - * need to have fetched at this stage. - * - The smallest maxpacket size is 8 bytes. Before we know the actual - * maxpacket the device uses, the USB controller may only accept a - * single packet. Consequently we are only guaranteed to receive 1 - * packet (at least 8 bytes) even in a non-error case. - * - * At least the DWC2 controller needs to be programmed with the number - * of packets in addition to the number of bytes. A request for 64 - * bytes of data with the maxpacket guessed as 64 (above) yields a - * request for 1 packet. - */ - if (err < 8) { - debug("usb_new_device: usb_get_descriptor() failed\n"); - return -EIO; - } - - dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0; - /* - * Fetch the device class, driver can use this info - * to differentiate between HUB and DEVICE. - */ - dev->descriptor.bDeviceClass = desc->bDeviceClass; -#endif + if (do_read) { + int err; - if (parent) { - /* reset the port for the second time */ - err = hub_port_reset(dev->parent, dev->portnr - 1, &portstatus); - if (err < 0) { - printf("\n Couldn't reset port %i\n", dev->portnr); - return -EIO; - } - } else { - usb_reset_root_port(); + /* + * Validate we've received only at least 8 bytes, not that we've + * received the entire descriptor. The reasoning is: + * - The code only uses fields in the first 8 bytes, so that's all we + * need to have fetched at this stage. + * - The smallest maxpacket size is 8 bytes. Before we know the actual + * maxpacket the device uses, the USB controller may only accept a + * single packet. Consequently we are only guaranteed to receive 1 + * packet (at least 8 bytes) even in a non-error case. + * + * At least the DWC2 controller needs to be programmed with the number + * of packets in addition to the number of bytes. A request for 64 + * bytes of data with the maxpacket guessed as 64 (above) yields a + * request for 1 packet. + */ + err = get_descriptor_len(dev, 64, 8); + if (err) + return err; } -#endif dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; @@ -1015,6 +996,33 @@ int usb_new_device(struct usb_device *dev) printf("usb_new_device: invalid max packet size\n"); return -EIO; } + + return 0; +} + +static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read, + struct usb_device *parent, int portnr) +{ + int err; + + /* + * Allocate usb 3.0 device context. + * USB 3.0 (xHCI) protocol tries to allocate device slot + * and related data structures first. This call does that. + * Refer to sec 4.3.2 in xHCI spec rev1.0 + */ + err = usb_alloc_device(dev); + if (err) { + printf("Cannot allocate device context to get SLOT_ID\n"); + return err; + } + err = usb_setup_descriptor(dev, do_read); + if (err) + return err; + err = usb_legacy_port_reset(parent, portnr); + if (err) + return err; + dev->devnum = addr; err = usb_set_address(dev); /* set address */ @@ -1022,45 +1030,49 @@ int usb_new_device(struct usb_device *dev) if (err < 0) { printf("\n USB device not accepting new address " \ "(error=%lX)\n", dev->status); - return -EIO; + return err; } mdelay(10); /* Let the SET_ADDRESS settle */ - tmp = sizeof(dev->descriptor); + return 0; +} + +int usb_select_config(struct usb_device *dev) +{ + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); + int err; + + err = get_descriptor_len(dev, USB_DT_DEVICE_SIZE, USB_DT_DEVICE_SIZE); + if (err) + return err; - err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, - tmpbuf, sizeof(dev->descriptor)); - if (err < tmp) { - if (err < 0) - printf("unable to get device descriptor (error=%d)\n", - err); - else - printf("USB device descriptor short read " \ - "(expected %i, got %i)\n", tmp, err); - return -EIO; - } - memcpy(&dev->descriptor, tmpbuf, sizeof(dev->descriptor)); /* correct le values */ le16_to_cpus(&dev->descriptor.bcdUSB); le16_to_cpus(&dev->descriptor.idVendor); le16_to_cpus(&dev->descriptor.idProduct); le16_to_cpus(&dev->descriptor.bcdDevice); + /* only support for one config for now */ err = usb_get_configuration_no(dev, tmpbuf, 0); if (err < 0) { printf("usb_new_device: Cannot read configuration, " \ "skipping device %04x:%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct); - return -EIO; + return err; } usb_parse_config(dev, tmpbuf, 0); usb_set_maxpacket(dev); - /* we set the default configuration here */ - if (usb_set_configuration(dev, dev->config.desc.bConfigurationValue)) { + /* + * we set the default configuration here + * This seems premature. If the driver wants a different configuration + * it will need to select itself. + */ + err = usb_set_configuration(dev, dev->config.desc.bConfigurationValue); + if (err < 0) { printf("failed to set default configuration " \ "len %d, status %lX\n", dev->act_len, dev->status); - return -EIO; + return err; } debug("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n", dev->descriptor.iManufacturer, dev->descriptor.iProduct, @@ -1080,11 +1092,63 @@ int usb_new_device(struct usb_device *dev) debug("Manufacturer %s\n", dev->mf); debug("Product %s\n", dev->prod); debug("SerialNumber %s\n", dev->serial); - /* now prode if the device is a hub */ - usb_hub_probe(dev, 0); + return 0; } +int usb_setup_device(struct usb_device *dev, bool do_read, + struct usb_device *parent, int portnr) +{ + int addr; + int ret; + + /* We still haven't set the Address yet */ + addr = dev->devnum; + dev->devnum = 0; + + ret = usb_prepare_device(dev, addr, do_read, parent, portnr); + if (ret) + return ret; + ret = usb_select_config(dev); + + return ret; +} + +#ifndef CONFIG_DM_USB +/* + * By the time we get here, the device has gotten a new device ID + * and is in the default state. We need to identify the thing and + * get the ball rolling.. + * + * Returns 0 for success, != 0 for error. + */ +int usb_new_device(struct usb_device *dev) +{ + bool do_read = true; + int err; + + /* + * XHCI needs to issue a Address device command to setup + * proper device context structures, before it can interact + * with the device. So a get_descriptor will fail before any + * of that is done for XHCI unlike EHCI. + */ +#ifdef CONFIG_USB_XHCI + do_read = false; +#endif + err = usb_setup_device(dev, do_read, dev->parent, dev->portnr); + if (err) + return err; + + /* Now probe if the device is a hub */ + err = usb_hub_probe(dev, 0); + if (err < 0) + return err; + + return 0; +} +#endif + __weak int board_usb_init(int index, enum usb_init_type init) { @@ -1096,4 +1160,14 @@ int board_usb_cleanup(int index, enum usb_init_type init) { return 0; } + +bool usb_device_has_child_on_port(struct usb_device *parent, int port) +{ +#ifdef CONFIG_DM_USB + return false; +#else + return parent->children[port] != NULL; +#endif +} + /* EOF */ diff --git a/common/usb_hub.c b/common/usb_hub.c index f54a404a49..c9be530d0b 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -24,11 +24,16 @@ #include <common.h> #include <command.h> +#include <dm.h> +#include <errno.h> #include <asm/processor.h> #include <asm/unaligned.h> #include <linux/ctype.h> #include <asm/byteorder.h> #include <asm/unaligned.h> +#include <dm/root.h> + +DECLARE_GLOBAL_DATA_PTR; #include <usb.h> #ifdef CONFIG_4xx @@ -37,6 +42,7 @@ #define USB_BUFSIZ 512 +/* TODO(sjg@chromium.org): Remove this when CONFIG_DM_USB is defined */ static struct usb_hub_device hub_dev[USB_MAX_HUB]; static int usb_hub_index; @@ -148,14 +154,19 @@ static inline char *portspeed(int portstatus) return speed_str; } -int hub_port_reset(struct usb_device *dev, int port, +int legacy_hub_port_reset(struct usb_device *dev, int port, unsigned short *portstat) { int tries; ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); unsigned short portstatus, portchange; - debug("hub_port_reset: resetting port %d...\n", port); +#ifdef CONFIG_DM_USB + debug("%s: resetting '%s' port %d...\n", __func__, dev->dev->name, + port + 1); +#else + debug("%s: resetting port %d...\n", __func__, port + 1); +#endif for (tries = 0; tries < MAX_TRIES; tries++) { usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET); @@ -213,17 +224,26 @@ int hub_port_reset(struct usb_device *dev, int port, return 0; } +#ifdef CONFIG_DM_USB +int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat) +{ + struct usb_device *udev = dev_get_parentdata(dev); -void usb_hub_port_connect_change(struct usb_device *dev, int port) + return legacy_hub_port_reset(udev, port, portstat); +} +#endif + +int usb_hub_port_connect_change(struct usb_device *dev, int port) { - struct usb_device *usb; ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); unsigned short portstatus; + int ret, speed; /* Check status */ - if (usb_get_port_status(dev, port + 1, portsts) < 0) { + ret = usb_get_port_status(dev, port + 1, portsts); + if (ret < 0) { debug("get_port_status failed\n"); - return; + return ret; } portstatus = le16_to_cpu(portsts->wPortStatus); @@ -237,51 +257,70 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port) /* Disconnect any existing devices under this port */ if (((!(portstatus & USB_PORT_STAT_CONNECTION)) && - (!(portstatus & USB_PORT_STAT_ENABLE))) || (dev->children[port])) { + (!(portstatus & USB_PORT_STAT_ENABLE))) || + usb_device_has_child_on_port(dev, port)) { debug("usb_disconnect(&hub->children[port]);\n"); /* Return now if nothing is connected */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) - return; + return -ENOTCONN; } mdelay(200); /* Reset the port */ - if (hub_port_reset(dev, port, &portstatus) < 0) { + ret = legacy_hub_port_reset(dev, port, &portstatus); + if (ret < 0) { printf("cannot reset port %i!?\n", port + 1); - return; + return ret; } mdelay(200); - /* Allocate a new device struct for it */ - usb = usb_alloc_new_device(dev->controller); - switch (portstatus & USB_PORT_STAT_SPEED_MASK) { case USB_PORT_STAT_SUPER_SPEED: - usb->speed = USB_SPEED_SUPER; + speed = USB_SPEED_SUPER; break; case USB_PORT_STAT_HIGH_SPEED: - usb->speed = USB_SPEED_HIGH; + speed = USB_SPEED_HIGH; break; case USB_PORT_STAT_LOW_SPEED: - usb->speed = USB_SPEED_LOW; + speed = USB_SPEED_LOW; break; default: - usb->speed = USB_SPEED_FULL; + speed = USB_SPEED_FULL; break; } +#ifdef CONFIG_DM_USB + struct udevice *child; + + ret = usb_scan_device(dev->dev, port + 1, speed, &child); +#else + struct usb_device *usb; + + ret = usb_alloc_new_device(dev->controller, &usb); + if (ret) { + printf("cannot create new device: ret=%d", ret); + return ret; + } + dev->children[port] = usb; + usb->speed = speed; usb->parent = dev; usb->portnr = port + 1; /* Run it through the hoops (find a driver, etc) */ - if (usb_new_device(usb)) { + ret = usb_new_device(usb); + if (ret < 0) { /* Woops, disable the port */ - usb_free_device(); + usb_free_device(dev->controller); dev->children[port] = NULL; + } +#endif + if (ret < 0) { debug("hub: disabling port %d\n", port + 1); usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE); } + + return ret; } @@ -294,27 +333,30 @@ static int usb_hub_configure(struct usb_device *dev) struct usb_hub_descriptor *descriptor; struct usb_hub_device *hub; __maybe_unused struct usb_hub_status *hubsts; + int ret; /* "allocate" Hub device */ hub = usb_hub_allocate(); if (hub == NULL) - return -1; + return -ENOMEM; hub->pusb_dev = dev; /* Get the the hub descriptor */ - if (usb_get_hub_descriptor(dev, buffer, 4) < 0) { + ret = usb_get_hub_descriptor(dev, buffer, 4); + if (ret < 0) { debug("usb_hub_configure: failed to get hub " \ "descriptor, giving up %lX\n", dev->status); - return -1; + return ret; } descriptor = (struct usb_hub_descriptor *)buffer; length = min_t(int, descriptor->bLength, sizeof(struct usb_hub_descriptor)); - if (usb_get_hub_descriptor(dev, buffer, length) < 0) { + ret = usb_get_hub_descriptor(dev, buffer, length); + if (ret < 0) { debug("usb_hub_configure: failed to get hub " \ "descriptor 2nd giving up %lX\n", dev->status); - return -1; + return ret; } memcpy((unsigned char *)&hub->desc, buffer, length); /* adjust 16bit values */ @@ -382,13 +424,14 @@ static int usb_hub_configure(struct usb_device *dev) if (sizeof(struct usb_hub_status) > USB_BUFSIZ) { debug("usb_hub_configure: failed to get Status - " \ "too long: %d\n", descriptor->bLength); - return -1; + return -EFBIG; } - if (usb_get_hub_status(dev, buffer) < 0) { + ret = usb_get_hub_status(dev, buffer); + if (ret < 0) { debug("usb_hub_configure: failed to get Status %lX\n", dev->status); - return -1; + return ret; } #ifdef DEBUG @@ -420,6 +463,11 @@ static int usb_hub_configure(struct usb_device *dev) int ret; ulong start = get_timer(0); +#ifdef CONFIG_DM_USB + debug("\n\nScanning '%s' port %d\n", dev->dev->name, i + 1); +#else + debug("\n\nScanning port %d\n", i + 1); +#endif /* * Wait for (whichever finishes first) * - A maximum of 10 seconds @@ -469,7 +517,7 @@ static int usb_hub_configure(struct usb_device *dev) * them again. Works at least with mouse driver */ if (!(portstatus & USB_PORT_STAT_ENABLE) && (portstatus & USB_PORT_STAT_CONNECTION) && - ((dev->children[i]))) { + usb_device_has_child_on_port(dev, i)) { debug("already running port %i " \ "disabled by hub (EMI?), " \ "re-enabling...\n", i + 1); @@ -500,33 +548,107 @@ static int usb_hub_configure(struct usb_device *dev) return 0; } -int usb_hub_probe(struct usb_device *dev, int ifnum) +static int usb_hub_check(struct usb_device *dev, int ifnum) { struct usb_interface *iface; - struct usb_endpoint_descriptor *ep; - int ret; + struct usb_endpoint_descriptor *ep = NULL; iface = &dev->config.if_desc[ifnum]; /* Is it a hub? */ if (iface->desc.bInterfaceClass != USB_CLASS_HUB) - return 0; + goto err; /* Some hubs have a subclass of 1, which AFAICT according to the */ /* specs is not defined, but it works */ if ((iface->desc.bInterfaceSubClass != 0) && (iface->desc.bInterfaceSubClass != 1)) - return 0; + goto err; /* Multiple endpoints? What kind of mutant ninja-hub is this? */ if (iface->desc.bNumEndpoints != 1) - return 0; + goto err; ep = &iface->ep_desc[0]; /* Output endpoint? Curiousier and curiousier.. */ if (!(ep->bEndpointAddress & USB_DIR_IN)) - return 0; + goto err; /* If it's not an interrupt endpoint, we'd better punt! */ if ((ep->bmAttributes & 3) != 3) - return 0; + goto err; /* We found a hub */ debug("USB hub found\n"); + return 0; + +err: + debug("USB hub not found: bInterfaceClass=%d, bInterfaceSubClass=%d, bNumEndpoints=%d\n", + iface->desc.bInterfaceClass, iface->desc.bInterfaceSubClass, + iface->desc.bNumEndpoints); + if (ep) { + debug(" bEndpointAddress=%#x, bmAttributes=%d", + ep->bEndpointAddress, ep->bmAttributes); + } + + return -ENOENT; +} + +int usb_hub_probe(struct usb_device *dev, int ifnum) +{ + int ret; + + ret = usb_hub_check(dev, ifnum); + if (ret) + return 0; ret = usb_hub_configure(dev); return ret; } + +#ifdef CONFIG_DM_USB +int usb_hub_scan(struct udevice *hub) +{ + struct usb_device *udev = dev_get_parentdata(hub); + + return usb_hub_configure(udev); +} + +static int usb_hub_post_bind(struct udevice *dev) +{ + /* Scan the bus for devices */ + return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); +} + +static int usb_hub_post_probe(struct udevice *dev) +{ + debug("%s\n", __func__); + return usb_hub_scan(dev); +} + +static const struct udevice_id usb_hub_ids[] = { + { .compatible = "usb-hub" }, + { } +}; + +U_BOOT_DRIVER(usb_generic_hub) = { + .name = "usb_hub", + .id = UCLASS_USB_HUB, + .of_match = usb_hub_ids, + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; + +UCLASS_DRIVER(usb_hub) = { + .id = UCLASS_USB_HUB, + .name = "usb_hub", + .post_bind = usb_hub_post_bind, + .post_probe = usb_hub_post_probe, + .child_pre_probe = usb_child_pre_probe, + .per_child_auto_alloc_size = sizeof(struct usb_device), + .per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata), +}; + +static const struct usb_device_id hub_id_table[] = { + { + .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS, + .bDeviceClass = USB_CLASS_HUB + }, + { } /* Terminating entry */ +}; + +USB_DEVICE(usb_generic_hub, hub_id_table); + +#endif diff --git a/common/usb_kbd.c b/common/usb_kbd.c index ecc3085cc0..24a1a56141 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -8,6 +8,7 @@ * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> +#include <dm.h> #include <errno.h> #include <malloc.h> #include <stdio_dev.h> @@ -471,60 +472,104 @@ static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) return 1; } +static int probe_usb_keyboard(struct usb_device *dev) +{ + char *stdinname; + struct stdio_dev usb_kbd_dev; + int error; + + /* Try probing the keyboard */ + if (usb_kbd_probe(dev, 0) != 1) + return -ENOENT; + + /* Register the keyboard */ + debug("USB KBD: register.\n"); + memset(&usb_kbd_dev, 0, sizeof(struct stdio_dev)); + strcpy(usb_kbd_dev.name, DEVNAME); + usb_kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + usb_kbd_dev.getc = usb_kbd_getc; + usb_kbd_dev.tstc = usb_kbd_testc; + usb_kbd_dev.priv = (void *)dev; + error = stdio_register(&usb_kbd_dev); + if (error) + return error; + + stdinname = getenv("stdin"); +#ifdef CONFIG_CONSOLE_MUX + error = iomux_doenv(stdin, stdinname); + if (error) + return error; +#else + /* Check if this is the standard input device. */ + if (strcmp(stdinname, DEVNAME)) + return 1; + + /* Reassign the console */ + if (overwrite_console()) + return 1; + + error = console_assign(stdin, DEVNAME); + if (error) + return error; +#endif + + return 0; +} + /* Search for keyboard and register it if found. */ int drv_usb_kbd_init(void) { - struct stdio_dev usb_kbd_dev; - struct usb_device *dev; - char *stdinname = getenv("stdin"); int error, i; + debug("%s: Probing for keyboard\n", __func__); +#ifdef CONFIG_DM_USB + /* + * TODO: We should add USB_DEVICE() declarations to each USB ethernet + * driver and then most of this file can be removed. + */ + struct udevice *bus; + struct uclass *uc; + int ret; + + ret = uclass_get(UCLASS_USB, &uc); + if (ret) + return ret; + uclass_foreach_dev(bus, uc) { + for (i = 0; i < USB_MAX_DEVICE; i++) { + struct usb_device *dev; + + dev = usb_get_dev_index(bus, i); /* get device */ + debug("i=%d, %p\n", i, dev); + if (!dev) + break; /* no more devices available */ + + error = probe_usb_keyboard(dev); + if (!error) + return 1; + if (error && error != -ENOENT) + return error; + } /* for */ + } +#else /* Scan all USB Devices */ for (i = 0; i < USB_MAX_DEVICE; i++) { + struct usb_device *dev; + /* Get USB device. */ dev = usb_get_dev_index(i); if (!dev) - return -1; + break; if (dev->devnum == -1) continue; - /* Try probing the keyboard */ - if (usb_kbd_probe(dev, 0) != 1) - continue; - - /* Register the keyboard */ - debug("USB KBD: register.\n"); - memset(&usb_kbd_dev, 0, sizeof(struct stdio_dev)); - strcpy(usb_kbd_dev.name, DEVNAME); - usb_kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; - usb_kbd_dev.getc = usb_kbd_getc; - usb_kbd_dev.tstc = usb_kbd_testc; - usb_kbd_dev.priv = (void *)dev; - error = stdio_register(&usb_kbd_dev); - if (error) - return error; - -#ifdef CONFIG_CONSOLE_MUX - error = iomux_doenv(stdin, stdinname); - if (error) - return error; -#else - /* Check if this is the standard input device. */ - if (strcmp(stdinname, DEVNAME)) - return 1; - - /* Reassign the console */ - if (overwrite_console()) + error = probe_usb_keyboard(dev); + if (!error) return 1; - - error = console_assign(stdin, DEVNAME); - if (error) + if (error && error != -ENOENT) return error; -#endif - - return 1; } +#endif /* No USB Keyboard found */ return -1; diff --git a/common/usb_storage.c b/common/usb_storage.c index a4ca7a5957..cc9b3e37a1 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -9,6 +9,8 @@ * * Adapted for U-Boot: * (C) Copyright 2001 Denis Peter, MPL AG Switzerland + * Driver model conversion: + * (C) Copyright 2015 Google, Inc * * For BBB support (C) Copyright 2003 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de> @@ -33,9 +35,13 @@ #include <common.h> #include <command.h> +#include <dm.h> +#include <errno.h> #include <inttypes.h> +#include <mapmem.h> #include <asm/byteorder.h> #include <asm/processor.h> +#include <dm/device-internal.h> #include <part.h> #include <usb.h> @@ -56,49 +62,8 @@ static const unsigned char us_direction[256/8] = { #define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1) static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN))); - -/* - * CBI style - */ - -#define US_CBI_ADSC 0 - -/* - * BULK only - */ -#define US_BBB_RESET 0xff -#define US_BBB_GET_MAX_LUN 0xfe - -/* Command Block Wrapper */ -typedef struct { - __u32 dCBWSignature; -# define CBWSIGNATURE 0x43425355 - __u32 dCBWTag; - __u32 dCBWDataTransferLength; - __u8 bCBWFlags; -# define CBWFLAGS_OUT 0x00 -# define CBWFLAGS_IN 0x80 - __u8 bCBWLUN; - __u8 bCDBLength; -# define CBWCDBLENGTH 16 - __u8 CBWCDB[CBWCDBLENGTH]; -} umass_bbb_cbw_t; -#define UMASS_BBB_CBW_SIZE 31 static __u32 CBWTag; -/* Command Status Wrapper */ -typedef struct { - __u32 dCSWSignature; -# define CSWSIGNATURE 0x53425355 - __u32 dCSWTag; - __u32 dCSWDataResidue; - __u8 bCSWStatus; -# define CSWSTATUS_GOOD 0x0 -# define CSWSTATUS_FAILED 0x1 -# define CSWSTATUS_PHASE 0x2 -} umass_bbb_csw_t; -#define UMASS_BBB_CSW_SIZE 13 - #define USB_MAX_STOR_DEV 5 static int usb_max_devs; /* number of highest available usb device */ @@ -145,7 +110,6 @@ struct us_data { static struct us_data usb_stor[USB_MAX_STOR_DEV]; - #define USB_STOR_TRANSPORT_GOOD 0 #define USB_STOR_TRANSPORT_FAILED -1 #define USB_STOR_TRANSPORT_ERROR -2 @@ -158,7 +122,6 @@ unsigned long usb_stor_read(int device, lbaint_t blknr, lbaint_t blkcnt, void *buffer); unsigned long usb_stor_write(int device, lbaint_t blknr, lbaint_t blkcnt, const void *buffer); -struct usb_device * usb_get_dev_index(int index); void uhci_show_temp_int_td(void); #ifdef CONFIG_PARTITIONS @@ -208,30 +171,61 @@ static unsigned int usb_get_max_lun(struct us_data *us) return (len > 0) ? *result : 0; } -static int usb_storage_register(struct usb_device *dev, unsigned char iface) +static int usb_stor_probe_device(struct usb_device *dev) { - int lun, max_lun, start = usb_max_devs; - int nb_dev = 0; - - if (!usb_storage_probe(dev, iface, &usb_stor[usb_max_devs])) - return nb_dev; - - /* - * OK, it's a storage device. Iterate over its LUNs - * and populate `usb_dev_desc'. - */ - max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]); - for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV; lun++) { - usb_dev_desc[usb_max_devs].lun = lun; - if (usb_stor_get_info(dev, &usb_stor[start], - &usb_dev_desc[usb_max_devs]) == 1) { - nb_dev++; + if (dev == NULL) + return -ENOENT; /* no more devices available */ + + debug("\n\nProbing for storage\n"); + if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) { + /* OK, it's a storage device. Iterate over its LUNs + * and populate `usb_dev_desc'. + */ + int lun, max_lun, start = usb_max_devs; + + max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]); + for (lun = 0; + lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV; + lun++) { + struct block_dev_desc *blkdev; + + blkdev = &usb_dev_desc[usb_max_devs]; + memset(blkdev, '\0', sizeof(block_dev_desc_t)); + blkdev->if_type = IF_TYPE_USB; + blkdev->dev = usb_max_devs; + blkdev->part_type = PART_TYPE_UNKNOWN; + blkdev->target = 0xff; + blkdev->type = DEV_TYPE_UNKNOWN; + blkdev->block_read = usb_stor_read; + blkdev->block_write = usb_stor_write; + blkdev->lun = lun; + blkdev->priv = dev; + + if (usb_stor_get_info(dev, &usb_stor[start], + &usb_dev_desc[usb_max_devs]) == + 1) { + usb_max_devs++; + debug("%s: Found device %p\n", __func__, dev); + } } } - return nb_dev; + /* if storage device */ + if (usb_max_devs == USB_MAX_STOR_DEV) { + printf("max USB Storage Device reached: %d stopping\n", + usb_max_devs); + return -ENOSPC; + } + + return 0; +} + +void usb_stor_reset(void) +{ + usb_max_devs = 0; } +#ifndef CONFIG_DM_USB /******************************************************************************* * scan the usb and reports device info * to the user if mode = 1 @@ -239,42 +233,21 @@ static int usb_storage_register(struct usb_device *dev, unsigned char iface) */ int usb_stor_scan(int mode) { - unsigned char i, iface; - struct usb_device *dev; + unsigned char i; if (mode == 1) printf(" scanning usb for storage devices... "); usb_disable_asynch(1); /* asynch transfer not allowed */ - for (i = 0; i < USB_MAX_STOR_DEV; i++) { - memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t)); - usb_dev_desc[i].if_type = IF_TYPE_USB; - usb_dev_desc[i].dev = i; - usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - usb_dev_desc[i].target = 0xff; - usb_dev_desc[i].type = DEV_TYPE_UNKNOWN; - usb_dev_desc[i].block_read = usb_stor_read; - usb_dev_desc[i].block_write = usb_stor_write; - } - - usb_max_devs = 0; + usb_stor_reset(); for (i = 0; i < USB_MAX_DEVICE; i++) { + struct usb_device *dev; + dev = usb_get_dev_index(i); /* get device */ debug("i=%d\n", i); - if (dev == NULL) - break; /* no more devices available */ - - for (iface = 0; iface < dev->config.no_of_if; iface++) { - usb_max_devs += usb_storage_register(dev, iface); - } - - /* if storage device */ - if (usb_max_devs == USB_MAX_STOR_DEV) { - printf("max USB Storage Device reached: %d stopping\n", - usb_max_devs); + if (usb_stor_probe_device(dev)) break; - } } /* for */ usb_disable_asynch(0); /* asynch transfer allowed */ @@ -283,6 +256,7 @@ int usb_stor_scan(int mode) return 0; return -1; } +#endif static int usb_stor_irq(struct usb_device *dev) { @@ -347,8 +321,9 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length) /* set up the transfer loop */ do { /* transfer the data */ - debug("Bulk xfer %p(%d) try #%d\n", - buf, this_xfer, 11 - maxtry); + debug("Bulk xfer 0x%lx(%d) try #%d\n", + (ulong)map_to_sysmem(buf), this_xfer, + 11 - maxtry); result = usb_bulk_msg(us->pusb_dev, pipe, buf, this_xfer, &partial, USB_CNTL_TIMEOUT * 5); @@ -494,7 +469,7 @@ static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us) int actlen; int dir_in; unsigned int pipe; - ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1); + ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1); dir_in = US_DIRECTION(srb->cmd[0]); @@ -670,7 +645,7 @@ static int usb_stor_BBB_transport(ccb *srb, struct us_data *us) int dir_in; int actlen, data_actlen; unsigned int pipe, pipein, pipeout; - ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1); + ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1); #ifdef BBB_XPORT_TRACE unsigned char *ptr; int index; @@ -1059,7 +1034,7 @@ unsigned long usb_stor_read(int device, lbaint_t blknr, unsigned short smallblks; struct usb_device *dev; struct us_data *ss; - int retry, i; + int retry; ccb *srb = &usb_ccb; if (blkcnt == 0) @@ -1067,14 +1042,11 @@ unsigned long usb_stor_read(int device, lbaint_t blknr, device &= 0xff; /* Setup device */ - debug("\nusb_read: dev %d \n", device); - dev = NULL; - for (i = 0; i < USB_MAX_DEVICE; i++) { - dev = usb_get_dev_index(i); - if (dev == NULL) - return 0; - if (dev->devnum == usb_dev_desc[device].target) - break; + debug("\nusb_read: dev %d\n", device); + dev = usb_dev_desc[device].priv; + if (!dev) { + debug("%s: No device\n", __func__); + return 0; } ss = (struct us_data *)dev->privptr; @@ -1132,7 +1104,7 @@ unsigned long usb_stor_write(int device, lbaint_t blknr, unsigned short smallblks; struct usb_device *dev; struct us_data *ss; - int retry, i; + int retry; ccb *srb = &usb_ccb; if (blkcnt == 0) @@ -1140,15 +1112,10 @@ unsigned long usb_stor_write(int device, lbaint_t blknr, device &= 0xff; /* Setup device */ - debug("\nusb_write: dev %d \n", device); - dev = NULL; - for (i = 0; i < USB_MAX_DEVICE; i++) { - dev = usb_get_dev_index(i); - if (dev == NULL) - return 0; - if (dev->devnum == usb_dev_desc[device].target) - break; - } + debug("\nusb_write: dev %d\n", device); + dev = usb_dev_desc[device].priv; + if (!dev) + return 0; ss = (struct us_data *)dev->privptr; usb_disable_asynch(1); /* asynch transfer not allowed */ @@ -1232,6 +1199,7 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum, iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE || iface->desc.bInterfaceSubClass < US_SC_MIN || iface->desc.bInterfaceSubClass > US_SC_MAX) { + debug("Not mass storage\n"); /* if it's not a mass storage, we go no further */ return 0; } @@ -1358,8 +1326,10 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, pccb->lun = dev_desc->lun; debug(" address %d\n", dev_desc->target); - if (usb_inquiry(pccb, ss)) + if (usb_inquiry(pccb, ss)) { + debug("%s: usb_inquiry() failed\n", __func__); return -1; + } perq = usb_stor_buf[0]; modi = usb_stor_buf[1]; @@ -1369,6 +1339,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, * they would not respond to test_unit_ready . */ if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) { + debug("%s: unknown/unsupported device\n", __func__); return 0; } if ((modi&0x80) == 0x80) { @@ -1431,3 +1402,46 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, debug("partype: %d\n", dev_desc->part_type); return 1; } + +#ifdef CONFIG_DM_USB + +static int usb_mass_storage_probe(struct udevice *dev) +{ + struct usb_device *udev = dev_get_parentdata(dev); + int ret; + + usb_disable_asynch(1); /* asynch transfer not allowed */ + ret = usb_stor_probe_device(udev); + usb_disable_asynch(0); /* asynch transfer allowed */ + + return ret; +} + +static const struct udevice_id usb_mass_storage_ids[] = { + { .compatible = "usb-mass-storage" }, + { } +}; + +U_BOOT_DRIVER(usb_mass_storage) = { + .name = "usb_mass_storage", + .id = UCLASS_MASS_STORAGE, + .of_match = usb_mass_storage_ids, + .probe = usb_mass_storage_probe, +}; + +UCLASS_DRIVER(usb_mass_storage) = { + .id = UCLASS_MASS_STORAGE, + .name = "usb_mass_storage", +}; + +static const struct usb_device_id mass_storage_id_table[] = { + { + .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, + .bInterfaceClass = USB_CLASS_MASS_STORAGE + }, + { } /* Terminating entry */ +}; + +USB_DEVICE(usb_mass_storage, mass_storage_id_table); + +#endif |