diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/core/uclass.c | 2 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 10 | ||||
-rw-r--r-- | drivers/gpio/gpio-uclass.c | 181 | ||||
-rw-r--r-- | drivers/mmc/Kconfig | 15 | ||||
-rw-r--r-- | drivers/mmc/mmc_legacy.c | 9 | ||||
-rw-r--r-- | drivers/pci/pci-uclass.c | 4 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-single.c | 65 | ||||
-rw-r--r-- | drivers/power/pmic/Kconfig | 21 | ||||
-rw-r--r-- | drivers/power/regulator/Kconfig | 26 | ||||
-rw-r--r-- | drivers/power/regulator/regulator-uclass.c | 3 | ||||
-rw-r--r-- | drivers/rtc/Kconfig | 10 | ||||
-rw-r--r-- | drivers/rtc/Makefile | 1 | ||||
-rw-r--r-- | drivers/rtc/ds1307.c | 14 | ||||
-rw-r--r-- | drivers/rtc/rv8803.c | 167 | ||||
-rw-r--r-- | drivers/usb/musb-new/omap2430.c | 8 |
15 files changed, 499 insertions, 37 deletions
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index dc9eb62893..b33296542f 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -260,7 +260,7 @@ int uclass_find_device_by_name(enum uclass_id id, const char *name, return ret; uclass_foreach_dev(dev, uc) { - if (!strncmp(dev->name, name, strlen(name))) { + if (!strcmp(dev->name, name)) { *devp = dev; return 0; } diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e36a8abc42..fa1c99700f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -14,6 +14,16 @@ config DM_GPIO particular GPIOs that they provide. The uclass interface is defined in include/asm-generic/gpio.h. +config DM_GPIO_HOG + bool "Enable GPIO hog support" + depends on DM_GPIO + default n + help + Enable gpio hog support + The GPIO chip may contain GPIO hog definitions. GPIO hogging + is a mechanism providing automatic GPIO request and config- + uration as part of the gpio-controller's driver probe function. + config ALTERA_PIO bool "Altera PIO driver" depends on DM_GPIO diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index da5e9ba6e5..308d0863ad 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -5,6 +5,9 @@ #include <common.h> #include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/uclass-internal.h> #include <dt-bindings/gpio/gpio.h> #include <errno.h> #include <fdtdec.h> @@ -141,6 +144,118 @@ static int gpio_find_and_xlate(struct gpio_desc *desc, return gpio_xlate_offs_flags(desc->dev, desc, args); } +#if defined(CONFIG_DM_GPIO_HOG) + +struct gpio_hog_priv { + struct gpio_desc gpiod; +}; + +struct gpio_hog_data { + int gpiod_flags; + int value; + u32 val[2]; +}; + +static int gpio_hog_ofdata_to_platdata(struct udevice *dev) +{ + struct gpio_hog_data *plat = dev_get_platdata(dev); + const char *nodename; + int ret; + + plat->value = 0; + if (dev_read_bool(dev, "input")) { + plat->gpiod_flags = GPIOD_IS_IN; + } else if (dev_read_bool(dev, "output-high")) { + plat->value = 1; + plat->gpiod_flags = GPIOD_IS_OUT; + } else if (dev_read_bool(dev, "output-low")) { + plat->gpiod_flags = GPIOD_IS_OUT; + } else { + printf("%s: missing gpio-hog state.\n", __func__); + return -EINVAL; + } + ret = dev_read_u32_array(dev, "gpios", plat->val, 2); + if (ret) { + printf("%s: wrong gpios property, 2 values needed %d\n", + __func__, ret); + return ret; + } + nodename = dev_read_string(dev, "line-name"); + if (!nodename) + nodename = dev_read_name(dev); + device_set_name(dev, nodename); + + return 0; +} + +static int gpio_hog_probe(struct udevice *dev) +{ + struct gpio_hog_data *plat = dev_get_platdata(dev); + struct gpio_hog_priv *priv = dev_get_priv(dev); + int ret; + + ret = gpio_dev_request_index(dev->parent, dev->name, "gpio-hog", + plat->val[0], plat->gpiod_flags, + plat->val[1], &priv->gpiod); + if (ret < 0) { + debug("%s: node %s could not get gpio.\n", __func__, + dev->name); + return ret; + } + dm_gpio_set_dir(&priv->gpiod); + if (plat->gpiod_flags == GPIOD_IS_OUT) + dm_gpio_set_value(&priv->gpiod, plat->value); + + return 0; +} + +int gpio_hog_probe_all(void) +{ + struct udevice *dev; + int ret; + + for (uclass_first_device(UCLASS_NOP, &dev); + dev; + uclass_find_next_device(&dev)) { + if (dev->driver == DM_GET_DRIVER(gpio_hog)) { + ret = device_probe(dev); + if (ret) + return ret; + } + } + + return 0; +} + +struct gpio_desc *gpio_hog_lookup_name(const char *name) +{ + struct udevice *dev; + + gpio_hog_probe_all(); + if (!uclass_get_device_by_name(UCLASS_NOP, name, &dev)) { + struct gpio_hog_priv *priv = dev_get_priv(dev); + + return &priv->gpiod; + } + + return NULL; +} + +U_BOOT_DRIVER(gpio_hog) = { + .name = "gpio_hog", + .id = UCLASS_NOP, + .ofdata_to_platdata = gpio_hog_ofdata_to_platdata, + .probe = gpio_hog_probe, + .priv_auto_alloc_size = sizeof(struct gpio_hog_priv), + .platdata_auto_alloc_size = sizeof(struct gpio_hog_data), +}; +#else +struct gpio_desc *gpio_hog_lookup_name(const char *name) +{ + return NULL; +} +#endif + int dm_gpio_request(struct gpio_desc *desc, const char *label) { struct udevice *dev = desc->dev; @@ -640,22 +755,25 @@ int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count) return vector; } -static int gpio_request_tail(int ret, ofnode node, +static int gpio_request_tail(int ret, const char *nodename, struct ofnode_phandle_args *args, const char *list_name, int index, - struct gpio_desc *desc, int flags, bool add_index) + struct gpio_desc *desc, int flags, + bool add_index, struct udevice *dev) { - desc->dev = NULL; + desc->dev = dev; desc->offset = 0; desc->flags = 0; if (ret) goto err; - ret = uclass_get_device_by_ofnode(UCLASS_GPIO, args->node, - &desc->dev); - if (ret) { - debug("%s: uclass_get_device_by_ofnode failed\n", __func__); - goto err; + if (!desc->dev) { + ret = uclass_get_device_by_ofnode(UCLASS_GPIO, args->node, + &desc->dev); + if (ret) { + debug("%s: uclass_get_device_by_ofnode failed\n", __func__); + goto err; + } } ret = gpio_find_and_xlate(desc, args); if (ret) { @@ -663,8 +781,7 @@ static int gpio_request_tail(int ret, ofnode node, goto err; } ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s", - ofnode_get_name(node), - list_name, index); + nodename, list_name, index); if (ret) { debug("%s: dm_gpio_requestf failed\n", __func__); goto err; @@ -678,7 +795,7 @@ static int gpio_request_tail(int ret, ofnode node, return 0; err: debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n", - __func__, ofnode_get_name(node), list_name, index, ret); + __func__, nodename, list_name, index, ret); return ret; } @@ -692,8 +809,8 @@ static int _gpio_request_by_name_nodev(ofnode node, const char *list_name, ret = ofnode_parse_phandle_with_args(node, list_name, "#gpio-cells", 0, index, &args); - return gpio_request_tail(ret, node, &args, list_name, index, desc, - flags, add_index); + return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name, + index, desc, flags, add_index, NULL); } int gpio_request_by_name_nodev(ofnode node, const char *list_name, int index, @@ -707,13 +824,14 @@ int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, struct gpio_desc *desc, int flags) { struct ofnode_phandle_args args; + ofnode node; int ret; ret = dev_read_phandle_with_args(dev, list_name, "#gpio-cells", 0, index, &args); - - return gpio_request_tail(ret, dev_ofnode(dev), &args, list_name, - index, desc, flags, index > 0); + node = dev_ofnode(dev); + return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name, + index, desc, flags, index > 0, NULL); } int gpio_request_list_by_name_nodev(ofnode node, const char *list_name, @@ -854,8 +972,28 @@ static int gpio_pre_remove(struct udevice *dev) return gpio_renumber(dev); } +int gpio_dev_request_index(struct udevice *dev, const char *nodename, + char *list_name, int index, int flags, + int dtflags, struct gpio_desc *desc) +{ + struct ofnode_phandle_args args; + + args.node = ofnode_null(); + args.args_count = 2; + args.args[0] = index; + args.args[1] = dtflags; + + return gpio_request_tail(0, nodename, &args, list_name, index, desc, + flags, 0, dev); +} + static int gpio_post_bind(struct udevice *dev) { +#if defined(CONFIG_DM_GPIO_HOG) + struct udevice *child; + ofnode node; +#endif + #if defined(CONFIG_NEEDS_MANUAL_RELOC) struct dm_gpio_ops *ops = (struct dm_gpio_ops *)device_get_ops(dev); static int reloc_done; @@ -885,6 +1023,17 @@ static int gpio_post_bind(struct udevice *dev) reloc_done++; } #endif + +#if defined(CONFIG_DM_GPIO_HOG) + dev_for_each_subnode(node, dev) { + if (ofnode_read_bool(node, "gpio-hog")) { + const char *name = ofnode_get_name(node); + + device_bind_driver_to_node(dev, "gpio_hog", name, + node, &child); + } + } +#endif return 0; } diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 93588725f2..b5180ea4a0 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -158,21 +158,6 @@ config MMC_TRACE If you need to see the MMC core message, say Y. -config SPL_MMC_TINY - bool "Tiny MMC framework in SPL" - help - Enable MMC framework tinification support. This option is useful if - if your SPL is extremely size constrained. Heed the warning, enable - this option if and only if you know exactly what you are doing, if - you are reading this help text, you most likely have no idea :-) - - The MMC framework is reduced to bare minimum to be useful. No malloc - support is needed for the MMC framework operation with this option - enabled. The framework supports exactly one MMC device and exactly - one MMC driver. The MMC driver can be adjusted to avoid any malloc - operations too, which can remove the need for malloc support in SPL - and thus further reduce footprint. - config MMC_DAVINCI bool "TI DAVINCI Multimedia Card Interface support" depends on ARCH_DAVINCI diff --git a/drivers/mmc/mmc_legacy.c b/drivers/mmc/mmc_legacy.c index 66a7cda440..b0f5cf58a2 100644 --- a/drivers/mmc/mmc_legacy.c +++ b/drivers/mmc/mmc_legacy.c @@ -150,6 +150,15 @@ struct mmc *mmc_create(const struct mmc_config *cfg, void *priv) { struct mmc *mmc = &mmc_static; + /* First MMC device registered, fail to register a new one. + * Given users are not expecting this to fail, instead + * of failing let's just return the only MMC device + */ + if (mmc->cfg) { + debug("Warning: MMC_TINY doesn't support multiple MMC devices\n"); + return mmc; + } + mmc->cfg = cfg; mmc->priv = priv; diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index c74ebf6a76..ab3e1310eb 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -1572,9 +1572,9 @@ void pci_init(void) * Enumerate all known controller devices. Enumeration has the side- * effect of probing them, so PCIe devices will be enumerated too. */ - for (uclass_first_device(UCLASS_PCI, &bus); + for (uclass_first_device_check(UCLASS_PCI, &bus); bus; - uclass_next_device(&bus)) { + uclass_next_device_check(&bus)) { ; } } diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 9dec88c1aa..1dfc97dcea 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -16,6 +16,7 @@ struct single_pdata { int offset; /* index of last configuration register */ u32 mask; /* configuration-value mask bits */ int width; /* configuration register bit width */ + bool bits_per_mux; }; struct single_fdt_pin_cfg { @@ -23,6 +24,12 @@ struct single_fdt_pin_cfg { fdt32_t val; /* configuration register value */ }; +struct single_fdt_bits_cfg { + fdt32_t reg; /* configuration register offset */ + fdt32_t val; /* configuration register value */ + fdt32_t mask; /* configuration register mask */ +}; + /** * single_configure_pins() - Configure pins based on FDT data * @@ -71,15 +78,53 @@ static int single_configure_pins(struct udevice *dev, return 0; } +static int single_configure_bits(struct udevice *dev, + const struct single_fdt_bits_cfg *pins, + int size) +{ + struct single_pdata *pdata = dev->platdata; + int count = size / sizeof(struct single_fdt_bits_cfg); + phys_addr_t n, reg; + u32 val, mask; + + for (n = 0; n < count; n++, pins++) { + reg = fdt32_to_cpu(pins->reg); + if ((reg < 0) || (reg > pdata->offset)) { + dev_dbg(dev, " invalid register offset 0x%pa\n", ®); + continue; + } + reg += pdata->base; + + mask = fdt32_to_cpu(pins->mask); + val = fdt32_to_cpu(pins->val) & mask; + + switch (pdata->width) { + case 16: + writew((readw(reg) & ~mask) | val, reg); + break; + case 32: + writel((readl(reg) & ~mask) | val, reg); + break; + default: + dev_warn(dev, "unsupported register width %i\n", + pdata->width); + continue; + } + dev_dbg(dev, " reg/val 0x%pa/0x%08x\n", ®, val); + } + return 0; +} static int single_set_state(struct udevice *dev, struct udevice *config) { const void *fdt = gd->fdt_blob; const struct single_fdt_pin_cfg *prop; + const struct single_fdt_bits_cfg *prop_bits; int len; prop = fdt_getprop(fdt, dev_of_offset(config), "pinctrl-single,pins", &len); + if (prop) { dev_dbg(dev, "configuring pins for %s\n", config->name); if (len % sizeof(struct single_fdt_pin_cfg)) { @@ -87,9 +132,24 @@ static int single_set_state(struct udevice *dev, return -FDT_ERR_BADSTRUCTURE; } single_configure_pins(dev, prop, len); - len = 0; + return 0; } + /* pinctrl-single,pins not found so check for pinctrl-single,bits */ + prop_bits = fdt_getprop(fdt, dev_of_offset(config), + "pinctrl-single,bits", + &len); + if (prop_bits) { + dev_dbg(dev, "configuring pins for %s\n", config->name); + if (len % sizeof(struct single_fdt_bits_cfg)) { + dev_dbg(dev, " invalid bits configuration in fdt\n"); + return -FDT_ERR_BADSTRUCTURE; + } + single_configure_bits(dev, prop_bits, len); + return 0; + } + + /* Neither 'pinctrl-single,pins' nor 'pinctrl-single,bits' were found */ return len; } @@ -119,6 +179,9 @@ static int single_ofdata_to_platdata(struct udevice *dev) pdata->mask = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "pinctrl-single,function-mask", 0xffffffff); + pdata->bits_per_mux = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev), + "pinctrl-single,bit-per-mux"); + return 0; } diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index 450935fdc1..cb1d10b2a9 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -245,3 +245,24 @@ config PMIC_STPMIC1 The STPMIC1 PMIC provides 4 BUCKs, 6 LDOs, 1 VREF and 2 power switches. It is accessed via an I2C interface. The device is used with STM32MP1 SoCs. This driver implements register read/write operations. + +config SPL_PMIC_PALMAS + bool "Enable driver for Texas Instruments PALMAS PMIC" + depends on DM_PMIC + help + The PALMAS is a PMIC containing several LDOs, SMPS. + This driver binds the pmic children in SPL. + +config SPL_PMIC_LP873X + bool "Enable driver for Texas Instruments LP873X PMIC" + depends on DM_PMIC + help + The LP873X is a PMIC containing couple of LDOs and couple of SMPS. + This driver binds the pmic children in SPL. + +config SPL_PMIC_LP87565 + bool "Enable driver for Texas Instruments LP87565 PMIC" + depends on DM_PMIC + help + The LP87565 is a PMIC containing a bunch of SMPS. + This driver binds the pmic children in SPL. diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 72dfc48981..147e68d5c9 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -258,3 +258,29 @@ config SPL_DM_REGULATOR_STPMIC1 depends on SPL_DM_REGULATOR && PMIC_STPMIC1 help Enable support for the regulator functions of the STPMIC1 PMIC in SPL. + +config SPL_DM_REGULATOR_PALMAS + bool "Enable driver for PALMAS PMIC regulators" + depends on SPL_PMIC_PALMAS + help + This enables implementation of driver-model regulator uclass + features for REGULATOR PALMAS and the family of PALMAS PMICs. + The driver implements get/set api for: value and enable in SPL. + +config SPL_DM_REGULATOR_LP87565 + bool "Enable driver for LP87565 PMIC regulators" + depends on SPL_PMIC_LP87565 + help + This enables implementation of driver-model regulator uclass + features for REGULATOR LP87565 and the family of LP87565 PMICs. + LP87565 series of PMICs have 4 single phase BUCKs that can also + be configured in multi phase modes. The driver implements + get/set api for value and enable in SPL. + +config SPL_DM_REGULATOR_LP873X + bool "Enable driver for LP873X PMIC regulators" + depends on SPL_PMIC_LP873X + help + This enables implementation of driver-model regulator uclass + features for REGULATOR LP873X and the family of LP873X PMICs. + The driver implements get/set api for: value and enable in SPL. diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c index 9118b8eb39..76be95bcd1 100644 --- a/drivers/power/regulator/regulator-uclass.c +++ b/drivers/power/regulator/regulator-uclass.c @@ -238,6 +238,9 @@ int regulator_autoset(struct udevice *dev) if (!uc_pdata->always_on && !uc_pdata->boot_on) return -EMEDIUMTYPE; + if (uc_pdata->type == REGULATOR_TYPE_FIXED) + return regulator_set_enable(dev, true); + if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV) ret = regulator_set_value(dev, uc_pdata->min_uV); if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index fd0009b2e2..532e94d337 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -70,6 +70,16 @@ config RTC_RV3029 This driver supports reading and writing the RTC/calendar and the battery-baced SRAM section. +config RTC_RV8803 + bool "Enable RV8803 driver" + depends on DM_RTC + help + The Micro Crystal RV8803 is a high accuracy, ultra-low power I2C + Real Time Clock (RTC) with temperature compensation. + + This driver supports reading and writing the RTC/calendar and + detects total power failures. + config RTC_RX8010SJ bool "Enable RX8010SJ driver" depends on DM_RTC diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 1724602f1c..915adb87fe 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_RTC_PL031) += pl031.o obj-$(CONFIG_RTC_PT7C4338) += pt7c4338.o obj-$(CONFIG_RTC_RS5C372A) += rs5c372.o obj-$(CONFIG_RTC_RV3029) += rv3029.o +obj-$(CONFIG_RTC_RV8803) += rv8803.o obj-$(CONFIG_RTC_RX8025) += rx8025.o obj-$(CONFIG_RTC_RX8010SJ) += rx8010sj.o obj-$(CONFIG_RTC_S3C24X0) += s3c24x0_rtc.o diff --git a/drivers/rtc/ds1307.c b/drivers/rtc/ds1307.c index 48220b45db..a33f47525f 100644 --- a/drivers/rtc/ds1307.c +++ b/drivers/rtc/ds1307.c @@ -23,6 +23,7 @@ enum ds_type { ds_1307, ds_1337, ds_1340, + m41t11, mcp794xx, }; @@ -260,6 +261,18 @@ read_rtc: } } + if (type == m41t11) { + /* clock halted? turn it on, so clock can tick. */ + if (buf[RTC_SEC_REG_ADDR] & RTC_SEC_BIT_CH) { + buf[RTC_SEC_REG_ADDR] &= ~RTC_SEC_BIT_CH; + dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR, + MCP7941X_BIT_ST); + dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR, + buf[RTC_SEC_REG_ADDR]); + goto read_rtc; + } + } + if (type == mcp794xx) { /* make sure that the backup battery is enabled */ if (!(buf[RTC_DAY_REG_ADDR] & MCP7941X_BIT_VBATEN)) { @@ -332,6 +345,7 @@ static const struct udevice_id ds1307_rtc_ids[] = { { .compatible = "dallas,ds1337", .data = ds_1337 }, { .compatible = "dallas,ds1340", .data = ds_1340 }, { .compatible = "microchip,mcp7941x", .data = mcp794xx }, + { .compatible = "st,m41t11", .data = m41t11 }, { } }; diff --git a/drivers/rtc/rv8803.c b/drivers/rtc/rv8803.c new file mode 100644 index 0000000000..2ab40f0833 --- /dev/null +++ b/drivers/rtc/rv8803.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Date & Time support for Micro Crystal RV-8803-C7. + * + * based on ds1307.c which is + * (C) Copyright 2001, 2002, 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Keith Outwater, keith_outwater@mvis.com` + * Steven Scholz, steven.scholz@imc-berlin.de + * + */ + +#include <common.h> +#include <command.h> +#include <dm.h> +#include <rtc.h> +#include <i2c.h> + +/* + * RTC register addresses + */ +#define RTC_SEC_REG_ADDR 0x00 +#define RTC_MIN_REG_ADDR 0x01 +#define RTC_HR_REG_ADDR 0x02 +#define RTC_DAY_REG_ADDR 0x03 +#define RTC_DATE_REG_ADDR 0x04 +#define RTC_MON_REG_ADDR 0x05 +#define RTC_YR_REG_ADDR 0x06 + +#define RTC_FLAG_REG_ADDR 0x0E +#define RTC_FLAG_BIT_V1F BIT(0) +#define RTC_FLAG_BIT_V2F BIT(1) + +#define RTC_CTL_REG_ADDR 0x0F +#define RTC_CTL_BIT_RST BIT(0) + +static int rv8803_rtc_set(struct udevice *dev, const struct rtc_time *tm) +{ + int ret; + u8 buf[7]; + + debug("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + if (tm->tm_year < 2000 || tm->tm_year > 2099) + printf("WARNING: year should be between 2000 and 2099!\n"); + + buf[RTC_YR_REG_ADDR] = bin2bcd(tm->tm_year % 100); + buf[RTC_MON_REG_ADDR] = bin2bcd(tm->tm_mon); + buf[RTC_DAY_REG_ADDR] = 1 << (tm->tm_wday & 0x7); + buf[RTC_DATE_REG_ADDR] = bin2bcd(tm->tm_mday); + buf[RTC_HR_REG_ADDR] = bin2bcd(tm->tm_hour); + buf[RTC_MIN_REG_ADDR] = bin2bcd(tm->tm_min); + buf[RTC_SEC_REG_ADDR] = bin2bcd(tm->tm_sec); + + ret = dm_i2c_write(dev, 0, buf, sizeof(buf)); + if (ret < 0) + return ret; + + return 0; +} + +static int rv8803_rtc_get(struct udevice *dev, struct rtc_time *tm) +{ + int ret; + u8 buf[7]; + int flags; + + flags = dm_i2c_reg_read(dev, RTC_FLAG_REG_ADDR); + if (flags < 0) + return flags; + debug("%s: flags=%Xh\n", __func__, flags); + + if (flags & RTC_FLAG_BIT_V1F) + printf("### Warning: temperature compensation has stopped\n"); + + if (flags & RTC_FLAG_BIT_V2F) { + printf("### Warning: Voltage low, data is invalid\n"); + return -1; + } + + ret = dm_i2c_read(dev, 0, buf, sizeof(buf)); + if (ret < 0) + return ret; + + tm->tm_sec = bcd2bin(buf[RTC_SEC_REG_ADDR] & 0x7F); + tm->tm_min = bcd2bin(buf[RTC_MIN_REG_ADDR] & 0x7F); + tm->tm_hour = bcd2bin(buf[RTC_HR_REG_ADDR] & 0x3F); + tm->tm_mday = bcd2bin(buf[RTC_DATE_REG_ADDR] & 0x3F); + tm->tm_mon = bcd2bin(buf[RTC_MON_REG_ADDR] & 0x1F); + tm->tm_year = bcd2bin(buf[RTC_YR_REG_ADDR]) + 2000; + tm->tm_wday = fls(buf[RTC_DAY_REG_ADDR] & 0x7F) - 1; + tm->tm_yday = 0; + tm->tm_isdst = 0; + + debug("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + return 0; +} + +static int rv8803_rtc_reset(struct udevice *dev) +{ + int ret; + struct rtc_time tmp = { + .tm_year = 2000, + .tm_mon = 1, + .tm_mday = 1, + .tm_hour = 0, + .tm_min = 0, + .tm_sec = 0, + }; + + /* assert reset */ + ret = dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR, RTC_CTL_BIT_RST); + if (ret < 0) + return ret; + + /* clear all flags */ + ret = dm_i2c_reg_write(dev, RTC_FLAG_REG_ADDR, 0); + if (ret < 0) + return ret; + + ret = rv8803_rtc_set(dev, &tmp); + if (ret < 0) + return ret; + + /* clear reset */ + ret = dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR, 0); + if (ret < 0) + return ret; + + debug("RTC: %4d-%02d-%02d %2d:%02d:%02d UTC\n", + tmp.tm_year, tmp.tm_mon, tmp.tm_mday, + tmp.tm_hour, tmp.tm_min, tmp.tm_sec); + + return 0; +} + +static int rv8803_probe(struct udevice *dev) +{ + i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS | + DM_I2C_CHIP_WR_ADDRESS); + + return 0; +} + +static const struct rtc_ops rv8803_rtc_ops = { + .get = rv8803_rtc_get, + .set = rv8803_rtc_set, + .reset = rv8803_rtc_reset, +}; + +static const struct udevice_id rv8803_rtc_ids[] = { + { .compatible = "microcrystal,rv8803", }, + { } +}; + +U_BOOT_DRIVER(rtc_rv8803) = { + .name = "rtc-rv8803", + .id = UCLASS_RTC, + .probe = rv8803_probe, + .of_match = rv8803_rtc_ids, + .ops = &rv8803_rtc_ops, +}; diff --git a/drivers/usb/musb-new/omap2430.c b/drivers/usb/musb-new/omap2430.c index 32743aa72c..cca1653f1e 100644 --- a/drivers/usb/musb-new/omap2430.c +++ b/drivers/usb/musb-new/omap2430.c @@ -215,11 +215,13 @@ static int omap2430_musb_probe(struct udevice *dev) { #ifdef CONFIG_USB_MUSB_HOST struct musb_host_data *host = dev_get_priv(dev); +#else + struct musb *musbp; #endif struct omap2430_musb_platdata *platdata = dev_get_platdata(dev); struct usb_bus_priv *priv = dev_get_uclass_priv(dev); struct omap_musb_board_data *otg_board_data; - int ret; + int ret = 0; void *base = dev_read_addr_ptr(dev); priv->desc_before_addr = true; @@ -236,9 +238,11 @@ static int omap2430_musb_probe(struct udevice *dev) ret = musb_lowlevel_init(host); #else - ret = musb_register(&platdata->plat, + musbp = musb_register(&platdata->plat, (struct device *)otg_board_data, platdata->base); + if (IS_ERR_OR_NULL(musbp)) + return -EINVAL; #endif return ret; } |