xref: /rk3399_rockchip-uboot/drivers/power/regulator/act8846.c (revision 85f87de3132db38143b58bae1805e4d066dc9524)
19119820bSSimon Glass /*
29119820bSSimon Glass  * Copyright (C) 2015 Google, Inc
39119820bSSimon Glass  * Written by Simon Glass <sjg@chromium.org>
49119820bSSimon Glass  *
59119820bSSimon Glass  * Based on Rockchip's drivers/power/pmic/pmic_act8846.c:
69119820bSSimon Glass  * Copyright (C) 2012 rockchips
79119820bSSimon Glass  * zyw <zyw@rock-chips.com>
89119820bSSimon Glass  *
99119820bSSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
109119820bSSimon Glass  */
119119820bSSimon Glass 
129119820bSSimon Glass #include <common.h>
139119820bSSimon Glass #include <dm.h>
149119820bSSimon Glass #include <errno.h>
159119820bSSimon Glass #include <power/act8846_pmic.h>
169119820bSSimon Glass #include <power/pmic.h>
179119820bSSimon Glass #include <power/regulator.h>
189119820bSSimon Glass 
199119820bSSimon Glass static const u16 voltage_map[] = {
209119820bSSimon Glass 	600, 625, 650, 675, 700, 725, 750, 775,
219119820bSSimon Glass 	800, 825, 850, 875, 900, 925, 950, 975,
229119820bSSimon Glass 	1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175,
239119820bSSimon Glass 	1200, 1250, 1300, 1350, 1400, 1450, 1500, 1550,
249119820bSSimon Glass 	1600, 1650, 1700, 1750, 1800, 1850, 1900, 1950,
259119820bSSimon Glass 	2000, 2050, 2100, 2150, 2200, 2250, 2300, 2350,
269119820bSSimon Glass 	2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100,
279119820bSSimon Glass 	3200, 3300, 3400, 3500, 3600, 3700, 3800, 3900,
289119820bSSimon Glass };
299119820bSSimon Glass 
309119820bSSimon Glass enum {
319119820bSSimon Glass 	REG_SYS0,
329119820bSSimon Glass 	REG_SYS1,
339119820bSSimon Glass 	REG1_VOL	= 0x10,
349119820bSSimon Glass 	REG1_CTL	= 0X11,
359119820bSSimon Glass 	REG2_VOL0	= 0x20,
369119820bSSimon Glass 	REG2_VOL1,
379119820bSSimon Glass 	REG2_CTL,
389119820bSSimon Glass 	REG3_VOL0	= 0x30,
399119820bSSimon Glass 	REG3_VOL1,
409119820bSSimon Glass 	REG3_CTL,
419119820bSSimon Glass 	REG4_VOL0	= 0x40,
429119820bSSimon Glass 	REG4_VOL1,
439119820bSSimon Glass 	REG4_CTL,
449119820bSSimon Glass 	REG5_VOL	= 0x50,
459119820bSSimon Glass 	REG5_CTL,
469119820bSSimon Glass 	REG6_VOL	= 0X58,
479119820bSSimon Glass 	REG6_CTL,
489119820bSSimon Glass 	REG7_VOL	= 0x60,
499119820bSSimon Glass 	REG7_CTL,
509119820bSSimon Glass 	REG8_VOL	= 0x68,
519119820bSSimon Glass 	REG8_CTL,
529119820bSSimon Glass 	REG9_VOL	= 0x70,
539119820bSSimon Glass 	REG9_CTL,
549119820bSSimon Glass 	REG10_VOL	= 0x80,
559119820bSSimon Glass 	REG10_CTL,
569119820bSSimon Glass 	REG11_VOL	= 0x90,
579119820bSSimon Glass 	REG11_CTL,
589119820bSSimon Glass 	REG12_VOL	= 0xa0,
599119820bSSimon Glass 	REG12_CTL,
609119820bSSimon Glass 	REG13		= 0xb1,
619119820bSSimon Glass };
629119820bSSimon Glass 
639119820bSSimon Glass static const u8 addr_vol[] = {
649119820bSSimon Glass 	0, REG1_VOL, REG2_VOL0, REG3_VOL0, REG4_VOL0,
659119820bSSimon Glass 	REG5_VOL, REG6_VOL, REG7_VOL, REG8_VOL, REG9_VOL,
669119820bSSimon Glass 	REG10_VOL, REG11_VOL, REG12_VOL,
679119820bSSimon Glass };
689119820bSSimon Glass 
699119820bSSimon Glass static const u8 addr_ctl[] = {
709119820bSSimon Glass 	0, REG1_CTL, REG2_CTL, REG3_CTL, REG4_CTL,
719119820bSSimon Glass 	REG5_CTL, REG6_CTL, REG7_CTL, REG8_CTL, REG9_CTL,
729119820bSSimon Glass 	REG10_CTL, REG11_CTL, REG12_CTL,
739119820bSSimon Glass };
749119820bSSimon Glass 
check_volt_table(const u16 * volt_table,int uvolt)759119820bSSimon Glass static int check_volt_table(const u16 *volt_table, int uvolt)
769119820bSSimon Glass {
779119820bSSimon Glass 	int i;
789119820bSSimon Glass 
799119820bSSimon Glass 	for (i = VOL_MIN_IDX; i < VOL_MAX_IDX; i++) {
809119820bSSimon Glass 		if (uvolt <= (volt_table[i] * 1000))
819119820bSSimon Glass 			return i;
829119820bSSimon Glass 	}
839119820bSSimon Glass 	return -EINVAL;
849119820bSSimon Glass }
859119820bSSimon Glass 
reg_get_value(struct udevice * dev)869119820bSSimon Glass static int reg_get_value(struct udevice *dev)
879119820bSSimon Glass {
889119820bSSimon Glass 	int reg = dev->driver_data;
899119820bSSimon Glass 	int ret;
909119820bSSimon Glass 
9165f89be2SJohn Keeping 	ret = pmic_reg_read(dev->parent, addr_vol[reg]);
929119820bSSimon Glass 	if (ret < 0)
939119820bSSimon Glass 		return ret;
949119820bSSimon Glass 
959119820bSSimon Glass 	return voltage_map[ret & LDO_VOL_MASK] * 1000;
969119820bSSimon Glass }
979119820bSSimon Glass 
reg_set_value(struct udevice * dev,int uvolt)989119820bSSimon Glass static int reg_set_value(struct udevice *dev, int uvolt)
999119820bSSimon Glass {
1009119820bSSimon Glass 	int reg = dev->driver_data;
1019119820bSSimon Glass 	int val;
1029119820bSSimon Glass 
1039119820bSSimon Glass 	val = check_volt_table(voltage_map, uvolt);
1049119820bSSimon Glass 	if (val < 0)
1059119820bSSimon Glass 		return val;
1069119820bSSimon Glass 
1079119820bSSimon Glass 	return pmic_clrsetbits(dev->parent, addr_vol[reg], LDO_VOL_MASK, val);
1089119820bSSimon Glass }
1099119820bSSimon Glass 
reg_set_enable(struct udevice * dev,bool enable)1109119820bSSimon Glass static int reg_set_enable(struct udevice *dev, bool enable)
1119119820bSSimon Glass {
1129119820bSSimon Glass 	int reg = dev->driver_data;
1139119820bSSimon Glass 
1149119820bSSimon Glass 	return pmic_clrsetbits(dev->parent, addr_ctl[reg], LDO_EN_MASK,
1159119820bSSimon Glass 			       enable ? LDO_EN_MASK : 0);
1169119820bSSimon Glass }
1179119820bSSimon Glass 
reg_get_enable(struct udevice * dev)118*85f87de3SKeerthy static int reg_get_enable(struct udevice *dev)
1199119820bSSimon Glass {
1209119820bSSimon Glass 	int reg = dev->driver_data;
1219119820bSSimon Glass 	int ret;
1229119820bSSimon Glass 
12365f89be2SJohn Keeping 	ret = pmic_reg_read(dev->parent, addr_ctl[reg]);
1249119820bSSimon Glass 	if (ret < 0)
1259119820bSSimon Glass 		return ret;
1269119820bSSimon Glass 
1279119820bSSimon Glass 	return ret & LDO_EN_MASK ? true : false;
1289119820bSSimon Glass }
1299119820bSSimon Glass 
act8846_reg_probe(struct udevice * dev)1309119820bSSimon Glass static int act8846_reg_probe(struct udevice *dev)
1319119820bSSimon Glass {
1329119820bSSimon Glass 	struct dm_regulator_uclass_platdata *uc_pdata;
1339119820bSSimon Glass 	int reg = dev->driver_data;
1349119820bSSimon Glass 
1359119820bSSimon Glass 	uc_pdata = dev_get_uclass_platdata(dev);
1369119820bSSimon Glass 
1379119820bSSimon Glass 	uc_pdata->type = reg <= 4 ? REGULATOR_TYPE_BUCK : REGULATOR_TYPE_LDO;
1389119820bSSimon Glass 	uc_pdata->mode_count = 0;
1399119820bSSimon Glass 
1409119820bSSimon Glass 	return 0;
1419119820bSSimon Glass }
1429119820bSSimon Glass 
1439119820bSSimon Glass static const struct dm_regulator_ops act8846_reg_ops = {
1449119820bSSimon Glass 	.get_value  = reg_get_value,
1459119820bSSimon Glass 	.set_value  = reg_set_value,
1469119820bSSimon Glass 	.get_enable = reg_get_enable,
1479119820bSSimon Glass 	.set_enable = reg_set_enable,
1489119820bSSimon Glass };
1499119820bSSimon Glass 
1509119820bSSimon Glass U_BOOT_DRIVER(act8846_buck) = {
1519119820bSSimon Glass 	.name = "act8846_reg",
1529119820bSSimon Glass 	.id = UCLASS_REGULATOR,
1539119820bSSimon Glass 	.ops = &act8846_reg_ops,
1549119820bSSimon Glass 	.probe = act8846_reg_probe,
1559119820bSSimon Glass };
156