638 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			638 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * TI LP8788 MFD - ldo regulator driver
 | |
|  *
 | |
|  * Copyright 2012 Texas Instruments
 | |
|  *
 | |
|  * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU General Public License version 2 as
 | |
|  * published by the Free Software Foundation.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <linux/module.h>
 | |
| #include <linux/slab.h>
 | |
| #include <linux/err.h>
 | |
| #include <linux/platform_device.h>
 | |
| #include <linux/regulator/driver.h>
 | |
| #include <linux/gpio/consumer.h>
 | |
| #include <linux/mfd/lp8788.h>
 | |
| 
 | |
| /* register address */
 | |
| #define LP8788_EN_LDO_A			0x0D	/* DLDO 1 ~ 8 */
 | |
| #define LP8788_EN_LDO_B			0x0E	/* DLDO 9 ~ 12, ALDO 1 ~ 4 */
 | |
| #define LP8788_EN_LDO_C			0x0F	/* ALDO 5 ~ 10 */
 | |
| #define LP8788_EN_SEL			0x10
 | |
| #define LP8788_DLDO1_VOUT		0x2E
 | |
| #define LP8788_DLDO2_VOUT		0x2F
 | |
| #define LP8788_DLDO3_VOUT		0x30
 | |
| #define LP8788_DLDO4_VOUT		0x31
 | |
| #define LP8788_DLDO5_VOUT		0x32
 | |
| #define LP8788_DLDO6_VOUT		0x33
 | |
| #define LP8788_DLDO7_VOUT		0x34
 | |
| #define LP8788_DLDO8_VOUT		0x35
 | |
| #define LP8788_DLDO9_VOUT		0x36
 | |
| #define LP8788_DLDO10_VOUT		0x37
 | |
| #define LP8788_DLDO11_VOUT		0x38
 | |
| #define LP8788_DLDO12_VOUT		0x39
 | |
| #define LP8788_ALDO1_VOUT		0x3A
 | |
| #define LP8788_ALDO2_VOUT		0x3B
 | |
| #define LP8788_ALDO3_VOUT		0x3C
 | |
| #define LP8788_ALDO4_VOUT		0x3D
 | |
| #define LP8788_ALDO5_VOUT		0x3E
 | |
| #define LP8788_ALDO6_VOUT		0x3F
 | |
| #define LP8788_ALDO7_VOUT		0x40
 | |
| #define LP8788_ALDO8_VOUT		0x41
 | |
| #define LP8788_ALDO9_VOUT		0x42
 | |
| #define LP8788_ALDO10_VOUT		0x43
 | |
| #define LP8788_DLDO1_TIMESTEP		0x44
 | |
| 
 | |
| /* mask/shift bits */
 | |
| #define LP8788_EN_DLDO1_M		BIT(0)	/* Addr 0Dh ~ 0Fh */
 | |
| #define LP8788_EN_DLDO2_M		BIT(1)
 | |
| #define LP8788_EN_DLDO3_M		BIT(2)
 | |
| #define LP8788_EN_DLDO4_M		BIT(3)
 | |
| #define LP8788_EN_DLDO5_M		BIT(4)
 | |
| #define LP8788_EN_DLDO6_M		BIT(5)
 | |
| #define LP8788_EN_DLDO7_M		BIT(6)
 | |
| #define LP8788_EN_DLDO8_M		BIT(7)
 | |
| #define LP8788_EN_DLDO9_M		BIT(0)
 | |
| #define LP8788_EN_DLDO10_M		BIT(1)
 | |
| #define LP8788_EN_DLDO11_M		BIT(2)
 | |
| #define LP8788_EN_DLDO12_M		BIT(3)
 | |
| #define LP8788_EN_ALDO1_M		BIT(4)
 | |
| #define LP8788_EN_ALDO2_M		BIT(5)
 | |
| #define LP8788_EN_ALDO3_M		BIT(6)
 | |
| #define LP8788_EN_ALDO4_M		BIT(7)
 | |
| #define LP8788_EN_ALDO5_M		BIT(0)
 | |
| #define LP8788_EN_ALDO6_M		BIT(1)
 | |
| #define LP8788_EN_ALDO7_M		BIT(2)
 | |
| #define LP8788_EN_ALDO8_M		BIT(3)
 | |
| #define LP8788_EN_ALDO9_M		BIT(4)
 | |
| #define LP8788_EN_ALDO10_M		BIT(5)
 | |
| #define LP8788_EN_SEL_DLDO911_M		BIT(0)	/* Addr 10h */
 | |
| #define LP8788_EN_SEL_DLDO7_M		BIT(1)
 | |
| #define LP8788_EN_SEL_ALDO7_M		BIT(2)
 | |
| #define LP8788_EN_SEL_ALDO5_M		BIT(3)
 | |
| #define LP8788_EN_SEL_ALDO234_M		BIT(4)
 | |
| #define LP8788_EN_SEL_ALDO1_M		BIT(5)
 | |
| #define LP8788_VOUT_5BIT_M		0x1F	/* Addr 2Eh ~ 43h */
 | |
| #define LP8788_VOUT_4BIT_M		0x0F
 | |
| #define LP8788_VOUT_3BIT_M		0x07
 | |
| #define LP8788_VOUT_1BIT_M		0x01
 | |
| #define LP8788_STARTUP_TIME_M		0xF8	/* Addr 44h ~ 59h */
 | |
| #define LP8788_STARTUP_TIME_S		3
 | |
| 
 | |
| #define ENABLE_TIME_USEC		32
 | |
| 
 | |
| enum lp8788_ldo_id {
 | |
| 	DLDO1,
 | |
| 	DLDO2,
 | |
| 	DLDO3,
 | |
| 	DLDO4,
 | |
| 	DLDO5,
 | |
| 	DLDO6,
 | |
| 	DLDO7,
 | |
| 	DLDO8,
 | |
| 	DLDO9,
 | |
| 	DLDO10,
 | |
| 	DLDO11,
 | |
| 	DLDO12,
 | |
| 	ALDO1,
 | |
| 	ALDO2,
 | |
| 	ALDO3,
 | |
| 	ALDO4,
 | |
| 	ALDO5,
 | |
| 	ALDO6,
 | |
| 	ALDO7,
 | |
| 	ALDO8,
 | |
| 	ALDO9,
 | |
| 	ALDO10,
 | |
| };
 | |
| 
 | |
| struct lp8788_ldo {
 | |
| 	struct lp8788 *lp;
 | |
| 	struct regulator_desc *desc;
 | |
| 	struct regulator_dev *regulator;
 | |
| 	struct gpio_desc *ena_gpiod;
 | |
| };
 | |
| 
 | |
| /* DLDO 1, 2, 3, 9 voltage table */
 | |
| static const int lp8788_dldo1239_vtbl[] = {
 | |
| 	1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
 | |
| 	2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000,
 | |
| 	2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
 | |
| 	2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
 | |
| };
 | |
| 
 | |
| /* DLDO 4 voltage table */
 | |
| static const int lp8788_dldo4_vtbl[] = { 1800000, 3000000 };
 | |
| 
 | |
| /* DLDO 5, 7, 8 and ALDO 6 voltage table */
 | |
| static const int lp8788_dldo578_aldo6_vtbl[] = {
 | |
| 	1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
 | |
| 	2600000, 2700000, 2800000, 2900000, 3000000, 3000000, 3000000, 3000000,
 | |
| };
 | |
| 
 | |
| /* DLDO 6 voltage table */
 | |
| static const int lp8788_dldo6_vtbl[] = {
 | |
| 	3000000, 3100000, 3200000, 3300000, 3400000, 3500000, 3600000, 3600000,
 | |
| };
 | |
| 
 | |
| /* DLDO 10, 11 voltage table */
 | |
| static const int lp8788_dldo1011_vtbl[] = {
 | |
| 	1100000, 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000,
 | |
| 	1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000,
 | |
| };
 | |
| 
 | |
| /* ALDO 1 voltage table */
 | |
| static const int lp8788_aldo1_vtbl[] = { 1800000, 2850000 };
 | |
| 
 | |
| /* ALDO 7 voltage table */
 | |
| static const int lp8788_aldo7_vtbl[] = {
 | |
| 	1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1800000,
 | |
| };
 | |
| 
 | |
| static int lp8788_ldo_enable_time(struct regulator_dev *rdev)
 | |
| {
 | |
| 	struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
 | |
| 	enum lp8788_ldo_id id = rdev_get_id(rdev);
 | |
| 	u8 val, addr = LP8788_DLDO1_TIMESTEP + id;
 | |
| 
 | |
| 	if (lp8788_read_byte(ldo->lp, addr, &val))
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S;
 | |
| 
 | |
| 	return ENABLE_TIME_USEC * val;
 | |
| }
 | |
| 
 | |
| static const struct regulator_ops lp8788_ldo_voltage_table_ops = {
 | |
| 	.list_voltage = regulator_list_voltage_table,
 | |
| 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 | |
| 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 | |
| 	.enable = regulator_enable_regmap,
 | |
| 	.disable = regulator_disable_regmap,
 | |
| 	.is_enabled = regulator_is_enabled_regmap,
 | |
| 	.enable_time = lp8788_ldo_enable_time,
 | |
| };
 | |
| 
 | |
| static const struct regulator_ops lp8788_ldo_voltage_fixed_ops = {
 | |
| 	.list_voltage = regulator_list_voltage_linear,
 | |
| 	.enable = regulator_enable_regmap,
 | |
| 	.disable = regulator_disable_regmap,
 | |
| 	.is_enabled = regulator_is_enabled_regmap,
 | |
| 	.enable_time = lp8788_ldo_enable_time,
 | |
| };
 | |
| 
 | |
| static struct regulator_desc lp8788_dldo_desc[] = {
 | |
| 	{
 | |
| 		.name = "dldo1",
 | |
| 		.id = DLDO1,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
 | |
| 		.volt_table = lp8788_dldo1239_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_DLDO1_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_5BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_A,
 | |
| 		.enable_mask = LP8788_EN_DLDO1_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "dldo2",
 | |
| 		.id = DLDO2,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
 | |
| 		.volt_table = lp8788_dldo1239_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_DLDO2_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_5BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_A,
 | |
| 		.enable_mask = LP8788_EN_DLDO2_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "dldo3",
 | |
| 		.id = DLDO3,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
 | |
| 		.volt_table = lp8788_dldo1239_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_DLDO3_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_5BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_A,
 | |
| 		.enable_mask = LP8788_EN_DLDO3_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "dldo4",
 | |
| 		.id = DLDO4,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_dldo4_vtbl),
 | |
| 		.volt_table = lp8788_dldo4_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_DLDO4_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_1BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_A,
 | |
| 		.enable_mask = LP8788_EN_DLDO4_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "dldo5",
 | |
| 		.id = DLDO5,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
 | |
| 		.volt_table = lp8788_dldo578_aldo6_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_DLDO5_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_4BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_A,
 | |
| 		.enable_mask = LP8788_EN_DLDO5_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "dldo6",
 | |
| 		.id = DLDO6,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_dldo6_vtbl),
 | |
| 		.volt_table = lp8788_dldo6_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_DLDO6_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_3BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_A,
 | |
| 		.enable_mask = LP8788_EN_DLDO6_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "dldo7",
 | |
| 		.id = DLDO7,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
 | |
| 		.volt_table = lp8788_dldo578_aldo6_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_DLDO7_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_4BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_A,
 | |
| 		.enable_mask = LP8788_EN_DLDO7_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "dldo8",
 | |
| 		.id = DLDO8,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
 | |
| 		.volt_table = lp8788_dldo578_aldo6_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_DLDO8_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_4BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_A,
 | |
| 		.enable_mask = LP8788_EN_DLDO8_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "dldo9",
 | |
| 		.id = DLDO9,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
 | |
| 		.volt_table = lp8788_dldo1239_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_DLDO9_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_5BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_B,
 | |
| 		.enable_mask = LP8788_EN_DLDO9_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "dldo10",
 | |
| 		.id = DLDO10,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl),
 | |
| 		.volt_table = lp8788_dldo1011_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_DLDO10_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_4BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_B,
 | |
| 		.enable_mask = LP8788_EN_DLDO10_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "dldo11",
 | |
| 		.id = DLDO11,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl),
 | |
| 		.volt_table = lp8788_dldo1011_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_DLDO11_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_4BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_B,
 | |
| 		.enable_mask = LP8788_EN_DLDO11_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "dldo12",
 | |
| 		.id = DLDO12,
 | |
| 		.ops = &lp8788_ldo_voltage_fixed_ops,
 | |
| 		.n_voltages = 1,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.enable_reg = LP8788_EN_LDO_B,
 | |
| 		.enable_mask = LP8788_EN_DLDO12_M,
 | |
| 		.min_uV = 2500000,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct regulator_desc lp8788_aldo_desc[] = {
 | |
| 	{
 | |
| 		.name = "aldo1",
 | |
| 		.id = ALDO1,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_aldo1_vtbl),
 | |
| 		.volt_table = lp8788_aldo1_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_ALDO1_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_1BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_B,
 | |
| 		.enable_mask = LP8788_EN_ALDO1_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "aldo2",
 | |
| 		.id = ALDO2,
 | |
| 		.ops = &lp8788_ldo_voltage_fixed_ops,
 | |
| 		.n_voltages = 1,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.enable_reg = LP8788_EN_LDO_B,
 | |
| 		.enable_mask = LP8788_EN_ALDO2_M,
 | |
| 		.min_uV = 2850000,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "aldo3",
 | |
| 		.id = ALDO3,
 | |
| 		.ops = &lp8788_ldo_voltage_fixed_ops,
 | |
| 		.n_voltages = 1,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.enable_reg = LP8788_EN_LDO_B,
 | |
| 		.enable_mask = LP8788_EN_ALDO3_M,
 | |
| 		.min_uV = 2850000,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "aldo4",
 | |
| 		.id = ALDO4,
 | |
| 		.ops = &lp8788_ldo_voltage_fixed_ops,
 | |
| 		.n_voltages = 1,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.enable_reg = LP8788_EN_LDO_B,
 | |
| 		.enable_mask = LP8788_EN_ALDO4_M,
 | |
| 		.min_uV = 2850000,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "aldo5",
 | |
| 		.id = ALDO5,
 | |
| 		.ops = &lp8788_ldo_voltage_fixed_ops,
 | |
| 		.n_voltages = 1,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.enable_reg = LP8788_EN_LDO_C,
 | |
| 		.enable_mask = LP8788_EN_ALDO5_M,
 | |
| 		.min_uV = 2850000,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "aldo6",
 | |
| 		.id = ALDO6,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
 | |
| 		.volt_table = lp8788_dldo578_aldo6_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_ALDO6_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_4BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_C,
 | |
| 		.enable_mask = LP8788_EN_ALDO6_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "aldo7",
 | |
| 		.id = ALDO7,
 | |
| 		.ops = &lp8788_ldo_voltage_table_ops,
 | |
| 		.n_voltages = ARRAY_SIZE(lp8788_aldo7_vtbl),
 | |
| 		.volt_table = lp8788_aldo7_vtbl,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.vsel_reg = LP8788_ALDO7_VOUT,
 | |
| 		.vsel_mask = LP8788_VOUT_3BIT_M,
 | |
| 		.enable_reg = LP8788_EN_LDO_C,
 | |
| 		.enable_mask = LP8788_EN_ALDO7_M,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "aldo8",
 | |
| 		.id = ALDO8,
 | |
| 		.ops = &lp8788_ldo_voltage_fixed_ops,
 | |
| 		.n_voltages = 1,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.enable_reg = LP8788_EN_LDO_C,
 | |
| 		.enable_mask = LP8788_EN_ALDO8_M,
 | |
| 		.min_uV = 2500000,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "aldo9",
 | |
| 		.id = ALDO9,
 | |
| 		.ops = &lp8788_ldo_voltage_fixed_ops,
 | |
| 		.n_voltages = 1,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.enable_reg = LP8788_EN_LDO_C,
 | |
| 		.enable_mask = LP8788_EN_ALDO9_M,
 | |
| 		.min_uV = 2500000,
 | |
| 	},
 | |
| 	{
 | |
| 		.name = "aldo10",
 | |
| 		.id = ALDO10,
 | |
| 		.ops = &lp8788_ldo_voltage_fixed_ops,
 | |
| 		.n_voltages = 1,
 | |
| 		.type = REGULATOR_VOLTAGE,
 | |
| 		.owner = THIS_MODULE,
 | |
| 		.enable_reg = LP8788_EN_LDO_C,
 | |
| 		.enable_mask = LP8788_EN_ALDO10_M,
 | |
| 		.min_uV = 1100000,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static int lp8788_config_ldo_enable_mode(struct platform_device *pdev,
 | |
| 					struct lp8788_ldo *ldo,
 | |
| 					enum lp8788_ldo_id id)
 | |
| {
 | |
| 	struct lp8788 *lp = ldo->lp;
 | |
| 	enum lp8788_ext_ldo_en_id enable_id;
 | |
| 	u8 en_mask[] = {
 | |
| 		[EN_ALDO1]   = LP8788_EN_SEL_ALDO1_M,
 | |
| 		[EN_ALDO234] = LP8788_EN_SEL_ALDO234_M,
 | |
| 		[EN_ALDO5]   = LP8788_EN_SEL_ALDO5_M,
 | |
| 		[EN_ALDO7]   = LP8788_EN_SEL_ALDO7_M,
 | |
| 		[EN_DLDO7]   = LP8788_EN_SEL_DLDO7_M,
 | |
| 		[EN_DLDO911] = LP8788_EN_SEL_DLDO911_M,
 | |
| 	};
 | |
| 
 | |
| 	switch (id) {
 | |
| 	case DLDO7:
 | |
| 		enable_id = EN_DLDO7;
 | |
| 		break;
 | |
| 	case DLDO9:
 | |
| 	case DLDO11:
 | |
| 		enable_id = EN_DLDO911;
 | |
| 		break;
 | |
| 	case ALDO1:
 | |
| 		enable_id = EN_ALDO1;
 | |
| 		break;
 | |
| 	case ALDO2 ... ALDO4:
 | |
| 		enable_id = EN_ALDO234;
 | |
| 		break;
 | |
| 	case ALDO5:
 | |
| 		enable_id = EN_ALDO5;
 | |
| 		break;
 | |
| 	case ALDO7:
 | |
| 		enable_id = EN_ALDO7;
 | |
| 		break;
 | |
| 	default:
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	/* FIXME: check default mode for GPIO here: high or low? */
 | |
| 	ldo->ena_gpiod = devm_gpiod_get_index_optional(&pdev->dev,
 | |
| 						       "enable",
 | |
| 						       enable_id,
 | |
| 						       GPIOD_OUT_HIGH);
 | |
| 	if (IS_ERR(ldo->ena_gpiod))
 | |
| 		return PTR_ERR(ldo->ena_gpiod);
 | |
| 
 | |
| 	/* if no GPIO for ldo pin, then set default enable mode */
 | |
| 	if (!ldo->ena_gpiod)
 | |
| 		goto set_default_ldo_enable_mode;
 | |
| 
 | |
| 	return 0;
 | |
| 
 | |
| set_default_ldo_enable_mode:
 | |
| 	return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id], 0);
 | |
| }
 | |
| 
 | |
| static int lp8788_dldo_probe(struct platform_device *pdev)
 | |
| {
 | |
| 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
 | |
| 	int id = pdev->id;
 | |
| 	struct lp8788_ldo *ldo;
 | |
| 	struct regulator_config cfg = { };
 | |
| 	struct regulator_dev *rdev;
 | |
| 	int ret;
 | |
| 
 | |
| 	ldo = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_ldo), GFP_KERNEL);
 | |
| 	if (!ldo)
 | |
| 		return -ENOMEM;
 | |
| 
 | |
| 	ldo->lp = lp;
 | |
| 	ret = lp8788_config_ldo_enable_mode(pdev, ldo, id);
 | |
| 	if (ret)
 | |
| 		return ret;
 | |
| 
 | |
| 	if (ldo->ena_gpiod)
 | |
| 		cfg.ena_gpiod = ldo->ena_gpiod;
 | |
| 
 | |
| 	cfg.dev = pdev->dev.parent;
 | |
| 	cfg.init_data = lp->pdata ? lp->pdata->dldo_data[id] : NULL;
 | |
| 	cfg.driver_data = ldo;
 | |
| 	cfg.regmap = lp->regmap;
 | |
| 
 | |
| 	rdev = devm_regulator_register(&pdev->dev, &lp8788_dldo_desc[id], &cfg);
 | |
| 	if (IS_ERR(rdev)) {
 | |
| 		ret = PTR_ERR(rdev);
 | |
| 		dev_err(&pdev->dev, "DLDO%d regulator register err = %d\n",
 | |
| 				id + 1, ret);
 | |
| 		return ret;
 | |
| 	}
 | |
| 
 | |
| 	ldo->regulator = rdev;
 | |
| 	platform_set_drvdata(pdev, ldo);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static struct platform_driver lp8788_dldo_driver = {
 | |
| 	.probe = lp8788_dldo_probe,
 | |
| 	.driver = {
 | |
| 		.name = LP8788_DEV_DLDO,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static int lp8788_aldo_probe(struct platform_device *pdev)
 | |
| {
 | |
| 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
 | |
| 	int id = pdev->id;
 | |
| 	struct lp8788_ldo *ldo;
 | |
| 	struct regulator_config cfg = { };
 | |
| 	struct regulator_dev *rdev;
 | |
| 	int ret;
 | |
| 
 | |
| 	ldo = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_ldo), GFP_KERNEL);
 | |
| 	if (!ldo)
 | |
| 		return -ENOMEM;
 | |
| 
 | |
| 	ldo->lp = lp;
 | |
| 	ret = lp8788_config_ldo_enable_mode(pdev, ldo, id + ALDO1);
 | |
| 	if (ret)
 | |
| 		return ret;
 | |
| 
 | |
| 	if (ldo->ena_gpiod)
 | |
| 		cfg.ena_gpiod = ldo->ena_gpiod;
 | |
| 
 | |
| 	cfg.dev = pdev->dev.parent;
 | |
| 	cfg.init_data = lp->pdata ? lp->pdata->aldo_data[id] : NULL;
 | |
| 	cfg.driver_data = ldo;
 | |
| 	cfg.regmap = lp->regmap;
 | |
| 
 | |
| 	rdev = devm_regulator_register(&pdev->dev, &lp8788_aldo_desc[id], &cfg);
 | |
| 	if (IS_ERR(rdev)) {
 | |
| 		ret = PTR_ERR(rdev);
 | |
| 		dev_err(&pdev->dev, "ALDO%d regulator register err = %d\n",
 | |
| 				id + 1, ret);
 | |
| 		return ret;
 | |
| 	}
 | |
| 
 | |
| 	ldo->regulator = rdev;
 | |
| 	platform_set_drvdata(pdev, ldo);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static struct platform_driver lp8788_aldo_driver = {
 | |
| 	.probe = lp8788_aldo_probe,
 | |
| 	.driver = {
 | |
| 		.name = LP8788_DEV_ALDO,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static struct platform_driver * const drivers[] = {
 | |
| 	&lp8788_dldo_driver,
 | |
| 	&lp8788_aldo_driver,
 | |
| };
 | |
| 
 | |
| static int __init lp8788_ldo_init(void)
 | |
| {
 | |
| 	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
 | |
| }
 | |
| subsys_initcall(lp8788_ldo_init);
 | |
| 
 | |
| static void __exit lp8788_ldo_exit(void)
 | |
| {
 | |
| 	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
 | |
| }
 | |
| module_exit(lp8788_ldo_exit);
 | |
| 
 | |
| MODULE_DESCRIPTION("TI LP8788 LDO Driver");
 | |
| MODULE_AUTHOR("Milo Kim");
 | |
| MODULE_LICENSE("GPL");
 | |
| MODULE_ALIAS("platform:lp8788-dldo");
 | |
| MODULE_ALIAS("platform:lp8788-aldo");
 | 
