diff options
Diffstat (limited to 'drivers/power')
| -rw-r--r-- | drivers/power/pmic/pmic_max77686.c | 192 | 
1 files changed, 192 insertions, 0 deletions
| diff --git a/drivers/power/pmic/pmic_max77686.c b/drivers/power/pmic/pmic_max77686.c index 7208e5b67..d4c430e22 100644 --- a/drivers/power/pmic/pmic_max77686.c +++ b/drivers/power/pmic/pmic_max77686.c @@ -14,6 +14,198 @@  DECLARE_GLOBAL_DATA_PTR; +static const char max77686_buck_addr[] = { +	0xff, 0x10, 0x12, 0x1c, 0x26, 0x30, 0x32, 0x34, 0x36, 0x38 +}; + +static unsigned int max77686_ldo_volt2hex(int ldo, ulong uV) +{ +	unsigned int hex = 0; + +	switch (ldo) { +	case 1: +	case 2: +	case 6: +	case 7: +	case 8: +	case 15: +		hex = (uV - 800000) / 25000; +		break; +	default: +		hex = (uV - 800000) / 50000; +	} + +	if (hex >= 0 && hex <= MAX77686_LDO_VOLT_MAX_HEX) +		return hex; + +	debug("%s: %ld is wrong voltage value for LDO%d\n", __func__, uV, ldo); +	return 0; +} + +int max77686_set_ldo_voltage(struct pmic *p, int ldo, ulong uV) +{ +	unsigned int val, ret, hex, adr; + +	if (ldo < 1 && ldo > 26) { +		printf("%s: %d is wrong ldo number\n", __func__, ldo); +		return -1; +	} + +	adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1; +	hex = max77686_ldo_volt2hex(ldo, uV); + +	if (!hex) +		return -1; + +	ret = pmic_reg_read(p, adr, &val); +	if (ret) +		return ret; + +	val &= ~MAX77686_LDO_VOLT_MASK; +	val |= hex; +	ret |= pmic_reg_write(p, adr, val); + +	return ret; +} + +int max77686_set_ldo_mode(struct pmic *p, int ldo, char opmode) +{ +	unsigned int val, ret, adr, mode; + +	if (ldo < 1 && 26 < ldo) { +		printf("%s: %d is wrong ldo number\n", __func__, ldo); +		return -1; +	} + +	adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1; + +	/* mode */ +	switch (opmode) { +	case OPMODE_OFF: +		mode = MAX77686_LDO_MODE_OFF; +		break; +	case OPMODE_STANDBY: +		switch (ldo) { +		case 2: +		case 6: +		case 7: +		case 8: +		case 10: +		case 11: +		case 12: +		case 14: +		case 15: +		case 16: +			mode = MAX77686_LDO_MODE_STANDBY; +			break; +		default: +			mode = 0xff; +		} +		break; +	case OPMODE_LPM: +		mode = MAX77686_LDO_MODE_LPM; +		break; +	case OPMODE_ON: +		mode = MAX77686_LDO_MODE_ON; +		break; +	default: +		mode = 0xff; +	} + +	if (mode == 0xff) { +		printf("%s: %d is not supported on LDO%d\n", +		       __func__, opmode, ldo); +		return -1; +	} + +	ret = pmic_reg_read(p, adr, &val); +	if (ret) +		return ret; + +	val &= ~MAX77686_LDO_MODE_MASK; +	val |= mode; +	ret |= pmic_reg_write(p, adr, val); + +	return ret; +} + +int max77686_set_buck_mode(struct pmic *p, int buck, char opmode) +{ +	unsigned int val, ret, mask, adr, size, mode, mode_shift; + +	size = ARRAY_SIZE(max77686_buck_addr); +	if (buck >= size) { +		printf("%s: %d is wrong buck number\n", __func__, buck); +		return -1; +	} + +	adr = max77686_buck_addr[buck]; + +	/* mask */ +	switch (buck) { +	case 2: +	case 3: +	case 4: +		mode_shift = MAX77686_BUCK_MODE_SHIFT_2; +		break; +	default: +		mode_shift = MAX77686_BUCK_MODE_SHIFT_1; +	} + +	mask = MAX77686_BUCK_MODE_MASK << mode_shift; + +	/* mode */ +	switch (opmode) { +	case OPMODE_OFF: +		mode = MAX77686_BUCK_MODE_OFF; +		break; +	case OPMODE_STANDBY: +		switch (buck) { +		case 1: +		case 2: +		case 3: +		case 4: +			mode = MAX77686_BUCK_MODE_STANDBY << mode_shift; +			break; +		default: +			mode = 0xff; +		} +		break; +	case OPMODE_LPM: +		switch (buck) { +		case 2: +		case 3: +		case 4: +			mode = MAX77686_BUCK_MODE_LPM << mode_shift; +			break; +		default: +			mode = 0xff; +		} +		break; +	case OPMODE_ON: +		mode = MAX77686_BUCK_MODE_ON << mode_shift; +		break; +	default: +		mode = 0xff; +	} + +	if (mode == 0xff) { +		printf("%s: %d is not supported on BUCK%d\n", +		       __func__, opmode, buck); +		return -1; +	} + +	ret = pmic_reg_read(p, adr, &val); +	if (ret) +		return ret; + +	val &= ~mask; +	val |= mode; +	ret |= pmic_reg_write(p, adr, val); + +	return ret; +} +  int pmic_init(unsigned char bus)  {  	static const char name[] = "MAX77686_PMIC"; |