diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 36 | ||||
-rw-r--r-- | common/Makefile | 4 | ||||
-rw-r--r-- | common/board_r.c | 14 | ||||
-rw-r--r-- | common/cmd_date.c | 57 | ||||
-rw-r--r-- | common/cmd_i2c.c | 63 | ||||
-rw-r--r-- | common/cmd_mem.c | 8 | ||||
-rw-r--r-- | common/cmd_part.c | 2 | ||||
-rw-r--r-- | common/cmd_pmic.c | 210 | ||||
-rw-r--r-- | common/cmd_regulator.c | 408 | ||||
-rw-r--r-- | common/cmd_setexpr.c | 32 | ||||
-rw-r--r-- | common/edid.c | 105 | ||||
-rw-r--r-- | common/fdt_support.c | 2 | ||||
-rw-r--r-- | common/image-android.c | 27 | ||||
-rw-r--r-- | common/image.c | 2 | ||||
-rw-r--r-- | common/spl/spl.c | 2 | ||||
-rw-r--r-- | common/spl/spl_mmc.c | 131 | ||||
-rw-r--r-- | common/usb.c | 49 | ||||
-rw-r--r-- | common/usb_hub.c | 11 |
18 files changed, 1041 insertions, 122 deletions
diff --git a/common/Kconfig b/common/Kconfig index 15759f75aa3..5b8b0c3fe7e 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -460,4 +460,40 @@ config BOOTSTAGE_STASH_SIZE endmenu +menu "Power commands" +config CMD_PMIC + bool "Enable Driver Model PMIC command" + depends on DM_PMIC + help + This is the pmic command, based on a driver model pmic's API. + Command features are unchanged: + - list - list pmic devices + - pmic dev <id> - show or [set] operating pmic device (NEW) + - pmic dump - dump registers + - pmic read address - read byte of register at address + - pmic write address - write byte to register at address + The only one change for this command is 'dev' subcommand. + +config CMD_REGULATOR + bool "Enable Driver Model REGULATOR command" + depends on DM_REGULATOR + help + This command is based on driver model regulator's API. + User interface features: + - list - list regulator devices + - regulator dev <id> - show or [set] operating regulator device + - regulator info - print constraints info + - regulator status - print operating status + - regulator value <val] <-f> - print/[set] voltage value [uV] + - regulator current <val> - print/[set] current value [uA] + - regulator mode <id> - print/[set] operating mode id + - regulator enable - enable the regulator output + - regulator disable - disable the regulator output + + The '-f' (force) option can be used for set the value which exceeds + the limits, which are found in device-tree and are kept in regulator's + uclass platdata structure. + +endmenu + endmenu diff --git a/common/Makefile b/common/Makefile index 9084c73ad99..d6c1d4844dd 100644 --- a/common/Makefile +++ b/common/Makefile @@ -211,6 +211,10 @@ obj-$(CONFIG_UPDATE_TFTP) += update.o obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o obj-$(CONFIG_CMD_DFU) += cmd_dfu.o obj-$(CONFIG_CMD_GPT) += cmd_gpt.o + +# Power +obj-$(CONFIG_CMD_PMIC) += cmd_pmic.o +obj-$(CONFIG_CMD_REGULATOR) += cmd_regulator.o endif ifdef CONFIG_SPL_BUILD diff --git a/common/board_r.c b/common/board_r.c index 1a46f6224fa..bf6c72572d7 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -480,17 +480,6 @@ static int initr_malloc_bootparams(void) } #endif -#ifdef CONFIG_SC3 -/* TODO: with new initcalls, move this into the driver */ -extern void sc3_read_eeprom(void); - -static int initr_sc3_read_eeprom(void) -{ - sc3_read_eeprom(); - return 0; -} -#endif - static int initr_jumptable(void) { jumptable_init(); @@ -804,9 +793,6 @@ init_fnc_t init_sequence_r[] = { #endif INIT_FUNC_WATCHDOG_RESET initr_secondary_cpu, -#ifdef CONFIG_SC3 - initr_sc3_read_eeprom, -#endif #if defined(CONFIG_ID_EEPROM) || defined(CONFIG_SYS_I2C_MAC_OFFSET) mac_read_from_eeprom, #endif diff --git a/common/cmd_date.c b/common/cmd_date.c index 4a653e5bcfa..61727e3d1f2 100644 --- a/common/cmd_date.c +++ b/common/cmd_date.c @@ -10,6 +10,7 @@ */ #include <common.h> #include <command.h> +#include <dm.h> #include <rtc.h> #include <i2c.h> @@ -33,10 +34,18 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct rtc_time tm; int rcode = 0; - int old_bus; + int old_bus __maybe_unused; /* switch to correct I2C bus */ -#ifdef CONFIG_SYS_I2C +#ifdef CONFIG_DM_I2C + struct udevice *dev; + + rcode = uclass_get_device(UCLASS_RTC, 0, &dev); + if (rcode) { + printf("Cannot find RTC: err=%d\n", rcode); + return CMD_RET_FAILURE; + } +#elif defined(CONFIG_SYS_I2C) old_bus = i2c_get_bus_num(); i2c_set_bus_num(CONFIG_SYS_RTC_BUS_NUM); #else @@ -48,32 +57,50 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) case 2: /* set date & time */ if (strcmp(argv[1],"reset") == 0) { puts ("Reset RTC...\n"); - rtc_reset (); +#ifdef CONFIG_DM_I2C + rcode = dm_rtc_reset(dev); + if (!rcode) + rcode = dm_rtc_set(dev, &default_tm); +#else + rtc_reset(); rcode = rtc_set(&default_tm); +#endif if (rcode) puts("## Failed to set date after RTC reset\n"); } else { /* initialize tm with current time */ - rcode = rtc_get (&tm); - - if(!rcode) { +#ifdef CONFIG_DM_I2C + rcode = dm_rtc_get(dev, &tm); +#else + rcode = rtc_get(&tm); +#endif + if (!rcode) { /* insert new date & time */ - if (mk_date (argv[1], &tm) != 0) { + if (mk_date(argv[1], &tm) != 0) { puts ("## Bad date format\n"); break; } /* and write to RTC */ - rcode = rtc_set (&tm); - if(rcode) - puts("## Set date failed\n"); +#ifdef CONFIG_DM_I2C + rcode = dm_rtc_set(dev, &tm); +#else + rcode = rtc_set(&tm); +#endif + if (rcode) { + printf("## Set date failed: err=%d\n", + rcode); + } } else { puts("## Get date failed\n"); } } /* FALL TROUGH */ case 1: /* get date & time */ - rcode = rtc_get (&tm); - +#ifdef CONFIG_DM_I2C + rcode = dm_rtc_get(dev, &tm); +#else + rcode = rtc_get(&tm); +#endif if (rcode) { puts("## Get date failed\n"); break; @@ -93,11 +120,11 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* switch back to original I2C bus */ #ifdef CONFIG_SYS_I2C i2c_set_bus_num(old_bus); -#else +#elif !defined(CONFIG_DM_I2C) I2C_SET_BUS(old_bus); #endif - return rcode; + return rcode ? CMD_RET_FAILURE : 0; } /* @@ -201,7 +228,7 @@ int mk_date (const char *datestr, struct rtc_time *tmp) tmp->tm_min = val; /* calculate day of week */ - GregorianDay (tmp); + rtc_calc_weekday(tmp); return (0); default: diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c index ad38cbf6e17..1bc0db860c3 100644 --- a/common/cmd_i2c.c +++ b/common/cmd_i2c.c @@ -1623,6 +1623,27 @@ int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) } #endif /* CONFIG_I2C_EDID */ +#ifdef CONFIG_DM_I2C +static void show_bus(struct udevice *bus) +{ + struct udevice *dev; + + printf("Bus %d:\t%s", bus->req_seq, bus->name); + if (device_active(bus)) + printf(" (active %d)", bus->seq); + printf("\n"); + for (device_find_first_child(bus, &dev); + dev; + device_find_next_child(&dev)) { + struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); + + printf(" %02x: %s, offset len %x, flags %x\n", + chip->chip_addr, dev->name, chip->offset_len, + chip->flags); + } +} +#endif + /** * do_i2c_show_bus() - Handle the "i2c bus" command-line command * @cmdtp: Command data struct pointer @@ -1632,20 +1653,30 @@ int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) * * Returns zero always. */ -#if defined(CONFIG_SYS_I2C) +#if defined(CONFIG_SYS_I2C) || defined(CONFIG_DM_I2C) static int do_i2c_show_bus(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - int i; -#ifndef CONFIG_SYS_I2C_DIRECT_BUS - int j; -#endif - if (argc == 1) { /* show all busses */ +#ifdef CONFIG_DM_I2C + struct udevice *bus; + struct uclass *uc; + int ret; + + ret = uclass_get(UCLASS_I2C, &uc); + if (ret) + return CMD_RET_FAILURE; + uclass_foreach_dev(bus, uc) + show_bus(bus); +#else + int i; + for (i = 0; i < CONFIG_SYS_NUM_I2C_BUSES; i++) { printf("Bus %d:\t%s", i, I2C_ADAP_NR(i)->name); #ifndef CONFIG_SYS_I2C_DIRECT_BUS + int j; + for (j = 0; j < CONFIG_SYS_I2C_MAX_HOPS; j++) { if (i2c_bus[i].next_hop[j].chip == 0) break; @@ -1657,15 +1688,30 @@ static int do_i2c_show_bus(cmd_tbl_t *cmdtp, int flag, int argc, #endif printf("\n"); } +#endif } else { + int i; + /* show specific bus */ i = simple_strtoul(argv[1], NULL, 10); +#ifdef CONFIG_DM_I2C + struct udevice *bus; + int ret; + + ret = uclass_get_device_by_seq(UCLASS_I2C, i, &bus); + if (ret) { + printf("Invalid bus %d: err=%d\n", i, ret); + return CMD_RET_FAILURE; + } + show_bus(bus); +#else if (i >= CONFIG_SYS_NUM_I2C_BUSES) { printf("Invalid bus %d\n", i); return -1; } printf("Bus %d:\t%s", i, I2C_ADAP_NR(i)->name); #ifndef CONFIG_SYS_I2C_DIRECT_BUS + int j; for (j = 0; j < CONFIG_SYS_I2C_MAX_HOPS; j++) { if (i2c_bus[i].next_hop[j].chip == 0) break; @@ -1676,6 +1722,7 @@ static int do_i2c_show_bus(cmd_tbl_t *cmdtp, int flag, int argc, } #endif printf("\n"); +#endif } return 0; @@ -1835,7 +1882,7 @@ static int do_i2c_reset(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv } static cmd_tbl_t cmd_i2c_sub[] = { -#if defined(CONFIG_SYS_I2C) +#if defined(CONFIG_SYS_I2C) || defined(CONFIG_DM_I2C) U_BOOT_CMD_MKENT(bus, 1, 1, do_i2c_show_bus, "", ""), #endif U_BOOT_CMD_MKENT(crc32, 3, 1, do_i2c_crc, "", ""), @@ -1902,7 +1949,7 @@ static int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) /***************************************************/ #ifdef CONFIG_SYS_LONGHELP static char i2c_help_text[] = -#if defined(CONFIG_SYS_I2C) +#if defined(CONFIG_SYS_I2C) || defined(CONFIG_DM_I2C) "bus [muxtype:muxaddr:muxchannel] - show I2C bus info\n" #endif "crc32 chip address[.0, .1, .2] count - compute CRC32 checksum\n" diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 5d8c9e6c061..2e85d53dd23 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -1227,7 +1227,7 @@ static int do_mem_crc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ac = argc - 1; #ifdef CONFIG_HASH_VERIFY if (strcmp(*av, "-v") == 0) { - flags |= HASH_FLAG_VERIFY; + flags |= HASH_FLAG_VERIFY | HASH_FLAG_ENV; av++; ac--; } @@ -1303,7 +1303,7 @@ U_BOOT_CMD( #ifdef CONFIG_CMD_CRC32 -#ifndef CONFIG_CRC32_VERIFY +#ifndef CONFIG_HASH_VERIFY U_BOOT_CMD( crc32, 4, 1, do_mem_crc, @@ -1311,7 +1311,7 @@ U_BOOT_CMD( "address count [addr]\n - compute CRC32 checksum [save at addr]" ); -#else /* CONFIG_CRC32_VERIFY */ +#else /* CONFIG_HASH_VERIFY */ U_BOOT_CMD( crc32, 5, 1, do_mem_crc, @@ -1320,7 +1320,7 @@ U_BOOT_CMD( "-v address count crc\n - verify crc of memory area" ); -#endif /* CONFIG_CRC32_VERIFY */ +#endif /* CONFIG_HASH_VERIFY */ #endif diff --git a/common/cmd_part.c b/common/cmd_part.c index d04588ec22c..8483c1230d5 100644 --- a/common/cmd_part.c +++ b/common/cmd_part.c @@ -128,7 +128,7 @@ static int do_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( part, CONFIG_SYS_MAXARGS, 1, do_part, "disk partition related commands", - "part uuid <interface> <dev>:<part>\n" + "uuid <interface> <dev>:<part>\n" " - print partition UUID\n" "part uuid <interface> <dev>:<part> <varname>\n" " - set environment variable to partition UUID\n" diff --git a/common/cmd_pmic.c b/common/cmd_pmic.c new file mode 100644 index 00000000000..970767cdfa7 --- /dev/null +++ b/common/cmd_pmic.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2014-2015 Samsung Electronics + * Przemyslaw Marczak <p.marczak@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <errno.h> +#include <dm.h> +#include <dm/uclass-internal.h> +#include <power/pmic.h> + +#define LIMIT_DEV 32 +#define LIMIT_PARENT 20 + +static struct udevice *currdev; + +static int failure(int ret) +{ + printf("Error: %d (%s)\n", ret, errno_str(ret)); + + return CMD_RET_FAILURE; +} + +static int do_dev(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *name; + int ret = -ENODEV; + + switch (argc) { + case 2: + name = argv[1]; + ret = pmic_get(name, &currdev); + if (ret) { + printf("Can't get PMIC: %s!\n", name); + return failure(ret); + } + case 1: + if (!currdev) { + printf("PMIC device is not set!\n\n"); + return CMD_RET_USAGE; + } + + printf("dev: %d @ %s\n", currdev->seq, currdev->name); + } + + return CMD_RET_SUCCESS; +} + +static int do_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + int ret; + + printf("| %-*.*s| %-*.*s| %s @ %s\n", + LIMIT_DEV, LIMIT_DEV, "Name", + LIMIT_PARENT, LIMIT_PARENT, "Parent name", + "Parent uclass", "seq"); + + for (ret = uclass_first_device(UCLASS_PMIC, &dev); dev; + ret = uclass_next_device(&dev)) { + if (ret) + continue; + + printf("| %-*.*s| %-*.*s| %s @ %d\n", + LIMIT_DEV, LIMIT_DEV, dev->name, + LIMIT_PARENT, LIMIT_PARENT, dev->parent->name, + dev_get_uclass_name(dev->parent), dev->parent->seq); + } + + if (ret) + return CMD_RET_FAILURE; + + return CMD_RET_SUCCESS; +} + +static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + uint8_t value; + uint reg; + int ret; + + if (!currdev) { + printf("First, set the PMIC device!\n"); + return CMD_RET_USAGE; + } + + dev = currdev; + + printf("Dump pmic: %s registers\n", dev->name); + + for (reg = 0; reg < pmic_reg_count(dev); reg++) { + ret = pmic_read(dev, reg, &value, 1); + if (ret) { + printf("Can't read register: %d\n", reg); + return failure(ret); + } + + if (!(reg % 16)) + printf("\n0x%02x: ", reg); + + printf("%2.2x ", value); + } + printf("\n"); + + return CMD_RET_SUCCESS; +} + +static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + int regs, ret; + uint8_t value; + uint reg; + + if (!currdev) { + printf("First, set the PMIC device!\n"); + return CMD_RET_USAGE; + } + + dev = currdev; + + if (argc != 2) + return CMD_RET_USAGE; + + reg = simple_strtoul(argv[1], NULL, 0); + regs = pmic_reg_count(dev); + if (reg > regs) { + printf("PMIC max reg: %d\n", regs); + return failure(-EFAULT); + } + + ret = pmic_read(dev, reg, &value, 1); + if (ret) { + printf("Can't read PMIC register: %d!\n", reg); + return failure(ret); + } + + printf("0x%02x: 0x%2.2x\n", reg, value); + + return CMD_RET_SUCCESS; +} + +static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + int regs, ret; + uint8_t value; + uint reg; + + if (!currdev) { + printf("First, set the PMIC device!\n"); + return CMD_RET_USAGE; + } + + dev = currdev; + + if (argc != 3) + return CMD_RET_USAGE; + + reg = simple_strtoul(argv[1], NULL, 0); + regs = pmic_reg_count(dev); + if (reg > regs) { + printf("PMIC max reg: %d\n", regs); + return failure(-EFAULT); + } + + value = simple_strtoul(argv[2], NULL, 0); + + ret = pmic_write(dev, reg, &value, 1); + if (ret) { + printf("Can't write PMIC register: %d!\n", reg); + return failure(ret); + } + + return CMD_RET_SUCCESS; +} + +static cmd_tbl_t subcmd[] = { + U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""), + U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""), + U_BOOT_CMD_MKENT(dump, 1, 1, do_dump, "", ""), + U_BOOT_CMD_MKENT(read, 2, 1, do_read, "", ""), + U_BOOT_CMD_MKENT(write, 3, 1, do_write, "", ""), +}; + +static int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + cmd_tbl_t *cmd; + + argc--; + argv++; + + cmd = find_cmd_tbl(argv[0], subcmd, ARRAY_SIZE(subcmd)); + if (cmd == NULL || argc > cmd->maxargs) + return CMD_RET_USAGE; + + return cmd->cmd(cmdtp, flag, argc, argv); +} + +U_BOOT_CMD(pmic, CONFIG_SYS_MAXARGS, 1, do_pmic, + " operations", + "list - list pmic devices\n" + "pmic dev [name] - show or [set] operating PMIC device\n" + "pmic dump - dump registers\n" + "pmic read address - read byte of register at address\n" + "pmic write address - write byte to register at address\n" +); diff --git a/common/cmd_regulator.c b/common/cmd_regulator.c new file mode 100644 index 00000000000..6149d1ee440 --- /dev/null +++ b/common/cmd_regulator.c @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2014-2015 Samsung Electronics + * Przemyslaw Marczak <p.marczak@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <errno.h> +#include <dm.h> +#include <dm/uclass-internal.h> +#include <power/regulator.h> + +#define LIMIT_DEVNAME 20 +#define LIMIT_OFNAME 32 +#define LIMIT_INFO 18 + +static struct udevice *currdev; + +static int failure(int ret) +{ + printf("Error: %d (%s)\n", ret, errno_str(ret)); + + return CMD_RET_FAILURE; +} + +static int do_dev(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + const char *name; + int ret = -ENXIO; + + switch (argc) { + case 2: + name = argv[1]; + ret = regulator_get_by_platname(name, &currdev); + if (ret) { + printf("Can't get the regulator: %s!\n", name); + return failure(ret); + } + case 1: + if (!currdev) { + printf("Regulator device is not set!\n\n"); + return CMD_RET_USAGE; + } + + uc_pdata = dev_get_uclass_platdata(currdev); + if (!uc_pdata) { + printf("%s: no regulator platform data!\n", currdev->name); + return failure(ret); + } + + printf("dev: %s @ %s\n", uc_pdata->name, currdev->name); + } + + return CMD_RET_SUCCESS; +} + +static int curr_dev_and_platdata(struct udevice **devp, + struct dm_regulator_uclass_platdata **uc_pdata, + bool allow_type_fixed) +{ + *devp = NULL; + *uc_pdata = NULL; + + if (!currdev) { + printf("First, set the regulator device!\n"); + return CMD_RET_FAILURE; + } + + *devp = currdev; + + *uc_pdata = dev_get_uclass_platdata(*devp); + if (!*uc_pdata) { + error("Regulator: %s - missing platform data!", currdev->name); + return CMD_RET_FAILURE; + } + + if (!allow_type_fixed && (*uc_pdata)->type == REGULATOR_TYPE_FIXED) { + printf("Operation not allowed for fixed regulator!\n"); + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + +static int do_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + struct udevice *dev; + int ret; + + printf("| %-*.*s| %-*.*s| %s\n", + LIMIT_DEVNAME, LIMIT_DEVNAME, "Device", + LIMIT_OFNAME, LIMIT_OFNAME, "regulator-name", + "Parent"); + + for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev; + ret = uclass_find_next_device(&dev)) { + if (ret) + continue; + + uc_pdata = dev_get_uclass_platdata(dev); + printf("| %-*.*s| %-*.*s| %s\n", + LIMIT_DEVNAME, LIMIT_DEVNAME, dev->name, + LIMIT_OFNAME, LIMIT_OFNAME, uc_pdata->name, + dev->parent->name); + } + + return ret; +} + +static int constraint(const char *name, int val, const char *val_name) +{ + printf("%-*s", LIMIT_INFO, name); + if (val < 0) { + printf(" %s (err: %d)\n", errno_str(val), val); + return val; + } + + if (val_name) + printf(" %d (%s)\n", val, val_name); + else + printf(" %d\n", val); + + return 0; +} + +static const char *get_mode_name(struct dm_regulator_mode *mode, + int mode_count, + int mode_id) +{ + while (mode_count--) { + if (mode->id == mode_id) + return mode->name; + mode++; + } + + return NULL; +} + +static int do_info(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct dm_regulator_uclass_platdata *uc_pdata; + struct dm_regulator_mode *modes; + const char *parent_uc; + int mode_count; + int ret; + int i; + + ret = curr_dev_and_platdata(&dev, &uc_pdata, true); + if (ret) + return ret; + + parent_uc = dev_get_uclass_name(dev->parent); + + printf("%s\n%-*s %s\n%-*s %s\n%-*s %s\n%-*s %s\n%-*s\n", + "Regulator info:", + LIMIT_INFO, "* regulator-name:", uc_pdata->name, + LIMIT_INFO, "* device name:", dev->name, + LIMIT_INFO, "* parent name:", dev->parent->name, + LIMIT_INFO, "* parent uclass:", parent_uc, + LIMIT_INFO, "* constraints:"); + + constraint(" - min uV:", uc_pdata->min_uV, NULL); + constraint(" - max uV:", uc_pdata->max_uV, NULL); + constraint(" - min uA:", uc_pdata->min_uA, NULL); + constraint(" - max uA:", uc_pdata->max_uA, NULL); + constraint(" - always on:", uc_pdata->always_on, + uc_pdata->always_on ? "true" : "false"); + constraint(" - boot on:", uc_pdata->boot_on, + uc_pdata->boot_on ? "true" : "false"); + + mode_count = regulator_mode(dev, &modes); + constraint("* op modes:", mode_count, NULL); + + for (i = 0; i < mode_count; i++, modes++) + constraint(" - mode id:", modes->id, modes->name); + + return CMD_RET_SUCCESS; +} + +static int do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + int current, value, mode, ret; + const char *mode_name = NULL; + struct udevice *dev; + bool enabled; + + ret = curr_dev_and_platdata(&dev, &uc_pdata, true); + if (ret) + return ret; + + printf("Regulator %s status:\n", uc_pdata->name); + + enabled = regulator_get_enable(dev); + constraint(" * enable:", enabled, enabled ? "true" : "false"); + + value = regulator_get_value(dev); + constraint(" * value uV:", value, NULL); + + current = regulator_get_current(dev); + constraint(" * current uA:", current, NULL); + + mode = regulator_get_mode(dev); + mode_name = get_mode_name(uc_pdata->mode, uc_pdata->mode_count, mode); + constraint(" * mode id:", mode, mode_name); + + return CMD_RET_SUCCESS; +} + +static int do_value(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct dm_regulator_uclass_platdata *uc_pdata; + int value; + int force; + int ret; + + ret = curr_dev_and_platdata(&dev, &uc_pdata, argc == 1); + if (ret) + return ret; + + if (argc == 1) { + ret = regulator_get_value(dev); + if (ret < 0) { + printf("Regulator: %s - can't get the Voltage!\n", + uc_pdata->name); + return failure(ret); + } + + printf("%d uV\n", ret); + return CMD_RET_SUCCESS; + } + + if (argc == 3) + force = !strcmp("-f", argv[2]); + else + force = 0; + + value = simple_strtoul(argv[1], NULL, 0); + if ((value < uc_pdata->min_uV || value > uc_pdata->max_uV) && !force) { + printf("Value exceeds regulator constraint limits\n"); + return CMD_RET_FAILURE; + } + + ret = regulator_set_value(dev, value); + if (ret) { + printf("Regulator: %s - can't set the Voltage!\n", + uc_pdata->name); + return failure(ret); + } + + return CMD_RET_SUCCESS; +} + +static int do_current(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct dm_regulator_uclass_platdata *uc_pdata; + int current; + int ret; + + ret = curr_dev_and_platdata(&dev, &uc_pdata, argc == 1); + if (ret) + return ret; + + if (argc == 1) { + ret = regulator_get_current(dev); + if (ret < 0) { + printf("Regulator: %s - can't get the Current!\n", + uc_pdata->name); + return failure(ret); + } + + printf("%d uA\n", ret); + return CMD_RET_SUCCESS; + } + + current = simple_strtoul(argv[1], NULL, 0); + if (current < uc_pdata->min_uA || current > uc_pdata->max_uA) { + printf("Current exceeds regulator constraint limits\n"); + return CMD_RET_FAILURE; + } + + ret = regulator_set_current(dev, current); + if (ret) { + printf("Regulator: %s - can't set the Current!\n", + uc_pdata->name); + return failure(ret); + } + + return CMD_RET_SUCCESS; +} + +static int do_mode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct dm_regulator_uclass_platdata *uc_pdata; + int mode; + int ret; + + ret = curr_dev_and_platdata(&dev, &uc_pdata, false); + if (ret) + return ret; + + if (argc == 1) { + ret = regulator_get_mode(dev); + if (ret < 0) { + printf("Regulator: %s - can't get the operation mode!\n", + uc_pdata->name); + return failure(ret); + } + + printf("mode id: %d\n", ret); + return CMD_RET_SUCCESS; + } + + mode = simple_strtoul(argv[1], NULL, 0); + + ret = regulator_set_mode(dev, mode); + if (ret) { + printf("Regulator: %s - can't set the operation mode!\n", + uc_pdata->name); + return failure(ret); + } + + return CMD_RET_SUCCESS; +} + +static int do_enable(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct dm_regulator_uclass_platdata *uc_pdata; + int ret; + + ret = curr_dev_and_platdata(&dev, &uc_pdata, true); + if (ret) + return ret; + + ret = regulator_set_enable(dev, true); + if (ret) { + printf("Regulator: %s - can't enable!\n", uc_pdata->name); + return failure(ret); + } + + return CMD_RET_SUCCESS; +} + +static int do_disable(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct dm_regulator_uclass_platdata *uc_pdata; + int ret; + + ret = curr_dev_and_platdata(&dev, &uc_pdata, true); + if (ret) + return ret; + + ret = regulator_set_enable(dev, false); + if (ret) { + printf("Regulator: %s - can't disable!\n", uc_pdata->name); + return failure(ret); + } + + return CMD_RET_SUCCESS; +} + +static cmd_tbl_t subcmd[] = { + U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""), + U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""), + U_BOOT_CMD_MKENT(info, 2, 1, do_info, "", ""), + U_BOOT_CMD_MKENT(status, 2, 1, do_status, "", ""), + U_BOOT_CMD_MKENT(value, 3, 1, do_value, "", ""), + U_BOOT_CMD_MKENT(current, 3, 1, do_current, "", ""), + U_BOOT_CMD_MKENT(mode, 2, 1, do_mode, "", ""), + U_BOOT_CMD_MKENT(enable, 1, 1, do_enable, "", ""), + U_BOOT_CMD_MKENT(disable, 1, 1, do_disable, "", ""), +}; + +static int do_regulator(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + cmd_tbl_t *cmd; + + argc--; + argv++; + + cmd = find_cmd_tbl(argv[0], subcmd, ARRAY_SIZE(subcmd)); + if (cmd == NULL || argc > cmd->maxargs) + return CMD_RET_USAGE; + + return cmd->cmd(cmdtp, flag, argc, argv); +} + +U_BOOT_CMD(regulator, CONFIG_SYS_MAXARGS, 1, do_regulator, + "uclass operations", + "list - list UCLASS regulator devices\n" + "regulator dev [regulator-name] - show/[set] operating regulator device\n" + "regulator info - print constraints info\n" + "regulator status - print operating status\n" + "regulator value [val] [-f] - print/[set] voltage value [uV] (force)\n" + "regulator current [val] - print/[set] current value [uA]\n" + "regulator mode [id] - print/[set] operating mode id\n" + "regulator enable - enable the regulator output\n" + "regulator disable - disable the regulator output\n" +); diff --git a/common/cmd_setexpr.c b/common/cmd_setexpr.c index 926339b9f17..e7194fc4f41 100644 --- a/common/cmd_setexpr.c +++ b/common/cmd_setexpr.c @@ -12,23 +12,37 @@ #include <common.h> #include <config.h> #include <command.h> +#include <mapmem.h> static ulong get_arg(char *s, int w) { - ulong *p; - /* - * if the parameter starts with a '*' then assume - * it is a pointer to the value we want + * If the parameter starts with a '*' then assume it is a pointer to + * the value we want. */ - if (s[0] == '*') { - p = (ulong *)simple_strtoul(&s[1], NULL, 16); + ulong *p; + ulong addr; + ulong val; + + addr = simple_strtoul(&s[1], NULL, 16); switch (w) { - case 1: return((ulong)(*(uchar *)p)); - case 2: return((ulong)(*(ushort *)p)); + case 1: + p = map_sysmem(addr, sizeof(uchar)); + val = (ulong)*(uchar *)p; + unmap_sysmem(p); + return val; + case 2: + p = map_sysmem(addr, sizeof(ushort)); + val = (ulong)*(ushort *)p; + unmap_sysmem(p); + return val; case 4: - default: return(*p); + default: + p = map_sysmem(addr, sizeof(ulong)); + val = *p; + unmap_sysmem(p); + return val; } } else { return simple_strtoul(s, NULL, 16); diff --git a/common/edid.c b/common/edid.c index df797fcdd5b..e08e4209202 100644 --- a/common/edid.c +++ b/common/edid.c @@ -13,6 +13,7 @@ #include <common.h> #include <edid.h> #include <errno.h> +#include <fdtdec.h> #include <linux/ctype.h> #include <linux/string.h> @@ -65,6 +66,110 @@ int edid_get_ranges(struct edid1_info *edid, unsigned int *hmin, return -1; } +/* Set all parts of a timing entry to the same value */ +static void set_entry(struct timing_entry *entry, u32 value) +{ + entry->min = value; + entry->typ = value; + entry->max = value; +} + +/** + * decode_timing() - Decoding an 18-byte detailed timing record + * + * @buf: Pointer to EDID detailed timing record + * @timing: Place to put timing + */ +static void decode_timing(u8 *buf, struct display_timing *timing) +{ + uint x_mm, y_mm; + unsigned int ha, hbl, hso, hspw, hborder; + unsigned int va, vbl, vso, vspw, vborder; + + /* Edid contains pixel clock in terms of 10KHz */ + set_entry(&timing->pixelclock, (buf[0] + (buf[1] << 8)) * 10000); + x_mm = (buf[12] + ((buf[14] & 0xf0) << 4)); + y_mm = (buf[13] + ((buf[14] & 0x0f) << 8)); + ha = (buf[2] + ((buf[4] & 0xf0) << 4)); + hbl = (buf[3] + ((buf[4] & 0x0f) << 8)); + hso = (buf[8] + ((buf[11] & 0xc0) << 2)); + hspw = (buf[9] + ((buf[11] & 0x30) << 4)); + hborder = buf[15]; + va = (buf[5] + ((buf[7] & 0xf0) << 4)); + vbl = (buf[6] + ((buf[7] & 0x0f) << 8)); + vso = ((buf[10] >> 4) + ((buf[11] & 0x0c) << 2)); + vspw = ((buf[10] & 0x0f) + ((buf[11] & 0x03) << 4)); + vborder = buf[16]; + + set_entry(&timing->hactive, ha); + set_entry(&timing->hfront_porch, hso); + set_entry(&timing->hback_porch, hbl - hso - hspw); + set_entry(&timing->hsync_len, hspw); + + set_entry(&timing->vactive, va); + set_entry(&timing->vfront_porch, vso); + set_entry(&timing->vback_porch, vbl - vso - vspw); + set_entry(&timing->vsync_len, vspw); + + debug("Detailed mode clock %u Hz, %d mm x %d mm\n" + " %04x %04x %04x %04x hborder %x\n" + " %04x %04x %04x %04x vborder %x\n", + timing->pixelclock.typ, + x_mm, y_mm, + ha, ha + hso, ha + hso + hspw, + ha + hbl, hborder, + va, va + vso, va + vso + vspw, + va + vbl, vborder); +} + +int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing, + int *panel_bits_per_colourp) +{ + struct edid1_info *edid = (struct edid1_info *)buf; + bool timing_done; + int i; + + if (buf_size < sizeof(*edid) || edid_check_info(edid)) { + debug("%s: Invalid buffer\n", __func__); + return -EINVAL; + } + + if (!EDID1_INFO_FEATURE_PREFERRED_TIMING_MODE(*edid)) { + debug("%s: No preferred timing\n", __func__); + return -ENOENT; + } + + /* Look for detailed timing */ + timing_done = false; + for (i = 0; i < 4; i++) { + struct edid_monitor_descriptor *desc; + + desc = &edid->monitor_details.descriptor[i]; + if (desc->zero_flag_1 != 0) { + decode_timing((u8 *)desc, timing); + timing_done = true; + break; + } + } + if (!timing_done) + return -EINVAL; + + if (!EDID1_INFO_VIDEO_INPUT_DIGITAL(*edid)) { + debug("%s: Not a digital display\n", __func__); + return -ENOSYS; + } + if (edid->version != 1 || edid->revision < 4) { + debug("%s: EDID version %d.%d does not have required info\n", + __func__, edid->version, edid->revision); + *panel_bits_per_colourp = -1; + } else { + *panel_bits_per_colourp = + ((edid->video_input_definition & 0x70) >> 3) + 4; + } + + return 0; +} + /** * Snip the tailing whitespace/return of a string. * diff --git a/common/fdt_support.c b/common/fdt_support.c index c5ed5ad89ee..9e501484625 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -1533,7 +1533,7 @@ int fdt_setup_simplefb_node(void *fdt, int node, u64 base_address, u32 width, if (ret < 0) return ret; - snprintf(name, sizeof(name), "framebuffer@%llx", base_address); + snprintf(name, sizeof(name), "framebuffer@%" PRIx64, base_address); ret = fdt_set_name(fdt, node, name); if (ret < 0) return ret; diff --git a/common/image-android.c b/common/image-android.c index 59079fc32b5..d946c2f814c 100644 --- a/common/image-android.c +++ b/common/image-android.c @@ -10,8 +10,29 @@ #include <malloc.h> #include <errno.h> +#define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR 0x10008000 + static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1]; +static ulong android_image_get_kernel_addr(const struct andr_img_hdr *hdr) +{ + /* + * All the Android tools that generate a boot.img use this + * address as the default. + * + * Even though it doesn't really make a lot of sense, and it + * might be valid on some platforms, we treat that adress as + * the default value for this field, and try to execute the + * kernel in place in such a case. + * + * Otherwise, we will return the actual value set by the user. + */ + if (hdr->kernel_addr == ANDROID_IMAGE_DEFAULT_KERNEL_ADDR) + return (ulong)hdr + hdr->page_size; + + return hdr->kernel_addr; +} + /** * android_image_get_kernel() - processes kernel part of Android boot images * @hdr: Pointer to image header, which is at the start @@ -30,6 +51,8 @@ static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1]; int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, ulong *os_data, ulong *os_len) { + u32 kernel_addr = android_image_get_kernel_addr(hdr); + /* * Not all Android tools use the id field for signing the image with * sha1 (or anything) so we don't check it. It is not obvious that the @@ -41,7 +64,7 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, printf("Android's image name: %s\n", andr_tmp_str); printf("Kernel load addr 0x%08x size %u KiB\n", - hdr->kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024)); + kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024)); int len = 0; if (*hdr->cmdline) { @@ -101,7 +124,7 @@ ulong android_image_get_end(const struct andr_img_hdr *hdr) ulong android_image_get_kload(const struct andr_img_hdr *hdr) { - return hdr->kernel_addr; + return android_image_get_kernel_addr(hdr); } int android_image_get_ramdisk(const struct andr_img_hdr *hdr, diff --git a/common/image.c b/common/image.c index abc0d890f28..fdec496c4bf 100644 --- a/common/image.c +++ b/common/image.c @@ -533,7 +533,7 @@ void genimg_print_time(time_t timestamp) #ifndef USE_HOSTCC struct rtc_time tm; - to_tm(timestamp, &tm); + rtc_to_tm(timestamp, &tm); printf("%4d-%02d-%02d %2d:%02d:%02d UTC\n", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); diff --git a/common/spl/spl.c b/common/spl/spl.c index 690c9b04ff2..aeb0645eda4 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -328,7 +328,7 @@ ulong spl_relocate_stack_gd(void) ulong ptr; /* Get stack position: use 8-byte alignment for ABI compliance */ - ptr = CONFIG_SPL_STACK_R - sizeof(gd_t); + ptr = CONFIG_SPL_STACK_R_ADDR - sizeof(gd_t); ptr &= ~7; new_gd = (gd_t *)ptr; memcpy(new_gd, (void *)gd, sizeof(gd_t)); diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index e580f2291af..5d688d6f0fc 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -8,6 +8,7 @@ */ #include <common.h> #include <spl.h> +#include <linux/compiler.h> #include <asm/u-boot.h> #include <mmc.h> #include <image.h> @@ -21,7 +22,7 @@ static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector) struct image_header *header; header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - - sizeof(struct image_header)); + sizeof(struct image_header)); /* read image header to find the image size & load address */ err = mmc->block_dev.block_read(0, sector, 1, header); @@ -35,7 +36,7 @@ static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector) /* convert size to sectors - round up */ image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) / - mmc->read_bl_len; + mmc->read_bl_len; /* Read the header too to avoid extra memcpy */ err = mmc->block_dev.block_read(0, sector, image_size_sectors, @@ -44,7 +45,7 @@ static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector) end: #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT if (err == 0) - printf("spl: mmc blk read err - %lu\n", err); + printf("spl: mmc block read error\n"); #endif return (err == 0); @@ -69,33 +70,38 @@ static int mmc_load_image_raw_partition(struct mmc *mmc, int partition) #ifdef CONFIG_SPL_OS_BOOT static int mmc_load_image_raw_os(struct mmc *mmc) { - if (!mmc->block_dev.block_read(0, - CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, - CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS, - (void *)CONFIG_SYS_SPL_ARGS_ADDR)) { + unsigned long err; + + err = mmc->block_dev.block_read(0, + CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, + CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS, + (void *)CONFIG_SYS_SPL_ARGS_ADDR); + if (err) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - printf("mmc args blk read error\n"); + printf("spl: mmc block read error\n"); #endif return -1; } return mmc_load_image_raw_sector(mmc, - CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR); + CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR); } #endif void spl_mmc_load_image(void) { struct mmc *mmc; - int err; u32 boot_mode; + int err; + __maybe_unused int part; mmc_initialize(gd->bd); + /* We register only one device. So, the dev id is always 0 */ mmc = find_mmc_device(0); if (!mmc) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - puts("spl: mmc device not found!!\n"); + puts("spl: mmc device not found\n"); #endif hang(); } @@ -103,16 +109,22 @@ void spl_mmc_load_image(void) err = mmc_init(mmc); if (err) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - printf("spl: mmc init failed: err - %d\n", err); + printf("spl: mmc init failed with error: %d\n", err); #endif hang(); } boot_mode = spl_boot_mode(); - if (boot_mode == MMCSD_MODE_RAW) { - debug("boot mode - RAW\n"); + switch (boot_mode) { + case MMCSD_MODE_RAW: + debug("spl: mmc boot mode: raw\n"); + #ifdef CONFIG_SPL_OS_BOOT - if (spl_start_uboot() || mmc_load_image_raw_os(mmc)) + if (!spl_start_uboot()) { + err = mmc_load_image_raw_os(mmc); + if (!err) + return; + } #endif #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION err = mmc_load_image_raw_partition(mmc, @@ -121,76 +133,87 @@ void spl_mmc_load_image(void) err = mmc_load_image_raw_sector(mmc, CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); #endif + if (!err) + return; #if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) - } - if (err || boot_mode == MMCSD_MODE_FS) { - debug("boot mode - FS\n"); + case MMCSD_MODE_FS: + debug("spl: mmc boot mode: fs\n"); + #ifdef CONFIG_SPL_FAT_SUPPORT #ifdef CONFIG_SPL_OS_BOOT - if (spl_start_uboot() || spl_load_image_fat_os(&mmc->block_dev, - CONFIG_SYS_MMCSD_FS_BOOT_PARTITION)) + if (!spl_start_uboot()) { + err = spl_load_image_fat_os(&mmc->block_dev, + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); + if (!err) + return; + } #endif err = spl_load_image_fat(&mmc->block_dev, - CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, - CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); - if(err) -#endif /* CONFIG_SPL_FAT_SUPPORT */ - { + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); + if (!err) + return; +#endif #ifdef CONFIG_SPL_EXT_SUPPORT #ifdef CONFIG_SPL_OS_BOOT - if (spl_start_uboot() || spl_load_image_ext_os(&mmc->block_dev, - CONFIG_SYS_MMCSD_FS_BOOT_PARTITION)) + if (!spl_start_uboot()) { + err = spl_load_image_ext_os(&mmc->block_dev, + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); + if (!err) + return; + } #endif err = spl_load_image_ext(&mmc->block_dev, - CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, - CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); -#endif /* CONFIG_SPL_EXT_SUPPORT */ - } -#endif /* defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) */ + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); + if (!err) + return; +#endif +#endif #ifdef CONFIG_SUPPORT_EMMC_BOOT - } else if (boot_mode == MMCSD_MODE_EMMCBOOT) { + case MMCSD_MODE_EMMCBOOT: /* * We need to check what the partition is configured to. * 1 and 2 match up to boot0 / boot1 and 7 is user data * which is the first physical partition (0). */ - int part = (mmc->part_config >> 3) & PART_ACCESS_MASK; + part = (mmc->part_config >> 3) & PART_ACCESS_MASK; if (part == 7) part = 0; if (mmc_switch_part(0, part)) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - puts("MMC partition switch failed\n"); + puts("spl: mmc partition switch failed\n"); #endif hang(); } + #ifdef CONFIG_SPL_OS_BOOT - if (spl_start_uboot() || mmc_load_image_raw_os(mmc)) + if (!spl_start_uboot()) { + err = mmc_load_image_raw_os(mmc); + if (!err) + return; + } #endif +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION + err = mmc_load_image_raw_partition(mmc, + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION); +#else err = mmc_load_image_raw_sector(mmc, CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); #endif - } - - switch(boot_mode){ - case MMCSD_MODE_RAW: -#if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) - case MMCSD_MODE_FS: -#endif -#ifdef CONFIG_SUPPORT_EMMC_BOOT - case MMCSD_MODE_EMMCBOOT: + if (!err) + return; #endif - /* Boot mode is ok. Nothing to do. */ - break; - case MMCSD_MODE_UNDEFINED: - default: + case MMCSD_MODE_UNDEFINED: + default: #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - puts("spl: wrong MMC boot mode\n"); + if (err) + puts("spl: mmc: no boot mode left to try\n"); + else + puts("spl: mmc: wrong boot mode\n"); #endif - hang(); - } - - if (err) hang(); + } } diff --git a/common/usb.c b/common/usb.c index a4820d3e949..6283f3992c7 100644 --- a/common/usb.c +++ b/common/usb.c @@ -148,6 +148,32 @@ int usb_stop(void) return 0; } +/****************************************************************************** + * Detect if a USB device has been plugged or unplugged. + */ +int usb_detect_change(void) +{ + int i, j; + int change = 0; + + for (j = 0; j < USB_MAX_DEVICE; j++) { + for (i = 0; i < usb_dev[j].maxchild; i++) { + struct usb_port_status status; + + if (usb_get_port_status(&usb_dev[j], i + 1, + &status) < 0) + /* USB request failed */ + continue; + + if (le16_to_cpu(status.wPortChange) & + USB_PORT_STAT_C_CONNECTION) + change++; + } + } + + return change; +} + /* * disables the asynch behaviour of the control message. This is used for data * transfers that uses the exclusiv access to the control and bulk messages. @@ -192,6 +218,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, void *data, unsigned short size, int timeout) { ALLOC_CACHE_ALIGN_BUFFER(struct devrequest, setup_packet, 1); + int err; if ((timeout == 0) && (!asynch_allowed)) { /* request for a asynch control pipe is not allowed */ @@ -209,8 +236,9 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, request, requesttype, value, index, size); dev->status = USB_ST_NOT_PROC; /*not yet processed */ - if (submit_control_msg(dev, pipe, data, size, setup_packet) < 0) - return -EIO; + err = submit_control_msg(dev, pipe, data, size, setup_packet); + if (err < 0) + return err; if (timeout == 0) return (int)size; @@ -946,13 +974,18 @@ static int usb_setup_descriptor(struct usb_device *dev, bool do_read) * 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. */ + * some more, or keeps on retransmitting the 8 byte header. + */ - 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; + if (dev->speed == USB_SPEED_LOW) { + dev->descriptor.bMaxPacketSize0 = 8; + dev->maxpacketsize = PACKET_SIZE_8; + } else { + dev->descriptor.bMaxPacketSize0 = 64; + dev->maxpacketsize = PACKET_SIZE_64; + } + dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0; + dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; if (do_read) { int err; diff --git a/common/usb_hub.c b/common/usb_hub.c index c9be530d0bf..be01f4f257d 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -79,7 +79,7 @@ static int usb_get_hub_status(struct usb_device *dev, void *data) data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT); } -static int usb_get_port_status(struct usb_device *dev, int port, void *data) +int usb_get_port_status(struct usb_device *dev, int port, void *data) { return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, @@ -157,7 +157,7 @@ static inline char *portspeed(int portstatus) int legacy_hub_port_reset(struct usb_device *dev, int port, unsigned short *portstat) { - int tries; + int err, tries; ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); unsigned short portstatus, portchange; @@ -168,8 +168,10 @@ int legacy_hub_port_reset(struct usb_device *dev, int port, debug("%s: resetting port %d...\n", __func__, port + 1); #endif for (tries = 0; tries < MAX_TRIES; tries++) { + err = usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET); + if (err < 0) + return err; - usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET); mdelay(200); if (usb_get_port_status(dev, port + 1, portsts) < 0) { @@ -269,7 +271,8 @@ int usb_hub_port_connect_change(struct usb_device *dev, int port) /* Reset the port */ ret = legacy_hub_port_reset(dev, port, &portstatus); if (ret < 0) { - printf("cannot reset port %i!?\n", port + 1); + if (ret != -ENXIO) + printf("cannot reset port %i!?\n", port + 1); return ret; } |