diff options
author | Tom Rini <trini@konsulko.com> | 2024-10-05 11:18:16 -0600 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2024-10-05 11:18:16 -0600 |
commit | 7321b7dd36b3722fdbe2c661c8c478c429cd5267 (patch) | |
tree | 14eb3498aed79b317c97f5c19fc12102765b4246 /drivers | |
parent | be99d3cba64afda8b963b98682fa6e158e713c05 (diff) | |
parent | ef815d75514da91dd98f9e3278d810439fd1f1ea (diff) |
Merge tag 'u-boot-imx-next-20241005' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx into next
CI: https://source.denx.de/u-boot/custodians/u-boot-imx/-/pipelines/22526
- Add DA9063 watchdog support for the imx6q-lxr2 board.
- Add support for DH electronics i.MX8M Plus DHCOM PicoITX
- Add DH i.MX8MP DHCOM SoM on DRC02 carrier board
- Several fsl_esdhc_imx improvements.
- Pas no-mmc-hs400 to mmc2 on imx8mm-cl-iot-gate.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/Kconfig | 6 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 2 | ||||
-rw-r--r-- | drivers/mmc/fsl_esdhc_imx.c | 44 | ||||
-rw-r--r-- | drivers/power/pmic/da9063.c | 12 | ||||
-rw-r--r-- | drivers/watchdog/Kconfig | 6 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 1 | ||||
-rw-r--r-- | drivers/watchdog/da9063-wdt.c | 149 |
7 files changed, 206 insertions, 14 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3996333fe8d..1e5711663eb 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -700,4 +700,10 @@ config RZG2L_GPIO Support the gpio functionality of the pin function controller (PFC) on the Renesas RZ/G2L SoC family. +config SPL_ADP5585_GPIO + bool "ADP5585 GPIO driver in SPL" + depends on SPL_DM_GPIO && SPL_I2C + help + Support ADP5585 GPIO expander in SPL. + endif diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index da0faf05246..56c20e4c635 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -76,5 +76,5 @@ obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o obj-$(CONFIG_SLG7XL45106_I2C_GPO) += gpio_slg7xl45106.o obj-$(CONFIG_FTGPIO010) += ftgpio010.o -obj-$(CONFIG_ADP5585_GPIO) += adp5585_gpio.o +obj-$(CONFIG_$(SPL_)ADP5585_GPIO) += adp5585_gpio.o obj-$(CONFIG_RZG2L_GPIO) += rzg2l-gpio.o diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c index 03de7dcd505..fb410104c1f 100644 --- a/drivers/mmc/fsl_esdhc_imx.c +++ b/drivers/mmc/fsl_esdhc_imx.c @@ -148,6 +148,7 @@ struct fsl_esdhc_priv { struct fsl_esdhc *esdhc_regs; unsigned int sdhc_clk; struct clk per_clk; + struct clk_bulk clk_bulk; unsigned int clock; unsigned int mode; #if !CONFIG_IS_ENABLED(DM_MMC) @@ -986,11 +987,11 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) ulong start; /* Reset the entire host controller */ - esdhc_setbits32(®s->sysctl, SYSCTL_RSTA); + esdhc_setbits32(®s->sysctl, SYSCTL_RSTA | SYSCTL_RSTT); /* Wait until the controller is available */ start = get_timer(0); - while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA)) { + while ((esdhc_read32(®s->sysctl) & (SYSCTL_RSTA | SYSCTL_RSTT))) { if (get_timer(start) > 1000) return -ETIMEDOUT; } @@ -1034,6 +1035,11 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) /* Set timout to the maximum value */ esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16); + /* max 1ms delay with clock on for initialization */ + esdhc_setbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); + udelay(1000); + esdhc_clrbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); + return 0; } @@ -1089,11 +1095,11 @@ static int esdhc_reset(struct fsl_esdhc *regs) ulong start; /* reset the controller */ - esdhc_setbits32(®s->sysctl, SYSCTL_RSTA); + esdhc_setbits32(®s->sysctl, SYSCTL_RSTA | SYSCTL_RSTT); /* hardware clears the bit when it is done */ start = get_timer(0); - while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA)) { + while ((esdhc_read32(®s->sysctl) & (SYSCTL_RSTA | SYSCTL_RSTT))) { if (get_timer(start) > 100) { printf("MMC/SD: Reset never completed.\n"); return -ETIMEDOUT; @@ -1188,8 +1194,6 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv, esdhc_write32(®s->irqstaten, SDHCI_IRQ_EN_BITS); cfg = &plat->cfg; - if (!CONFIG_IS_ENABLED(DM_MMC)) - memset(cfg, '\0', sizeof(*cfg)); caps = esdhc_read32(®s->hostcapblt); @@ -1323,6 +1327,8 @@ int fsl_esdhc_initialize(struct bd_info *bis, struct fsl_esdhc_cfg *cfg) break; default: printf("invalid max bus width %u\n", cfg->max_bus_width); + free(plat); + free(priv); return -EINVAL; } @@ -1521,14 +1527,21 @@ static int fsl_esdhc_probe(struct udevice *dev) #if CONFIG_IS_ENABLED(CLK) /* Assigned clock already set clock */ - ret = clk_get_by_name(dev, "per", &priv->per_clk); + ret = clk_get_bulk(dev, &priv->clk_bulk); if (ret) { - printf("Failed to get per_clk\n"); + dev_err(dev, "Failed to get clks: %d\n", ret); + return ret; + } + + ret = clk_enable_bulk(&priv->clk_bulk); + if (ret) { + dev_err(dev, "Failed to enable clks: %d\n", ret); return ret; } - ret = clk_enable(&priv->per_clk); + + ret = clk_get_by_name(dev, "per", &priv->per_clk); if (ret) { - printf("Failed to enable per_clk\n"); + printf("Failed to get per_clk\n"); return ret; } @@ -1561,7 +1574,7 @@ static int fsl_esdhc_probe(struct udevice *dev) upriv->mmc = mmc; - return esdhc_init_common(priv, mmc); + return 0; } static int fsl_esdhc_get_cd(struct udevice *dev) @@ -1613,6 +1626,14 @@ static int fsl_esdhc_wait_dat0(struct udevice *dev, int state, return esdhc_wait_dat0_common(priv, state, timeout_us); } +static int fsl_esdhc_reinit(struct udevice *dev) +{ + struct fsl_esdhc_plat *plat = dev_get_plat(dev); + struct fsl_esdhc_priv *priv = dev_get_priv(dev); + + return esdhc_init_common(priv, &plat->mmc); +} + static const struct dm_mmc_ops fsl_esdhc_ops = { .get_cd = fsl_esdhc_get_cd, .send_cmd = fsl_esdhc_send_cmd, @@ -1624,6 +1645,7 @@ static const struct dm_mmc_ops fsl_esdhc_ops = { .set_enhanced_strobe = fsl_esdhc_set_enhanced_strobe, #endif .wait_dat0 = fsl_esdhc_wait_dat0, + .reinit = fsl_esdhc_reinit, }; static struct esdhc_soc_data usdhc_imx7d_data = { diff --git a/drivers/power/pmic/da9063.c b/drivers/power/pmic/da9063.c index 7bd3df39142..59c65702863 100644 --- a/drivers/power/pmic/da9063.c +++ b/drivers/power/pmic/da9063.c @@ -7,6 +7,9 @@ #include <fdtdec.h> #include <errno.h> #include <dm.h> +#include <dm/device-internal.h> +#include <dm/device_compat.h> +#include <dm/lists.h> #include <i2c.h> #include <log.h> #include <linux/printk.h> @@ -86,6 +89,7 @@ static int da9063_read(struct udevice *dev, uint reg, uint8_t *buff, int len) static int da9063_bind(struct udevice *dev) { ofnode regulators_node; + struct driver *drv; int children; regulators_node = dev_read_subnode(dev, "regulators"); @@ -101,8 +105,12 @@ static int da9063_bind(struct udevice *dev) if (!children) debug("%s: %s - no child found\n", __func__, dev->name); - /* Always return success for this device */ - return 0; + drv = lists_driver_lookup_name("da9063-wdt"); + if (!drv) + return 0; + + return device_bind_with_driver_data(dev, drv, "da9063-wdt", dev->driver_data, + dev_ofnode(dev), &dev); } static int da9063_probe(struct udevice *dev) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 0c3e9913318..90bc5653ee3 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -169,6 +169,12 @@ config WDT_CORTINA This driver support all CPU ISAs supported by Cortina Access CAxxxx SoCs. +config WDT_DA9063 + bool "DA9063 watchdog timer support" + depends on WDT && DM_PMIC_DA9063 + help + Enable support for the watchdog timer in Dialog DA9063. + config WDT_GPIO bool "External gpio watchdog support" depends on WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 7b39adcf0ff..6b564b7f96d 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_WDT_BOOKE) += booke_wdt.o obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o obj-$(CONFIG_WDT_ORION) += orion_wdt.o obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o +obj-$(CONFIG_WDT_DA9063) += da9063-wdt.o obj-$(CONFIG_WDT_FTWDT010) += ftwdt010_wdt.o obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o obj-$(CONFIG_WDT_MAX6370) += max6370_wdt.o diff --git a/drivers/watchdog/da9063-wdt.c b/drivers/watchdog/da9063-wdt.c new file mode 100644 index 00000000000..b7216b57863 --- /dev/null +++ b/drivers/watchdog/da9063-wdt.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Based on the Linux drivers/watchdog/da9063_wdt.c file. + * + * Watchdog driver for DA9063 PMICs. + * + * Copyright(c) 2012 Dialog Semiconductor Ltd. + * + * Author: Mariusz Wojtasik <mariusz.wojtasik@diasemi.com> + * + * Ported to U-Boot by Fabio Estevam <festevam@denx.de> + * + */ + +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/device_compat.h> +#include <dm/lists.h> +#include <i2c.h> +#include <linux/delay.h> +#include <wdt.h> + +#define DA9063_REG_CONTROL_D 0x11 +/* DA9063_REG_CONTROL_D (addr=0x11) */ +#define DA9063_TWDSCALE_MASK 0x0 +#define DA9063_TWDSCALE_DISABLE 0 +#define DA9063_REG_CONTROL_F 0x13 +/* DA9063_REG_CONTROL_F (addr=0x13) */ +#define DA9063_WATCHDOG 0x01 +#define DA9063_SHUTDOWN 0x02 + +/* + * Watchdog selector to timeout in seconds. + * 0: WDT disabled; + * others: timeout = 2048 ms * 2^(TWDSCALE-1). + */ +static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 }; + +#define DA9063_TWDSCALE_DISABLE 0 +#define DA9063_TWDSCALE_MIN 1 +#define DA9063_TWDSCALE_MAX (ARRAY_SIZE(wdt_timeout) - 1) + +static unsigned int da9063_wdt_timeout_to_sel(unsigned int secs) +{ + unsigned int i; + + for (i = DA9063_TWDSCALE_MIN; i <= DA9063_TWDSCALE_MAX; i++) { + if (wdt_timeout[i] >= secs) + return i; + } + + return DA9063_TWDSCALE_MAX; +} + +static int da9063_read(struct udevice *dev, uint reg, uint8_t *buff, int len) +{ + return dm_i2c_read(dev->parent, reg, buff, len); +} + +static int da9063_write(struct udevice *dev, uint reg, const u8 *buff, int len) +{ + return dm_i2c_write(dev->parent, reg, buff, len); +} + +static int da9063_wdt_disable_timer(struct udevice *dev) +{ + u8 val; + + da9063_read(dev, DA9063_REG_CONTROL_D, &val, 1); + val &= ~DA9063_TWDSCALE_MASK; + val |= DA9063_TWDSCALE_DISABLE; + da9063_write(dev, DA9063_REG_CONTROL_D, &val, 1); + + return 0; +} + +static int da9063_wdt_update_timeout(struct udevice *dev, unsigned int timeout) +{ + unsigned int regval; + int ret; + u8 val; + + /* + * The watchdog triggers a reboot if a timeout value is already + * programmed because the timeout value combines two functions + * in one: indicating the counter limit and starting the watchdog. + * The watchdog must be disabled to be able to change the timeout + * value if the watchdog is already running. Then we can set the + * new timeout value which enables the watchdog again. + */ + ret = da9063_wdt_disable_timer(dev); + if (ret) + return ret; + + udelay(300); + + regval = da9063_wdt_timeout_to_sel(timeout); + + da9063_read(dev, DA9063_REG_CONTROL_D, &val, 1); + val &= ~DA9063_TWDSCALE_MASK; + val |= regval; + da9063_write(dev, DA9063_REG_CONTROL_D, &val, 1); + + return 0; +} + +static int da9063_wdt_start(struct udevice *dev, u64 timeout, ulong flags) +{ + return da9063_wdt_update_timeout(dev, timeout); +} + +static int da9063_wdt_stop(struct udevice *dev) +{ + return da9063_wdt_disable_timer(dev); +} + +static int da9063_wdt_reset(struct udevice *dev) +{ + u8 val = DA9063_WATCHDOG; + + return da9063_write(dev, DA9063_REG_CONTROL_F, &val, 1); +} + +static int da9063_wdt_expire_now(struct udevice *dev, ulong flags) +{ + u8 val = DA9063_SHUTDOWN; + + return da9063_write(dev, DA9063_REG_CONTROL_F, &val, 1); +} + +static const struct wdt_ops da9063_wdt_ops = { + .start = da9063_wdt_start, + .stop = da9063_wdt_stop, + .reset = da9063_wdt_reset, + .expire_now = da9063_wdt_expire_now, +}; + +static const struct udevice_id da9063_wdt_ids[] = { + { .compatible = "dlg,da9063-watchdog", }, + {} +}; + +U_BOOT_DRIVER(da9063_wdt) = { + .name = "da9063-wdt", + .id = UCLASS_WDT, + .of_match = da9063_wdt_ids, + .ops = &da9063_wdt_ops, + .flags = DM_FLAG_PROBE_AFTER_BIND, +}; |