1
2
3
4#include <linux/acpi.h>
5#include <linux/clkdev.h>
6#include <linux/clk-provider.h>
7#include <linux/device.h>
8#include <linux/gpio/consumer.h>
9#include <linux/gpio/machine.h>
10#include <linux/i2c.h>
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/overflow.h>
14#include <linux/platform_device.h>
15#include <linux/uuid.h>
16
17#include "intel_skl_int3472_common.h"
18
19
20
21
22
23
24
25
26static const guid_t int3472_gpio_guid =
27 GUID_INIT(0x79234640, 0x9e10, 0x4fea,
28 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f);
29
30
31
32
33
34
35static const guid_t cio2_sensor_module_guid =
36 GUID_INIT(0x822ace8f, 0x2814, 0x4174,
37 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee);
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52static const struct int3472_gpio_function_remap ov2680_gpio_function_remaps[] = {
53 { "reset", NULL },
54 { "powerdown", "reset" },
55 { }
56};
57
58static const struct int3472_sensor_config int3472_sensor_configs[] = {
59
60 { "GNDF140809R", { 0 }, ov2680_gpio_function_remaps },
61
62 { "GEFF150023R", REGULATOR_SUPPLY("avdd", NULL), NULL },
63
64 { "YHCU", REGULATOR_SUPPLY("avdd", NULL), NULL },
65};
66
67static const struct int3472_sensor_config *
68skl_int3472_get_sensor_module_config(struct int3472_discrete_device *int3472)
69{
70 union acpi_object *obj;
71 unsigned int i;
72
73 obj = acpi_evaluate_dsm_typed(int3472->sensor->handle,
74 &cio2_sensor_module_guid, 0x00,
75 0x01, NULL, ACPI_TYPE_STRING);
76
77 if (!obj) {
78 dev_err(int3472->dev,
79 "Failed to get sensor module string from _DSM\n");
80 return ERR_PTR(-ENODEV);
81 }
82
83 if (obj->string.type != ACPI_TYPE_STRING) {
84 dev_err(int3472->dev,
85 "Sensor _DSM returned a non-string value\n");
86
87 ACPI_FREE(obj);
88 return ERR_PTR(-EINVAL);
89 }
90
91 for (i = 0; i < ARRAY_SIZE(int3472_sensor_configs); i++) {
92 if (!strcmp(int3472_sensor_configs[i].sensor_module_name,
93 obj->string.pointer))
94 break;
95 }
96
97 ACPI_FREE(obj);
98
99 if (i >= ARRAY_SIZE(int3472_sensor_configs))
100 return ERR_PTR(-EINVAL);
101
102 return &int3472_sensor_configs[i];
103}
104
105static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472,
106 struct acpi_resource_gpio *agpio,
107 const char *func, u32 polarity)
108{
109 const struct int3472_sensor_config *sensor_config;
110 char *path = agpio->resource_source.string_ptr;
111 struct gpiod_lookup *table_entry;
112 struct acpi_device *adev;
113 acpi_handle handle;
114 acpi_status status;
115 int ret;
116
117 if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) {
118 dev_warn(int3472->dev, "Too many GPIOs mapped\n");
119 return -EINVAL;
120 }
121
122 sensor_config = int3472->sensor_config;
123 if (!IS_ERR(sensor_config) && sensor_config->function_maps) {
124 const struct int3472_gpio_function_remap *remap;
125
126 for (remap = sensor_config->function_maps; remap->documented; remap++) {
127 if (!strcmp(func, remap->documented)) {
128 func = remap->actual;
129 break;
130 }
131 }
132 }
133
134
135 if (!func)
136 return 0;
137
138 status = acpi_get_handle(NULL, path, &handle);
139 if (ACPI_FAILURE(status))
140 return -EINVAL;
141
142 ret = acpi_bus_get_device(handle, &adev);
143 if (ret)
144 return -ENODEV;
145
146 table_entry = &int3472->gpios.table[int3472->n_sensor_gpios];
147 table_entry->key = acpi_dev_name(adev);
148 table_entry->chip_hwnum = agpio->pin_table[0];
149 table_entry->con_id = func;
150 table_entry->idx = 0;
151 table_entry->flags = polarity;
152
153 int3472->n_sensor_gpios++;
154
155 return 0;
156}
157
158static int skl_int3472_map_gpio_to_clk(struct int3472_discrete_device *int3472,
159 struct acpi_resource_gpio *agpio, u8 type)
160{
161 char *path = agpio->resource_source.string_ptr;
162 u16 pin = agpio->pin_table[0];
163 struct gpio_desc *gpio;
164
165 switch (type) {
166 case INT3472_GPIO_TYPE_CLK_ENABLE:
167 gpio = acpi_get_and_request_gpiod(path, pin, "int3472,clk-enable");
168 if (IS_ERR(gpio))
169 return (PTR_ERR(gpio));
170
171 int3472->clock.ena_gpio = gpio;
172 break;
173 case INT3472_GPIO_TYPE_PRIVACY_LED:
174 gpio = acpi_get_and_request_gpiod(path, pin, "int3472,privacy-led");
175 if (IS_ERR(gpio))
176 return (PTR_ERR(gpio));
177
178 int3472->clock.led_gpio = gpio;
179 break;
180 default:
181 dev_err(int3472->dev, "Invalid GPIO type 0x%02x for clock\n", type);
182 break;
183 }
184
185 return 0;
186}
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
221 void *data)
222{
223 struct int3472_discrete_device *int3472 = data;
224 struct acpi_resource_gpio *agpio;
225 union acpi_object *obj;
226 const char *err_msg;
227 int ret;
228 u8 type;
229
230 if (!acpi_gpio_get_io_resource(ares, &agpio))
231 return 1;
232
233
234
235
236
237 obj = acpi_evaluate_dsm_typed(int3472->adev->handle,
238 &int3472_gpio_guid, 0x00,
239 int3472->ngpios + 2,
240 NULL, ACPI_TYPE_INTEGER);
241
242 if (!obj) {
243 dev_warn(int3472->dev, "No _DSM entry for GPIO pin %u\n",
244 agpio->pin_table[0]);
245 return 1;
246 }
247
248 type = obj->integer.value & 0xff;
249
250 switch (type) {
251 case INT3472_GPIO_TYPE_RESET:
252 ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, "reset",
253 GPIO_ACTIVE_LOW);
254 if (ret)
255 err_msg = "Failed to map reset pin to sensor\n";
256
257 break;
258 case INT3472_GPIO_TYPE_POWERDOWN:
259 ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, "powerdown",
260 GPIO_ACTIVE_LOW);
261 if (ret)
262 err_msg = "Failed to map powerdown pin to sensor\n";
263
264 break;
265 case INT3472_GPIO_TYPE_CLK_ENABLE:
266 case INT3472_GPIO_TYPE_PRIVACY_LED:
267 ret = skl_int3472_map_gpio_to_clk(int3472, agpio, type);
268 if (ret)
269 err_msg = "Failed to map GPIO to clock\n";
270
271 break;
272 case INT3472_GPIO_TYPE_POWER_ENABLE:
273 ret = skl_int3472_register_regulator(int3472, agpio);
274 if (ret)
275 err_msg = "Failed to map regulator to sensor\n";
276
277 break;
278 default:
279 dev_warn(int3472->dev,
280 "GPIO type 0x%02x unknown; the sensor may not work\n",
281 type);
282 ret = 1;
283 break;
284 }
285
286 int3472->ngpios++;
287 ACPI_FREE(obj);
288
289 if (ret < 0)
290 return dev_err_probe(int3472->dev, ret, err_msg);
291
292 return ret;
293}
294
295static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472)
296{
297 LIST_HEAD(resource_list);
298 int ret;
299
300
301
302
303
304 int3472->sensor_config = skl_int3472_get_sensor_module_config(int3472);
305
306 ret = acpi_dev_get_resources(int3472->adev, &resource_list,
307 skl_int3472_handle_gpio_resources,
308 int3472);
309 if (ret < 0)
310 return ret;
311
312 acpi_dev_free_resource_list(&resource_list);
313
314
315
316
317
318
319 if (int3472->clock.ena_gpio) {
320 ret = skl_int3472_register_clock(int3472);
321 if (ret)
322 return ret;
323 } else {
324 if (int3472->clock.led_gpio)
325 dev_warn(int3472->dev,
326 "No clk GPIO. The privacy LED won't work\n");
327 }
328
329 int3472->gpios.dev_id = int3472->sensor_name;
330 gpiod_add_lookup_table(&int3472->gpios);
331
332 return 0;
333}
334
335int skl_int3472_discrete_probe(struct platform_device *pdev)
336{
337 struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
338 struct int3472_discrete_device *int3472;
339 struct int3472_cldb cldb;
340 int ret;
341
342 ret = skl_int3472_fill_cldb(adev, &cldb);
343 if (ret) {
344 dev_err(&pdev->dev, "Couldn't fill CLDB structure\n");
345 return ret;
346 }
347
348 if (cldb.control_logic_type != 1) {
349 dev_err(&pdev->dev, "Unsupported control logic type %u\n",
350 cldb.control_logic_type);
351 return -EINVAL;
352 }
353
354
355 int3472 = devm_kzalloc(&pdev->dev, struct_size(int3472, gpios.table,
356 INT3472_MAX_SENSOR_GPIOS + 1), GFP_KERNEL);
357 if (!int3472)
358 return -ENOMEM;
359
360 int3472->adev = adev;
361 int3472->dev = &pdev->dev;
362 platform_set_drvdata(pdev, int3472);
363
364 int3472->sensor = acpi_dev_get_first_consumer_dev(adev);
365 if (!int3472->sensor) {
366 dev_err(&pdev->dev, "INT3472 seems to have no dependents.\n");
367 return -ENODEV;
368 }
369
370 int3472->sensor_name = devm_kasprintf(int3472->dev, GFP_KERNEL,
371 I2C_DEV_NAME_FORMAT,
372 acpi_dev_name(int3472->sensor));
373 if (!int3472->sensor_name) {
374 ret = -ENOMEM;
375 goto err_put_sensor;
376 }
377
378
379
380
381
382 INIT_LIST_HEAD(&int3472->gpios.list);
383
384 ret = skl_int3472_parse_crs(int3472);
385 if (ret) {
386 skl_int3472_discrete_remove(pdev);
387 return ret;
388 }
389
390 return 0;
391
392err_put_sensor:
393 acpi_dev_put(int3472->sensor);
394
395 return ret;
396}
397
398int skl_int3472_discrete_remove(struct platform_device *pdev)
399{
400 struct int3472_discrete_device *int3472 = platform_get_drvdata(pdev);
401
402 gpiod_remove_lookup_table(&int3472->gpios);
403
404 if (int3472->clock.cl)
405 skl_int3472_unregister_clock(int3472);
406
407 gpiod_put(int3472->clock.ena_gpio);
408 gpiod_put(int3472->clock.led_gpio);
409
410 skl_int3472_unregister_regulator(int3472);
411
412 return 0;
413}
414