1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/ |
4 | * |
5 | * Author: Keerthy <j-keerthy@ti.com> |
6 | */ |
7 | |
8 | #include <linux/gpio/consumer.h> |
9 | #include <linux/i2c.h> |
10 | #include <linux/interrupt.h> |
11 | #include <linux/mfd/core.h> |
12 | #include <linux/mod_devicetable.h> |
13 | #include <linux/module.h> |
14 | #include <linux/regmap.h> |
15 | |
16 | #include <linux/mfd/lp87565.h> |
17 | |
18 | static const struct regmap_config lp87565_regmap_config = { |
19 | .reg_bits = 8, |
20 | .val_bits = 8, |
21 | .max_register = LP87565_REG_MAX, |
22 | }; |
23 | |
24 | static const struct mfd_cell lp87565_cells[] = { |
25 | { .name = "lp87565-q1-regulator" , }, |
26 | { .name = "lp87565-q1-gpio" , }, |
27 | }; |
28 | |
29 | static const struct of_device_id of_lp87565_match_table[] = { |
30 | { .compatible = "ti,lp87565" , }, |
31 | { |
32 | .compatible = "ti,lp87524-q1" , |
33 | .data = (void *)LP87565_DEVICE_TYPE_LP87524_Q1, |
34 | }, |
35 | { |
36 | .compatible = "ti,lp87565-q1" , |
37 | .data = (void *)LP87565_DEVICE_TYPE_LP87565_Q1, |
38 | }, |
39 | { |
40 | .compatible = "ti,lp87561-q1" , |
41 | .data = (void *)LP87565_DEVICE_TYPE_LP87561_Q1, |
42 | }, |
43 | {} |
44 | }; |
45 | MODULE_DEVICE_TABLE(of, of_lp87565_match_table); |
46 | |
47 | static int lp87565_probe(struct i2c_client *client) |
48 | { |
49 | struct lp87565 *lp87565; |
50 | int ret; |
51 | unsigned int otpid; |
52 | |
53 | lp87565 = devm_kzalloc(dev: &client->dev, size: sizeof(*lp87565), GFP_KERNEL); |
54 | if (!lp87565) |
55 | return -ENOMEM; |
56 | |
57 | lp87565->dev = &client->dev; |
58 | |
59 | lp87565->regmap = devm_regmap_init_i2c(client, &lp87565_regmap_config); |
60 | if (IS_ERR(ptr: lp87565->regmap)) { |
61 | ret = PTR_ERR(ptr: lp87565->regmap); |
62 | dev_err(lp87565->dev, |
63 | "Failed to initialize register map: %d\n" , ret); |
64 | return ret; |
65 | } |
66 | |
67 | lp87565->reset_gpio = devm_gpiod_get_optional(dev: lp87565->dev, con_id: "reset" , |
68 | flags: GPIOD_OUT_LOW); |
69 | if (IS_ERR(ptr: lp87565->reset_gpio)) { |
70 | ret = PTR_ERR(ptr: lp87565->reset_gpio); |
71 | if (ret == -EPROBE_DEFER) |
72 | return ret; |
73 | } |
74 | |
75 | if (lp87565->reset_gpio) { |
76 | gpiod_set_value_cansleep(desc: lp87565->reset_gpio, value: 1); |
77 | /* The minimum assertion time is undocumented, just guess */ |
78 | usleep_range(min: 2000, max: 4000); |
79 | |
80 | gpiod_set_value_cansleep(desc: lp87565->reset_gpio, value: 0); |
81 | /* Min 1.2 ms before first I2C transaction */ |
82 | usleep_range(min: 1500, max: 3000); |
83 | } |
84 | |
85 | ret = regmap_read(map: lp87565->regmap, LP87565_REG_OTP_REV, val: &otpid); |
86 | if (ret) { |
87 | dev_err(lp87565->dev, "Failed to read OTP ID\n" ); |
88 | return ret; |
89 | } |
90 | |
91 | lp87565->rev = otpid & LP87565_OTP_REV_OTP_ID; |
92 | lp87565->dev_type = (uintptr_t)i2c_get_match_data(client); |
93 | |
94 | i2c_set_clientdata(client, data: lp87565); |
95 | |
96 | return devm_mfd_add_devices(dev: lp87565->dev, PLATFORM_DEVID_AUTO, |
97 | cells: lp87565_cells, ARRAY_SIZE(lp87565_cells), |
98 | NULL, irq_base: 0, NULL); |
99 | } |
100 | |
101 | static void lp87565_shutdown(struct i2c_client *client) |
102 | { |
103 | struct lp87565 *lp87565 = i2c_get_clientdata(client); |
104 | |
105 | gpiod_set_value_cansleep(desc: lp87565->reset_gpio, value: 1); |
106 | } |
107 | |
108 | static const struct i2c_device_id lp87565_id_table[] = { |
109 | { "lp87565-q1" , 0 }, |
110 | { }, |
111 | }; |
112 | MODULE_DEVICE_TABLE(i2c, lp87565_id_table); |
113 | |
114 | static struct i2c_driver lp87565_driver = { |
115 | .driver = { |
116 | .name = "lp87565" , |
117 | .of_match_table = of_lp87565_match_table, |
118 | }, |
119 | .probe = lp87565_probe, |
120 | .shutdown = lp87565_shutdown, |
121 | .id_table = lp87565_id_table, |
122 | }; |
123 | module_i2c_driver(lp87565_driver); |
124 | |
125 | MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>" ); |
126 | MODULE_DESCRIPTION("lp87565 chip family Multi-Function Device driver" ); |
127 | MODULE_LICENSE("GPL v2" ); |
128 | |