xref: /rk3399_rockchip-uboot/drivers/power/regulator/lp87565_regulator.c (revision a79e8dfed6e8dad5887d37b59a497b8ebb17f8fa)
12dd9dc02SKeerthy /*
22dd9dc02SKeerthy  * (C) Copyright 2017
32dd9dc02SKeerthy  * Texas Instruments Incorporated, <www.ti.com>
42dd9dc02SKeerthy  *
52dd9dc02SKeerthy  * Keerthy <j-keerthy@ti.com>
62dd9dc02SKeerthy  *
72dd9dc02SKeerthy  * SPDX-License-Identifier:	GPL-2.0+
82dd9dc02SKeerthy  */
92dd9dc02SKeerthy 
102dd9dc02SKeerthy #include <common.h>
112dd9dc02SKeerthy #include <fdtdec.h>
122dd9dc02SKeerthy #include <errno.h>
132dd9dc02SKeerthy #include <dm.h>
142dd9dc02SKeerthy #include <i2c.h>
152dd9dc02SKeerthy #include <power/pmic.h>
162dd9dc02SKeerthy #include <power/regulator.h>
172dd9dc02SKeerthy #include <power/lp87565.h>
182dd9dc02SKeerthy 
192dd9dc02SKeerthy DECLARE_GLOBAL_DATA_PTR;
202dd9dc02SKeerthy 
212dd9dc02SKeerthy static const char lp87565_buck_ctrl1[LP87565_BUCK_NUM] = {0x2, 0x4, 0x6, 0x8, 0x2, 0x6};
222dd9dc02SKeerthy static const char lp87565_buck_vout[LP87565_BUCK_NUM] = {0xA, 0xC, 0xE, 0x10, 0xA, 0xE };
232dd9dc02SKeerthy 
lp87565_buck_enable(struct udevice * dev,int op,bool * enable)242dd9dc02SKeerthy static int lp87565_buck_enable(struct udevice *dev, int op, bool *enable)
252dd9dc02SKeerthy {
262dd9dc02SKeerthy 	int ret;
272dd9dc02SKeerthy 	unsigned int adr;
282dd9dc02SKeerthy 	struct dm_regulator_uclass_platdata *uc_pdata;
292dd9dc02SKeerthy 
302dd9dc02SKeerthy 	uc_pdata = dev_get_uclass_platdata(dev);
312dd9dc02SKeerthy 	adr = uc_pdata->ctrl_reg;
322dd9dc02SKeerthy 
332dd9dc02SKeerthy 	ret = pmic_reg_read(dev->parent, adr);
342dd9dc02SKeerthy 	if (ret < 0)
352dd9dc02SKeerthy 		return ret;
362dd9dc02SKeerthy 
372dd9dc02SKeerthy 	if (op == PMIC_OP_GET) {
382dd9dc02SKeerthy 		ret &= LP87565_BUCK_MODE_MASK;
392dd9dc02SKeerthy 
402dd9dc02SKeerthy 		if (ret)
412dd9dc02SKeerthy 			*enable = true;
422dd9dc02SKeerthy 		else
432dd9dc02SKeerthy 			*enable = false;
442dd9dc02SKeerthy 
452dd9dc02SKeerthy 		return 0;
462dd9dc02SKeerthy 	} else if (op == PMIC_OP_SET) {
472dd9dc02SKeerthy 		if (*enable)
482dd9dc02SKeerthy 			ret |= LP87565_BUCK_MODE_MASK;
492dd9dc02SKeerthy 		else
502dd9dc02SKeerthy 			ret &= ~LP87565_BUCK_MODE_MASK;
512dd9dc02SKeerthy 		ret = pmic_reg_write(dev->parent, adr, ret);
522dd9dc02SKeerthy 		if (ret)
532dd9dc02SKeerthy 			return ret;
542dd9dc02SKeerthy 	}
552dd9dc02SKeerthy 
562dd9dc02SKeerthy 	return 0;
572dd9dc02SKeerthy }
582dd9dc02SKeerthy 
lp87565_buck_volt2val(int uV)592dd9dc02SKeerthy static int lp87565_buck_volt2val(int uV)
602dd9dc02SKeerthy {
612dd9dc02SKeerthy 	if (uV > LP87565_BUCK_VOLT_MAX)
622dd9dc02SKeerthy 		return -EINVAL;
632dd9dc02SKeerthy 	else if (uV > 1400000)
642dd9dc02SKeerthy 		return (uV - 1420000) / 20000 + 0x9E;
652dd9dc02SKeerthy 	else if (uV > 730000)
662dd9dc02SKeerthy 		return (uV - 735000) / 5000 + 0x18;
672dd9dc02SKeerthy 	else if (uV >= 500000)
682dd9dc02SKeerthy 		return (uV - 500000) / 10000;
692dd9dc02SKeerthy 	else
702dd9dc02SKeerthy 		return -EINVAL;
712dd9dc02SKeerthy }
722dd9dc02SKeerthy 
lp87565_buck_val2volt(int val)732dd9dc02SKeerthy static int lp87565_buck_val2volt(int val)
742dd9dc02SKeerthy {
752dd9dc02SKeerthy 	if (val > LP87565_BUCK_VOLT_MAX_HEX)
762dd9dc02SKeerthy 		return -EINVAL;
772dd9dc02SKeerthy 	else if (val > 0x9D)
782dd9dc02SKeerthy 		return 1400000 + (val - 0x9D) * 20000;
792dd9dc02SKeerthy 	else if (val > 0x17)
802dd9dc02SKeerthy 		return 730000 + (val - 0x17) * 5000;
812dd9dc02SKeerthy 	else if (val >= 0x0)
822dd9dc02SKeerthy 		return 500000 + val * 10000;
832dd9dc02SKeerthy 	else
842dd9dc02SKeerthy 		return -EINVAL;
852dd9dc02SKeerthy }
862dd9dc02SKeerthy 
lp87565_buck_val(struct udevice * dev,int op,int * uV)872dd9dc02SKeerthy static int lp87565_buck_val(struct udevice *dev, int op, int *uV)
882dd9dc02SKeerthy {
892dd9dc02SKeerthy 	unsigned int hex, adr;
902dd9dc02SKeerthy 	int ret;
912dd9dc02SKeerthy 	struct dm_regulator_uclass_platdata *uc_pdata;
922dd9dc02SKeerthy 
932dd9dc02SKeerthy 	uc_pdata = dev_get_uclass_platdata(dev);
942dd9dc02SKeerthy 
952dd9dc02SKeerthy 	if (op == PMIC_OP_GET)
962dd9dc02SKeerthy 		*uV = 0;
972dd9dc02SKeerthy 
982dd9dc02SKeerthy 	adr = uc_pdata->volt_reg;
992dd9dc02SKeerthy 
1002dd9dc02SKeerthy 	ret = pmic_reg_read(dev->parent, adr);
1012dd9dc02SKeerthy 	if (ret < 0)
1022dd9dc02SKeerthy 		return ret;
1032dd9dc02SKeerthy 
1042dd9dc02SKeerthy 	if (op == PMIC_OP_GET) {
1052dd9dc02SKeerthy 		ret &= LP87565_BUCK_VOLT_MASK;
1062dd9dc02SKeerthy 		ret = lp87565_buck_val2volt(ret);
1072dd9dc02SKeerthy 		if (ret < 0)
1082dd9dc02SKeerthy 			return ret;
1092dd9dc02SKeerthy 		*uV = ret;
1102dd9dc02SKeerthy 
1112dd9dc02SKeerthy 		return 0;
1122dd9dc02SKeerthy 	}
1132dd9dc02SKeerthy 
1142dd9dc02SKeerthy 	hex = lp87565_buck_volt2val(*uV);
1152dd9dc02SKeerthy 	if (hex < 0)
1162dd9dc02SKeerthy 		return hex;
1172dd9dc02SKeerthy 
1182dd9dc02SKeerthy 	ret &= 0x0;
1192dd9dc02SKeerthy 	ret = hex;
1202dd9dc02SKeerthy 
1212dd9dc02SKeerthy 	ret = pmic_reg_write(dev->parent, adr, ret);
1222dd9dc02SKeerthy 
1232dd9dc02SKeerthy 	return ret;
1242dd9dc02SKeerthy }
1252dd9dc02SKeerthy 
lp87565_buck_probe(struct udevice * dev)1262dd9dc02SKeerthy static int lp87565_buck_probe(struct udevice *dev)
1272dd9dc02SKeerthy {
1282dd9dc02SKeerthy 	struct dm_regulator_uclass_platdata *uc_pdata;
1292dd9dc02SKeerthy 	int idx;
1302dd9dc02SKeerthy 
1312dd9dc02SKeerthy 	uc_pdata = dev_get_uclass_platdata(dev);
1322dd9dc02SKeerthy 	uc_pdata->type = REGULATOR_TYPE_BUCK;
1332dd9dc02SKeerthy 
1342dd9dc02SKeerthy 	idx = dev->driver_data;
1352dd9dc02SKeerthy 	if (idx == 0 || idx == 1 || idx == 2 || idx == 3) {
1362dd9dc02SKeerthy 		debug("Single phase regulator\n");
1372dd9dc02SKeerthy 	} else if (idx == 23) {
1382dd9dc02SKeerthy 		idx = 5;
1392dd9dc02SKeerthy 	} else if (idx == 10) {
1402dd9dc02SKeerthy 		idx = 4;
1412dd9dc02SKeerthy 	} else {
1422dd9dc02SKeerthy 		printf("Wrong ID for regulator\n");
1432dd9dc02SKeerthy 		return -EINVAL;
1442dd9dc02SKeerthy 	}
1452dd9dc02SKeerthy 
1462dd9dc02SKeerthy 	uc_pdata->ctrl_reg = lp87565_buck_ctrl1[idx];
1472dd9dc02SKeerthy 	uc_pdata->volt_reg = lp87565_buck_vout[idx];
1482dd9dc02SKeerthy 
1492dd9dc02SKeerthy 	return 0;
1502dd9dc02SKeerthy }
1512dd9dc02SKeerthy 
buck_get_value(struct udevice * dev)1522dd9dc02SKeerthy static int buck_get_value(struct udevice *dev)
1532dd9dc02SKeerthy {
1542dd9dc02SKeerthy 	int uV;
1552dd9dc02SKeerthy 	int ret;
1562dd9dc02SKeerthy 
1572dd9dc02SKeerthy 	ret = lp87565_buck_val(dev, PMIC_OP_GET, &uV);
1582dd9dc02SKeerthy 	if (ret)
1592dd9dc02SKeerthy 		return ret;
1602dd9dc02SKeerthy 
1612dd9dc02SKeerthy 	return uV;
1622dd9dc02SKeerthy }
1632dd9dc02SKeerthy 
buck_set_value(struct udevice * dev,int uV)1642dd9dc02SKeerthy static int buck_set_value(struct udevice *dev, int uV)
1652dd9dc02SKeerthy {
1662dd9dc02SKeerthy 	return lp87565_buck_val(dev, PMIC_OP_SET, &uV);
1672dd9dc02SKeerthy }
1682dd9dc02SKeerthy 
buck_get_enable(struct udevice * dev)169*a79e8dfeSKeerthy static int buck_get_enable(struct udevice *dev)
1702dd9dc02SKeerthy {
1712dd9dc02SKeerthy 	bool enable = false;
1722dd9dc02SKeerthy 	int ret;
1732dd9dc02SKeerthy 
1742dd9dc02SKeerthy 
1752dd9dc02SKeerthy 	ret = lp87565_buck_enable(dev, PMIC_OP_GET, &enable);
1762dd9dc02SKeerthy 	if (ret)
1772dd9dc02SKeerthy 		return ret;
1782dd9dc02SKeerthy 
1792dd9dc02SKeerthy 	return enable;
1802dd9dc02SKeerthy }
1812dd9dc02SKeerthy 
buck_set_enable(struct udevice * dev,bool enable)1822dd9dc02SKeerthy static int buck_set_enable(struct udevice *dev, bool enable)
1832dd9dc02SKeerthy {
1842dd9dc02SKeerthy 	return lp87565_buck_enable(dev, PMIC_OP_SET, &enable);
1852dd9dc02SKeerthy }
1862dd9dc02SKeerthy 
1872dd9dc02SKeerthy static const struct dm_regulator_ops lp87565_buck_ops = {
1882dd9dc02SKeerthy 	.get_value  = buck_get_value,
1892dd9dc02SKeerthy 	.set_value  = buck_set_value,
1902dd9dc02SKeerthy 	.get_enable = buck_get_enable,
1912dd9dc02SKeerthy 	.set_enable = buck_set_enable,
1922dd9dc02SKeerthy };
1932dd9dc02SKeerthy 
1942dd9dc02SKeerthy U_BOOT_DRIVER(lp87565_buck) = {
1952dd9dc02SKeerthy 	.name = LP87565_BUCK_DRIVER,
1962dd9dc02SKeerthy 	.id = UCLASS_REGULATOR,
1972dd9dc02SKeerthy 	.ops = &lp87565_buck_ops,
1982dd9dc02SKeerthy 	.probe = lp87565_buck_probe,
1992dd9dc02SKeerthy };
200