xref: /rk3399_rockchip-uboot/drivers/power/regulator/tps65090_regulator.c (revision 2a4747d3cd515168affaaadd8d10928e0ebb4996)
11c88b67eSSimon Glass /*
21c88b67eSSimon Glass  * Copyright (c) 2015 Google, Inc
31c88b67eSSimon Glass  *
41c88b67eSSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
51c88b67eSSimon Glass  */
61c88b67eSSimon Glass 
71c88b67eSSimon Glass #include <common.h>
81c88b67eSSimon Glass #include <dm.h>
91c88b67eSSimon Glass #include <errno.h>
101c88b67eSSimon Glass #include <power/pmic.h>
111c88b67eSSimon Glass #include <power/regulator.h>
121c88b67eSSimon Glass #include <power/tps65090.h>
131c88b67eSSimon Glass 
tps65090_fet_probe(struct udevice * dev)141c88b67eSSimon Glass static int tps65090_fet_probe(struct udevice *dev)
151c88b67eSSimon Glass {
161c88b67eSSimon Glass 	struct dm_regulator_uclass_platdata *uc_pdata;
171c88b67eSSimon Glass 
181c88b67eSSimon Glass 	uc_pdata = dev_get_uclass_platdata(dev);
191c88b67eSSimon Glass 
201c88b67eSSimon Glass 	uc_pdata->type = REGULATOR_TYPE_OTHER;
211c88b67eSSimon Glass 	uc_pdata->mode_count = 0;
221c88b67eSSimon Glass 
231c88b67eSSimon Glass 	return 0;
241c88b67eSSimon Glass }
251c88b67eSSimon Glass 
tps65090_fet_get_enable(struct udevice * dev)26*2a4747d3SKeerthy static int tps65090_fet_get_enable(struct udevice *dev)
271c88b67eSSimon Glass {
281c88b67eSSimon Glass 	struct udevice *pmic = dev_get_parent(dev);
291c88b67eSSimon Glass 	int ret, fet_id;
301c88b67eSSimon Glass 
311c88b67eSSimon Glass 	fet_id = dev->driver_data;
321c88b67eSSimon Glass 	debug("%s: fet_id=%d\n", __func__, fet_id);
331c88b67eSSimon Glass 
341c88b67eSSimon Glass 	ret = pmic_reg_read(pmic, REG_FET_BASE + fet_id);
351c88b67eSSimon Glass 	if (ret < 0)
361c88b67eSSimon Glass 		return ret;
371c88b67eSSimon Glass 
381c88b67eSSimon Glass 	return ret & FET_CTRL_ENFET;
391c88b67eSSimon Glass }
401c88b67eSSimon Glass 
411c88b67eSSimon Glass /**
421c88b67eSSimon Glass  * Set the power state for a FET
431c88b67eSSimon Glass  *
441c88b67eSSimon Glass  * @param pmic		pmic structure for the tps65090
451c88b67eSSimon Glass  * @param fet_id	FET number to set (1..MAX_FET_NUM)
461c88b67eSSimon Glass  * @param set		1 to power on FET, 0 to power off
471c88b67eSSimon Glass  * @return -EIO if we got a comms error, -EAGAIN if the FET failed to
481c88b67eSSimon Glass  * change state. If all is ok, returns 0.
491c88b67eSSimon Glass  */
tps65090_fet_set(struct udevice * pmic,int fet_id,bool set)501c88b67eSSimon Glass static int tps65090_fet_set(struct udevice *pmic, int fet_id, bool set)
511c88b67eSSimon Glass {
521c88b67eSSimon Glass 	int retry;
531c88b67eSSimon Glass 	u32 value;
541c88b67eSSimon Glass 	int ret;
551c88b67eSSimon Glass 
561c88b67eSSimon Glass 	value = FET_CTRL_ADENFET | FET_CTRL_WAIT;
571c88b67eSSimon Glass 	if (set)
581c88b67eSSimon Glass 		value |= FET_CTRL_ENFET;
591c88b67eSSimon Glass 
601c88b67eSSimon Glass 	if (pmic_reg_write(pmic, REG_FET_BASE + fet_id, value))
611c88b67eSSimon Glass 		return -EIO;
621c88b67eSSimon Glass 
631c88b67eSSimon Glass 	/* Try reading until we get a result */
641c88b67eSSimon Glass 	for (retry = 0; retry < MAX_CTRL_READ_TRIES; retry++) {
651c88b67eSSimon Glass 		ret = pmic_reg_read(pmic, REG_FET_BASE + fet_id);
661c88b67eSSimon Glass 		if (ret < 0)
671c88b67eSSimon Glass 			return ret;
681c88b67eSSimon Glass 
691c88b67eSSimon Glass 		/* Check that the FET went into the expected state */
701c88b67eSSimon Glass 		debug("%s: flags=%x\n", __func__, ret);
711c88b67eSSimon Glass 		if (!!(ret & FET_CTRL_PGFET) == set)
721c88b67eSSimon Glass 			return 0;
731c88b67eSSimon Glass 
741c88b67eSSimon Glass 		/* If we got a timeout, there is no point in waiting longer */
751c88b67eSSimon Glass 		if (ret & FET_CTRL_TOFET)
761c88b67eSSimon Glass 			break;
771c88b67eSSimon Glass 
781c88b67eSSimon Glass 		mdelay(1);
791c88b67eSSimon Glass 	}
801c88b67eSSimon Glass 
811c88b67eSSimon Glass 	debug("FET %d: Power good should have set to %d but reg=%#02x\n",
821c88b67eSSimon Glass 	      fet_id, set, ret);
831c88b67eSSimon Glass 	return -EAGAIN;
841c88b67eSSimon Glass }
851c88b67eSSimon Glass 
tps65090_fet_set_enable(struct udevice * dev,bool enable)861c88b67eSSimon Glass static int tps65090_fet_set_enable(struct udevice *dev, bool enable)
871c88b67eSSimon Glass {
881c88b67eSSimon Glass 	struct udevice *pmic = dev_get_parent(dev);
891c88b67eSSimon Glass 	int ret, fet_id;
901c88b67eSSimon Glass 	ulong start;
911c88b67eSSimon Glass 	int loops;
921c88b67eSSimon Glass 
931c88b67eSSimon Glass 	fet_id = dev->driver_data;
941c88b67eSSimon Glass 	debug("%s: fet_id=%d, enable=%d\n", __func__, fet_id, enable);
951c88b67eSSimon Glass 
961c88b67eSSimon Glass 	start = get_timer(0);
971c88b67eSSimon Glass 	for (loops = 0;; loops++) {
981c88b67eSSimon Glass 		ret = tps65090_fet_set(pmic, fet_id, enable);
991c88b67eSSimon Glass 		if (!ret)
1001c88b67eSSimon Glass 			break;
1011c88b67eSSimon Glass 
1021c88b67eSSimon Glass 		if (get_timer(start) > 100)
1031c88b67eSSimon Glass 			break;
1041c88b67eSSimon Glass 
1051c88b67eSSimon Glass 		/* Turn it off and try again until we time out */
1061c88b67eSSimon Glass 		tps65090_fet_set(pmic, fet_id, false);
1071c88b67eSSimon Glass 	}
1081c88b67eSSimon Glass 
1091c88b67eSSimon Glass 	if (ret)
1101c88b67eSSimon Glass 		debug("%s: FET%d failed to power on: time=%lums, loops=%d\n",
1111c88b67eSSimon Glass 		      __func__, fet_id, get_timer(start), loops);
1121c88b67eSSimon Glass 	else if (loops)
1131c88b67eSSimon Glass 		debug("%s: FET%d powered on after %lums, loops=%d\n",
1141c88b67eSSimon Glass 		      __func__, fet_id, get_timer(start), loops);
1151c88b67eSSimon Glass 
1161c88b67eSSimon Glass 	/*
1171c88b67eSSimon Glass 	 * Unfortunately there are some conditions where the power-good bit
1181c88b67eSSimon Glass 	 * will be 0, but the FET still comes up. One such case occurs with
1191c88b67eSSimon Glass 	 * the LCD backlight on snow. We'll just return 0 here and assume
1201c88b67eSSimon Glass 	 * that the FET will eventually come up.
1211c88b67eSSimon Glass 	 */
1221c88b67eSSimon Glass 	if (ret == -EAGAIN)
1231c88b67eSSimon Glass 		ret = 0;
1241c88b67eSSimon Glass 
1251c88b67eSSimon Glass 	return ret;
1261c88b67eSSimon Glass }
1271c88b67eSSimon Glass 
1281c88b67eSSimon Glass static const struct dm_regulator_ops tps65090_fet_ops = {
1291c88b67eSSimon Glass 	.get_enable = tps65090_fet_get_enable,
1301c88b67eSSimon Glass 	.set_enable = tps65090_fet_set_enable,
1311c88b67eSSimon Glass };
1321c88b67eSSimon Glass 
1331c88b67eSSimon Glass U_BOOT_DRIVER(tps65090_fet) = {
1341c88b67eSSimon Glass 	.name = TPS65090_FET_DRIVER,
1351c88b67eSSimon Glass 	.id = UCLASS_REGULATOR,
1361c88b67eSSimon Glass 	.ops = &tps65090_fet_ops,
1371c88b67eSSimon Glass 	.probe = tps65090_fet_probe,
1381c88b67eSSimon Glass };
139