diff options
author | Tom Rini <trini@konsulko.com> | 2021-01-26 03:46:02 +0300 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2021-01-26 03:46:02 +0300 |
commit | e262b2973e22174da666038514d17f0f7171466b (patch) | |
tree | 0b0b605f1192d4d2e18c956b6e8ef340b2799bfd /drivers | |
parent | c99be953e787cfb2414de67390427e00b6812240 (diff) | |
parent | 38be6b838780e8ad0ee80e716752c8843cd87e05 (diff) | |
download | u-boot-e262b2973e22174da666038514d17f0f7171466b.tar.xz |
Merge https://gitlab.denx.de/u-boot/custodians/u-boot-sunxi
- New Allwinner H616 SoC support (sans Ethernet & USB)
- H6 DT update
- Tanix TX6 TV box support
- OrangePi 3 support
- OrangePi Zero2 (H616) support
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/sunxi/Kconfig | 7 | ||||
-rw-r--r-- | drivers/clk/sunxi/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk_h616.c | 120 | ||||
-rw-r--r-- | drivers/gpio/sunxi_gpio.c | 2 | ||||
-rw-r--r-- | drivers/i2c/mvtwsi.c | 2 | ||||
-rw-r--r-- | drivers/mmc/sunxi_mmc.c | 96 | ||||
-rw-r--r-- | drivers/net/sun8i_emac.c | 3 | ||||
-rw-r--r-- | drivers/power/Kconfig | 14 | ||||
-rw-r--r-- | drivers/power/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/axp305.c | 83 |
10 files changed, 260 insertions, 69 deletions
diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig index 5ff101b993..bf084fa7a8 100644 --- a/drivers/clk/sunxi/Kconfig +++ b/drivers/clk/sunxi/Kconfig @@ -79,6 +79,13 @@ config CLK_SUN50I_H6 This enables common clock driver support for platforms based on Allwinner H6 SoC. +config CLK_SUN50I_H616 + bool "Clock driver for Allwinner H616" + default MACH_SUN50I_H616 + help + This enables common clock driver support for platforms based + on Allwinner H616 SoC. + config CLK_SUN50I_A64 bool "Clock driver for Allwinner A64" default MACH_SUN50I diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile index 36fb2aeb56..0dfc0593fb 100644 --- a/drivers/clk/sunxi/Makefile +++ b/drivers/clk/sunxi/Makefile @@ -16,4 +16,5 @@ obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o obj-$(CONFIG_CLK_SUN9I_A80) += clk_a80.o obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o obj-$(CONFIG_CLK_SUN50I_H6) += clk_h6.o +obj-$(CONFIG_CLK_SUN50I_H616) += clk_h616.o obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o diff --git a/drivers/clk/sunxi/clk_h616.c b/drivers/clk/sunxi/clk_h616.c new file mode 100644 index 0000000000..553d7c6e55 --- /dev/null +++ b/drivers/clk/sunxi/clk_h616.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2021 Jernej Skrabec <jernej.skrabec@siol.net> + */ + +#include <common.h> +#include <clk-uclass.h> +#include <dm.h> +#include <errno.h> +#include <asm/arch/ccu.h> +#include <dt-bindings/clock/sun50i-h616-ccu.h> +#include <dt-bindings/reset/sun50i-h616-ccu.h> +#include <linux/bitops.h> + +static struct ccu_clk_gate h616_gates[] = { + [CLK_BUS_MMC0] = GATE(0x84c, BIT(0)), + [CLK_BUS_MMC1] = GATE(0x84c, BIT(1)), + [CLK_BUS_MMC2] = GATE(0x84c, BIT(2)), + + [CLK_BUS_UART0] = GATE(0x90c, BIT(0)), + [CLK_BUS_UART1] = GATE(0x90c, BIT(1)), + [CLK_BUS_UART2] = GATE(0x90c, BIT(2)), + [CLK_BUS_UART3] = GATE(0x90c, BIT(3)), + [CLK_BUS_UART4] = GATE(0x90c, BIT(4)), + [CLK_BUS_UART5] = GATE(0x90c, BIT(5)), + + [CLK_SPI0] = GATE(0x940, BIT(31)), + [CLK_SPI1] = GATE(0x944, BIT(31)), + + [CLK_BUS_SPI0] = GATE(0x96c, BIT(0)), + [CLK_BUS_SPI1] = GATE(0x96c, BIT(1)), + + [CLK_BUS_EMAC0] = GATE(0x97c, BIT(0)), + [CLK_BUS_EMAC1] = GATE(0x97c, BIT(1)), + + [CLK_USB_PHY0] = GATE(0xa70, BIT(29)), + [CLK_USB_OHCI0] = GATE(0xa70, BIT(31)), + + [CLK_USB_PHY1] = GATE(0xa74, BIT(29)), + [CLK_USB_OHCI1] = GATE(0xa74, BIT(31)), + + [CLK_USB_PHY2] = GATE(0xa78, BIT(29)), + [CLK_USB_OHCI2] = GATE(0xa78, BIT(31)), + + [CLK_USB_PHY3] = GATE(0xa7c, BIT(29)), + [CLK_USB_OHCI3] = GATE(0xa7c, BIT(31)), + + [CLK_BUS_OHCI0] = GATE(0xa8c, BIT(0)), + [CLK_BUS_OHCI1] = GATE(0xa8c, BIT(1)), + [CLK_BUS_OHCI2] = GATE(0xa8c, BIT(2)), + [CLK_BUS_OHCI3] = GATE(0xa8c, BIT(3)), + [CLK_BUS_EHCI0] = GATE(0xa8c, BIT(4)), + [CLK_BUS_EHCI1] = GATE(0xa8c, BIT(5)), + [CLK_BUS_EHCI2] = GATE(0xa8c, BIT(6)), + [CLK_BUS_EHCI3] = GATE(0xa8c, BIT(7)), + [CLK_BUS_OTG] = GATE(0xa8c, BIT(8)), +}; + +static struct ccu_reset h616_resets[] = { + [RST_BUS_MMC0] = RESET(0x84c, BIT(16)), + [RST_BUS_MMC1] = RESET(0x84c, BIT(17)), + [RST_BUS_MMC2] = RESET(0x84c, BIT(18)), + + [RST_BUS_UART0] = RESET(0x90c, BIT(16)), + [RST_BUS_UART1] = RESET(0x90c, BIT(17)), + [RST_BUS_UART2] = RESET(0x90c, BIT(18)), + [RST_BUS_UART3] = RESET(0x90c, BIT(19)), + [RST_BUS_UART4] = RESET(0x90c, BIT(20)), + [RST_BUS_UART5] = RESET(0x90c, BIT(21)), + + [RST_BUS_SPI0] = RESET(0x96c, BIT(16)), + [RST_BUS_SPI1] = RESET(0x96c, BIT(17)), + + [RST_BUS_EMAC0] = RESET(0x97c, BIT(16)), + [RST_BUS_EMAC1] = RESET(0x97c, BIT(17)), + + [RST_USB_PHY0] = RESET(0xa70, BIT(30)), + + [RST_USB_PHY1] = RESET(0xa74, BIT(30)), + + [RST_USB_PHY2] = RESET(0xa78, BIT(30)), + + [RST_USB_PHY3] = RESET(0xa7c, BIT(30)), + + [RST_BUS_OHCI0] = RESET(0xa8c, BIT(16)), + [RST_BUS_OHCI1] = RESET(0xa8c, BIT(17)), + [RST_BUS_OHCI2] = RESET(0xa8c, BIT(18)), + [RST_BUS_OHCI3] = RESET(0xa8c, BIT(19)), + [RST_BUS_EHCI0] = RESET(0xa8c, BIT(20)), + [RST_BUS_EHCI1] = RESET(0xa8c, BIT(21)), + [RST_BUS_EHCI2] = RESET(0xa8c, BIT(22)), + [RST_BUS_EHCI3] = RESET(0xa8c, BIT(23)), + [RST_BUS_OTG] = RESET(0xa8c, BIT(24)), +}; + +static const struct ccu_desc h616_ccu_desc = { + .gates = h616_gates, + .resets = h616_resets, +}; + +static int h616_clk_bind(struct udevice *dev) +{ + return sunxi_reset_bind(dev, ARRAY_SIZE(h616_resets)); +} + +static const struct udevice_id h616_ccu_ids[] = { + { .compatible = "allwinner,sun50i-h616-ccu", + .data = (ulong)&h616_ccu_desc }, + { } +}; + +U_BOOT_DRIVER(clk_sun50i_h616) = { + .name = "sun50i_h616_ccu", + .id = UCLASS_CLK, + .of_match = h616_ccu_ids, + .priv_auto = sizeof(struct ccu_priv), + .ops = &sunxi_clk_ops, + .probe = sunxi_clk_probe, + .bind = h616_clk_bind, +}; diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index 7633422b0b..24cb604e3e 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -355,6 +355,7 @@ static const struct udevice_id sunxi_gpio_ids[] = { ID("allwinner,sun9i-a80-pinctrl", a_all), ID("allwinner,sun50i-a64-pinctrl", a_all), ID("allwinner,sun50i-h6-pinctrl", a_all), + ID("allwinner,sun50i-h616-pinctrl", a_all), ID("allwinner,sun6i-a31-r-pinctrl", l_2), ID("allwinner,sun8i-a23-r-pinctrl", l_1), ID("allwinner,sun8i-a83t-r-pinctrl", l_1), @@ -362,6 +363,7 @@ static const struct udevice_id sunxi_gpio_ids[] = { ID("allwinner,sun9i-a80-r-pinctrl", l_3), ID("allwinner,sun50i-a64-r-pinctrl", l_1), ID("allwinner,sun50i-h6-r-pinctrl", l_2), + ID("allwinner,sun50i-h616-r-pinctrl", l_1), { } }; diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index a4d59b67a2..37b1a06ee0 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -121,7 +121,7 @@ enum mvtwsi_ctrl_register_fields { * on other platforms, it is a normal r/w bit, which is cleared by writing 0. */ -#ifdef CONFIG_SUNXI_GEN_SUN6I +#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) #define MVTWSI_CONTROL_CLEAR_IFLG 0x00000008 #else #define MVTWSI_CONTROL_CLEAR_IFLG 0x00000000 diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index b33f80b9da..3503ccdb2e 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -23,12 +23,6 @@ #include <asm-generic/gpio.h> #include <linux/delay.h> -#ifdef CONFIG_DM_MMC -struct sunxi_mmc_variant { - u16 mclk_offset; -}; -#endif - struct sunxi_mmc_plat { struct mmc_config cfg; struct mmc mmc; @@ -42,9 +36,6 @@ struct sunxi_mmc_priv { int cd_inverted; /* Inverted Card Detect */ struct sunxi_mmc *reg; struct mmc_config cfg; -#ifdef CONFIG_DM_MMC - const struct sunxi_mmc_variant *variant; -#endif }; #if !CONFIG_IS_ENABLED(DM_MMC) @@ -122,7 +113,7 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz) if (IS_ENABLED(CONFIG_MACH_SUN8I_A83T) && priv->mmc_no != 2) new_mode = false; -#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6) +#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_SUN50I_GEN_H6) calibrate = true; #endif @@ -133,7 +124,7 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz) #ifdef CONFIG_MACH_SUN9I pll = CCM_MMC_CTRL_PLL_PERIPH0; pll_hz = clock_get_pll4_periph0(); -#elif defined(CONFIG_MACH_SUN50I_H6) +#elif defined(CONFIG_SUN50I_GEN_H6) pll = CCM_MMC_CTRL_PLL6X2; pll_hz = clock_get_pll6() * 2; #else @@ -249,7 +240,7 @@ static int mmc_config_clock(struct sunxi_mmc_priv *priv, struct mmc *mmc) rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK; writel(rval, &priv->reg->clkcr); -#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6) +#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_SUN50I_GEN_H6) /* A64 supports calibration of delays on MMC controller and we * have to set delay of zero before starting calibration. * Allwinner BSP driver sets a delay only in the case of @@ -530,7 +521,7 @@ struct mmc *sunxi_mmc_init(int sdc_no) cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; cfg->host_caps = MMC_MODE_4BIT; -#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN50I_H6) +#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I) || defined(CONFIG_SUN50I_GEN_H6) if (sdc_no == 2) cfg->host_caps = MMC_MODE_8BIT; #endif @@ -545,7 +536,7 @@ struct mmc *sunxi_mmc_init(int sdc_no) /* config ahb clock */ debug("init mmc %d clock and io\n", sdc_no); -#if !defined(CONFIG_MACH_SUN50I_H6) +#if !defined(CONFIG_SUN50I_GEN_H6) setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no)); #ifdef CONFIG_SUNXI_GEN_SUN6I @@ -557,7 +548,7 @@ struct mmc *sunxi_mmc_init(int sdc_no) writel(SUNXI_MMC_COMMON_CLK_GATE | SUNXI_MMC_COMMON_RESET, SUNXI_MMC_COMMON_BASE + 4 * sdc_no); #endif -#else /* CONFIG_MACH_SUN50I_H6 */ +#else /* CONFIG_SUN50I_GEN_H6 */ setbits_le32(&ccm->sd_gate_reset, 1 << sdc_no); /* unassert reset */ setbits_le32(&ccm->sd_gate_reset, 1 << (RESET_SHIFT + sdc_no)); @@ -605,6 +596,17 @@ static const struct dm_mmc_ops sunxi_mmc_ops = { .get_cd = sunxi_mmc_getcd, }; +static unsigned get_mclk_offset(void) +{ + if (IS_ENABLED(CONFIG_MACH_SUN9I_A80)) + return 0x410; + + if (IS_ENABLED(CONFIG_SUN50I_GEN_H6)) + return 0x830; + + return 0x88; +}; + static int sunxi_mmc_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); @@ -633,8 +635,6 @@ static int sunxi_mmc_probe(struct udevice *dev) cfg->f_max = 52000000; priv->reg = (void *)dev_read_addr(dev); - priv->variant = - (const struct sunxi_mmc_variant *)dev_get_driver_data(dev); /* We don't have a sunxi clock driver so find the clock address here */ ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0, @@ -644,8 +644,7 @@ static int sunxi_mmc_probe(struct udevice *dev) ccu_reg = (u32 *)ofnode_get_addr(args.node); priv->mmc_no = ((uintptr_t)priv->reg - SUNXI_MMC0_BASE) / 0x1000; - priv->mclkreg = (void *)ccu_reg + - (priv->variant->mclk_offset + (priv->mmc_no * 4)); + priv->mclkreg = (void *)ccu_reg + get_mclk_offset() + priv->mmc_no * 4; ret = clk_get_by_name(dev, "ahb", &gate_clk); if (!ret) @@ -687,55 +686,18 @@ static int sunxi_mmc_bind(struct udevice *dev) return mmc_bind(dev, &plat->mmc, &plat->cfg); } -static const struct sunxi_mmc_variant sun4i_a10_variant = { - .mclk_offset = 0x88, -}; - -static const struct sunxi_mmc_variant sun9i_a80_variant = { - .mclk_offset = 0x410, -}; - -static const struct sunxi_mmc_variant sun50i_h6_variant = { - .mclk_offset = 0x830, -}; - static const struct udevice_id sunxi_mmc_ids[] = { - { - .compatible = "allwinner,sun4i-a10-mmc", - .data = (ulong)&sun4i_a10_variant, - }, - { - .compatible = "allwinner,sun5i-a13-mmc", - .data = (ulong)&sun4i_a10_variant, - }, - { - .compatible = "allwinner,sun7i-a20-mmc", - .data = (ulong)&sun4i_a10_variant, - }, - { - .compatible = "allwinner,sun8i-a83t-emmc", - .data = (ulong)&sun4i_a10_variant, - }, - { - .compatible = "allwinner,sun9i-a80-mmc", - .data = (ulong)&sun9i_a80_variant, - }, - { - .compatible = "allwinner,sun50i-a64-mmc", - .data = (ulong)&sun4i_a10_variant, - }, - { - .compatible = "allwinner,sun50i-a64-emmc", - .data = (ulong)&sun4i_a10_variant, - }, - { - .compatible = "allwinner,sun50i-h6-mmc", - .data = (ulong)&sun50i_h6_variant, - }, - { - .compatible = "allwinner,sun50i-h6-emmc", - .data = (ulong)&sun50i_h6_variant, - }, + { .compatible = "allwinner,sun4i-a10-mmc" }, + { .compatible = "allwinner,sun5i-a13-mmc" }, + { .compatible = "allwinner,sun7i-a20-mmc" }, + { .compatible = "allwinner,sun8i-a83t-emmc" }, + { .compatible = "allwinner,sun9i-a80-mmc" }, + { .compatible = "allwinner,sun50i-a64-mmc" }, + { .compatible = "allwinner,sun50i-a64-emmc" }, + { .compatible = "allwinner,sun50i-h6-mmc" }, + { .compatible = "allwinner,sun50i-h6-emmc" }, + { .compatible = "allwinner,sun50i-a100-mmc" }, + { .compatible = "allwinner,sun50i-a100-emmc" }, { /* sentinel */ } }; diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c index cf15e9f475..9f91a20d1d 100644 --- a/drivers/net/sun8i_emac.c +++ b/drivers/net/sun8i_emac.c @@ -353,6 +353,9 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata, /* default */ break; case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: reg |= SC_EPIT | SC_ETCS_INT_GMII; break; case PHY_INTERFACE_MODE_RMII: diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 02050f6f35..c5fbf1f832 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -13,6 +13,7 @@ choice depends on ARCH_SUNXI default AXP209_POWER if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I default AXP221_POWER if MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33 || MACH_SUN8I_R40 + default AXP305_POWER if MACH_SUN50I_H616 default AXP818_POWER if MACH_SUN8I_A83T default SUNXI_NO_PMIC if MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_V3S @@ -48,6 +49,15 @@ config AXP221_POWER Select this to enable support for the axp221/axp223 pmic found on most A23 and A31 boards. +config AXP305_POWER + bool "axp305 pmic support" + depends on MACH_SUN50I_H616 + select AXP_PMIC_BUS + select CMD_POWEROFF + ---help--- + Select this to enable support for the axp305 pmic found on most + H616 boards. + config AXP809_POWER bool "axp809 pmic support" depends on MACH_SUN9I @@ -127,11 +137,12 @@ config AXP_DCDC3_VOLT config AXP_DCDC4_VOLT int "axp pmic dcdc4 voltage" - depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER + depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP305_POWER default 1250 if AXP152_POWER default 1200 if MACH_SUN6I default 0 if MACH_SUN8I default 900 if MACH_SUN9I + default 1500 if AXP305_POWER ---help--- Set the voltage (mV) to program the axp pmic dcdc4 at, set to 0 to disable dcdc4. @@ -140,6 +151,7 @@ config AXP_DCDC4_VOLT On A23 / A33 boards dcdc4 is unused and should be disabled. On A80 boards dcdc4 powers VDD-SYS, HDMI, USB OTG and should be 0.9V. On A83T boards dcdc4 is used for VDD-GPU. + On H616 boards dcdcd is used for VCC-DRAM. config AXP_DCDC5_VOLT int "axp pmic dcdc5 voltage" diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 2dcc7bb99d..0bef06920a 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_AXP152_POWER) += axp152.o obj-$(CONFIG_AXP209_POWER) += axp209.o obj-$(CONFIG_AXP221_POWER) += axp221.o +obj-$(CONFIG_AXP305_POWER) += axp305.o obj-$(CONFIG_AXP809_POWER) += axp809.o obj-$(CONFIG_AXP818_POWER) += axp818.o obj-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o diff --git a/drivers/power/axp305.c b/drivers/power/axp305.c new file mode 100644 index 0000000000..0191e4d427 --- /dev/null +++ b/drivers/power/axp305.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * AXP305 driver + * + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net> + * + * Based on axp221.c + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com> + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl> + */ + +#include <common.h> +#include <command.h> +#include <errno.h> +#include <asm/arch/pmic_bus.h> +#include <axp_pmic.h> + +#define AXP305_DCDC4_1600MV_OFFSET 46 + +static u8 axp305_mvolt_to_cfg(int mvolt, int min, int max, int div) +{ + if (mvolt < min) + mvolt = min; + else if (mvolt > max) + mvolt = max; + + return (mvolt - min) / div; +} + +int axp_set_dcdc4(unsigned int mvolt) +{ + int ret; + u8 cfg; + + if (mvolt >= 1600) + cfg = AXP305_DCDC4_1600MV_OFFSET + + axp305_mvolt_to_cfg(mvolt, 1600, 3300, 100); + else + cfg = axp305_mvolt_to_cfg(mvolt, 600, 1500, 20); + + if (mvolt == 0) + return pmic_bus_clrbits(AXP305_OUTPUT_CTRL1, + AXP305_OUTPUT_CTRL1_DCDCD_EN); + + ret = pmic_bus_write(AXP305_DCDCD_VOLTAGE, cfg); + if (ret) + return ret; + + return pmic_bus_setbits(AXP305_OUTPUT_CTRL1, + AXP305_OUTPUT_CTRL1_DCDCD_EN); +} + +int axp_init(void) +{ + u8 axp_chip_id; + int ret; + + ret = pmic_bus_init(); + if (ret) + return ret; + + ret = pmic_bus_read(AXP305_CHIP_VERSION, &axp_chip_id); + if (ret) + return ret; + + if ((axp_chip_id & AXP305_CHIP_VERSION_MASK) != 0x40) + return -ENODEV; + + return ret; +} + +#ifndef CONFIG_PSCI_RESET +int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + pmic_bus_write(AXP305_SHUTDOWN, AXP305_POWEROFF); + + /* infinite loop during shutdown */ + while (1) {} + + /* not reached */ + return 0; +} +#endif |