From 6617894b6903e1cfc829add1558143be75d6bcd0 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 12 Sep 2021 09:22:40 -0500 Subject: phy: sun4i-usb: Remove a couple of debug messages Both of these messages log the GPIO number of the ID detection GPIO, which is not terribly useful, especially in the VBUS detection function. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/phy/allwinner/phy-sun4i-usb.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 82713b83815..5302b809ee6 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -393,8 +393,6 @@ int sun4i_usb_phy_vbus_detect(struct phy *phy) struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; int err, retries = 3; - debug("%s: id_det = %d\n", __func__, usb_phy->gpio_id_det); - if (usb_phy->gpio_vbus_det < 0) return usb_phy->gpio_vbus_det; @@ -417,8 +415,6 @@ int sun4i_usb_phy_id_detect(struct phy *phy) struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; - debug("%s: id_det = %d\n", __func__, usb_phy->gpio_id_det); - if (usb_phy->gpio_id_det < 0) return usb_phy->gpio_id_det; -- cgit v1.3.1 From 1da7b88cade196434b84e701c1dadcd3b37c97bc Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 12 Sep 2021 09:22:41 -0500 Subject: phy: sun4i-usb: Refactor VBUS detection to match Linux The Linux driver checks the VBUS detection GPIO first; then VBUS power supply; then finally assumes VBUS is present. When adding VBUS power supply support, we want to match that order, so we get the same behavior in case both a GPIO and a power supply are provided in the device tree. So refactor the function a bit to remove the early return, and use the same "assume VBUS is present" final fallback. Signed-off-by: Samuel Holland Acked-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/phy/allwinner/phy-sun4i-usb.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 5302b809ee6..827ecd70f27 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -391,20 +391,19 @@ int sun4i_usb_phy_vbus_detect(struct phy *phy) { struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; - int err, retries = 3; - - if (usb_phy->gpio_vbus_det < 0) - return usb_phy->gpio_vbus_det; - - err = gpio_get_value(usb_phy->gpio_vbus_det); - /* - * Vbus may have been provided by the board and just been turned of - * some milliseconds ago on reset, what we're measuring then is a - * residual charge on Vbus, sleep a bit and try again. - */ - while (err > 0 && retries--) { - mdelay(100); + int err = 1, retries = 3; + + if (usb_phy->gpio_vbus_det >= 0) { err = gpio_get_value(usb_phy->gpio_vbus_det); + /* + * Vbus may have been provided by the board and just turned off + * some milliseconds ago on reset. What we're measuring then is + * a residual charge on Vbus. Sleep a bit and try again. + */ + while (err > 0 && retries--) { + mdelay(100); + err = gpio_get_value(usb_phy->gpio_vbus_det); + } } return err; -- cgit v1.3.1 From 6fa41cdd19b93b27483f071f96da8b66bebd7a37 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 12 Sep 2021 09:22:42 -0500 Subject: phy: sun4i-usb: Support VBUS detection via power supply The device tree binding provides for getting VBUS state from a device referenced by phandle, as an optional alternative to using a GPIO. In U-Boot, where there is no power supply class, this VBUS detection will be implemented using a regulator device and its get_enable method. Let's hook this up to the PHY driver. Signed-off-by: Samuel Holland Acked-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/phy/allwinner/Kconfig | 1 + drivers/phy/allwinner/phy-sun4i-usb.c | 7 +++++++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig index 6bfb79cbcad..d3ff82f73a0 100644 --- a/drivers/phy/allwinner/Kconfig +++ b/drivers/phy/allwinner/Kconfig @@ -4,6 +4,7 @@ config PHY_SUN4I_USB bool "Allwinner Sun4I USB PHY driver" depends on ARCH_SUNXI + select DM_REGULATOR select PHY help Enable this to support the transceiver that is part of Allwinner diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 827ecd70f27..ab2a5d17fcf 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -26,6 +26,7 @@ #include #include #include +#include #define REG_ISCR 0x00 #define REG_PHYCTL_A10 0x04 @@ -137,6 +138,7 @@ struct sun4i_usb_phy_data { void __iomem *base; const struct sun4i_usb_phy_cfg *cfg; struct sun4i_usb_phy_plat *usb_phy; + struct udevice *vbus_power_supply; }; static int initial_usb_scan_delay = CONFIG_INITIAL_USB_SCAN_DELAY; @@ -404,6 +406,8 @@ int sun4i_usb_phy_vbus_detect(struct phy *phy) mdelay(100); err = gpio_get_value(usb_phy->gpio_vbus_det); } + } else if (data->vbus_power_supply) { + err = regulator_get_enable(data->vbus_power_supply); } return err; @@ -447,6 +451,9 @@ static int sun4i_usb_phy_probe(struct udevice *dev) if (IS_ERR(data->base)) return PTR_ERR(data->base); + device_get_supply_regulator(dev, "usb0_vbus_power-supply", + &data->vbus_power_supply); + data->usb_phy = plat; for (i = 0; i < data->cfg->num_phys; i++) { struct sun4i_usb_phy_plat *phy = &plat[i]; -- cgit v1.3.1 From 830e161eb4e9dbd3e9eb20ad6a3255eb8b4ed3c4 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 22 Aug 2021 18:18:05 -0500 Subject: power: axp: Avoid do_poweroff conflict with sysreset The sysreset uclass has an option to provide the do_poweroff() function. When that option is enabled, the AXP power drivers should not provide their own definition. For the AXP305, which is paired with 64-bit systems where TF-A provides PSCI, there is another possible conflict with the PSCI firmware driver. This driver can be enabled even if CONFIG_PSCI_RESET is disabled, so make sure to use the right symbol in the condition. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/power/axp152.c | 2 ++ drivers/power/axp209.c | 2 ++ drivers/power/axp221.c | 2 ++ drivers/power/axp305.c | 2 +- drivers/power/axp809.c | 2 ++ drivers/power/axp818.c | 2 ++ 6 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/power/axp152.c b/drivers/power/axp152.c index d6e36125c12..a93987c1538 100644 --- a/drivers/power/axp152.c +++ b/drivers/power/axp152.c @@ -79,6 +79,7 @@ int axp_init(void) return 0; } +#if !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF) int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { pmic_bus_write(AXP152_SHUTDOWN, AXP152_POWEROFF); @@ -89,3 +90,4 @@ int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) /* not reached */ return 0; } +#endif diff --git a/drivers/power/axp209.c b/drivers/power/axp209.c index ade531940b9..3447b9f0113 100644 --- a/drivers/power/axp209.c +++ b/drivers/power/axp209.c @@ -230,6 +230,7 @@ int axp_init(void) return 0; } +#if !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF) int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { pmic_bus_write(AXP209_SHUTDOWN, AXP209_POWEROFF); @@ -240,3 +241,4 @@ int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) /* not reached */ return 0; } +#endif diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c index 3446fe7365d..d251c314b98 100644 --- a/drivers/power/axp221.c +++ b/drivers/power/axp221.c @@ -264,6 +264,7 @@ int axp_get_sid(unsigned int *sid) return 0; } +#if !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF) int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { pmic_bus_write(AXP221_SHUTDOWN, AXP221_SHUTDOWN_POWEROFF); @@ -274,3 +275,4 @@ int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) /* not reached */ return 0; } +#endif diff --git a/drivers/power/axp305.c b/drivers/power/axp305.c index 0191e4d427e..049ef07f746 100644 --- a/drivers/power/axp305.c +++ b/drivers/power/axp305.c @@ -69,7 +69,7 @@ int axp_init(void) return ret; } -#ifndef CONFIG_PSCI_RESET +#if !CONFIG_IS_ENABLED(ARM_PSCI_FW) && !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF) int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { pmic_bus_write(AXP305_SHUTDOWN, AXP305_POWEROFF); diff --git a/drivers/power/axp809.c b/drivers/power/axp809.c index 0396502cdb5..d327a584ded 100644 --- a/drivers/power/axp809.c +++ b/drivers/power/axp809.c @@ -219,6 +219,7 @@ int axp_init(void) return pmic_bus_init(); } +#if !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF) int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { pmic_bus_write(AXP809_SHUTDOWN, AXP809_SHUTDOWN_POWEROFF); @@ -229,3 +230,4 @@ int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) /* not reached */ return 0; } +#endif diff --git a/drivers/power/axp818.c b/drivers/power/axp818.c index 2dc736467bb..08286ea3b55 100644 --- a/drivers/power/axp818.c +++ b/drivers/power/axp818.c @@ -255,6 +255,7 @@ int axp_init(void) return 0; } +#if !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF) int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { pmic_bus_write(AXP818_SHUTDOWN, AXP818_SHUTDOWN_POWEROFF); @@ -265,3 +266,4 @@ int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) /* not reached */ return 0; } +#endif -- cgit v1.3.1 From 95d9ffd7b678414cc79365c8d2be0d12c326a7ad Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 24 Oct 2021 21:00:10 -0500 Subject: power: pmic: axp: Implement poweroff via sysreset The AXP PMICs have the ability to power off the system. The existing code for this is duplicated for each PMIC variant, and uses the legacy non-DM "pmic_bus" interface. When SYSRESET is enabled, this can all be replaced with a sysreset device using the DM_PMIC interface. Since the trigger bit is the same on all PMIC variants, use the register definitions from the oldest supported PMIC. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/power/pmic/Kconfig | 2 ++ drivers/power/pmic/axp.c | 49 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index 92e2ace279d..b9fda428df9 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -66,6 +66,8 @@ config PMIC_ACT8846 config PMIC_AXP bool "Enable Driver Model for X-Powers AXP PMICs" depends on DM_I2C + select SYSRESET_CMD_POWEROFF if SYSRESET && CMD_POWEROFF + imply CMD_POWEROFF if SYSRESET help This config enables driver-model PMIC uclass features for X-Powers AXP152, AXP2xx, and AXP8xx PMICs. diff --git a/drivers/power/pmic/axp.c b/drivers/power/pmic/axp.c index 74c94bdb47b..0f2b24a8b5f 100644 --- a/drivers/power/pmic/axp.c +++ b/drivers/power/pmic/axp.c @@ -1,8 +1,37 @@ // SPDX-License-Identifier: GPL-2.0+ +#include #include +#include #include #include +#include + +#if CONFIG_IS_ENABLED(SYSRESET) +static int axp_sysreset_request(struct udevice *dev, enum sysreset_t type) +{ + int ret; + + if (type != SYSRESET_POWER_OFF) + return -EPROTONOSUPPORT; + + ret = pmic_clrsetbits(dev->parent, AXP152_SHUTDOWN, 0, AXP152_POWEROFF); + if (ret < 0) + return ret; + + return -EINPROGRESS; +} + +static struct sysreset_ops axp_sysreset_ops = { + .request = axp_sysreset_request, +}; + +U_BOOT_DRIVER(axp_sysreset) = { + .name = "axp_sysreset", + .id = UCLASS_SYSRESET, + .ops = &axp_sysreset_ops, +}; +#endif static int axp_pmic_reg_count(struct udevice *dev) { @@ -16,6 +45,24 @@ static struct dm_pmic_ops axp_pmic_ops = { .write = dm_i2c_write, }; +static int axp_pmic_bind(struct udevice *dev) +{ + int ret; + + ret = dm_scan_fdt_dev(dev); + if (ret) + return ret; + + if (CONFIG_IS_ENABLED(SYSRESET)) { + ret = device_bind_driver_to_node(dev, "axp_sysreset", "axp_sysreset", + dev_ofnode(dev), NULL); + if (ret) + return ret; + } + + return 0; +} + static const struct udevice_id axp_pmic_ids[] = { { .compatible = "x-powers,axp152" }, { .compatible = "x-powers,axp202" }, @@ -33,6 +80,6 @@ U_BOOT_DRIVER(axp_pmic) = { .name = "axp_pmic", .id = UCLASS_PMIC, .of_match = axp_pmic_ids, - .bind = dm_scan_fdt_dev, + .bind = axp_pmic_bind, .ops = &axp_pmic_ops, }; -- cgit v1.3.1 From e0c628d728d6f2b0ab01488706b1a9679512a982 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 11 Sep 2021 14:45:31 -0500 Subject: clk: sunxi: Extend DM_RESET selection to SPL The sunxi clock driver exposes a reset controller, so it selects the reset controller framework. Ensure that dependency is also satisfied when building the driver for the SPL. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/clk/sunxi/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig index f89c7ffd42a..f19908113e1 100644 --- a/drivers/clk/sunxi/Kconfig +++ b/drivers/clk/sunxi/Kconfig @@ -2,6 +2,7 @@ config CLK_SUNXI bool "Clock support for Allwinner SoCs" depends on CLK && ARCH_SUNXI select DM_RESET + select SPL_DM_RESET if SPL_CLK default y help This enables support for common clock driver API on Allwinner -- cgit v1.3.1 From 93d34faeda4cb8bb059a6b6fbff4f9969c6f41a7 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 22 Aug 2021 13:53:27 -0500 Subject: watchdog: Add a driver for the sunxi watchdog This driver supports the sun4i/sun6i/sun20i watchdog timers. They have a maximum timeout of 16 seconds. Signed-off-by: Samuel Holland Signed-off-by: Andre Przywara --- drivers/watchdog/Kconfig | 8 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/sunxi_wdt.c | 188 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+) create mode 100644 drivers/watchdog/sunxi_wdt.c (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 7d2d6ea5e90..d306054a8c2 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -27,6 +27,7 @@ config WATCHDOG_TIMEOUT_MSECS default 128000 if ARCH_MX31 || ARCH_MX5 || ARCH_MX6 default 128000 if ARCH_MX7 || ARCH_VF610 default 30000 if ARCH_SOCFPGA + default 16000 if ARCH_SUNXI default 60000 help Watchdog timeout in msec @@ -270,6 +271,13 @@ config WDT_STM32MP Enable the STM32 watchdog (IWDG) driver. Enable support to configure STM32's on-SoC watchdog. +config WDT_SUNXI + bool "Allwinner sunxi watchdog timer support" + depends on WDT && ARCH_SUNXI + default y + help + Enable support for the watchdog timer in Allwinner sunxi SoCs. + config XILINX_TB_WATCHDOG bool "Xilinx Axi watchdog timer support" depends on WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index f14415bb8e3..fa7ce583ce2 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -36,5 +36,6 @@ obj-$(CONFIG_WDT_SBSA) += sbsa_gwdt.o obj-$(CONFIG_WDT_K3_RTI) += rti_wdt.o obj-$(CONFIG_WDT_SP805) += sp805_wdt.o obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o +obj-$(CONFIG_WDT_SUNXI) += sunxi_wdt.o obj-$(CONFIG_WDT_TANGIER) += tangier_wdt.o obj-$(CONFIG_WDT_XILINX) += xilinx_wwdt.o diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c new file mode 100644 index 00000000000..b40a1d29caa --- /dev/null +++ b/drivers/watchdog/sunxi_wdt.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Derived from linux/drivers/watchdog/sunxi_wdt.c: + * Copyright (C) 2013 Carlo Caione + * Copyright (C) 2012 Henrik Nordstrom + */ + +#include +#include +#include +#include + +#define MSEC_PER_SEC 1000 + +#define WDT_MAX_TIMEOUT 16 +#define WDT_TIMEOUT_MASK 0xf + +#define WDT_CTRL_RELOAD ((1 << 0) | (0x0a57 << 1)) + +#define WDT_MODE_EN BIT(0) + +struct sunxi_wdt_reg { + u8 wdt_ctrl; + u8 wdt_cfg; + u8 wdt_mode; + u8 wdt_timeout_shift; + u8 wdt_reset_mask; + u8 wdt_reset_val; + u32 wdt_key_val; +}; + +struct sunxi_wdt_priv { + void __iomem *base; + const struct sunxi_wdt_reg *regs; +}; + +/* Map of timeout in seconds to register value */ +static const u8 wdt_timeout_map[1 + WDT_MAX_TIMEOUT] = { + [0] = 0x0, + [1] = 0x1, + [2] = 0x2, + [3] = 0x3, + [4] = 0x4, + [5] = 0x5, + [6] = 0x6, + [7] = 0x7, + [8] = 0x7, + [9] = 0x8, + [10] = 0x8, + [11] = 0x9, + [12] = 0x9, + [13] = 0xa, + [14] = 0xa, + [15] = 0xb, + [16] = 0xb, +}; + +static int sunxi_wdt_reset(struct udevice *dev) +{ + struct sunxi_wdt_priv *priv = dev_get_priv(dev); + const struct sunxi_wdt_reg *regs = priv->regs; + void __iomem *base = priv->base; + + writel(WDT_CTRL_RELOAD, base + regs->wdt_ctrl); + + return 0; +} + +static int sunxi_wdt_start(struct udevice *dev, u64 timeout, ulong flags) +{ + struct sunxi_wdt_priv *priv = dev_get_priv(dev); + const struct sunxi_wdt_reg *regs = priv->regs; + void __iomem *base = priv->base; + u32 val; + + timeout /= MSEC_PER_SEC; + if (timeout > WDT_MAX_TIMEOUT) + timeout = WDT_MAX_TIMEOUT; + + /* Set system reset function */ + val = readl(base + regs->wdt_cfg); + val &= ~regs->wdt_reset_mask; + val |= regs->wdt_reset_val; + val |= regs->wdt_key_val; + writel(val, base + regs->wdt_cfg); + + /* Set timeout and enable watchdog */ + val = readl(base + regs->wdt_mode); + val &= ~(WDT_TIMEOUT_MASK << regs->wdt_timeout_shift); + val |= wdt_timeout_map[timeout] << regs->wdt_timeout_shift; + val |= WDT_MODE_EN; + val |= regs->wdt_key_val; + writel(val, base + regs->wdt_mode); + + return sunxi_wdt_reset(dev); +} + +static int sunxi_wdt_stop(struct udevice *dev) +{ + struct sunxi_wdt_priv *priv = dev_get_priv(dev); + const struct sunxi_wdt_reg *regs = priv->regs; + void __iomem *base = priv->base; + + writel(regs->wdt_key_val, base + regs->wdt_mode); + + return 0; +} + +static int sunxi_wdt_expire_now(struct udevice *dev, ulong flags) +{ + int ret; + + ret = sunxi_wdt_start(dev, 0, flags); + if (ret) + return ret; + + mdelay(500); + + return 0; +} + +static const struct wdt_ops sunxi_wdt_ops = { + .reset = sunxi_wdt_reset, + .start = sunxi_wdt_start, + .stop = sunxi_wdt_stop, + .expire_now = sunxi_wdt_expire_now, +}; + +static const struct sunxi_wdt_reg sun4i_wdt_reg = { + .wdt_ctrl = 0x00, + .wdt_cfg = 0x04, + .wdt_mode = 0x04, + .wdt_timeout_shift = 3, + .wdt_reset_mask = 0x2, + .wdt_reset_val = 0x2, +}; + +static const struct sunxi_wdt_reg sun6i_wdt_reg = { + .wdt_ctrl = 0x10, + .wdt_cfg = 0x14, + .wdt_mode = 0x18, + .wdt_timeout_shift = 4, + .wdt_reset_mask = 0x3, + .wdt_reset_val = 0x1, +}; + +static const struct sunxi_wdt_reg sun20i_wdt_reg = { + .wdt_ctrl = 0x10, + .wdt_cfg = 0x14, + .wdt_mode = 0x18, + .wdt_timeout_shift = 4, + .wdt_reset_mask = 0x03, + .wdt_reset_val = 0x01, + .wdt_key_val = 0x16aa0000, +}; + +static const struct udevice_id sunxi_wdt_ids[] = { + { .compatible = "allwinner,sun4i-a10-wdt", .data = (ulong)&sun4i_wdt_reg }, + { .compatible = "allwinner,sun6i-a31-wdt", .data = (ulong)&sun6i_wdt_reg }, + { .compatible = "allwinner,sun20i-d1-wdt", .data = (ulong)&sun20i_wdt_reg }, + { /* sentinel */ } +}; + +static int sunxi_wdt_probe(struct udevice *dev) +{ + struct sunxi_wdt_priv *priv = dev_get_priv(dev); + + priv->base = dev_remap_addr(dev); + if (!priv->base) + return -EINVAL; + + priv->regs = (void *)dev_get_driver_data(dev); + if (!priv->regs) + return -EINVAL; + + sunxi_wdt_stop(dev); + + return 0; +} + +U_BOOT_DRIVER(sunxi_wdt) = { + .name = "sunxi_wdt", + .id = UCLASS_WDT, + .of_match = sunxi_wdt_ids, + .probe = sunxi_wdt_probe, + .priv_auto = sizeof(struct sunxi_wdt_priv), + .ops = &sunxi_wdt_ops, +}; -- cgit v1.3.1 From c846fe43f0561311eb7261b34023a04646cdbd0d Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Thu, 22 Jul 2021 14:30:05 +0800 Subject: mmc: sunxi: conditionally include MMC2 initialization code Allwinner R329 has no MMC2. Only include the code of MMC2 if the base address of it is defined. Signed-off-by: Icenowy Zheng Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/mmc/sunxi_mmc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index c170c16d5ab..4bf8a9b92ce 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -72,10 +72,12 @@ static int mmc_resource_init(int sdc_no) priv->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE; priv->mclkreg = &ccm->sd1_clk_cfg; break; +#ifdef SUNXI_MMC2_BASE case 2: priv->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE; priv->mclkreg = &ccm->sd2_clk_cfg; break; +#endif #ifdef SUNXI_MMC3_BASE case 3: priv->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE; -- cgit v1.3.1