diff options
Diffstat (limited to 'drivers/power/pmic')
| -rw-r--r-- | drivers/power/pmic/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/power/pmic/axp.c | 1 | ||||
| -rw-r--r-- | drivers/power/pmic/max8997.c | 2 | ||||
| -rw-r--r-- | drivers/power/pmic/pca9450.c | 100 | ||||
| -rw-r--r-- | drivers/power/pmic/rk8xx.c | 21 | ||||
| -rw-r--r-- | drivers/power/pmic/s2mps11.c | 39 | 
6 files changed, 129 insertions, 38 deletions
| diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index ec7ccc3a63f..b1a5b1c2a1f 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -228,9 +228,9 @@ config PMIC_MAX8997  	This is a Power Management IC with RTC, Fuel Gauge, MUIC control on Chip.  	- 21x LDOs  	- 12x GPIOs -	- Haptic Motor driver +	- Haptic motor driver  	- RTC with two alarms -	- Fueal Gauge and One backup battery charger +	- Fuel Gauge and one backup battery charger  	- MUIC  	- Others diff --git a/drivers/power/pmic/axp.c b/drivers/power/pmic/axp.c index c300fd2bbc2..1204ec00f8d 100644 --- a/drivers/power/pmic/axp.c +++ b/drivers/power/pmic/axp.c @@ -89,6 +89,7 @@ static const struct udevice_id axp_pmic_ids[] = {  	{ .compatible = "x-powers,axp221", .data = AXP221_ID },  	{ .compatible = "x-powers,axp223", .data = AXP223_ID },  	{ .compatible = "x-powers,axp313a", .data = AXP313_ID }, +	{ .compatible = "x-powers,axp323", .data = AXP323_ID },  	{ .compatible = "x-powers,axp717", .data = AXP717_ID },  	{ .compatible = "x-powers,axp803", .data = AXP803_ID },  	{ .compatible = "x-powers,axp806", .data = AXP806_ID }, diff --git a/drivers/power/pmic/max8997.c b/drivers/power/pmic/max8997.c index 4afa6c84ef8..fb65a3ca730 100644 --- a/drivers/power/pmic/max8997.c +++ b/drivers/power/pmic/max8997.c @@ -46,7 +46,7 @@ static struct dm_pmic_ops max8997_ops = {  };  static const struct udevice_id max8997_ids[] = { -	{ .compatible = "maxim,max8997" }, +	{ .compatible = "maxim,max8997-pmic" },  	{ },  }; diff --git a/drivers/power/pmic/pca9450.c b/drivers/power/pmic/pca9450.c index 9d875f8bdbe..e5c1f037b61 100644 --- a/drivers/power/pmic/pca9450.c +++ b/drivers/power/pmic/pca9450.c @@ -7,15 +7,16 @@  #include <errno.h>  #include <dm.h>  #include <dm/device_compat.h> +#include <dm/lists.h>  #include <i2c.h> -#include <linux/err.h>  #include <log.h>  #include <asm/global_data.h> -#include <asm-generic/gpio.h> +#include <linux/delay.h>  #include <linux/printk.h>  #include <power/pmic.h>  #include <power/regulator.h>  #include <power/pca9450.h> +#include <sysreset.h>  DECLARE_GLOBAL_DATA_PTR; @@ -29,10 +30,6 @@ static const struct pmic_child_info pmic_children_info[] = {  	{ },  }; -struct pca9450_priv { -	struct gpio_desc *sd_vsel_gpio; -}; -  static int pca9450_reg_count(struct udevice *dev)  {  	return PCA9450_REG_NUM; @@ -85,20 +82,15 @@ static int pca9450_bind(struct udevice *dev)  static int pca9450_probe(struct udevice *dev)  { -	struct pca9450_priv *priv = dev_get_priv(dev);  	unsigned int reset_ctrl; -	int ret = 0; - -	if (CONFIG_IS_ENABLED(DM_GPIO) && CONFIG_IS_ENABLED(DM_REGULATOR_PCA9450)) { -		priv->sd_vsel_gpio = devm_gpiod_get_optional(dev, "sd-vsel", -							     GPIOD_IS_OUT | -							     GPIOD_IS_OUT_ACTIVE); -		if (IS_ERR(priv->sd_vsel_gpio)) { -			ret = PTR_ERR(priv->sd_vsel_gpio); -			dev_err(dev, "Failed to request SD_VSEL GPIO: %d\n", ret); -			if (ret) -				return ret; -		} +	int ret; + +	if (CONFIG_IS_ENABLED(SYSRESET)) { +		ret = device_bind_driver_to_node(dev, "pca9450_sysreset", +						 "pca9450_sysreset", +						 dev_ofnode(dev), NULL); +		if (ret) +			return ret;  	}  	if (ofnode_read_bool(dev_ofnode(dev), "nxp,wdog_b-warm-reset")) @@ -132,5 +124,73 @@ U_BOOT_DRIVER(pmic_pca9450) = {  	.bind = pca9450_bind,  	.probe = pca9450_probe,  	.ops = &pca9450_ops, -	.priv_auto = sizeof(struct pca9450_priv),  }; + +#ifdef CONFIG_SYSRESET +static int pca9450_sysreset_request(struct udevice *dev, enum sysreset_t type) +{ +	u8 cmd = PCA9450_SW_RST_COLD_RST; + +	if (type != SYSRESET_COLD) +		return -EPROTONOSUPPORT; + +	if (pmic_write(dev->parent, PCA9450_SW_RST, &cmd, 1)) { +		dev_err(dev, "reset command failed\n"); +	} else { +		/* tRESTART is 250ms, delay 300ms just to be sure */ +		mdelay(300); +		/* Should not get here, warn if we do */ +		dev_warn(dev, "didn't respond to reset command\n"); +	} + +	return -EINPROGRESS; +} + +int pca9450_sysreset_get_status(struct udevice *dev, char *buf, int size) +{ +	const char *reason; +	int ret; +	u8 reg; + +	ret = pmic_read(dev->parent, PCA9450_PWRON_STAT, ®, 1); +	if (ret) +		return ret; + +	switch (reg) { +	case PCA9450_PWRON_STAT_PWRON_MASK: +		reason = "PWRON"; +		break; +	case PCA9450_PWRON_STAT_WDOG_MASK: +		reason = "WDOGB"; +		break; +	case PCA9450_PWRON_STAT_SW_RST_MASK: +		reason = "SW_RST"; +		break; +	case PCA9450_PWRON_STAT_PMIC_RST_MASK: +		reason = "PMIC_RST"; +		break; +	default: +		reason = "UNKNOWN"; +		break; +	} + +	ret = snprintf(buf, size, "Reset Status: %s\n", reason); +	if (ret < 0) { +		dev_err(dev, "Write reset status error (err = %d)\n", ret); +		return -EIO; +	} + +	return 0; +} + +static struct sysreset_ops pca9450_sysreset_ops = { +	.request	= pca9450_sysreset_request, +	.get_status	= pca9450_sysreset_get_status, +}; + +U_BOOT_DRIVER(pca9450_sysreset) = { +	.name		= "pca9450_sysreset", +	.id		= UCLASS_SYSRESET, +	.ops		= &pca9450_sysreset_ops, +}; +#endif /* CONFIG_SYSRESET */ diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c index 3bc696d4caa..d11f7a7886e 100644 --- a/drivers/power/pmic/rk8xx.c +++ b/drivers/power/pmic/rk8xx.c @@ -89,11 +89,6 @@ void rk8xx_off_for_plugin(struct udevice *dev)  	}  } -static struct reg_data rk806_init_reg[] = { -	/* RST_FUN */ -	{ RK806_REG_SYS_CFG3, BIT(7), GENMASK(7, 6)}, -}; -  static struct reg_data rk817_init_reg[] = {  /* enable the under-voltage protection,   * the under-voltage protection will shutdown the LDO3 and reset the PMIC @@ -306,12 +301,20 @@ static int rk8xx_probe(struct udevice *dev)  		value = (power_en2 & 0x0f) | ((power_en3 & 0x0f) << 4);  		pmic_reg_write(dev, RK817_POWER_EN_SAVE1, value);  		break; -	case RK806_ID: +	case RK806_ID: { +		u32 rst_fun = 2; +  		on_source = RK806_ON_SOURCE;  		off_source = RK806_OFF_SOURCE; -		init_data = rk806_init_reg; -		init_data_num = ARRAY_SIZE(rk806_init_reg); -		break; + +		ret = dev_read_u32(dev, "rockchip,reset-mode", &rst_fun); +		if (ret) +			debug("rockchip,reset-mode property missing, defaulting to %d\n", +			      rst_fun); + +		pmic_clrsetbits(dev, RK806_REG_SYS_CFG3, RK806_RST_FUN_MSK, +				FIELD_PREP(RK806_RST_FUN_MSK, rst_fun)); +		break; }  	default:  		printf("Unknown PMIC: RK%x!!\n", show_variant);  		return -EINVAL; diff --git a/drivers/power/pmic/s2mps11.c b/drivers/power/pmic/s2mps11.c index 17780017035..5cf9d34ffaf 100644 --- a/drivers/power/pmic/s2mps11.c +++ b/drivers/power/pmic/s2mps11.c @@ -13,15 +13,28 @@  #include <power/pmic.h>  #include <power/s2mps11.h> -static const struct pmic_child_info pmic_children_info[] = { +static const struct pmic_child_info s2mps11_pmic_children_info[] = {  	{ .prefix = S2MPS11_OF_LDO_PREFIX, .driver = S2MPS11_LDO_DRIVER },  	{ .prefix = S2MPS11_OF_BUCK_PREFIX, .driver = S2MPS11_BUCK_DRIVER },  	{ },  }; +static const struct pmic_child_info s2mpu05_pmic_children_info[] = { +	{ .prefix = S2MPU05_OF_LDO_PREFIX, .driver = S2MPS11_LDO_DRIVER }, +	{ .prefix = S2MPU05_OF_BUCK_PREFIX, .driver = S2MPS11_BUCK_DRIVER }, +	{ }, +}; +  static int s2mps11_reg_count(struct udevice *dev)  { -	return S2MPS11_REG_COUNT; +	switch (dev_get_driver_data(dev)) { +	case VARIANT_S2MPS11: +		return S2MPS11_REG_COUNT; +	case VARIANT_S2MPU05: +		return S2MPU05_REG_COUNT; +	default: +		return -EINVAL; +	}  }  static int s2mps11_write(struct udevice *dev, uint reg, const uint8_t *buff, @@ -47,12 +60,13 @@ static int s2mps11_read(struct udevice *dev, uint reg, uint8_t *buff, int len)  	return ret;  } -static int s2mps11_probe(struct udevice *dev) +static int s2mps11_bind(struct udevice *dev)  {  	ofnode regulators_node;  	int children; +	const struct pmic_child_info *pmic_children_info; -	regulators_node = dev_read_subnode(dev, "voltage-regulators"); +	regulators_node = dev_read_subnode(dev, "regulators");  	if (!ofnode_valid(regulators_node)) {  		debug("%s: %s regulators subnode not found!\n", __func__,  		      dev->name); @@ -61,6 +75,18 @@ static int s2mps11_probe(struct udevice *dev)  	debug("%s: '%s' - found regulators subnode\n", __func__, dev->name); +	switch (dev_get_driver_data(dev)) { +	case VARIANT_S2MPS11: +		pmic_children_info = s2mps11_pmic_children_info; +		break; +	case VARIANT_S2MPU05: +		pmic_children_info = s2mpu05_pmic_children_info; +		break; +	default: +		debug("%s: unknown device type\n", __func__); +		return -EINVAL; +	} +  	children = pmic_bind_children(dev, regulators_node, pmic_children_info);  	if (!children)  		debug("%s: %s - no child found\n", __func__, dev->name); @@ -75,7 +101,8 @@ static struct dm_pmic_ops s2mps11_ops = {  };  static const struct udevice_id s2mps11_ids[] = { -	{ .compatible = "samsung,s2mps11-pmic" }, +	{ .compatible = "samsung,s2mps11-pmic", .data = VARIANT_S2MPS11 }, +	{ .compatible = "samsung,s2mpu05-pmic", .data = VARIANT_S2MPU05 },  	{ }  }; @@ -84,5 +111,5 @@ U_BOOT_DRIVER(pmic_s2mps11) = {  	.id = UCLASS_PMIC,  	.of_match = s2mps11_ids,  	.ops = &s2mps11_ops, -	.probe = s2mps11_probe, +	.bind = s2mps11_bind,  }; | 
