1d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/*
2d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * drivers/regulator/ab3100.c
3d619bc143e311a738113dbbe7792bd032403939fLinus Walleij *
4d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * Copyright (C) 2008-2009 ST-Ericsson AB
5d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * License terms: GNU General Public License (GPL) version 2
6d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * Low-level control of the AB3100 IC Low Dropout (LDO)
7d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * regulators, external regulator and buck converter
8d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * Author: Mattias Wallin <mattias.wallin@stericsson.com>
9d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * Author: Linus Walleij <linus.walleij@stericsson.com>
10d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */
11d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
12d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/module.h>
13d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/kernel.h>
14d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/init.h>
15d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/err.h>
16d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/delay.h>
17d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/platform_device.h>
18d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/regulator/driver.h>
19812f9e9d424dde9ccb35975c0281edb6f8543735Linus Walleij#include <linux/mfd/abx500.h>
20d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
21d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* LDO registers and some handy masking definitions for AB3100 */
22d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_A		0x40
23d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_C		0x41
24d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_D		0x42
25d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_E		0x43
26d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_E_SLEEP	0x44
27d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_F		0x45
28d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_G		0x46
29d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_H		0x47
30d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_H_SLEEP_MODE	0
31d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_H_SLEEP_EN	2
32d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_ON		4
33d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_H_VSEL_AC	5
34d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_K		0x48
35d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_EXT		0x49
36d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_BUCK		0x4A
37d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_BUCK_SLEEP	0x4B
38d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_REG_ON_MASK	0x10
39d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
40d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/**
41d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * struct ab3100_regulator
42d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * A struct passed around the individual regulator functions
43d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * @platform_device: platform device holding this regulator
44fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin * @dev: handle to the device
45d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * @plfdata: AB3100 platform data passed in at probe time
46d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * @regreg: regulator register number in the AB3100
47d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * @fixed_voltage: a fixed voltage for this regulator, if this
48d619bc143e311a738113dbbe7792bd032403939fLinus Walleij *          0 the voltages array is used instead.
49d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * @typ_voltages: an array of available typical voltages for
50d619bc143e311a738113dbbe7792bd032403939fLinus Walleij *          this regulator
51d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * @voltages_len: length of the array of available voltages
52d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */
53d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstruct ab3100_regulator {
54d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	struct regulator_dev *rdev;
55fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin	struct device *dev;
56d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	struct ab3100_platform_data *plfdata;
57d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	u8 regreg;
58d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int fixed_voltage;
59d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int const *typ_voltages;
60d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	u8 voltages_len;
61d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
62d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
63d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* The order in which registers are initialized */
64d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic const u8 ab3100_reg_init_order[AB3100_NUM_REGULATORS+2] = {
65d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	AB3100_LDO_A,
66d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	AB3100_LDO_C,
67d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	AB3100_LDO_E,
68d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	AB3100_LDO_E_SLEEP,
69d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	AB3100_LDO_F,
70d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	AB3100_LDO_G,
71d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	AB3100_LDO_H,
72d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	AB3100_LDO_K,
73d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	AB3100_LDO_EXT,
74d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	AB3100_BUCK,
75d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	AB3100_BUCK_SLEEP,
76d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	AB3100_LDO_D,
77d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
78d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
79d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* Preset (hardware defined) voltages for these regulators */
80d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define LDO_A_VOLTAGE 2750000
81d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define LDO_C_VOLTAGE 2650000
82d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define LDO_D_VOLTAGE 2650000
83d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
849992ef40ff2e16559e49ff1ae63d133cb9849e8fMark Brownstatic const int ldo_e_buck_typ_voltages[] = {
85d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1800000,
86d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1400000,
87d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1300000,
88d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1200000,
89d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1100000,
90d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1050000,
91d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	900000,
92d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
93d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
949992ef40ff2e16559e49ff1ae63d133cb9849e8fMark Brownstatic const int ldo_f_typ_voltages[] = {
95d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1800000,
96d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1400000,
97d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1300000,
98d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1200000,
99d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1100000,
100d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1050000,
101d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	2500000,
102d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	2650000,
103d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
104d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
1059992ef40ff2e16559e49ff1ae63d133cb9849e8fMark Brownstatic const int ldo_g_typ_voltages[] = {
106d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	2850000,
107d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	2750000,
108d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1800000,
109d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1500000,
110d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
111d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
1129992ef40ff2e16559e49ff1ae63d133cb9849e8fMark Brownstatic const int ldo_h_typ_voltages[] = {
113d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	2750000,
114d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1800000,
115d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1500000,
116d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1200000,
117d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
118d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
1199992ef40ff2e16559e49ff1ae63d133cb9849e8fMark Brownstatic const int ldo_k_typ_voltages[] = {
120d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	2750000,
121d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	1800000,
122d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
123d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
124d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
125d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* The regulator devices */
126d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct ab3100_regulator
127d619bc143e311a738113dbbe7792bd032403939fLinus Walleijab3100_regulators[AB3100_NUM_REGULATORS] = {
128d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
129d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.regreg = AB3100_LDO_A,
130d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.fixed_voltage = LDO_A_VOLTAGE,
131d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
132d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
133d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.regreg = AB3100_LDO_C,
134d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.fixed_voltage = LDO_C_VOLTAGE,
135d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
136d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
137d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.regreg = AB3100_LDO_D,
138d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.fixed_voltage = LDO_D_VOLTAGE,
139d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
140d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
141d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.regreg = AB3100_LDO_E,
142d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.typ_voltages = ldo_e_buck_typ_voltages,
143d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages),
144d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
145d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
146d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.regreg = AB3100_LDO_F,
147d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.typ_voltages = ldo_f_typ_voltages,
148d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.voltages_len = ARRAY_SIZE(ldo_f_typ_voltages),
149d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
150d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
151d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.regreg = AB3100_LDO_G,
152d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.typ_voltages = ldo_g_typ_voltages,
153d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.voltages_len = ARRAY_SIZE(ldo_g_typ_voltages),
154d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
155d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
156d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.regreg = AB3100_LDO_H,
157d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.typ_voltages = ldo_h_typ_voltages,
158d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.voltages_len = ARRAY_SIZE(ldo_h_typ_voltages),
159d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
160d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
161d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.regreg = AB3100_LDO_K,
162d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.typ_voltages = ldo_k_typ_voltages,
163d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.voltages_len = ARRAY_SIZE(ldo_k_typ_voltages),
164d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
165d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
166d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.regreg = AB3100_LDO_EXT,
167d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		/* No voltages for the external regulator */
168d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
169d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
170d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.regreg = AB3100_BUCK,
171d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.typ_voltages = ldo_e_buck_typ_voltages,
172d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages),
173d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
174d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
175d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
176d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/*
177d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * General functions for enable, disable and is_enabled used for
178d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * LDO: A,C,E,F,G,H,K,EXT and BUCK
179d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */
180d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_enable_regulator(struct regulator_dev *reg)
181d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
182d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	struct ab3100_regulator *abreg = reg->reg_data;
183d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int err;
184d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	u8 regval;
185d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
186fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin	err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg,
187d619bc143e311a738113dbbe7792bd032403939fLinus Walleij						&regval);
188d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (err) {
189d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_warn(&reg->dev, "failed to get regid %d value\n",
190d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			 abreg->regreg);
191d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return err;
192d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
193d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
194d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/* The regulator is already on, no reason to go further */
195d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (regval & AB3100_REG_ON_MASK)
196d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return 0;
197d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
198d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	regval |= AB3100_REG_ON_MASK;
199d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
200fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin	err = abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg,
201d619bc143e311a738113dbbe7792bd032403939fLinus Walleij						regval);
202d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (err) {
203d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_warn(&reg->dev, "failed to set regid %d value\n",
204d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			 abreg->regreg);
205d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return err;
206d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
207d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
208d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	return 0;
209d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
210d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
211d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_disable_regulator(struct regulator_dev *reg)
212d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
213d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	struct ab3100_regulator *abreg = reg->reg_data;
214d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int err;
215d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	u8 regval;
216d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
217d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/*
218d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 * LDO D is a special regulator. When it is disabled, the entire
219d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 * system is shut down. So this is handled specially.
220d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 */
221176f45b9c9b7e451ac46becb92110f5e2de02d8cLinus Walleij	pr_info("Called ab3100_disable_regulator\n");
222d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (abreg->regreg == AB3100_LDO_D) {
223d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_info(&reg->dev, "disabling LDO D - shut down system\n");
224d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		/* Setting LDO D to 0x00 cuts the power to the SoC */
225fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin		return abx500_set_register_interruptible(abreg->dev, 0,
226d619bc143e311a738113dbbe7792bd032403939fLinus Walleij							 AB3100_LDO_D, 0x00U);
227d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
228d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
229d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/*
230d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 * All other regulators are handled here
231d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 */
232fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin	err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg,
233d619bc143e311a738113dbbe7792bd032403939fLinus Walleij						&regval);
234d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (err) {
235d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_err(&reg->dev, "unable to get register 0x%x\n",
236d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			abreg->regreg);
237d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return err;
238d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
239d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	regval &= ~AB3100_REG_ON_MASK;
240fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin	return abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg,
241d619bc143e311a738113dbbe7792bd032403939fLinus Walleij						 regval);
242d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
243d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
244d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_is_enabled_regulator(struct regulator_dev *reg)
245d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
246d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	struct ab3100_regulator *abreg = reg->reg_data;
247d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	u8 regval;
248d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int err;
249d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
250fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin	err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg,
251d619bc143e311a738113dbbe7792bd032403939fLinus Walleij						&regval);
252d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (err) {
253d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_err(&reg->dev, "unable to get register 0x%x\n",
254d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			abreg->regreg);
255d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return err;
256d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
257d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
258d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	return regval & AB3100_REG_ON_MASK;
259d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
260d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
261d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_list_voltage_regulator(struct regulator_dev *reg,
262d619bc143e311a738113dbbe7792bd032403939fLinus Walleij					 unsigned selector)
263d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
264d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	struct ab3100_regulator *abreg = reg->reg_data;
265d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
266979da89a9c230381ca55ea0764428a5d42a01e7fAxel Lin	if (selector >= abreg->voltages_len)
267d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return -EINVAL;
268d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	return abreg->typ_voltages[selector];
269d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
270d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
271d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_get_voltage_regulator(struct regulator_dev *reg)
272d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
273d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	struct ab3100_regulator *abreg = reg->reg_data;
274d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	u8 regval;
275d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int err;
276d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
277d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/* Return the voltage for fixed regulators immediately */
278d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (abreg->fixed_voltage)
279d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return abreg->fixed_voltage;
280d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
281d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/*
282d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 * For variable types, read out setting and index into
283d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 * supplied voltage list.
284d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 */
285fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin	err = abx500_get_register_interruptible(abreg->dev, 0,
286d619bc143e311a738113dbbe7792bd032403939fLinus Walleij						abreg->regreg, &regval);
287d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (err) {
288d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_warn(&reg->dev,
289d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			 "failed to get regulator value in register %02x\n",
290d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			 abreg->regreg);
291d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return err;
292d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
293d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
294d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/* The 3 highest bits index voltages */
295d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	regval &= 0xE0;
296d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	regval >>= 5;
297d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
298979da89a9c230381ca55ea0764428a5d42a01e7fAxel Lin	if (regval >= abreg->voltages_len) {
299d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_err(&reg->dev,
300d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			"regulator register %02x contains an illegal voltage setting\n",
301d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			abreg->regreg);
302d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return -EINVAL;
303d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
304d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
305d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	return abreg->typ_voltages[regval];
306d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
307d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
308d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_get_best_voltage_index(struct regulator_dev *reg,
309d619bc143e311a738113dbbe7792bd032403939fLinus Walleij				   int min_uV, int max_uV)
310d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
311d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	struct ab3100_regulator *abreg = reg->reg_data;
312d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int i;
313d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int bestmatch;
314d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int bestindex;
315d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
316d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/*
317d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 * Locate the minimum voltage fitting the criteria on
318d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 * this regulator. The switchable voltages are not
319d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 * in strict falling order so we need to check them
320d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 * all for the best match.
321d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	 */
322d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	bestmatch = INT_MAX;
323d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	bestindex = -1;
324d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	for (i = 0; i < abreg->voltages_len; i++) {
325d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		if (abreg->typ_voltages[i] <= max_uV &&
326d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		    abreg->typ_voltages[i] >= min_uV &&
327d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		    abreg->typ_voltages[i] < bestmatch) {
328d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			bestmatch = abreg->typ_voltages[i];
329d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			bestindex = i;
330d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		}
331d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
332d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
333d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (bestindex < 0) {
334d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_warn(&reg->dev, "requested %d<=x<=%d uV, out of range!\n",
335d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			 min_uV, max_uV);
336d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return -EINVAL;
337d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
338d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	return bestindex;
339d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
340d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
341d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_set_voltage_regulator(struct regulator_dev *reg,
3423a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown					int min_uV, int max_uV,
3433a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown					unsigned *selector)
344d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
345d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	struct ab3100_regulator *abreg = reg->reg_data;
346d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	u8 regval;
347d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int err;
348d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int bestindex;
349d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
350d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	bestindex = ab3100_get_best_voltage_index(reg, min_uV, max_uV);
351d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (bestindex < 0)
352d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return bestindex;
353d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
3543a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown	*selector = bestindex;
3553a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown
356fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin	err = abx500_get_register_interruptible(abreg->dev, 0,
357d619bc143e311a738113dbbe7792bd032403939fLinus Walleij						abreg->regreg, &regval);
358d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (err) {
359d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_warn(&reg->dev,
360d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			 "failed to get regulator register %02x\n",
361d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			 abreg->regreg);
362d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return err;
363d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
364d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
365d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/* The highest three bits control the variable regulators */
366d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	regval &= ~0xE0;
367d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	regval |= (bestindex << 5);
368d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
369fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin	err = abx500_set_register_interruptible(abreg->dev, 0,
370d619bc143e311a738113dbbe7792bd032403939fLinus Walleij						abreg->regreg, regval);
371d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (err)
372d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_warn(&reg->dev, "failed to set regulator register %02x\n",
373d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			abreg->regreg);
374d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
375d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	return err;
376d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
377d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
378d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
379d619bc143e311a738113dbbe7792bd032403939fLinus Walleij						int uV)
380d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
381d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	struct ab3100_regulator *abreg = reg->reg_data;
382d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	u8 regval;
383d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int err;
384d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int bestindex;
385d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	u8 targetreg;
386d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
387d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (abreg->regreg == AB3100_LDO_E)
388d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		targetreg = AB3100_LDO_E_SLEEP;
389d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	else if (abreg->regreg == AB3100_BUCK)
390d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		targetreg = AB3100_BUCK_SLEEP;
391d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	else
392d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return -EINVAL;
393d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
394d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/* LDO E and BUCK have special suspend voltages you can set */
395d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	bestindex = ab3100_get_best_voltage_index(reg, uV, uV);
396d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
397fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin	err = abx500_get_register_interruptible(abreg->dev, 0,
398d619bc143e311a738113dbbe7792bd032403939fLinus Walleij						targetreg, &regval);
399d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (err) {
400d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_warn(&reg->dev,
401d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			 "failed to get regulator register %02x\n",
402d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			 targetreg);
403d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return err;
404d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
405d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
406d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/* The highest three bits control the variable regulators */
407d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	regval &= ~0xE0;
408d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	regval |= (bestindex << 5);
409d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
410fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin	err = abx500_set_register_interruptible(abreg->dev, 0,
411d619bc143e311a738113dbbe7792bd032403939fLinus Walleij						targetreg, regval);
412d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (err)
413d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_warn(&reg->dev, "failed to set regulator register %02x\n",
414d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			abreg->regreg);
415d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
416d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	return err;
417d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
418d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
419d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/*
420d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * The external regulator can just define a fixed voltage.
421d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */
422d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_get_voltage_regulator_external(struct regulator_dev *reg)
423d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
424d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	struct ab3100_regulator *abreg = reg->reg_data;
425d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
426d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	return abreg->plfdata->external_voltage;
427d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
428d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
42919c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleijstatic int ab3100_enable_time_regulator(struct regulator_dev *reg)
43019c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij{
43119c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	struct ab3100_regulator *abreg = reg->reg_data;
43219c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij
43319c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	/* Per-regulator power on delay from spec */
43419c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	switch (abreg->regreg) {
43519c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	case AB3100_LDO_A: /* Fallthrough */
43619c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	case AB3100_LDO_C: /* Fallthrough */
43719c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	case AB3100_LDO_D: /* Fallthrough */
43819c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	case AB3100_LDO_E: /* Fallthrough */
43919c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	case AB3100_LDO_H: /* Fallthrough */
44019c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	case AB3100_LDO_K:
44119c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij		return 200;
44219c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	case AB3100_LDO_F:
44319c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij		return 600;
44419c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	case AB3100_LDO_G:
44519c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij		return 400;
44619c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	case AB3100_BUCK:
44719c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij		return 1000;
44819c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	default:
44919c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij		break;
45019c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	}
45119c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	return 0;
45219c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij}
45319c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij
454d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct regulator_ops regulator_ops_fixed = {
455d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.enable      = ab3100_enable_regulator,
456d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.disable     = ab3100_disable_regulator,
457d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.is_enabled  = ab3100_is_enabled_regulator,
458d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.get_voltage = ab3100_get_voltage_regulator,
45919c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	.enable_time = ab3100_enable_time_regulator,
460d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
461d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
462d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct regulator_ops regulator_ops_variable = {
463d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.enable      = ab3100_enable_regulator,
464d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.disable     = ab3100_disable_regulator,
465d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.is_enabled  = ab3100_is_enabled_regulator,
466d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.get_voltage = ab3100_get_voltage_regulator,
467d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.set_voltage = ab3100_set_voltage_regulator,
468d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.list_voltage = ab3100_list_voltage_regulator,
46919c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	.enable_time = ab3100_enable_time_regulator,
470d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
471d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
472d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct regulator_ops regulator_ops_variable_sleepable = {
473d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.enable      = ab3100_enable_regulator,
474d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.disable     = ab3100_disable_regulator,
475d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.is_enabled  = ab3100_is_enabled_regulator,
476d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.get_voltage = ab3100_get_voltage_regulator,
477d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.set_voltage = ab3100_set_voltage_regulator,
478d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.set_suspend_voltage = ab3100_set_suspend_voltage_regulator,
479d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.list_voltage = ab3100_list_voltage_regulator,
48019c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij	.enable_time = ab3100_enable_time_regulator,
481d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
482d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
483d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/*
484d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * LDO EXT is an external regulator so it is really
485d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * not possible to set any voltage locally here, AB3100
486d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * is an on/off switch plain an simple. The external
487d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * voltage is defined in the board set-up if any.
488d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */
489d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct regulator_ops regulator_ops_external = {
490d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.enable      = ab3100_enable_regulator,
491d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.disable     = ab3100_disable_regulator,
492d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.is_enabled  = ab3100_is_enabled_regulator,
493d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.get_voltage = ab3100_get_voltage_regulator_external,
494d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
495d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
496d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct regulator_desc
497d619bc143e311a738113dbbe7792bd032403939fLinus Walleijab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
498d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
499d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.name = "LDO_A",
500d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.id   = AB3100_LDO_A,
501d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.ops  = &regulator_ops_fixed,
502d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.type = REGULATOR_VOLTAGE,
50364714354a45a58a072cfc926db0a078611a63d43Axel Lin		.owner = THIS_MODULE,
504d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
505d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
506d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.name = "LDO_C",
507d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.id   = AB3100_LDO_C,
508d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.ops  = &regulator_ops_fixed,
509d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.type = REGULATOR_VOLTAGE,
51064714354a45a58a072cfc926db0a078611a63d43Axel Lin		.owner = THIS_MODULE,
511d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
512d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
513d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.name = "LDO_D",
514d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.id   = AB3100_LDO_D,
515d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.ops  = &regulator_ops_fixed,
516d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.type = REGULATOR_VOLTAGE,
51764714354a45a58a072cfc926db0a078611a63d43Axel Lin		.owner = THIS_MODULE,
518d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
519d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
520d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.name = "LDO_E",
521d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.id   = AB3100_LDO_E,
522d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.ops  = &regulator_ops_variable_sleepable,
52375f2ba8f0006440e720e47ae14c917e07c452d72Linus Walleij		.n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages),
524d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.type = REGULATOR_VOLTAGE,
52564714354a45a58a072cfc926db0a078611a63d43Axel Lin		.owner = THIS_MODULE,
526d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
527d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
528d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.name = "LDO_F",
529d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.id   = AB3100_LDO_F,
530d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.ops  = &regulator_ops_variable,
53175f2ba8f0006440e720e47ae14c917e07c452d72Linus Walleij		.n_voltages = ARRAY_SIZE(ldo_f_typ_voltages),
532d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.type = REGULATOR_VOLTAGE,
53364714354a45a58a072cfc926db0a078611a63d43Axel Lin		.owner = THIS_MODULE,
534d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
535d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
536d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.name = "LDO_G",
537d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.id   = AB3100_LDO_G,
538d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.ops  = &regulator_ops_variable,
53975f2ba8f0006440e720e47ae14c917e07c452d72Linus Walleij		.n_voltages = ARRAY_SIZE(ldo_g_typ_voltages),
540d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.type = REGULATOR_VOLTAGE,
54164714354a45a58a072cfc926db0a078611a63d43Axel Lin		.owner = THIS_MODULE,
542d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
543d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
544d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.name = "LDO_H",
545d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.id   = AB3100_LDO_H,
546d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.ops  = &regulator_ops_variable,
54775f2ba8f0006440e720e47ae14c917e07c452d72Linus Walleij		.n_voltages = ARRAY_SIZE(ldo_h_typ_voltages),
548d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.type = REGULATOR_VOLTAGE,
54964714354a45a58a072cfc926db0a078611a63d43Axel Lin		.owner = THIS_MODULE,
550d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
551d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
552d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.name = "LDO_K",
553d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.id   = AB3100_LDO_K,
554d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.ops  = &regulator_ops_variable,
55575f2ba8f0006440e720e47ae14c917e07c452d72Linus Walleij		.n_voltages = ARRAY_SIZE(ldo_k_typ_voltages),
556d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.type = REGULATOR_VOLTAGE,
55764714354a45a58a072cfc926db0a078611a63d43Axel Lin		.owner = THIS_MODULE,
558d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
559d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
560d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.name = "LDO_EXT",
561d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.id   = AB3100_LDO_EXT,
562d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.ops  = &regulator_ops_external,
563d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.type = REGULATOR_VOLTAGE,
56464714354a45a58a072cfc926db0a078611a63d43Axel Lin		.owner = THIS_MODULE,
565d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
566d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	{
567d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.name = "BUCK",
568d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.id   = AB3100_BUCK,
569d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.ops  = &regulator_ops_variable_sleepable,
57075f2ba8f0006440e720e47ae14c917e07c452d72Linus Walleij		.n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages),
571d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.type = REGULATOR_VOLTAGE,
57264714354a45a58a072cfc926db0a078611a63d43Axel Lin		.owner = THIS_MODULE,
573d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
574d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
575d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
576d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/*
577d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * NOTE: the following functions are regulators pluralis - it is the
578d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * binding to the AB3100 core driver and the parent platform device
579d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * for all the different regulators.
580d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */
581d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
58298bf7c057b35eaf418ac063c4aba4f9f86220b09Dmitry Torokhovstatic int __devinit ab3100_regulators_probe(struct platform_device *pdev)
583d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
584a771e36e16e9fdacb2bb8d3b9be50be68f211b82Samuel Ortiz	struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
585d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int err = 0;
586d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	u8 data;
587d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int i;
588d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
589d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/* Check chip state */
590fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin	err = abx500_get_register_interruptible(&pdev->dev, 0,
591d619bc143e311a738113dbbe7792bd032403939fLinus Walleij						AB3100_LDO_D, &data);
592d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (err) {
593d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_err(&pdev->dev, "could not read initial status of LDO_D\n");
594d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		return err;
595d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
596d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	if (data & 0x10)
597d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_notice(&pdev->dev,
598d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			   "chip is already in active mode (Warm start)\n");
599d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	else
600d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		dev_notice(&pdev->dev,
601d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			   "chip is in inactive mode (Cold start)\n");
602d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
603d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/* Set up regulators */
604d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) {
605fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin		err = abx500_set_register_interruptible(&pdev->dev, 0,
606d619bc143e311a738113dbbe7792bd032403939fLinus Walleij					ab3100_reg_init_order[i],
607d619bc143e311a738113dbbe7792bd032403939fLinus Walleij					plfdata->reg_initvals[i]);
608d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		if (err) {
609d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			dev_err(&pdev->dev, "regulator initialization failed with error %d\n",
610d619bc143e311a738113dbbe7792bd032403939fLinus Walleij				err);
611d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			return err;
612d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		}
613d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
614d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
615d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	/* Register the regulators */
616d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
617d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		struct ab3100_regulator *reg = &ab3100_regulators[i];
618d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		struct regulator_dev *rdev;
619d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
620d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		/*
621d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		 * Initialize per-regulator struct.
622d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		 * Inherit platform data, this comes down from the
623d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		 * i2c boarddata, from the machine. So if you want to
624d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		 * see what it looks like for a certain machine, go
625d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		 * into the machine I2C setup.
626d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		 */
627fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin		reg->dev = &pdev->dev;
628d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		reg->plfdata = plfdata;
629d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
630d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		/*
631d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		 * Register the regulator, pass around
632d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		 * the ab3100_regulator struct
633d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		 */
634d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		rdev = regulator_register(&ab3100_regulator_desc[i],
635d619bc143e311a738113dbbe7792bd032403939fLinus Walleij					  &pdev->dev,
636d619bc143e311a738113dbbe7792bd032403939fLinus Walleij					  &plfdata->reg_constraints[i],
6372c043bcbf287dc69848054d5c02c55c20f7a7bc5Rajendra Nayak					  reg, NULL);
638d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
639d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		if (IS_ERR(rdev)) {
640d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			err = PTR_ERR(rdev);
641d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			dev_err(&pdev->dev,
642d619bc143e311a738113dbbe7792bd032403939fLinus Walleij				"%s: failed to register regulator %s err %d\n",
643d619bc143e311a738113dbbe7792bd032403939fLinus Walleij				__func__, ab3100_regulator_desc[i].name,
644d619bc143e311a738113dbbe7792bd032403939fLinus Walleij				err);
645d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			/* remove the already registered regulators */
646b3fcf3e576749b911e984e752b6b390c326efb76Axel Lin			while (--i >= 0)
647d619bc143e311a738113dbbe7792bd032403939fLinus Walleij				regulator_unregister(ab3100_regulators[i].rdev);
648d619bc143e311a738113dbbe7792bd032403939fLinus Walleij			return err;
649d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		}
650d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
651d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		/* Then set a pointer back to the registered regulator */
652d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		reg->rdev = rdev;
653d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
654d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
655d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	return 0;
656d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
657d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
65898bf7c057b35eaf418ac063c4aba4f9f86220b09Dmitry Torokhovstatic int __devexit ab3100_regulators_remove(struct platform_device *pdev)
659d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
660d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	int i;
661d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
662d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
663d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		struct ab3100_regulator *reg = &ab3100_regulators[i];
664d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
665d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		regulator_unregister(reg->rdev);
666d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	}
667d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	return 0;
668d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
669d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
670d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct platform_driver ab3100_regulators_driver = {
671d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.driver = {
672d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.name  = "ab3100-regulators",
673d619bc143e311a738113dbbe7792bd032403939fLinus Walleij		.owner = THIS_MODULE,
674d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	},
675d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	.probe = ab3100_regulators_probe,
67698bf7c057b35eaf418ac063c4aba4f9f86220b09Dmitry Torokhov	.remove = __devexit_p(ab3100_regulators_remove),
677d619bc143e311a738113dbbe7792bd032403939fLinus Walleij};
678d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
679d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic __init int ab3100_regulators_init(void)
680d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
681d619bc143e311a738113dbbe7792bd032403939fLinus Walleij	return platform_driver_register(&ab3100_regulators_driver);
682d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
683d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
684d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic __exit void ab3100_regulators_exit(void)
685d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{
686176f45b9c9b7e451ac46becb92110f5e2de02d8cLinus Walleij	platform_driver_unregister(&ab3100_regulators_driver);
687d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}
688d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
689d619bc143e311a738113dbbe7792bd032403939fLinus Walleijsubsys_initcall(ab3100_regulators_init);
690d619bc143e311a738113dbbe7792bd032403939fLinus Walleijmodule_exit(ab3100_regulators_exit);
691d619bc143e311a738113dbbe7792bd032403939fLinus Walleij
692d619bc143e311a738113dbbe7792bd032403939fLinus WalleijMODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
693d619bc143e311a738113dbbe7792bd032403939fLinus WalleijMODULE_DESCRIPTION("AB3100 Regulator driver");
694d619bc143e311a738113dbbe7792bd032403939fLinus WalleijMODULE_LICENSE("GPL");
695d619bc143e311a738113dbbe7792bd032403939fLinus WalleijMODULE_ALIAS("platform:ab3100-regulators");
696