blob: 3d7b1726faf951c3558d554228c33b3e9d06cfcc [file] [log] [blame]
Rajesh Bharathwajd98f4be2020-01-27 15:54:03 -08001// SPDX-License-Identifier: GPL-2.0-only
2
3/*
Rajesh Bharathwaje07f3002021-04-27 11:54:03 -07004 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
Rajesh Bharathwajd98f4be2020-01-27 15:54:03 -08005 */
6
7#include <linux/device.h>
8#include <linux/i2c.h>
9#include <linux/slab.h>
10#include <linux/platform_device.h>
11#include <linux/input.h>
12#include <linux/types.h>
13#include <linux/module.h>
14#include <linux/fs.h>
15#include <linux/of.h>
16#include <linux/of_graph.h>
17#include <linux/kernel.h>
18#include <linux/of_gpio.h>
19#include <linux/gpio.h>
20#include <linux/delay.h>
21#include <linux/regulator/consumer.h>
22#include <linux/rwlock.h>
23#include <linux/uaccess.h>
24#include <linux/regmap.h>
25
26struct max31760 {
27 struct device *dev;
28 u8 i2c_addr;
29 struct regmap *regmap;
30 u32 fan_pwr_en;
31 u32 fan_pwr_bp;
32 struct i2c_client *i2c_client;
33 int pwm;
34 bool fan_off;
35};
36
37static void turn_gpio(struct max31760 *pdata, bool on)
38{
39 if (on) {
40 gpio_direction_output(pdata->fan_pwr_en, 0);
41 gpio_set_value(pdata->fan_pwr_en, 1);
42 pr_debug("%s gpio:%d set to high\n", __func__,
43 pdata->fan_pwr_en);
44 msleep(20);
45 gpio_direction_output(pdata->fan_pwr_bp, 0);
46 gpio_set_value(pdata->fan_pwr_bp, 1);
47 pr_debug("%s gpio:%d set to high\n", __func__,
48 pdata->fan_pwr_bp);
49 msleep(20);
50 } else {
51 gpio_direction_output(pdata->fan_pwr_en, 1);
52 gpio_set_value(pdata->fan_pwr_en, 0);
53 pr_debug("%s gpio:%d set to low\n", __func__,
54 pdata->fan_pwr_en);
55 msleep(20);
56 gpio_direction_output(pdata->fan_pwr_bp, 1);
57 gpio_set_value(pdata->fan_pwr_bp, 0);
58 pr_debug("%s gpio:%d set to low\n", __func__,
59 pdata->fan_pwr_bp);
60 msleep(20);
61 }
62}
63
64static int max31760_i2c_reg_get(struct max31760 *pdata,
65 u8 reg)
66{
67 int ret;
68 u32 val1;
69
70 pr_debug("%s, reg:%x\n", __func__, reg);
71 ret = regmap_read(pdata->regmap, (unsigned int)reg, &val1);
72 if (ret < 0) {
73 pr_err("%s failed reading reg 0x%02x failure\n", __func__, reg);
74 return ret;
75 }
76
77 pr_debug("%s success reading reg 0x%x=0x%x, val1=%x\n",
78 __func__, reg, val1, val1);
79
80 return 0;
81}
82
83static int max31760_i2c_reg_set(struct max31760 *pdata,
84 u8 reg, u8 val)
85{
86 int ret;
87 int i;
88
89 for (i = 0; i < 10; i++) {
90 ret = regmap_write(pdata->regmap, reg, val);
91 if (ret >= 0)
92 return ret;
93 msleep(20);
94 }
95 if (ret < 0)
96 pr_err("%s loop:%d failed to write reg 0x%02x=0x%02x\n",
97 __func__, i, reg, val);
98 return ret;
99}
100
101static ssize_t fan_show(struct device *dev, struct device_attribute *attr,
102 char *buf)
103{
104 struct max31760 *pdata;
105 int ret;
106
107 pdata = dev_get_drvdata(dev);
108 if (!pdata) {
109 pr_err("invalid driver pointer\n");
110 return -ENODEV;
111 }
112
113 if (pdata->fan_off)
114 ret = scnprintf(buf, PAGE_SIZE, "off\n");
115 else
116 ret = scnprintf(buf, PAGE_SIZE, "0x%x\n", pdata->pwm);
117
118 return ret;
119}
120
121static ssize_t fan_store(struct device *dev, struct device_attribute *attr,
122 const char *buf, size_t count)
123{
Rajesh Bharathwaje07f3002021-04-27 11:54:03 -0700124 long val, val1;
Rajesh Bharathwajd98f4be2020-01-27 15:54:03 -0800125 struct max31760 *pdata;
126
127 pdata = dev_get_drvdata(dev);
128 if (!pdata) {
129 pr_err("invalid driver pointer\n");
130 return -ENODEV;
131 }
132
133 kstrtol(buf, 0, &val);
Rajesh Bharathwaje07f3002021-04-27 11:54:03 -0700134 val1 = val >> 8;
135 pr_debug("%s, count:%d val:%lx, val1:%lx, buf:%s\n",
136 __func__, count, val, val1, buf);
137 if (val1 == 0x50) {
138 val1 = val & 0xFF;
139 pr_debug("%s, reg value val1:%lx\n", __func__, val1);
140 max31760_i2c_reg_set(pdata, 0x50, val1);
141 return count;
142 }
Rajesh Bharathwajd98f4be2020-01-27 15:54:03 -0800143
144 if (val == 0xff) {
145 turn_gpio(pdata, false);
146 pdata->fan_off = true;
147 } else if (val == 0xfe) {
148 pdata->fan_off = false;
149 turn_gpio(pdata, true);
150 max31760_i2c_reg_set(pdata, 0x00, pdata->pwm);
151 } else {
152 max31760_i2c_reg_set(pdata, 0x00, (int)val);
153 pdata->pwm = (int)val;
154 }
155
156 return count;
157}
158
159static DEVICE_ATTR_RW(fan);
160
161static struct attribute *max31760_fs_attrs[] = {
162 &dev_attr_fan.attr,
163 NULL
164};
165
166static struct attribute_group max31760_fs_attr_group = {
167 .attrs = max31760_fs_attrs,
168};
169
170static int max31760_parse_dt(struct device *dev,
171 struct max31760 *pdata)
172{
173 struct device_node *np = dev->of_node;
174 int ret;
175
176 pdata->fan_pwr_en =
177 of_get_named_gpio(np, "qcom,fan-pwr-en", 0);
178 if (!gpio_is_valid(pdata->fan_pwr_en)) {
179 pr_err("%s fan_pwr_en gpio not specified\n", __func__);
180 ret = -EINVAL;
181 } else {
182 ret = gpio_request(pdata->fan_pwr_en, "fan_pwr_en");
183 if (ret) {
184 pr_err("max31760 fan_pwr_en gpio request failed\n");
185 goto error1;
186 }
187 }
188
189 pdata->fan_pwr_bp =
190 of_get_named_gpio(np, "qcom,fan-pwr-bp", 0);
191 if (!gpio_is_valid(pdata->fan_pwr_bp)) {
192 pr_err("%s fan_pwr_bp gpio not specified\n", __func__);
193 ret = -EINVAL;
194 } else
195 ret = gpio_request(pdata->fan_pwr_bp, "fan_pwr_bp");
196 if (ret) {
197 pr_err("max31760 fan_pwr_bp gpio request failed\n");
198 goto error2;
199 }
200 turn_gpio(pdata, true);
201
202 return ret;
203
204error2:
205 gpio_free(pdata->fan_pwr_bp);
206error1:
207 gpio_free(pdata->fan_pwr_en);
208 return ret;
209}
210
211static int max31760_fan_pwr_enable_vregs(struct device *dev,
212 struct max31760 *pdata)
213{
214 int ret;
215 struct regulator *reg;
216
217 /* Fan Control LDO L10A */
218 reg = devm_regulator_get(dev, "pm8150_l10");
219 if (!IS_ERR(reg)) {
220 regulator_set_load(reg, 600000);
221 ret = regulator_enable(reg);
222 if (ret < 0) {
223 pr_err("%s pm8150_l10 failed\n", __func__);
224 return -EINVAL;
225 }
226 }
227
228 /* Fan Control LDO S4 */
229 reg = devm_regulator_get(dev, "pm8150_s4");
230 if (!IS_ERR(reg)) {
231 regulator_set_load(reg, 600000);
232 ret = regulator_enable(reg);
233 if (ret < 0) {
234 pr_err("%s pm8150_s4 failed\n", __func__);
235 return -EINVAL;
236 }
237 }
238
239 return ret;
240}
241
242static const struct regmap_config max31760_regmap = {
243 .reg_bits = 8,
244 .val_bits = 8,
245 .max_register = 0xFF,
246};
247
248static int max31760_probe(struct i2c_client *client,
249 const struct i2c_device_id *id)
250{
251 int ret;
252 struct max31760 *pdata;
253
254 if (!client || !client->dev.of_node) {
255 pr_err("%s invalid input\n", __func__);
256 return -EINVAL;
257 }
258
259 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
260 pr_err("%s device doesn't support I2C\n", __func__);
261 return -ENODEV;
262 }
263
264 pdata = devm_kzalloc(&client->dev,
265 sizeof(struct max31760), GFP_KERNEL);
266 if (!pdata)
267 return -ENOMEM;
268
269 pdata->regmap = devm_regmap_init_i2c(client, &max31760_regmap);
270 if (IS_ERR(pdata->regmap)) {
271 ret = PTR_ERR(pdata->regmap);
272 pr_err("%s Failed to allocate regmap: %d\n", __func__, ret);
273 return -EINVAL;
274 }
275
276 ret = max31760_parse_dt(&client->dev, pdata);
277 if (ret) {
278 pr_err("%s failed to parse device tree\n", __func__);
279 return -EINVAL;
280 }
281
282 ret = max31760_fan_pwr_enable_vregs(&client->dev, pdata);
283 if (ret) {
284 pr_err("%s failed to pwr regulators\n", __func__);
285 return -EINVAL;
286 }
287
288 pdata->dev = &client->dev;
289 i2c_set_clientdata(client, pdata);
290
291 pdata->i2c_client = client;
292
293 dev_set_drvdata(&client->dev, pdata);
294
295 ret = sysfs_create_group(&pdata->dev->kobj, &max31760_fs_attr_group);
296 if (ret)
297 pr_err("%s unable to register max31760 sysfs nodes\n");
298
299 /* 00 - 0x01 -- 33Hz */
300 /* 01 - 0x09 -- 150Hz */
301 /* 10 - 0x11 -- 1500Hz */
302 /* 11 - 0x19 -- 25Khz */
303 pdata->pwm = 0x19;
304 max31760_i2c_reg_set(pdata, 0x00, pdata->pwm);
305 max31760_i2c_reg_set(pdata, 0x01, 0x11);
306 max31760_i2c_reg_set(pdata, 0x02, 0x31);
307 max31760_i2c_reg_set(pdata, 0x03, 0x45);
308 max31760_i2c_reg_set(pdata, 0x04, 0xff);
309 max31760_i2c_reg_set(pdata, 0x50, 0xcf);
310 max31760_i2c_reg_set(pdata, 0x01, 0x11);
311 max31760_i2c_reg_set(pdata, 0x00, pdata->pwm);
312 max31760_i2c_reg_get(pdata, 0x00);
313
314 return ret;
315}
316
317static int max31760_remove(struct i2c_client *client)
318{
319 struct max31760 *pdata = i2c_get_clientdata(client);
320
321 if (!pdata)
322 goto end;
323
324 sysfs_remove_group(&pdata->dev->kobj, &max31760_fs_attr_group);
325 turn_gpio(pdata, false);
326end:
327 return 0;
328}
329
330
331static void max31760_shutdown(struct i2c_client *client)
332{
333}
334
335static int max31760_suspend(struct device *dev, pm_message_t state)
336{
337 struct max31760 *pdata = dev_get_drvdata(dev);
338
339 dev_dbg(dev, "suspend\n");
340 if (pdata)
341 turn_gpio(pdata, false);
342 return 0;
343}
344
345static int max31760_resume(struct device *dev)
346{
347 struct max31760 *pdata = dev_get_drvdata(dev);
348
349 dev_dbg(dev, "resume\n");
350 if (pdata) {
351 turn_gpio(pdata, true);
352 max31760_i2c_reg_set(pdata, 0x00, pdata->pwm);
353 }
354 return 0;
355}
356
357static const struct of_device_id max31760_id_table[] = {
358 { .compatible = "maxim,xrfancontroller",},
359 { },
360};
361static const struct i2c_device_id max31760_i2c_table[] = {
362 { "xrfancontroller", 0 },
363 { },
364};
365
366static struct i2c_driver max31760_i2c_driver = {
367 .probe = max31760_probe,
368 .remove = max31760_remove,
369 .shutdown = max31760_shutdown,
370 .driver = {
371 .name = "maxim xrfancontroller",
372 .of_match_table = max31760_id_table,
373 .suspend = max31760_suspend,
374 .resume = max31760_resume,
375 },
376 .id_table = max31760_i2c_table,
377};
378module_i2c_driver(max31760_i2c_driver);
379MODULE_DEVICE_TABLE(i2c, max31760_i2c_table);
380MODULE_DESCRIPTION("Maxim 31760 Fan Controller");
381MODULE_LICENSE("GPL v2");