1 // SPDX-License-Identifier: GPL-2.0
2 /* Author: Dan Scally <djrscally@gmail.com> */
3
4 #include <linux/acpi.h>
5 #include <linux/i2c.h>
6 #include <linux/kernel.h>
7 #include <linux/mfd/core.h>
8 #include <linux/mfd/tps68470.h>
9 #include <linux/platform_device.h>
10 #include <linux/platform_data/tps68470.h>
11 #include <linux/regmap.h>
12 #include <linux/string.h>
13
14 #include "common.h"
15 #include "tps68470.h"
16
17 #define DESIGNED_FOR_CHROMEOS 1
18 #define DESIGNED_FOR_WINDOWS 2
19
20 #define TPS68470_WIN_MFD_CELL_COUNT 3
21
22 static const struct mfd_cell tps68470_cros[] = {
23 { .name = "tps68470-gpio" },
24 { .name = "tps68470_pmic_opregion" },
25 };
26
27 static const struct regmap_config tps68470_regmap_config = {
28 .reg_bits = 8,
29 .val_bits = 8,
30 .max_register = TPS68470_REG_MAX,
31 };
32
tps68470_chip_init(struct device * dev,struct regmap * regmap)33 static int tps68470_chip_init(struct device *dev, struct regmap *regmap)
34 {
35 unsigned int version;
36 int ret;
37
38 /* Force software reset */
39 ret = regmap_write(regmap, TPS68470_REG_RESET, TPS68470_REG_RESET_MASK);
40 if (ret)
41 return ret;
42
43 ret = regmap_read(regmap, TPS68470_REG_REVID, &version);
44 if (ret) {
45 dev_err(dev, "Failed to read revision register: %d\n", ret);
46 return ret;
47 }
48
49 dev_info(dev, "TPS68470 REVID: 0x%02x\n", version);
50
51 return 0;
52 }
53
54 /** skl_int3472_tps68470_calc_type: Check what platform a device is designed for
55 * @adev: A pointer to a &struct acpi_device
56 *
57 * Check CLDB buffer against the PMIC's adev. If present, then we check
58 * the value of control_logic_type field and follow one of the
59 * following scenarios:
60 *
61 * 1. No CLDB - likely ACPI tables designed for ChromeOS. We
62 * create platform devices for the GPIOs and OpRegion drivers.
63 *
64 * 2. CLDB, with control_logic_type = 2 - probably ACPI tables
65 * made for Windows 2-in-1 platforms. Register pdevs for GPIO,
66 * Clock and Regulator drivers to bind to.
67 *
68 * 3. Any other value in control_logic_type, we should never have
69 * gotten to this point; fail probe and return.
70 *
71 * Return:
72 * * 1 Device intended for ChromeOS
73 * * 2 Device intended for Windows
74 * * -EINVAL Where @adev has an object named CLDB but it does not conform to
75 * our expectations
76 */
skl_int3472_tps68470_calc_type(struct acpi_device * adev)77 static int skl_int3472_tps68470_calc_type(struct acpi_device *adev)
78 {
79 struct int3472_cldb cldb = { 0 };
80 int ret;
81
82 /*
83 * A CLDB buffer that exists, but which does not match our expectations
84 * should trigger an error so we don't blindly continue.
85 */
86 ret = skl_int3472_fill_cldb(adev, &cldb);
87 if (ret && ret != -ENODEV)
88 return ret;
89
90 if (ret)
91 return DESIGNED_FOR_CHROMEOS;
92
93 if (cldb.control_logic_type != 2)
94 return -EINVAL;
95
96 return DESIGNED_FOR_WINDOWS;
97 }
98
99 /*
100 * Return the size of the flexible array member, because we'll need that later
101 * on to pass .pdata_size to cells.
102 */
103 static int
skl_int3472_fill_clk_pdata(struct device * dev,struct tps68470_clk_platform_data ** clk_pdata)104 skl_int3472_fill_clk_pdata(struct device *dev, struct tps68470_clk_platform_data **clk_pdata)
105 {
106 struct acpi_device *adev = ACPI_COMPANION(dev);
107 struct acpi_device *consumer;
108 unsigned int n_consumers = 0;
109 const char *sensor_name;
110 unsigned int i = 0;
111
112 for_each_acpi_consumer_dev(adev, consumer)
113 n_consumers++;
114
115 if (!n_consumers) {
116 dev_err(dev, "INT3472 seems to have no dependents\n");
117 return -ENODEV;
118 }
119
120 *clk_pdata = devm_kzalloc(dev, struct_size(*clk_pdata, consumers, n_consumers),
121 GFP_KERNEL);
122 if (!*clk_pdata)
123 return -ENOMEM;
124
125 (*clk_pdata)->n_consumers = n_consumers;
126 i = 0;
127
128 for_each_acpi_consumer_dev(adev, consumer) {
129 sensor_name = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT,
130 acpi_dev_name(consumer));
131 if (!sensor_name) {
132 acpi_dev_put(consumer);
133 return -ENOMEM;
134 }
135
136 (*clk_pdata)->consumers[i].consumer_dev_name = sensor_name;
137 i++;
138 }
139
140 return n_consumers;
141 }
142
skl_int3472_tps68470_probe(struct i2c_client * client)143 static int skl_int3472_tps68470_probe(struct i2c_client *client)
144 {
145 struct acpi_device *adev = ACPI_COMPANION(&client->dev);
146 const struct int3472_tps68470_board_data *board_data;
147 struct tps68470_clk_platform_data *clk_pdata;
148 struct mfd_cell *cells;
149 struct regmap *regmap;
150 int n_consumers;
151 int device_type;
152 int ret;
153 int i;
154
155 n_consumers = skl_int3472_fill_clk_pdata(&client->dev, &clk_pdata);
156 if (n_consumers < 0)
157 return n_consumers;
158
159 regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config);
160 if (IS_ERR(regmap)) {
161 dev_err(&client->dev, "Failed to create regmap: %ld\n", PTR_ERR(regmap));
162 return PTR_ERR(regmap);
163 }
164
165 i2c_set_clientdata(client, regmap);
166
167 ret = tps68470_chip_init(&client->dev, regmap);
168 if (ret < 0) {
169 dev_err(&client->dev, "TPS68470 init error %d\n", ret);
170 return ret;
171 }
172
173 device_type = skl_int3472_tps68470_calc_type(adev);
174 switch (device_type) {
175 case DESIGNED_FOR_WINDOWS:
176 board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
177 if (!board_data)
178 return dev_err_probe(&client->dev, -ENODEV, "No board-data found for this model\n");
179
180 cells = kcalloc(TPS68470_WIN_MFD_CELL_COUNT, sizeof(*cells), GFP_KERNEL);
181 if (!cells)
182 return -ENOMEM;
183
184 /*
185 * The order of the cells matters here! The clk must be first
186 * because the regulator depends on it. The gpios must be last,
187 * acpi_gpiochip_add() calls acpi_dev_clear_dependencies() and
188 * the clk + regulators must be ready when this happens.
189 */
190 cells[0].name = "tps68470-clk";
191 cells[0].platform_data = clk_pdata;
192 cells[0].pdata_size = struct_size(clk_pdata, consumers, n_consumers);
193 cells[1].name = "tps68470-regulator";
194 cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata;
195 cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data);
196 cells[2].name = "tps68470-gpio";
197
198 for (i = 0; i < board_data->n_gpiod_lookups; i++)
199 gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
200
201 ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
202 cells, TPS68470_WIN_MFD_CELL_COUNT,
203 NULL, 0, NULL);
204 kfree(cells);
205
206 if (ret) {
207 for (i = 0; i < board_data->n_gpiod_lookups; i++)
208 gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
209 }
210
211 break;
212 case DESIGNED_FOR_CHROMEOS:
213 ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
214 tps68470_cros, ARRAY_SIZE(tps68470_cros),
215 NULL, 0, NULL);
216 break;
217 default:
218 dev_err(&client->dev, "Failed to add MFD devices\n");
219 return device_type;
220 }
221
222 /*
223 * No acpi_dev_clear_dependencies() here, since the acpi_gpiochip_add()
224 * for the GPIO cell already does this.
225 */
226
227 return ret;
228 }
229
skl_int3472_tps68470_remove(struct i2c_client * client)230 static void skl_int3472_tps68470_remove(struct i2c_client *client)
231 {
232 const struct int3472_tps68470_board_data *board_data;
233 int i;
234
235 board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
236 if (board_data) {
237 for (i = 0; i < board_data->n_gpiod_lookups; i++)
238 gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
239 }
240 }
241
242 static const struct acpi_device_id int3472_device_id[] = {
243 { "INT3472", 0 },
244 { }
245 };
246 MODULE_DEVICE_TABLE(acpi, int3472_device_id);
247
248 static struct i2c_driver int3472_tps68470 = {
249 .driver = {
250 .name = "int3472-tps68470",
251 .acpi_match_table = int3472_device_id,
252 },
253 .probe = skl_int3472_tps68470_probe,
254 .remove = skl_int3472_tps68470_remove,
255 };
256 module_i2c_driver(int3472_tps68470);
257
258 MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI TPS68470 Device Driver");
259 MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
260 MODULE_LICENSE("GPL v2");
261 MODULE_SOFTDEP("pre: clk-tps68470 tps68470-regulator");
262