summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/core/uclass.c2
-rw-r--r--drivers/gpio/Kconfig10
-rw-r--r--drivers/gpio/gpio-uclass.c181
-rw-r--r--drivers/mmc/Kconfig15
-rw-r--r--drivers/mmc/mmc_legacy.c9
-rw-r--r--drivers/pci/pci-uclass.c4
-rw-r--r--drivers/pinctrl/pinctrl-single.c65
-rw-r--r--drivers/power/pmic/Kconfig21
-rw-r--r--drivers/power/regulator/Kconfig26
-rw-r--r--drivers/power/regulator/regulator-uclass.c3
-rw-r--r--drivers/rtc/Kconfig10
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/ds1307.c14
-rw-r--r--drivers/rtc/rv8803.c167
-rw-r--r--drivers/usb/musb-new/omap2430.c8
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", &reg);
+ 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", &reg, 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;
}