Commit 0c076151c7209610bddc33cb4d36b604ceef5209
Committed by
Jason Liu
1 parent
4e5eed0ee4
Exists in
smarc_8mm_imx_4.14.98_2.0.0_ga
and in
4 other branches
MLK-11556-1 pmic: max17135: add hwmon, mfd and regulator drivers for this pmic
Add PMIC 'MAX17135' module drivers to 4.1.y kernel. These are necessary to supply power for E-ink panel display functions. Signed-off-by: Robby Cai <r63905@freescale.com>
Showing 11 changed files with 1625 additions and 1 deletions Side-by-side Diff
drivers/hwmon/Kconfig
... | ... | @@ -843,6 +843,15 @@ |
843 | 843 | This driver can also be built as a module. If so, the module |
844 | 844 | will be called max1668. |
845 | 845 | |
846 | +config SENSORS_MAX17135 | |
847 | + tristate "Maxim MAX17135 EPD temperature sensor" | |
848 | + depends on I2C | |
849 | + help | |
850 | + If you say yes here you get support for MAX17135 PMIC sensor. | |
851 | + | |
852 | + This driver can also be built as a module. If so, the module | |
853 | + will be called max17135_sensor. | |
854 | + | |
846 | 855 | config SENSORS_MAX197 |
847 | 856 | tristate "Maxim MAX197 and compatibles" |
848 | 857 | help |
... | ... | @@ -1545,7 +1554,7 @@ |
1545 | 1554 | |
1546 | 1555 | config SENSORS_AMC6821 |
1547 | 1556 | tristate "Texas Instruments AMC6821" |
1548 | - depends on I2C | |
1557 | + depends on I2C | |
1549 | 1558 | help |
1550 | 1559 | If you say yes here you get support for the Texas Instruments |
1551 | 1560 | AMC6821 hardware monitoring chips. |
drivers/hwmon/Makefile
... | ... | @@ -116,6 +116,7 @@ |
116 | 116 | obj-$(CONFIG_SENSORS_MAX16065) += max16065.o |
117 | 117 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o |
118 | 118 | obj-$(CONFIG_SENSORS_MAX1668) += max1668.o |
119 | +obj-$(CONFIG_SENSORS_MAX17135) += max17135-hwmon.o | |
119 | 120 | obj-$(CONFIG_SENSORS_MAX197) += max197.o |
120 | 121 | obj-$(CONFIG_SENSORS_MAX31722) += max31722.o |
121 | 122 | obj-$(CONFIG_SENSORS_MAX6639) += max6639.o |
drivers/hwmon/max17135-hwmon.c
1 | +/* | |
2 | + * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. | |
3 | + * | |
4 | + * This program is free software; you can redistribute it and/or modify | |
5 | + * it under the terms of the GNU General Public License as published by | |
6 | + * the Free Software Foundation; either version 2 of the License, or | |
7 | + * (at your option) any later version. | |
8 | + * | |
9 | + * This program is distributed in the hope that it will be useful, | |
10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | + * GNU General Public License for more details. | |
13 | + * | |
14 | + * You should have received a copy of the GNU General Public License | |
15 | + * along with this program; if not, write to the Free Software | |
16 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
17 | + * | |
18 | + */ | |
19 | +/* | |
20 | + * max17135.c | |
21 | + * | |
22 | + * Based on the MAX1619 driver. | |
23 | + * Copyright (C) 2003-2004 Alexey Fisher <fishor@mail.ru> | |
24 | + * Jean Delvare <khali@linux-fr.org> | |
25 | + * | |
26 | + * The MAX17135 is a sensor chip made by Maxim. | |
27 | + * It reports up to two temperatures (its own plus up to | |
28 | + * one external one). | |
29 | + */ | |
30 | + | |
31 | + | |
32 | +#include <linux/module.h> | |
33 | +#include <linux/init.h> | |
34 | +#include <linux/slab.h> | |
35 | +#include <linux/jiffies.h> | |
36 | +#include <linux/hwmon.h> | |
37 | +#include <linux/hwmon-sysfs.h> | |
38 | +#include <linux/err.h> | |
39 | +#include <linux/sysfs.h> | |
40 | +#include <linux/platform_device.h> | |
41 | +#include <linux/mfd/max17135.h> | |
42 | + | |
43 | +/* | |
44 | + * Conversions | |
45 | + */ | |
46 | +static int temp_from_reg(int val) | |
47 | +{ | |
48 | + return val >> 8; | |
49 | +} | |
50 | + | |
51 | +/* | |
52 | + * Functions declaration | |
53 | + */ | |
54 | +static int max17135_sensor_probe(struct platform_device *pdev); | |
55 | +static int max17135_sensor_remove(struct platform_device *pdev); | |
56 | + | |
57 | +static const struct platform_device_id max17135_sns_id[] = { | |
58 | + { "max17135-sns", 0}, | |
59 | + { /* sentinel */ }, | |
60 | +}; | |
61 | +MODULE_DEVICE_TABLE(platform, max17135_sns_id); | |
62 | + | |
63 | +/* | |
64 | + * Driver data (common to all clients) | |
65 | + */ | |
66 | +static struct platform_driver max17135_sensor_driver = { | |
67 | + .probe = max17135_sensor_probe, | |
68 | + .remove = max17135_sensor_remove, | |
69 | + .id_table = max17135_sns_id, | |
70 | + .driver = { | |
71 | + .name = "max17135_sensor", | |
72 | + }, | |
73 | +}; | |
74 | + | |
75 | +/* | |
76 | + * Client data (each client gets its own) | |
77 | + */ | |
78 | +struct max17135_data { | |
79 | + struct device *hwmon_dev; | |
80 | +}; | |
81 | + | |
82 | +/* | |
83 | + * Sysfs stuff | |
84 | + */ | |
85 | +static ssize_t show_temp_input1(struct device *dev, | |
86 | + struct device_attribute *attr, char *buf) | |
87 | +{ | |
88 | + unsigned int reg_val; | |
89 | + max17135_reg_read(REG_MAX17135_INT_TEMP, ®_val); | |
90 | + return snprintf(buf, PAGE_SIZE, "%d\n", temp_from_reg(reg_val)); | |
91 | +} | |
92 | + | |
93 | +static ssize_t show_temp_input2(struct device *dev, | |
94 | + struct device_attribute *attr, char *buf) | |
95 | +{ | |
96 | + unsigned int reg_val; | |
97 | + max17135_reg_read(REG_MAX17135_EXT_TEMP, ®_val); | |
98 | + return snprintf(buf, PAGE_SIZE, "%d\n", temp_from_reg(reg_val)); | |
99 | +} | |
100 | + | |
101 | +static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL); | |
102 | +static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input2, NULL); | |
103 | + | |
104 | +static struct attribute *max17135_attributes[] = { | |
105 | + &dev_attr_temp1_input.attr, | |
106 | + &dev_attr_temp2_input.attr, | |
107 | + NULL | |
108 | +}; | |
109 | + | |
110 | +static const struct attribute_group max17135_group = { | |
111 | + .attrs = max17135_attributes, | |
112 | +}; | |
113 | + | |
114 | +/* | |
115 | + * Real code | |
116 | + */ | |
117 | +static int max17135_sensor_probe(struct platform_device *pdev) | |
118 | +{ | |
119 | + struct max17135_data *data; | |
120 | + int err; | |
121 | + | |
122 | + data = kzalloc(sizeof(struct max17135_data), GFP_KERNEL); | |
123 | + if (!data) { | |
124 | + err = -ENOMEM; | |
125 | + goto exit; | |
126 | + } | |
127 | + | |
128 | + /* Register sysfs hooks */ | |
129 | + err = sysfs_create_group(&pdev->dev.kobj, &max17135_group); | |
130 | + if (err) | |
131 | + goto exit_free; | |
132 | + | |
133 | + data->hwmon_dev = hwmon_device_register(&pdev->dev); | |
134 | + if (IS_ERR(data->hwmon_dev)) { | |
135 | + err = PTR_ERR(data->hwmon_dev); | |
136 | + goto exit_remove_files; | |
137 | + } | |
138 | + | |
139 | + platform_set_drvdata(pdev, data); | |
140 | + | |
141 | + return 0; | |
142 | + | |
143 | +exit_remove_files: | |
144 | + sysfs_remove_group(&pdev->dev.kobj, &max17135_group); | |
145 | +exit_free: | |
146 | + kfree(data); | |
147 | +exit: | |
148 | + return err; | |
149 | +} | |
150 | + | |
151 | +static int max17135_sensor_remove(struct platform_device *pdev) | |
152 | +{ | |
153 | + struct max17135_data *data = platform_get_drvdata(pdev); | |
154 | + | |
155 | + hwmon_device_unregister(data->hwmon_dev); | |
156 | + sysfs_remove_group(&pdev->dev.kobj, &max17135_group); | |
157 | + | |
158 | + kfree(data); | |
159 | + return 0; | |
160 | +} | |
161 | + | |
162 | +static int __init sensors_max17135_init(void) | |
163 | +{ | |
164 | + return platform_driver_register(&max17135_sensor_driver); | |
165 | +} | |
166 | +module_init(sensors_max17135_init); | |
167 | + | |
168 | +static void __exit sensors_max17135_exit(void) | |
169 | +{ | |
170 | + platform_driver_unregister(&max17135_sensor_driver); | |
171 | +} | |
172 | +module_exit(sensors_max17135_exit); | |
173 | + | |
174 | +MODULE_DESCRIPTION("MAX17135 sensor driver"); | |
175 | +MODULE_LICENSE("GPL"); |
drivers/mfd/Kconfig
... | ... | @@ -663,6 +663,14 @@ |
663 | 663 | additional drivers must be enabled in order to use the functionality |
664 | 664 | of the device. |
665 | 665 | |
666 | +config MFD_MAX17135 | |
667 | + tristate "Maxim MAX17135 EPD PMIC core" | |
668 | + depends on I2C | |
669 | + | |
670 | + help | |
671 | + This is the MAX17135 PMIC support. It includes | |
672 | + core support for communication with the MAX17135 chip. | |
673 | + | |
666 | 674 | config MFD_MAX77620 |
667 | 675 | bool "Maxim Semiconductor MAX77620 and MAX20024 PMIC Support" |
668 | 676 | depends on I2C=y |
drivers/mfd/Makefile
... | ... | @@ -141,6 +141,7 @@ |
141 | 141 | obj-$(CONFIG_MFD_DA9150) += da9150-core.o |
142 | 142 | |
143 | 143 | obj-$(CONFIG_MFD_MAX14577) += max14577.o |
144 | +obj-$(CONFIG_MFD_MAX17135) += max17135-core.o | |
144 | 145 | obj-$(CONFIG_MFD_MAX77620) += max77620.o |
145 | 146 | obj-$(CONFIG_MFD_MAX77686) += max77686.o |
146 | 147 | obj-$(CONFIG_MFD_MAX77693) += max77693.o |
drivers/mfd/max17135-core.c
1 | +/* | |
2 | + * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. | |
3 | + * | |
4 | + * This program is free software; you can redistribute it and/or modify | |
5 | + * it under the terms of the GNU General Public License as published by | |
6 | + * the Free Software Foundation; either version 2 of the License, or | |
7 | + * (at your option) any later version. | |
8 | + * | |
9 | + * This program is distributed in the hope that it will be useful, | |
10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | + * GNU General Public License for more details. | |
13 | + * | |
14 | + * You should have received a copy of the GNU General Public License | |
15 | + * along with this program; if not, write to the Free Software | |
16 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
17 | + * | |
18 | + */ | |
19 | + | |
20 | +/*! | |
21 | + * @file pmic/core/max17135.c | |
22 | + * @brief This file contains MAX17135 specific PMIC code. This implementaion | |
23 | + * may differ for each PMIC chip. | |
24 | + * | |
25 | + * @ingroup PMIC_CORE | |
26 | + */ | |
27 | + | |
28 | +/* | |
29 | + * Includes | |
30 | + */ | |
31 | +#include <linux/kernel.h> | |
32 | +#include <linux/module.h> | |
33 | +#include <linux/init.h> | |
34 | +#include <linux/slab.h> | |
35 | +#include <linux/device.h> | |
36 | +#include <linux/i2c.h> | |
37 | +#include <linux/delay.h> | |
38 | +#include <linux/err.h> | |
39 | +#include <linux/uaccess.h> | |
40 | +#include <linux/of.h> | |
41 | +#include <linux/of_device.h> | |
42 | +#include <linux/of_gpio.h> | |
43 | +#include <linux/platform_device.h> | |
44 | +#include <linux/regulator/machine.h> | |
45 | +#include <linux/pmic_status.h> | |
46 | +#include <linux/mfd/core.h> | |
47 | +#include <linux/mfd/max17135.h> | |
48 | +#include <asm/mach-types.h> | |
49 | + | |
50 | +static int max17135_detect(struct i2c_client *client, | |
51 | + struct i2c_board_info *info); | |
52 | +struct i2c_client *max17135_client; | |
53 | +static struct regulator *gpio_regulator; | |
54 | + | |
55 | +static struct mfd_cell max17135_devs[] = { | |
56 | + { .name = "max17135-pmic", }, | |
57 | + { .name = "max17135-sns", }, | |
58 | +}; | |
59 | + | |
60 | +static const unsigned short normal_i2c[] = {0x48, I2C_CLIENT_END}; | |
61 | + | |
62 | +int max17135_reg_read(int reg_num, unsigned int *reg_val) | |
63 | +{ | |
64 | + int result; | |
65 | + | |
66 | + if (max17135_client == NULL) | |
67 | + return PMIC_ERROR; | |
68 | + | |
69 | + if ((reg_num == REG_MAX17135_EXT_TEMP) || | |
70 | + (reg_num == REG_MAX17135_INT_TEMP)) { | |
71 | + result = i2c_smbus_read_word_data(max17135_client, reg_num); | |
72 | + if (result < 0) { | |
73 | + dev_err(&max17135_client->dev, | |
74 | + "Unable to read MAX17135 register via I2C\n"); | |
75 | + return PMIC_ERROR; | |
76 | + } | |
77 | + /* Swap bytes for dword read */ | |
78 | + result = (result >> 8) | ((result & 0xFF) << 8); | |
79 | + } else { | |
80 | + result = i2c_smbus_read_byte_data(max17135_client, reg_num); | |
81 | + if (result < 0) { | |
82 | + dev_err(&max17135_client->dev, | |
83 | + "Unable to read MAX17135 register via I2C\n"); | |
84 | + return PMIC_ERROR; | |
85 | + } | |
86 | + } | |
87 | + | |
88 | + *reg_val = result; | |
89 | + return PMIC_SUCCESS; | |
90 | +} | |
91 | + | |
92 | +int max17135_reg_write(int reg_num, const unsigned int reg_val) | |
93 | +{ | |
94 | + int result; | |
95 | + | |
96 | + if (max17135_client == NULL) | |
97 | + return PMIC_ERROR; | |
98 | + | |
99 | + result = i2c_smbus_write_byte_data(max17135_client, reg_num, reg_val); | |
100 | + if (result < 0) { | |
101 | + dev_err(&max17135_client->dev, | |
102 | + "Unable to write MAX17135 register via I2C\n"); | |
103 | + return PMIC_ERROR; | |
104 | + } | |
105 | + | |
106 | + return PMIC_SUCCESS; | |
107 | +} | |
108 | + | |
109 | +#ifdef CONFIG_OF | |
110 | +static struct max17135_platform_data *max17135_i2c_parse_dt_pdata( | |
111 | + struct device *dev) | |
112 | +{ | |
113 | + struct max17135_platform_data *pdata; | |
114 | + | |
115 | + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | |
116 | + if (!pdata) { | |
117 | + dev_err(dev, "could not allocate memory for pdata\n"); | |
118 | + return ERR_PTR(-ENOMEM); | |
119 | + } | |
120 | + | |
121 | + return pdata; | |
122 | +} | |
123 | +#else | |
124 | +static struct max17135_platform_data *max17135_i2c_parse_dt_pdata( | |
125 | + struct device *dev) | |
126 | +{ | |
127 | + return NULL; | |
128 | +} | |
129 | +#endif /* !CONFIG_OF */ | |
130 | + | |
131 | +static int max17135_probe(struct i2c_client *client, | |
132 | + const struct i2c_device_id *id) | |
133 | +{ | |
134 | + struct max17135 *max17135; | |
135 | + struct max17135_platform_data *pdata = client->dev.platform_data; | |
136 | + struct device_node *np = client->dev.of_node; | |
137 | + int ret = 0; | |
138 | + | |
139 | + if (!np) | |
140 | + return -ENODEV; | |
141 | + | |
142 | + gpio_regulator = devm_regulator_get(&client->dev, "SENSOR"); | |
143 | + if (!IS_ERR(gpio_regulator)) { | |
144 | + ret = regulator_enable(gpio_regulator); | |
145 | + if (ret) { | |
146 | + dev_err(&client->dev, "gpio set voltage error\n"); | |
147 | + return ret; | |
148 | + } | |
149 | + } | |
150 | + | |
151 | + /* Create the PMIC data structure */ | |
152 | + max17135 = kzalloc(sizeof(struct max17135), GFP_KERNEL); | |
153 | + if (max17135 == NULL) { | |
154 | + kfree(client); | |
155 | + return -ENOMEM; | |
156 | + } | |
157 | + | |
158 | + /* Initialize the PMIC data structure */ | |
159 | + i2c_set_clientdata(client, max17135); | |
160 | + max17135->dev = &client->dev; | |
161 | + max17135->i2c_client = client; | |
162 | + | |
163 | + max17135_client = client; | |
164 | + ret = max17135_detect(client, NULL); | |
165 | + if (ret) | |
166 | + goto err1; | |
167 | + | |
168 | + mfd_add_devices(max17135->dev, -1, max17135_devs, | |
169 | + ARRAY_SIZE(max17135_devs), | |
170 | + NULL, 0, NULL); | |
171 | + | |
172 | + if (max17135->dev->of_node) { | |
173 | + pdata = max17135_i2c_parse_dt_pdata(max17135->dev); | |
174 | + if (IS_ERR(pdata)) { | |
175 | + ret = PTR_ERR(pdata); | |
176 | + goto err2; | |
177 | + } | |
178 | + | |
179 | + } | |
180 | + max17135->pdata = pdata; | |
181 | + | |
182 | + dev_info(&client->dev, "PMIC MAX17135 for eInk display\n"); | |
183 | + | |
184 | + return ret; | |
185 | +err2: | |
186 | + mfd_remove_devices(max17135->dev); | |
187 | +err1: | |
188 | + kfree(max17135); | |
189 | + | |
190 | + return ret; | |
191 | +} | |
192 | + | |
193 | + | |
194 | +static int max17135_remove(struct i2c_client *i2c) | |
195 | +{ | |
196 | + struct max17135 *max17135 = i2c_get_clientdata(i2c); | |
197 | + | |
198 | + mfd_remove_devices(max17135->dev); | |
199 | + return 0; | |
200 | +} | |
201 | + | |
202 | +/* Return 0 if detection is successful, -ENODEV otherwise */ | |
203 | +static int max17135_detect(struct i2c_client *client, | |
204 | + struct i2c_board_info *info) | |
205 | +{ | |
206 | + struct i2c_adapter *adapter = client->adapter; | |
207 | + u8 chip_rev, chip_id; | |
208 | + | |
209 | + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | |
210 | + return -ENODEV; | |
211 | + | |
212 | + /* detection */ | |
213 | + if (i2c_smbus_read_byte_data(client, | |
214 | + REG_MAX17135_PRODUCT_REV) != 0) { | |
215 | + dev_err(&adapter->dev, | |
216 | + "Max17135 PMIC not found!\n"); | |
217 | + return -ENODEV; | |
218 | + } | |
219 | + | |
220 | + /* identification */ | |
221 | + chip_rev = i2c_smbus_read_byte_data(client, | |
222 | + REG_MAX17135_PRODUCT_REV); | |
223 | + chip_id = i2c_smbus_read_byte_data(client, | |
224 | + REG_MAX17135_PRODUCT_ID); | |
225 | + | |
226 | + if (chip_rev != 0x00 || chip_id != 0x4D) { /* identification failed */ | |
227 | + dev_info(&adapter->dev, | |
228 | + "Unsupported chip (man_id=0x%02X, " | |
229 | + "chip_id=0x%02X).\n", chip_rev, chip_id); | |
230 | + return -ENODEV; | |
231 | + } | |
232 | + | |
233 | + if (info) | |
234 | + strlcpy(info->type, "max17135_sensor", I2C_NAME_SIZE); | |
235 | + | |
236 | + return 0; | |
237 | +} | |
238 | + | |
239 | +static const struct i2c_device_id max17135_id[] = { | |
240 | + { "max17135", 0 }, | |
241 | + { } | |
242 | +}; | |
243 | +MODULE_DEVICE_TABLE(i2c, max17135_id); | |
244 | + | |
245 | +static const struct of_device_id max17135_dt_ids[] = { | |
246 | + { | |
247 | + .compatible = "maxim,max17135", | |
248 | + .data = (void *) &max17135_id[0], | |
249 | + }, { | |
250 | + /* sentinel */ | |
251 | + } | |
252 | +}; | |
253 | +MODULE_DEVICE_TABLE(of, max17135_dt_ids); | |
254 | + | |
255 | + | |
256 | +static struct i2c_driver max17135_driver = { | |
257 | + .driver = { | |
258 | + .name = "max17135", | |
259 | + .owner = THIS_MODULE, | |
260 | + .of_match_table = max17135_dt_ids, | |
261 | + }, | |
262 | + .probe = max17135_probe, | |
263 | + .remove = max17135_remove, | |
264 | + .id_table = max17135_id, | |
265 | + .detect = max17135_detect, | |
266 | + .address_list = &normal_i2c[0], | |
267 | +}; | |
268 | + | |
269 | +static int __init max17135_init(void) | |
270 | +{ | |
271 | + return i2c_add_driver(&max17135_driver); | |
272 | +} | |
273 | + | |
274 | +static void __exit max17135_exit(void) | |
275 | +{ | |
276 | + i2c_del_driver(&max17135_driver); | |
277 | +} | |
278 | + | |
279 | +/* | |
280 | + * Module entry points | |
281 | + */ | |
282 | +subsys_initcall(max17135_init); | |
283 | +module_exit(max17135_exit); |
drivers/regulator/Kconfig
... | ... | @@ -421,6 +421,10 @@ |
421 | 421 | regulator via I2C bus. The provided regulator is suitable |
422 | 422 | for PXA27x chips to control VCC_CORE and VCC_USIM voltages. |
423 | 423 | |
424 | +config REGULATOR_MAX17135 | |
425 | + tristate "Maxim MAX17135 Regulator Support" | |
426 | + depends on MFD_MAX17135 | |
427 | + | |
424 | 428 | config REGULATOR_MAX77620 |
425 | 429 | tristate "Maxim 77620/MAX20024 voltage regulator" |
426 | 430 | depends on MFD_MAX77620 |
drivers/regulator/Makefile
... | ... | @@ -56,6 +56,7 @@ |
56 | 56 | obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o |
57 | 57 | obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o |
58 | 58 | obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o |
59 | +obj-$(CONFIG_REGULATOR_MAX17135) += max17135-regulator.o | |
59 | 60 | obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o |
60 | 61 | obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o |
61 | 62 | obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o |
drivers/regulator/max17135-regulator.c
1 | +/* | |
2 | + * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. All Rights Reserved. | |
3 | + * | |
4 | + * This program is free software; you can redistribute it and/or modify | |
5 | + * it under the terms of the GNU General Public License as published by | |
6 | + * the Free Software Foundation; either version 2 of the License, or | |
7 | + * (at your option) any later version. | |
8 | + | |
9 | + * This program is distributed in the hope that it will be useful, | |
10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | + * GNU General Public License for more details. | |
13 | + | |
14 | + * You should have received a copy of the GNU General Public License along | |
15 | + * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | + */ | |
18 | +#include <linux/kernel.h> | |
19 | +#include <linux/module.h> | |
20 | +#include <linux/init.h> | |
21 | +#include <linux/slab.h> | |
22 | +#include <linux/i2c.h> | |
23 | +#include <linux/mutex.h> | |
24 | +#include <linux/delay.h> | |
25 | +#include <linux/err.h> | |
26 | +#include <linux/platform_device.h> | |
27 | +#include <linux/regulator/machine.h> | |
28 | +#include <linux/regulator/driver.h> | |
29 | +#include <linux/regulator/of_regulator.h> | |
30 | +#include <linux/mfd/max17135.h> | |
31 | +#include <linux/gpio.h> | |
32 | +#include <linux/of_gpio.h> | |
33 | + | |
34 | +/* | |
35 | + * Regulator definitions | |
36 | + * *_MIN_uV - minimum microvolt for regulator | |
37 | + * *_MAX_uV - maximum microvolt for regulator | |
38 | + * *_STEP_uV - microvolts between regulator output levels | |
39 | + * *_MIN_VAL - minimum register field value for regulator | |
40 | + * *_MAX_VAL - maximum register field value for regulator | |
41 | + */ | |
42 | +#define MAX17135_HVINP_MIN_uV 5000000 | |
43 | +#define MAX17135_HVINP_MAX_uV 20000000 | |
44 | +#define MAX17135_HVINP_STEP_uV 1000000 | |
45 | +#define MAX17135_HVINP_MIN_VAL 0 | |
46 | +#define MAX17135_HVINP_MAX_VAL 12 | |
47 | + | |
48 | +#define MAX17135_HVINN_MIN_uV 5000000 | |
49 | +#define MAX17135_HVINN_MAX_uV 20000000 | |
50 | +#define MAX17135_HVINN_STEP_uV 1000000 | |
51 | +#define MAX17135_HVINN_MIN_VAL 0 | |
52 | +#define MAX17135_HVINN_MAX_VAL 1 | |
53 | + | |
54 | +#define MAX17135_GVDD_MIN_uV 5000000 | |
55 | +#define MAX17135_GVDD_MAX_uV 20000000 | |
56 | +#define MAX17135_GVDD_STEP_uV 1000000 | |
57 | +#define MAX17135_GVDD_MIN_VAL 0 | |
58 | +#define MAX17135_GVDD_MAX_VAL 1 | |
59 | + | |
60 | +#define MAX17135_GVEE_MIN_uV 5000000 | |
61 | +#define MAX17135_GVEE_MAX_uV 20000000 | |
62 | +#define MAX17135_GVEE_STEP_uV 1000000 | |
63 | +#define MAX17135_GVEE_MIN_VAL 0 | |
64 | +#define MAX17135_GVEE_MAX_VAL 1 | |
65 | + | |
66 | +#define MAX17135_VCOM_MIN_VAL 0 | |
67 | +#define MAX17135_VCOM_MAX_VAL 255 | |
68 | + | |
69 | +#define MAX17135_VNEG_MIN_uV 5000000 | |
70 | +#define MAX17135_VNEG_MAX_uV 20000000 | |
71 | +#define MAX17135_VNEG_STEP_uV 1000000 | |
72 | +#define MAX17135_VNEG_MIN_VAL 0 | |
73 | +#define MAX17135_VNEG_MAX_VAL 1 | |
74 | + | |
75 | +#define MAX17135_VPOS_MIN_uV 5000000 | |
76 | +#define MAX17135_VPOS_MAX_uV 20000000 | |
77 | +#define MAX17135_VPOS_STEP_uV 1000000 | |
78 | +#define MAX17135_VPOS_MIN_VAL 0 | |
79 | +#define MAX17135_VPOS_MAX_VAL 1 | |
80 | + | |
81 | +struct max17135_vcom_programming_data { | |
82 | + int vcom_min_uV; | |
83 | + int vcom_max_uV; | |
84 | + int vcom_step_uV; | |
85 | +}; | |
86 | + | |
87 | +struct max17135_data { | |
88 | + int num_regulators; | |
89 | + struct max17135 *max17135; | |
90 | + struct regulator_dev **rdev; | |
91 | +}; | |
92 | + | |
93 | +static long unsigned int max17135_pass_num = { 1 }; | |
94 | +static int max17135_vcom = { -1250000 }; | |
95 | + | |
96 | +struct max17135_vcom_programming_data vcom_data[2] = { | |
97 | + { | |
98 | + -4325000, | |
99 | + -500000, | |
100 | + 15000, | |
101 | + }, | |
102 | + { | |
103 | + -3050000, | |
104 | + -500000, | |
105 | + 10000, | |
106 | + }, | |
107 | +}; | |
108 | + | |
109 | +static int max17135_is_power_good(struct max17135 *max17135); | |
110 | + | |
111 | +/* | |
112 | + * Regulator operations | |
113 | + */ | |
114 | +static int max17135_hvinp_set_voltage(struct regulator_dev *reg, | |
115 | + int minuV, int uV, unsigned *selector) | |
116 | +{ | |
117 | + unsigned int reg_val; | |
118 | + unsigned int fld_val; | |
119 | + | |
120 | + if ((uV >= MAX17135_HVINP_MIN_uV) && | |
121 | + (uV <= MAX17135_HVINP_MAX_uV)) | |
122 | + fld_val = (uV - MAX17135_HVINP_MIN_uV) / | |
123 | + MAX17135_HVINP_STEP_uV; | |
124 | + else | |
125 | + return -EINVAL; | |
126 | + | |
127 | + max17135_reg_read(REG_MAX17135_HVINP, ®_val); | |
128 | + | |
129 | + reg_val &= ~BITFMASK(HVINP); | |
130 | + reg_val |= BITFVAL(HVINP, fld_val); /* shift to correct bit */ | |
131 | + | |
132 | + return max17135_reg_write(REG_MAX17135_HVINP, reg_val); | |
133 | +} | |
134 | + | |
135 | +static int max17135_hvinp_get_voltage(struct regulator_dev *reg) | |
136 | +{ | |
137 | + unsigned int reg_val; | |
138 | + unsigned int fld_val; | |
139 | + int volt; | |
140 | + | |
141 | + max17135_reg_read(REG_MAX17135_HVINP, ®_val); | |
142 | + | |
143 | + fld_val = (reg_val & BITFMASK(HVINP)) >> HVINP_LSH; | |
144 | + | |
145 | + if ((fld_val >= MAX17135_HVINP_MIN_VAL) && | |
146 | + (fld_val <= MAX17135_HVINP_MAX_VAL)) { | |
147 | + volt = (fld_val * MAX17135_HVINP_STEP_uV) + | |
148 | + MAX17135_HVINP_MIN_uV; | |
149 | + } else { | |
150 | + printk(KERN_ERR "MAX17135: HVINP voltage is out of range\n"); | |
151 | + volt = 0; | |
152 | + } | |
153 | + return volt; | |
154 | +} | |
155 | + | |
156 | +static int max17135_hvinp_enable(struct regulator_dev *reg) | |
157 | +{ | |
158 | + return 0; | |
159 | +} | |
160 | + | |
161 | +static int max17135_hvinp_disable(struct regulator_dev *reg) | |
162 | +{ | |
163 | + return 0; | |
164 | +} | |
165 | + | |
166 | +/* Convert uV to the VCOM register bitfield setting */ | |
167 | +static inline int vcom_uV_to_rs(int uV, int pass_num) | |
168 | +{ | |
169 | + return (vcom_data[pass_num].vcom_max_uV - uV) | |
170 | + / vcom_data[pass_num].vcom_step_uV; | |
171 | +} | |
172 | + | |
173 | +/* Convert the VCOM register bitfield setting to uV */ | |
174 | +static inline int vcom_rs_to_uV(int rs, int pass_num) | |
175 | +{ | |
176 | + return vcom_data[pass_num].vcom_max_uV | |
177 | + - (vcom_data[pass_num].vcom_step_uV * rs); | |
178 | +} | |
179 | + | |
180 | +static int max17135_vcom_set_voltage(struct regulator_dev *reg, | |
181 | + int minuV, int uV, unsigned *selector) | |
182 | +{ | |
183 | + struct max17135 *max17135 = rdev_get_drvdata(reg); | |
184 | + unsigned int reg_val; | |
185 | + int vcom_read; | |
186 | + | |
187 | + if ((uV < vcom_data[max17135->pass_num-1].vcom_min_uV) | |
188 | + || (uV > vcom_data[max17135->pass_num-1].vcom_max_uV)) | |
189 | + return -EINVAL; | |
190 | + | |
191 | + max17135_reg_read(REG_MAX17135_DVR, ®_val); | |
192 | + | |
193 | + /* | |
194 | + * Only program VCOM if it is not set to the desired value. | |
195 | + * Programming VCOM excessively degrades ability to keep | |
196 | + * DVR register value persistent. | |
197 | + */ | |
198 | + vcom_read = vcom_rs_to_uV(reg_val, max17135->pass_num-1); | |
199 | + if (vcom_read != max17135->vcom_uV) { | |
200 | + reg_val &= ~BITFMASK(DVR); | |
201 | + reg_val |= BITFVAL(DVR, vcom_uV_to_rs(uV, | |
202 | + max17135->pass_num-1)); | |
203 | + max17135_reg_write(REG_MAX17135_DVR, reg_val); | |
204 | + | |
205 | + reg_val = BITFVAL(CTRL_DVR, true); /* shift to correct bit */ | |
206 | + return max17135_reg_write(REG_MAX17135_PRGM_CTRL, reg_val); | |
207 | + } | |
208 | + | |
209 | + return 0; | |
210 | +} | |
211 | + | |
212 | +static int max17135_vcom_get_voltage(struct regulator_dev *reg) | |
213 | +{ | |
214 | + struct max17135 *max17135 = rdev_get_drvdata(reg); | |
215 | + unsigned int reg_val; | |
216 | + | |
217 | + max17135_reg_read(REG_MAX17135_DVR, ®_val); | |
218 | + return vcom_rs_to_uV(BITFEXT(reg_val, DVR), max17135->pass_num-1); | |
219 | +} | |
220 | + | |
221 | +static int max17135_vcom_enable(struct regulator_dev *reg) | |
222 | +{ | |
223 | + struct max17135 *max17135 = rdev_get_drvdata(reg); | |
224 | + | |
225 | + /* | |
226 | + * Check to see if we need to set the VCOM voltage. | |
227 | + * Should only be done one time. And, we can | |
228 | + * only change vcom voltage if we have been enabled. | |
229 | + */ | |
230 | + if (!max17135->vcom_setup && max17135_is_power_good(max17135)) { | |
231 | + max17135_vcom_set_voltage(reg, | |
232 | + max17135->vcom_uV, | |
233 | + max17135->vcom_uV, | |
234 | + NULL); | |
235 | + max17135->vcom_setup = true; | |
236 | + } | |
237 | + | |
238 | + /* enable VCOM regulator output */ | |
239 | + if (max17135->pass_num == 1) | |
240 | + gpio_set_value(max17135->gpio_pmic_vcom_ctrl, 1); | |
241 | + else { | |
242 | + unsigned int reg_val; | |
243 | + | |
244 | + max17135_reg_read(REG_MAX17135_ENABLE, ®_val); | |
245 | + reg_val &= ~BITFMASK(VCOM_ENABLE); | |
246 | + reg_val |= BITFVAL(VCOM_ENABLE, 1); /* shift to correct bit */ | |
247 | + max17135_reg_write(REG_MAX17135_ENABLE, reg_val); | |
248 | + } | |
249 | + | |
250 | + return 0; | |
251 | +} | |
252 | + | |
253 | +static int max17135_vcom_disable(struct regulator_dev *reg) | |
254 | +{ | |
255 | + struct max17135 *max17135 = rdev_get_drvdata(reg); | |
256 | + | |
257 | + if (max17135->pass_num == 1) | |
258 | + gpio_set_value(max17135->gpio_pmic_vcom_ctrl, 0); | |
259 | + else { | |
260 | + unsigned int reg_val; | |
261 | + | |
262 | + max17135_reg_read(REG_MAX17135_ENABLE, ®_val); | |
263 | + reg_val &= ~BITFMASK(VCOM_ENABLE); | |
264 | + max17135_reg_write(REG_MAX17135_ENABLE, reg_val); | |
265 | + } | |
266 | + | |
267 | + return 0; | |
268 | +} | |
269 | + | |
270 | +static int max17135_vcom_is_enabled(struct regulator_dev *reg) | |
271 | +{ | |
272 | + struct max17135 *max17135 = rdev_get_drvdata(reg); | |
273 | + | |
274 | + /* read VCOM regulator enable setting */ | |
275 | + if (max17135->pass_num == 1) { | |
276 | + int gpio = gpio_get_value(max17135->gpio_pmic_vcom_ctrl); | |
277 | + if (gpio == 0) | |
278 | + return 0; | |
279 | + else | |
280 | + return 1; | |
281 | + } else { | |
282 | + unsigned int reg_val; | |
283 | + | |
284 | + max17135_reg_read(REG_MAX17135_ENABLE, ®_val); | |
285 | + reg_val &= BITFMASK(VCOM_ENABLE); | |
286 | + if (reg_val != 0) | |
287 | + return 1; | |
288 | + else | |
289 | + return 0; | |
290 | + } | |
291 | +} | |
292 | + | |
293 | +static int max17135_is_power_good(struct max17135 *max17135) | |
294 | +{ | |
295 | + unsigned int reg_val; | |
296 | + unsigned int fld_val; | |
297 | + | |
298 | + max17135_reg_read(REG_MAX17135_FAULT, ®_val); | |
299 | + fld_val = (reg_val & BITFMASK(FAULT_POK)) >> FAULT_POK_LSH; | |
300 | + | |
301 | + /* Check the POK bit */ | |
302 | + return fld_val; | |
303 | +} | |
304 | + | |
305 | +static int max17135_wait_power_good(struct max17135 *max17135) | |
306 | +{ | |
307 | + int i; | |
308 | + | |
309 | + for (i = 0; i < max17135->max_wait * 3; i++) { | |
310 | + if (max17135_is_power_good(max17135)) | |
311 | + return 0; | |
312 | + | |
313 | + msleep(1); | |
314 | + } | |
315 | + | |
316 | + return -ETIMEDOUT; | |
317 | +} | |
318 | + | |
319 | +static int max17135_display_enable(struct regulator_dev *reg) | |
320 | +{ | |
321 | + struct max17135 *max17135 = rdev_get_drvdata(reg); | |
322 | + | |
323 | + /* The Pass 1 parts cannot turn on the PMIC via I2C. */ | |
324 | + if (max17135->pass_num == 1) | |
325 | + gpio_set_value(max17135->gpio_pmic_wakeup, 1); | |
326 | + else { | |
327 | + unsigned int reg_val; | |
328 | + | |
329 | + max17135_reg_read(REG_MAX17135_ENABLE, ®_val); | |
330 | + reg_val &= ~BITFMASK(ENABLE); | |
331 | + reg_val |= BITFVAL(ENABLE, 1); | |
332 | + max17135_reg_write(REG_MAX17135_ENABLE, reg_val); | |
333 | + } | |
334 | + | |
335 | + return max17135_wait_power_good(max17135); | |
336 | +} | |
337 | + | |
338 | +static int max17135_display_disable(struct regulator_dev *reg) | |
339 | +{ | |
340 | + struct max17135 *max17135 = rdev_get_drvdata(reg); | |
341 | + | |
342 | + if (max17135->pass_num == 1) | |
343 | + gpio_set_value(max17135->gpio_pmic_wakeup, 0); | |
344 | + else { | |
345 | + unsigned int reg_val; | |
346 | + | |
347 | + max17135_reg_read(REG_MAX17135_ENABLE, ®_val); | |
348 | + reg_val &= ~BITFMASK(ENABLE); | |
349 | + max17135_reg_write(REG_MAX17135_ENABLE, reg_val); | |
350 | + } | |
351 | + | |
352 | + msleep(max17135->max_wait); | |
353 | + | |
354 | + return 0; | |
355 | +} | |
356 | + | |
357 | +static int max17135_display_is_enabled(struct regulator_dev *reg) | |
358 | +{ | |
359 | + struct max17135 *max17135 = rdev_get_drvdata(reg); | |
360 | + int gpio = gpio_get_value(max17135->gpio_pmic_wakeup); | |
361 | + | |
362 | + if (gpio == 0) | |
363 | + return 0; | |
364 | + else | |
365 | + return 1; | |
366 | +} | |
367 | + | |
368 | +static int max17135_v3p3_enable(struct regulator_dev *reg) | |
369 | +{ | |
370 | + struct max17135 *max17135 = rdev_get_drvdata(reg); | |
371 | + | |
372 | + gpio_set_value(max17135->gpio_pmic_v3p3, 1); | |
373 | + return 0; | |
374 | +} | |
375 | + | |
376 | +static int max17135_v3p3_disable(struct regulator_dev *reg) | |
377 | +{ | |
378 | + struct max17135 *max17135 = rdev_get_drvdata(reg); | |
379 | + | |
380 | + gpio_set_value(max17135->gpio_pmic_v3p3, 0); | |
381 | + return 0; | |
382 | +} | |
383 | + | |
384 | +static int max17135_v3p3_is_enabled(struct regulator_dev *reg) | |
385 | +{ | |
386 | + struct max17135 *max17135 = rdev_get_drvdata(reg); | |
387 | + int gpio = gpio_get_value(max17135->gpio_pmic_v3p3); | |
388 | + | |
389 | + if (gpio == 0) | |
390 | + return 0; | |
391 | + else | |
392 | + return 1; | |
393 | +} | |
394 | + | |
395 | +/* | |
396 | + * Regulator operations | |
397 | + */ | |
398 | + | |
399 | +static struct regulator_ops max17135_display_ops = { | |
400 | + .enable = max17135_display_enable, | |
401 | + .disable = max17135_display_disable, | |
402 | + .is_enabled = max17135_display_is_enabled, | |
403 | +}; | |
404 | + | |
405 | +static struct regulator_ops max17135_gvdd_ops = { | |
406 | +}; | |
407 | + | |
408 | +static struct regulator_ops max17135_gvee_ops = { | |
409 | +}; | |
410 | + | |
411 | +static struct regulator_ops max17135_hvinn_ops = { | |
412 | +}; | |
413 | + | |
414 | +static struct regulator_ops max17135_hvinp_ops = { | |
415 | + .enable = max17135_hvinp_enable, | |
416 | + .disable = max17135_hvinp_disable, | |
417 | + .get_voltage = max17135_hvinp_get_voltage, | |
418 | + .set_voltage = max17135_hvinp_set_voltage, | |
419 | +}; | |
420 | + | |
421 | +static struct regulator_ops max17135_vcom_ops = { | |
422 | + .enable = max17135_vcom_enable, | |
423 | + .disable = max17135_vcom_disable, | |
424 | + .get_voltage = max17135_vcom_get_voltage, | |
425 | + .set_voltage = max17135_vcom_set_voltage, | |
426 | + .is_enabled = max17135_vcom_is_enabled, | |
427 | +}; | |
428 | + | |
429 | +static struct regulator_ops max17135_vneg_ops = { | |
430 | +}; | |
431 | + | |
432 | +static struct regulator_ops max17135_vpos_ops = { | |
433 | +}; | |
434 | + | |
435 | +static struct regulator_ops max17135_v3p3_ops = { | |
436 | + .enable = max17135_v3p3_enable, | |
437 | + .disable = max17135_v3p3_disable, | |
438 | + .is_enabled = max17135_v3p3_is_enabled, | |
439 | +}; | |
440 | + | |
441 | + | |
442 | +/* | |
443 | + * Regulator descriptors | |
444 | + */ | |
445 | +static struct regulator_desc max17135_reg[MAX17135_NUM_REGULATORS] = { | |
446 | +{ | |
447 | + .name = "DISPLAY", | |
448 | + .id = MAX17135_DISPLAY, | |
449 | + .ops = &max17135_display_ops, | |
450 | + .type = REGULATOR_VOLTAGE, | |
451 | + .owner = THIS_MODULE, | |
452 | +}, | |
453 | +{ | |
454 | + .name = "GVDD", | |
455 | + .id = MAX17135_GVDD, | |
456 | + .ops = &max17135_gvdd_ops, | |
457 | + .type = REGULATOR_VOLTAGE, | |
458 | + .owner = THIS_MODULE, | |
459 | +}, | |
460 | +{ | |
461 | + .name = "GVEE", | |
462 | + .id = MAX17135_GVEE, | |
463 | + .ops = &max17135_gvee_ops, | |
464 | + .type = REGULATOR_VOLTAGE, | |
465 | + .owner = THIS_MODULE, | |
466 | +}, | |
467 | +{ | |
468 | + .name = "HVINN", | |
469 | + .id = MAX17135_HVINN, | |
470 | + .ops = &max17135_hvinn_ops, | |
471 | + .type = REGULATOR_VOLTAGE, | |
472 | + .owner = THIS_MODULE, | |
473 | +}, | |
474 | +{ | |
475 | + .name = "HVINP", | |
476 | + .id = MAX17135_HVINP, | |
477 | + .ops = &max17135_hvinp_ops, | |
478 | + .type = REGULATOR_VOLTAGE, | |
479 | + .owner = THIS_MODULE, | |
480 | +}, | |
481 | +{ | |
482 | + .name = "VCOM", | |
483 | + .id = MAX17135_VCOM, | |
484 | + .ops = &max17135_vcom_ops, | |
485 | + .type = REGULATOR_VOLTAGE, | |
486 | + .owner = THIS_MODULE, | |
487 | +}, | |
488 | +{ | |
489 | + .name = "VNEG", | |
490 | + .id = MAX17135_VNEG, | |
491 | + .ops = &max17135_vneg_ops, | |
492 | + .type = REGULATOR_VOLTAGE, | |
493 | + .owner = THIS_MODULE, | |
494 | +}, | |
495 | +{ | |
496 | + .name = "VPOS", | |
497 | + .id = MAX17135_VPOS, | |
498 | + .ops = &max17135_vpos_ops, | |
499 | + .type = REGULATOR_VOLTAGE, | |
500 | + .owner = THIS_MODULE, | |
501 | +}, | |
502 | +{ | |
503 | + .name = "V3P3", | |
504 | + .id = MAX17135_V3P3, | |
505 | + .ops = &max17135_v3p3_ops, | |
506 | + .type = REGULATOR_VOLTAGE, | |
507 | + .owner = THIS_MODULE, | |
508 | +}, | |
509 | +}; | |
510 | + | |
511 | +static void max17135_setup_timings(struct max17135 *max17135) | |
512 | +{ | |
513 | + unsigned int reg_val; | |
514 | + | |
515 | + int timing1, timing2, timing3, timing4, | |
516 | + timing5, timing6, timing7, timing8; | |
517 | + | |
518 | + max17135_reg_read(REG_MAX17135_TIMING1, &timing1); | |
519 | + max17135_reg_read(REG_MAX17135_TIMING2, &timing2); | |
520 | + max17135_reg_read(REG_MAX17135_TIMING3, &timing3); | |
521 | + max17135_reg_read(REG_MAX17135_TIMING4, &timing4); | |
522 | + max17135_reg_read(REG_MAX17135_TIMING5, &timing5); | |
523 | + max17135_reg_read(REG_MAX17135_TIMING6, &timing6); | |
524 | + max17135_reg_read(REG_MAX17135_TIMING7, &timing7); | |
525 | + max17135_reg_read(REG_MAX17135_TIMING8, &timing8); | |
526 | + | |
527 | + if ((timing1 != max17135->gvee_pwrup) || | |
528 | + (timing2 != max17135->vneg_pwrup) || | |
529 | + (timing3 != max17135->vpos_pwrup) || | |
530 | + (timing4 != max17135->gvdd_pwrup) || | |
531 | + (timing5 != max17135->gvdd_pwrdn) || | |
532 | + (timing6 != max17135->vpos_pwrdn) || | |
533 | + (timing7 != max17135->vneg_pwrdn) || | |
534 | + (timing8 != max17135->gvee_pwrdn)) { | |
535 | + max17135_reg_write(REG_MAX17135_TIMING1, max17135->gvee_pwrup); | |
536 | + max17135_reg_write(REG_MAX17135_TIMING2, max17135->vneg_pwrup); | |
537 | + max17135_reg_write(REG_MAX17135_TIMING3, max17135->vpos_pwrup); | |
538 | + max17135_reg_write(REG_MAX17135_TIMING4, max17135->gvdd_pwrup); | |
539 | + max17135_reg_write(REG_MAX17135_TIMING5, max17135->gvdd_pwrdn); | |
540 | + max17135_reg_write(REG_MAX17135_TIMING6, max17135->vpos_pwrdn); | |
541 | + max17135_reg_write(REG_MAX17135_TIMING7, max17135->vneg_pwrdn); | |
542 | + max17135_reg_write(REG_MAX17135_TIMING8, max17135->gvee_pwrdn); | |
543 | + | |
544 | + reg_val = BITFVAL(CTRL_TIMING, true); /* shift to correct bit */ | |
545 | + max17135_reg_write(REG_MAX17135_PRGM_CTRL, reg_val); | |
546 | + } | |
547 | +} | |
548 | + | |
549 | +#define CHECK_PROPERTY_ERROR_KFREE(prop) \ | |
550 | +do { \ | |
551 | + int ret = of_property_read_u32(max17135->dev->of_node, \ | |
552 | + #prop, &max17135->prop); \ | |
553 | + if (ret < 0) { \ | |
554 | + return ret; \ | |
555 | + } \ | |
556 | +} while (0); | |
557 | + | |
558 | +#ifdef CONFIG_OF | |
559 | +static int max17135_pmic_dt_parse_pdata(struct platform_device *pdev, | |
560 | + struct max17135_platform_data *pdata) | |
561 | +{ | |
562 | + struct max17135 *max17135 = dev_get_drvdata(pdev->dev.parent); | |
563 | + struct device_node *pmic_np, *regulators_np, *reg_np; | |
564 | + struct max17135_regulator_data *rdata; | |
565 | + int i, ret; | |
566 | + | |
567 | + pmic_np = of_node_get(max17135->dev->of_node); | |
568 | + if (!pmic_np) { | |
569 | + dev_err(&pdev->dev, "could not find pmic sub-node\n"); | |
570 | + return -ENODEV; | |
571 | + } | |
572 | + | |
573 | + regulators_np = of_find_node_by_name(pmic_np, "regulators"); | |
574 | + if (!regulators_np) { | |
575 | + dev_err(&pdev->dev, "could not find regulators sub-node\n"); | |
576 | + return -EINVAL; | |
577 | + } | |
578 | + | |
579 | + pdata->num_regulators = of_get_child_count(regulators_np); | |
580 | + dev_dbg(&pdev->dev, "num_regulators %d\n", pdata->num_regulators); | |
581 | + | |
582 | + rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * | |
583 | + pdata->num_regulators, GFP_KERNEL); | |
584 | + if (!rdata) { | |
585 | + of_node_put(regulators_np); | |
586 | + dev_err(&pdev->dev, "could not allocate memory for" | |
587 | + "regulator data\n"); | |
588 | + return -ENOMEM; | |
589 | + } | |
590 | + | |
591 | + pdata->regulators = rdata; | |
592 | + for_each_child_of_node(regulators_np, reg_np) { | |
593 | + for (i = 0; i < ARRAY_SIZE(max17135_reg); i++) | |
594 | + if (!of_node_cmp(reg_np->name, max17135_reg[i].name)) | |
595 | + break; | |
596 | + | |
597 | + if (i == ARRAY_SIZE(max17135_reg)) { | |
598 | + dev_warn(&pdev->dev, "don't know how to configure" | |
599 | + "regulator %s\n", reg_np->name); | |
600 | + continue; | |
601 | + } | |
602 | + | |
603 | + rdata->id = i; | |
604 | + rdata->initdata = of_get_regulator_init_data(&pdev->dev, | |
605 | + reg_np, | |
606 | + &max17135_reg[i]); | |
607 | + rdata->reg_node = reg_np; | |
608 | + rdata++; | |
609 | + } | |
610 | + of_node_put(regulators_np); | |
611 | + | |
612 | + CHECK_PROPERTY_ERROR_KFREE(vneg_pwrup); | |
613 | + CHECK_PROPERTY_ERROR_KFREE(gvee_pwrup); | |
614 | + CHECK_PROPERTY_ERROR_KFREE(vpos_pwrup); | |
615 | + CHECK_PROPERTY_ERROR_KFREE(gvdd_pwrup); | |
616 | + CHECK_PROPERTY_ERROR_KFREE(gvdd_pwrdn); | |
617 | + CHECK_PROPERTY_ERROR_KFREE(vpos_pwrdn); | |
618 | + CHECK_PROPERTY_ERROR_KFREE(gvee_pwrdn); | |
619 | + CHECK_PROPERTY_ERROR_KFREE(vneg_pwrdn); | |
620 | + | |
621 | + dev_dbg(&pdev->dev, "vneg_pwrup %d, vneg_pwrdn %d, vpos_pwrup %d," | |
622 | + "vpos_pwrdn %d, gvdd_pwrup %d, gvdd_pwrdn %d, gvee_pwrup %d," | |
623 | + "gvee_pwrdn %d\n", max17135->vneg_pwrup, max17135->vneg_pwrdn, | |
624 | + max17135->vpos_pwrup, max17135->vpos_pwrdn, | |
625 | + max17135->gvdd_pwrup, max17135->gvdd_pwrdn, | |
626 | + max17135->gvee_pwrup, max17135->gvee_pwrdn); | |
627 | + | |
628 | + max17135->max_wait = max17135->vpos_pwrup + max17135->vneg_pwrup + | |
629 | + max17135->gvdd_pwrup + max17135->gvee_pwrup; | |
630 | + | |
631 | + max17135->gpio_pmic_wakeup = of_get_named_gpio(pmic_np, | |
632 | + "gpio_pmic_wakeup", 0); | |
633 | + if (!gpio_is_valid(max17135->gpio_pmic_wakeup)) { | |
634 | + dev_err(&pdev->dev, "no epdc pmic wakeup pin available\n"); | |
635 | + goto err; | |
636 | + } | |
637 | + ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_wakeup, | |
638 | + GPIOF_OUT_INIT_LOW, "epdc-pmic-wake"); | |
639 | + if (ret < 0) | |
640 | + goto err; | |
641 | + | |
642 | + max17135->gpio_pmic_vcom_ctrl = of_get_named_gpio(pmic_np, | |
643 | + "gpio_pmic_vcom_ctrl", 0); | |
644 | + if (!gpio_is_valid(max17135->gpio_pmic_vcom_ctrl)) { | |
645 | + dev_err(&pdev->dev, "no epdc pmic vcom_ctrl pin available\n"); | |
646 | + goto err; | |
647 | + } | |
648 | + ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_vcom_ctrl, | |
649 | + GPIOF_OUT_INIT_LOW, "epdc-vcom"); | |
650 | + if (ret < 0) | |
651 | + goto err; | |
652 | + | |
653 | + max17135->gpio_pmic_v3p3 = of_get_named_gpio(pmic_np, | |
654 | + "gpio_pmic_v3p3", 0); | |
655 | + if (!gpio_is_valid(max17135->gpio_pmic_v3p3)) { | |
656 | + dev_err(&pdev->dev, "no epdc pmic v3p3 pin available\n"); | |
657 | + goto err; | |
658 | + } | |
659 | + ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_v3p3, | |
660 | + GPIOF_OUT_INIT_LOW, "epdc-v3p3"); | |
661 | + if (ret < 0) | |
662 | + goto err; | |
663 | + | |
664 | + max17135->gpio_pmic_intr = of_get_named_gpio(pmic_np, | |
665 | + "gpio_pmic_intr", 0); | |
666 | + if (!gpio_is_valid(max17135->gpio_pmic_intr)) { | |
667 | + dev_err(&pdev->dev, "no epdc pmic intr pin available\n"); | |
668 | + goto err; | |
669 | + } | |
670 | + ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_intr, | |
671 | + GPIOF_IN, "epdc-pmic-int"); | |
672 | + if (ret < 0) | |
673 | + goto err; | |
674 | + | |
675 | + max17135->gpio_pmic_pwrgood = of_get_named_gpio(pmic_np, | |
676 | + "gpio_pmic_pwrgood", 0); | |
677 | + if (!gpio_is_valid(max17135->gpio_pmic_pwrgood)) { | |
678 | + dev_err(&pdev->dev, "no epdc pmic pwrgood pin available\n"); | |
679 | + goto err; | |
680 | + } | |
681 | + ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_pwrgood, | |
682 | + GPIOF_IN, "epdc-pwrstat"); | |
683 | + if (ret < 0) | |
684 | + goto err; | |
685 | + | |
686 | +err: | |
687 | + return 0; | |
688 | + | |
689 | +} | |
690 | +#else | |
691 | +static int max17135_pmic_dt_parse_pdata(struct platform_device *pdev, | |
692 | + struct max17135 *max17135) | |
693 | +{ | |
694 | + return 0; | |
695 | +} | |
696 | +#endif /* !CONFIG_OF */ | |
697 | + | |
698 | +/* | |
699 | + * Regulator init/probing/exit functions | |
700 | + */ | |
701 | +static int max17135_regulator_probe(struct platform_device *pdev) | |
702 | +{ | |
703 | + struct max17135 *max17135 = dev_get_drvdata(pdev->dev.parent); | |
704 | + struct max17135_platform_data *pdata = max17135->pdata; | |
705 | + struct max17135_data *priv; | |
706 | + struct regulator_dev **rdev; | |
707 | + struct regulator_config config = { }; | |
708 | + int size, i, ret = 0; | |
709 | + | |
710 | + if (max17135->dev->of_node) { | |
711 | + ret = max17135_pmic_dt_parse_pdata(pdev, pdata); | |
712 | + if (ret) | |
713 | + return ret; | |
714 | + } | |
715 | + priv = devm_kzalloc(&pdev->dev, sizeof(struct max17135_data), | |
716 | + GFP_KERNEL); | |
717 | + if (!priv) | |
718 | + return -ENOMEM; | |
719 | + | |
720 | + size = sizeof(struct regulator_dev *) * pdata->num_regulators; | |
721 | + priv->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); | |
722 | + if (!priv->rdev) | |
723 | + return -ENOMEM; | |
724 | + | |
725 | + rdev = priv->rdev; | |
726 | + priv->num_regulators = pdata->num_regulators; | |
727 | + platform_set_drvdata(pdev, priv); | |
728 | + | |
729 | + max17135->vcom_setup = false; | |
730 | + max17135->pass_num = max17135_pass_num; | |
731 | + max17135->vcom_uV = max17135_vcom; | |
732 | + | |
733 | + for (i = 0; i < pdata->num_regulators; i++) { | |
734 | + int id = pdata->regulators[i].id; | |
735 | + | |
736 | + config.dev = max17135->dev; | |
737 | + config.init_data = pdata->regulators[i].initdata; | |
738 | + config.driver_data = max17135; | |
739 | + config.of_node = pdata->regulators[i].reg_node; | |
740 | + | |
741 | + rdev[i] = regulator_register(&max17135_reg[id], &config); | |
742 | + if (IS_ERR(rdev[i])) { | |
743 | + ret = PTR_ERR(rdev[i]); | |
744 | + dev_err(&pdev->dev, "regulator init failed for %d\n", | |
745 | + id); | |
746 | + rdev[i] = NULL; | |
747 | + goto err; | |
748 | + } | |
749 | + } | |
750 | + | |
751 | + /* | |
752 | + * Set up PMIC timing values. | |
753 | + * Should only be done one time! Timing values may only be | |
754 | + * changed a limited number of times according to spec. | |
755 | + */ | |
756 | + max17135_setup_timings(max17135); | |
757 | + | |
758 | + return 0; | |
759 | +err: | |
760 | + while (--i >= 0) | |
761 | + regulator_unregister(rdev[i]); | |
762 | + return ret; | |
763 | +} | |
764 | + | |
765 | +static int max17135_regulator_remove(struct platform_device *pdev) | |
766 | +{ | |
767 | + struct max17135_data *priv = platform_get_drvdata(pdev); | |
768 | + struct regulator_dev **rdev = priv->rdev; | |
769 | + int i; | |
770 | + | |
771 | + for (i = 0; i < priv->num_regulators; i++) | |
772 | + regulator_unregister(rdev[i]); | |
773 | + return 0; | |
774 | +} | |
775 | + | |
776 | +static const struct platform_device_id max17135_pmic_id[] = { | |
777 | + { "max17135-pmic", 0}, | |
778 | + { /* sentinel */ }, | |
779 | +}; | |
780 | +MODULE_DEVICE_TABLE(platform, max17135_pmic_id); | |
781 | + | |
782 | +static struct platform_driver max17135_regulator_driver = { | |
783 | + .probe = max17135_regulator_probe, | |
784 | + .remove = max17135_regulator_remove, | |
785 | + .id_table = max17135_pmic_id, | |
786 | + .driver = { | |
787 | + .name = "max17135-pmic", | |
788 | + }, | |
789 | +}; | |
790 | + | |
791 | +static int __init max17135_regulator_init(void) | |
792 | +{ | |
793 | + return platform_driver_register(&max17135_regulator_driver); | |
794 | +} | |
795 | +subsys_initcall_sync(max17135_regulator_init); | |
796 | + | |
797 | +static void __exit max17135_regulator_exit(void) | |
798 | +{ | |
799 | + platform_driver_unregister(&max17135_regulator_driver); | |
800 | +} | |
801 | +module_exit(max17135_regulator_exit); | |
802 | + | |
803 | +/* | |
804 | + * Parse user specified options (`max17135:') | |
805 | + * example: | |
806 | + * max17135:pass=2,vcom=-1250000 | |
807 | + */ | |
808 | +static int __init max17135_setup(char *options) | |
809 | +{ | |
810 | + int ret; | |
811 | + char *opt; | |
812 | + while ((opt = strsep(&options, ",")) != NULL) { | |
813 | + if (!*opt) | |
814 | + continue; | |
815 | + if (!strncmp(opt, "pass=", 5)) { | |
816 | + ret = kstrtoul(opt + 5, 0, &max17135_pass_num); | |
817 | + if (ret < 0) | |
818 | + return ret; | |
819 | + } | |
820 | + if (!strncmp(opt, "vcom=", 5)) { | |
821 | + int offs = 5; | |
822 | + if (opt[5] == '-') | |
823 | + offs = 6; | |
824 | + ret = kstrtoul(opt + offs, 0, | |
825 | + (long *)&max17135_vcom); | |
826 | + if (ret < 0) | |
827 | + return ret; | |
828 | + max17135_vcom = -max17135_vcom; | |
829 | + } | |
830 | + } | |
831 | + | |
832 | + return 1; | |
833 | +} | |
834 | + | |
835 | +__setup("max17135:", max17135_setup); | |
836 | + | |
837 | +/* Module information */ | |
838 | +MODULE_DESCRIPTION("MAX17135 regulator driver"); | |
839 | +MODULE_LICENSE("GPL"); |
include/linux/mfd/max17135.h
1 | +/* | |
2 | + * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. All Rights Reserved. | |
3 | + * | |
4 | + * This program is free software; you can redistribute it and/or modify | |
5 | + * it under the terms of the GNU General Public License as published by | |
6 | + * the Free Software Foundation; either version 2 of the License, or | |
7 | + * (at your option) any later version. | |
8 | + * | |
9 | + * This program is distributed in the hope that it will be useful, | |
10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | + * GNU General Public License for more details. | |
13 | + * | |
14 | + * You should have received a copy of the GNU General Public License | |
15 | + * along with this program; if not, write to the Free Software | |
16 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
17 | + * | |
18 | + */ | |
19 | +#ifndef __LINUX_REGULATOR_MAX17135_H_ | |
20 | +#define __LINUX_REGULATOR_MAX17135_H_ | |
21 | + | |
22 | +/* | |
23 | + * PMIC Register Addresses | |
24 | + */ | |
25 | +enum { | |
26 | + REG_MAX17135_EXT_TEMP = 0x0, | |
27 | + REG_MAX17135_CONFIG, | |
28 | + REG_MAX17135_INT_TEMP = 0x4, | |
29 | + REG_MAX17135_STATUS, | |
30 | + REG_MAX17135_PRODUCT_REV, | |
31 | + REG_MAX17135_PRODUCT_ID, | |
32 | + REG_MAX17135_DVR, | |
33 | + REG_MAX17135_ENABLE, | |
34 | + REG_MAX17135_FAULT, /*0x0A*/ | |
35 | + REG_MAX17135_HVINP, | |
36 | + REG_MAX17135_PRGM_CTRL, | |
37 | + REG_MAX17135_TIMING1 = 0x10, /* Timing regs base address is 0x10 */ | |
38 | + REG_MAX17135_TIMING2, | |
39 | + REG_MAX17135_TIMING3, | |
40 | + REG_MAX17135_TIMING4, | |
41 | + REG_MAX17135_TIMING5, | |
42 | + REG_MAX17135_TIMING6, | |
43 | + REG_MAX17135_TIMING7, | |
44 | + REG_MAX17135_TIMING8, | |
45 | +}; | |
46 | +#define MAX17135_REG_NUM 21 | |
47 | +#define MAX17135_MAX_REGISTER 0xFF | |
48 | + | |
49 | +/* | |
50 | + * Bitfield macros that use rely on bitfield width/shift information. | |
51 | + */ | |
52 | +#define BITFMASK(field) (((1U << (field ## _WID)) - 1) << (field ## _LSH)) | |
53 | +#define BITFVAL(field, val) ((val) << (field ## _LSH)) | |
54 | +#define BITFEXT(var, bit) ((var & BITFMASK(bit)) >> (bit ## _LSH)) | |
55 | + | |
56 | +/* | |
57 | + * Shift and width values for each register bitfield | |
58 | + */ | |
59 | +#define EXT_TEMP_LSH 7 | |
60 | +#define EXT_TEMP_WID 9 | |
61 | + | |
62 | +#define THERMAL_SHUTDOWN_LSH 0 | |
63 | +#define THERMAL_SHUTDOWN_WID 1 | |
64 | + | |
65 | +#define INT_TEMP_LSH 7 | |
66 | +#define INT_TEMP_WID 9 | |
67 | + | |
68 | +#define STAT_BUSY_LSH 0 | |
69 | +#define STAT_BUSY_WID 1 | |
70 | +#define STAT_OPEN_LSH 1 | |
71 | +#define STAT_OPEN_WID 1 | |
72 | +#define STAT_SHRT_LSH 2 | |
73 | +#define STAT_SHRT_WID 1 | |
74 | + | |
75 | +#define PROD_REV_LSH 0 | |
76 | +#define PROD_REV_WID 8 | |
77 | + | |
78 | +#define PROD_ID_LSH 0 | |
79 | +#define PROD_ID_WID 8 | |
80 | + | |
81 | +#define DVR_LSH 0 | |
82 | +#define DVR_WID 8 | |
83 | + | |
84 | +#define ENABLE_LSH 0 | |
85 | +#define ENABLE_WID 1 | |
86 | +#define VCOM_ENABLE_LSH 1 | |
87 | +#define VCOM_ENABLE_WID 1 | |
88 | + | |
89 | +#define FAULT_FBPG_LSH 0 | |
90 | +#define FAULT_FBPG_WID 1 | |
91 | +#define FAULT_HVINP_LSH 1 | |
92 | +#define FAULT_HVINP_WID 1 | |
93 | +#define FAULT_HVINN_LSH 2 | |
94 | +#define FAULT_HVINN_WID 1 | |
95 | +#define FAULT_FBNG_LSH 3 | |
96 | +#define FAULT_FBNG_WID 1 | |
97 | +#define FAULT_HVINPSC_LSH 4 | |
98 | +#define FAULT_HVINPSC_WID 1 | |
99 | +#define FAULT_HVINNSC_LSH 5 | |
100 | +#define FAULT_HVINNSC_WID 1 | |
101 | +#define FAULT_OT_LSH 6 | |
102 | +#define FAULT_OT_WID 1 | |
103 | +#define FAULT_POK_LSH 7 | |
104 | +#define FAULT_POK_WID 1 | |
105 | + | |
106 | +#define HVINP_LSH 0 | |
107 | +#define HVINP_WID 4 | |
108 | + | |
109 | +#define CTRL_DVR_LSH 0 | |
110 | +#define CTRL_DVR_WID 1 | |
111 | +#define CTRL_TIMING_LSH 1 | |
112 | +#define CTRL_TIMING_WID 1 | |
113 | + | |
114 | +#define TIMING1_LSH 0 | |
115 | +#define TIMING1_WID 8 | |
116 | +#define TIMING2_LSH 0 | |
117 | +#define TIMING2_WID 8 | |
118 | +#define TIMING3_LSH 0 | |
119 | +#define TIMING3_WID 8 | |
120 | +#define TIMING4_LSH 0 | |
121 | +#define TIMING4_WID 8 | |
122 | +#define TIMING5_LSH 0 | |
123 | +#define TIMING5_WID 8 | |
124 | +#define TIMING6_LSH 0 | |
125 | +#define TIMING6_WID 8 | |
126 | +#define TIMING7_LSH 0 | |
127 | +#define TIMING7_WID 8 | |
128 | +#define TIMING8_LSH 0 | |
129 | +#define TIMING8_WID 8 | |
130 | + | |
131 | +struct max17135 { | |
132 | + /* chip revision */ | |
133 | + int rev; | |
134 | + | |
135 | + struct device *dev; | |
136 | + struct max17135_platform_data *pdata; | |
137 | + | |
138 | + /* Platform connection */ | |
139 | + struct i2c_client *i2c_client; | |
140 | + | |
141 | + /* Timings */ | |
142 | + unsigned int gvee_pwrup; | |
143 | + unsigned int vneg_pwrup; | |
144 | + unsigned int vpos_pwrup; | |
145 | + unsigned int gvdd_pwrup; | |
146 | + unsigned int gvdd_pwrdn; | |
147 | + unsigned int vpos_pwrdn; | |
148 | + unsigned int vneg_pwrdn; | |
149 | + unsigned int gvee_pwrdn; | |
150 | + | |
151 | + /* GPIOs */ | |
152 | + int gpio_pmic_pwrgood; | |
153 | + int gpio_pmic_vcom_ctrl; | |
154 | + int gpio_pmic_wakeup; | |
155 | + int gpio_pmic_v3p3; | |
156 | + int gpio_pmic_intr; | |
157 | + | |
158 | + /* MAX17135 part variables */ | |
159 | + int pass_num; | |
160 | + int vcom_uV; | |
161 | + | |
162 | + /* One-time VCOM setup marker */ | |
163 | + bool vcom_setup; | |
164 | + | |
165 | + /* powerup/powerdown wait time */ | |
166 | + int max_wait; | |
167 | +}; | |
168 | + | |
169 | +enum { | |
170 | + /* In alphabetical order */ | |
171 | + MAX17135_DISPLAY, /* virtual master enable */ | |
172 | + MAX17135_GVDD, | |
173 | + MAX17135_GVEE, | |
174 | + MAX17135_HVINN, | |
175 | + MAX17135_HVINP, | |
176 | + MAX17135_VCOM, | |
177 | + MAX17135_VNEG, | |
178 | + MAX17135_VPOS, | |
179 | + MAX17135_V3P3, | |
180 | + MAX17135_NUM_REGULATORS, | |
181 | +}; | |
182 | + | |
183 | +/* | |
184 | + * Declarations | |
185 | + */ | |
186 | +struct regulator_init_data; | |
187 | +struct max17135_regulator_data; | |
188 | + | |
189 | +struct max17135_platform_data { | |
190 | + unsigned int gvee_pwrup; | |
191 | + unsigned int vneg_pwrup; | |
192 | + unsigned int vpos_pwrup; | |
193 | + unsigned int gvdd_pwrup; | |
194 | + unsigned int gvdd_pwrdn; | |
195 | + unsigned int vpos_pwrdn; | |
196 | + unsigned int vneg_pwrdn; | |
197 | + unsigned int gvee_pwrdn; | |
198 | + int gpio_pmic_pwrgood; | |
199 | + int gpio_pmic_vcom_ctrl; | |
200 | + int gpio_pmic_wakeup; | |
201 | + int gpio_pmic_v3p3; | |
202 | + int gpio_pmic_intr; | |
203 | + int pass_num; | |
204 | + int vcom_uV; | |
205 | + | |
206 | + /* PMIC */ | |
207 | + struct max17135_regulator_data *regulators; | |
208 | + int num_regulators; | |
209 | +}; | |
210 | + | |
211 | +struct max17135_regulator_data { | |
212 | + int id; | |
213 | + struct regulator_init_data *initdata; | |
214 | + struct device_node *reg_node; | |
215 | +}; | |
216 | + | |
217 | +int max17135_reg_read(int reg_num, unsigned int *reg_val); | |
218 | +int max17135_reg_write(int reg_num, const unsigned int reg_val); | |
219 | + | |
220 | +#endif |
include/linux/pmic_status.h
1 | +/* | |
2 | + * Copyright 2004-2015 Freescale Semiconductor, Inc. All Rights Reserved. | |
3 | + */ | |
4 | + | |
5 | +/* | |
6 | + * The code contained herein is licensed under the GNU Lesser General | |
7 | + * Public License. You may obtain a copy of the GNU Lesser General | |
8 | + * Public License Version 2.1 or later at the following locations: | |
9 | + * | |
10 | + * http://www.opensource.org/licenses/lgpl-license.html | |
11 | + * http://www.gnu.org/copyleft/lgpl.html | |
12 | + */ | |
13 | +#ifndef __ASM_ARCH_MXC_PMIC_STATUS_H__ | |
14 | +#define __ASM_ARCH_MXC_PMIC_STATUS_H__ | |
15 | +#include <asm-generic/errno-base.h> | |
16 | +#ifdef __KERNEL__ | |
17 | +#include <asm/uaccess.h> /* copy_{from,to}_user() */ | |
18 | +#endif | |
19 | +/*! | |
20 | + * @file arch-mxc/pmic_status.h | |
21 | + * @brief PMIC APIs return code definition. | |
22 | + * | |
23 | + * @ingroup PMIC_CORE | |
24 | + */ | |
25 | + | |
26 | +/*! | |
27 | + * @enum PMIC_STATUS | |
28 | + * @brief Define return values for all PMIC APIs. | |
29 | + * | |
30 | + * These return values are used by all of the PMIC APIs. | |
31 | + * | |
32 | + * @ingroup PMIC | |
33 | + */ | |
34 | +typedef enum { | |
35 | + PMIC_SUCCESS = 0, /*!< The requested operation was successfully | |
36 | + completed. */ | |
37 | + PMIC_ERROR = -1, /*!< The requested operation could not be completed | |
38 | + due to an error. */ | |
39 | + PMIC_PARAMETER_ERROR = -2, /*!< The requested operation failed because | |
40 | + one or more of the parameters was | |
41 | + invalid. */ | |
42 | + PMIC_NOT_SUPPORTED = -3, /*!< The requested operation could not be | |
43 | + completed because the PMIC hardware | |
44 | + does not support it. */ | |
45 | + PMIC_SYSTEM_ERROR_EINTR = -EINTR, | |
46 | + | |
47 | + PMIC_MALLOC_ERROR = -5, /*!< Error in malloc function */ | |
48 | + PMIC_UNSUBSCRIBE_ERROR = -6, /*!< Error in un-subscribe event */ | |
49 | + PMIC_EVENT_NOT_SUBSCRIBED = -7, /*!< Event occur and not subscribed */ | |
50 | + PMIC_EVENT_CALL_BACK = -8, /*!< Error - bad call back */ | |
51 | + PMIC_CLIENT_NBOVERFLOW = -9, /*!< The requested operation could not be | |
52 | + completed because there are too many | |
53 | + PMIC client requests */ | |
54 | +} PMIC_STATUS; | |
55 | + | |
56 | +/* | |
57 | + * Bitfield macros that use rely on bitfield width/shift information. | |
58 | + */ | |
59 | +#define BITFMASK(field) (((1U << (field ## _WID)) - 1) << (field ## _LSH)) | |
60 | +#define BITFVAL(field, val) ((val) << (field ## _LSH)) | |
61 | +#define BITFEXT(var, bit) ((var & BITFMASK(bit)) >> (bit ## _LSH)) | |
62 | + | |
63 | +/* | |
64 | + * Macros implementing error handling | |
65 | + */ | |
66 | +#define CHECK_ERROR(a) \ | |
67 | +do { \ | |
68 | + int ret = (a); \ | |
69 | + if (ret != PMIC_SUCCESS) \ | |
70 | + return ret; \ | |
71 | +} while (0) | |
72 | + | |
73 | +#define CHECK_ERROR_KFREE(func, freeptrs) \ | |
74 | +do { \ | |
75 | + int ret = (func); \ | |
76 | + if (ret != PMIC_SUCCESS) { \ | |
77 | + freeptrs; \ | |
78 | + return ret; \ | |
79 | + } \ | |
80 | +} while (0); | |
81 | + | |
82 | +#endif /* __ASM_ARCH_MXC_PMIC_STATUS_H__ */ |