summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Kconfig36
-rw-r--r--common/Makefile4
-rw-r--r--common/board_r.c14
-rw-r--r--common/cmd_date.c57
-rw-r--r--common/cmd_i2c.c63
-rw-r--r--common/cmd_mem.c8
-rw-r--r--common/cmd_part.c2
-rw-r--r--common/cmd_pmic.c210
-rw-r--r--common/cmd_regulator.c408
-rw-r--r--common/cmd_setexpr.c32
-rw-r--r--common/edid.c105
-rw-r--r--common/fdt_support.c2
-rw-r--r--common/image-android.c27
-rw-r--r--common/image.c2
-rw-r--r--common/spl/spl.c2
-rw-r--r--common/spl/spl_mmc.c131
-rw-r--r--common/usb.c49
-rw-r--r--common/usb_hub.c11
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;
}