1 // SPDX-License-Identifier: GPL-2.0+
2
3 /*
4 * Support for EC-connected GPIOs for identify
5 * LED/button on Barco P50 board
6 *
7 * Copyright (C) 2021 Barco NV
8 * Author: Santosh Kumar Yadav <santoshkumar.yadav@barco.com>
9 */
10
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12
13 #include <linux/delay.h>
14 #include <linux/dev_printk.h>
15 #include <linux/dmi.h>
16 #include <linux/err.h>
17 #include <linux/io.h>
18 #include <linux/kernel.h>
19 #include <linux/leds.h>
20 #include <linux/module.h>
21 #include <linux/platform_device.h>
22 #include <linux/gpio/driver.h>
23 #include <linux/gpio/machine.h>
24 #include <linux/gpio/property.h>
25 #include <linux/input-event-codes.h>
26 #include <linux/property.h>
27
28
29 #define DRIVER_NAME "barco-p50-gpio"
30
31 /* GPIO lines */
32 #define P50_GPIO_LINE_LED 0
33 #define P50_GPIO_LINE_BTN 1
34
35 /* GPIO IO Ports */
36 #define P50_GPIO_IO_PORT_BASE 0x299
37
38 #define P50_PORT_DATA 0x00
39 #define P50_PORT_CMD 0x01
40
41 #define P50_STATUS_OBF 0x01 /* EC output buffer full */
42 #define P50_STATUS_IBF 0x02 /* EC input buffer full */
43
44 #define P50_CMD_READ 0xa0
45 #define P50_CMD_WRITE 0x50
46
47 /* EC mailbox registers */
48 #define P50_MBOX_REG_CMD 0x00
49 #define P50_MBOX_REG_STATUS 0x01
50 #define P50_MBOX_REG_PARAM 0x02
51 #define P50_MBOX_REG_DATA 0x03
52
53 #define P50_MBOX_CMD_READ_GPIO 0x11
54 #define P50_MBOX_CMD_WRITE_GPIO 0x12
55 #define P50_MBOX_CMD_CLEAR 0xff
56
57 #define P50_MBOX_STATUS_SUCCESS 0x01
58
59 #define P50_MBOX_PARAM_LED 0x12
60 #define P50_MBOX_PARAM_BTN 0x13
61
62
63 struct p50_gpio {
64 struct gpio_chip gc;
65 struct mutex lock;
66 unsigned long base;
67 struct platform_device *leds_pdev;
68 struct platform_device *keys_pdev;
69 };
70
71 static struct platform_device *gpio_pdev;
72
73 static int gpio_params[] = {
74 [P50_GPIO_LINE_LED] = P50_MBOX_PARAM_LED,
75 [P50_GPIO_LINE_BTN] = P50_MBOX_PARAM_BTN,
76 };
77
78 static const char * const gpio_names[] = {
79 [P50_GPIO_LINE_LED] = "identify-led",
80 [P50_GPIO_LINE_BTN] = "identify-button",
81 };
82
83 static const struct software_node gpiochip_node = {
84 .name = DRIVER_NAME,
85 };
86
87 /* GPIO LEDs */
88 static const struct software_node gpio_leds_node = {
89 .name = "gpio-leds-identify",
90 };
91
92 static const struct property_entry identify_led_props[] = {
93 PROPERTY_ENTRY_GPIO("gpios", &gpiochip_node, P50_GPIO_LINE_LED, GPIO_ACTIVE_HIGH),
94 { }
95 };
96
97 static const struct software_node identify_led_node = {
98 .parent = &gpio_leds_node,
99 .name = "identify",
100 .properties = identify_led_props,
101 };
102
103 /* GPIO keyboard */
104 static const struct property_entry gpio_keys_props[] = {
105 PROPERTY_ENTRY_STRING("label", "identify"),
106 PROPERTY_ENTRY_U32("poll-interval", 100),
107 { }
108 };
109
110 static const struct software_node gpio_keys_node = {
111 .name = "gpio-keys-identify",
112 .properties = gpio_keys_props,
113 };
114
115 static struct property_entry vendor_key_props[] = {
116 PROPERTY_ENTRY_U32("linux,code", KEY_VENDOR),
117 PROPERTY_ENTRY_GPIO("gpios", &gpiochip_node, P50_GPIO_LINE_BTN, GPIO_ACTIVE_LOW),
118 { }
119 };
120
121 static const struct software_node vendor_key_node = {
122 .parent = &gpio_keys_node,
123 .properties = vendor_key_props,
124 };
125
126 static const struct software_node *p50_swnodes[] = {
127 &gpiochip_node,
128 &gpio_leds_node,
129 &identify_led_node,
130 &gpio_keys_node,
131 &vendor_key_node,
132 NULL
133 };
134
135 /* low level access routines */
136
p50_wait_ec(struct p50_gpio * p50,int mask,int expected)137 static int p50_wait_ec(struct p50_gpio *p50, int mask, int expected)
138 {
139 int i, val;
140
141 for (i = 0; i < 100; i++) {
142 val = inb(p50->base + P50_PORT_CMD) & mask;
143 if (val == expected)
144 return 0;
145 usleep_range(500, 2000);
146 }
147
148 dev_err(p50->gc.parent, "Timed out waiting for EC (0x%x)\n", val);
149 return -ETIMEDOUT;
150 }
151
152
p50_read_mbox_reg(struct p50_gpio * p50,int reg)153 static int p50_read_mbox_reg(struct p50_gpio *p50, int reg)
154 {
155 int ret;
156
157 ret = p50_wait_ec(p50, P50_STATUS_IBF, 0);
158 if (ret)
159 return ret;
160
161 /* clear output buffer flag, prevent unfinished commands */
162 inb(p50->base + P50_PORT_DATA);
163
164 /* cmd/address */
165 outb(P50_CMD_READ | reg, p50->base + P50_PORT_CMD);
166
167 ret = p50_wait_ec(p50, P50_STATUS_OBF, P50_STATUS_OBF);
168 if (ret)
169 return ret;
170
171 return inb(p50->base + P50_PORT_DATA);
172 }
173
p50_write_mbox_reg(struct p50_gpio * p50,int reg,int val)174 static int p50_write_mbox_reg(struct p50_gpio *p50, int reg, int val)
175 {
176 int ret;
177
178 ret = p50_wait_ec(p50, P50_STATUS_IBF, 0);
179 if (ret)
180 return ret;
181
182 /* cmd/address */
183 outb(P50_CMD_WRITE | reg, p50->base + P50_PORT_CMD);
184
185 ret = p50_wait_ec(p50, P50_STATUS_IBF, 0);
186 if (ret)
187 return ret;
188
189 /* data */
190 outb(val, p50->base + P50_PORT_DATA);
191
192 return 0;
193 }
194
195
196 /* mbox routines */
197
p50_wait_mbox_idle(struct p50_gpio * p50)198 static int p50_wait_mbox_idle(struct p50_gpio *p50)
199 {
200 int i, val;
201
202 for (i = 0; i < 1000; i++) {
203 val = p50_read_mbox_reg(p50, P50_MBOX_REG_CMD);
204 /* cmd is 0 when idle */
205 if (val <= 0)
206 return val;
207
208 usleep_range(500, 2000);
209 }
210
211 dev_err(p50->gc.parent, "Timed out waiting for EC mbox idle (CMD: 0x%x)\n", val);
212
213 return -ETIMEDOUT;
214 }
215
p50_send_mbox_cmd(struct p50_gpio * p50,int cmd,int param,int data)216 static int p50_send_mbox_cmd(struct p50_gpio *p50, int cmd, int param, int data)
217 {
218 int ret;
219
220 ret = p50_wait_mbox_idle(p50);
221 if (ret)
222 return ret;
223
224 ret = p50_write_mbox_reg(p50, P50_MBOX_REG_DATA, data);
225 if (ret)
226 return ret;
227
228 ret = p50_write_mbox_reg(p50, P50_MBOX_REG_PARAM, param);
229 if (ret)
230 return ret;
231
232 ret = p50_write_mbox_reg(p50, P50_MBOX_REG_CMD, cmd);
233 if (ret)
234 return ret;
235
236 ret = p50_wait_mbox_idle(p50);
237 if (ret)
238 return ret;
239
240 ret = p50_read_mbox_reg(p50, P50_MBOX_REG_STATUS);
241 if (ret < 0)
242 return ret;
243
244 if (ret == P50_MBOX_STATUS_SUCCESS)
245 return 0;
246
247 dev_err(p50->gc.parent, "Mbox command failed (CMD=0x%x STAT=0x%x PARAM=0x%x DATA=0x%x)\n",
248 cmd, ret, param, data);
249
250 return -EIO;
251 }
252
253
254 /* gpio routines */
255
p50_gpio_get_direction(struct gpio_chip * gc,unsigned int offset)256 static int p50_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
257 {
258 switch (offset) {
259 case P50_GPIO_LINE_BTN:
260 return GPIO_LINE_DIRECTION_IN;
261
262 case P50_GPIO_LINE_LED:
263 return GPIO_LINE_DIRECTION_OUT;
264
265 default:
266 return -EINVAL;
267 }
268 }
269
p50_gpio_get(struct gpio_chip * gc,unsigned int offset)270 static int p50_gpio_get(struct gpio_chip *gc, unsigned int offset)
271 {
272 struct p50_gpio *p50 = gpiochip_get_data(gc);
273 int ret;
274
275 mutex_lock(&p50->lock);
276
277 ret = p50_send_mbox_cmd(p50, P50_MBOX_CMD_READ_GPIO, gpio_params[offset], 0);
278 if (ret == 0)
279 ret = p50_read_mbox_reg(p50, P50_MBOX_REG_DATA);
280
281 mutex_unlock(&p50->lock);
282
283 return ret;
284 }
285
p50_gpio_set(struct gpio_chip * gc,unsigned int offset,int value)286 static int p50_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
287 {
288 struct p50_gpio *p50 = gpiochip_get_data(gc);
289 int ret;
290
291 mutex_lock(&p50->lock);
292
293 ret = p50_send_mbox_cmd(p50, P50_MBOX_CMD_WRITE_GPIO,
294 gpio_params[offset], value);
295
296 mutex_unlock(&p50->lock);
297
298 return ret;
299 }
300
p50_gpio_probe(struct platform_device * pdev)301 static int p50_gpio_probe(struct platform_device *pdev)
302 {
303 struct platform_device_info key_info = {
304 .name = "gpio-keys-polled",
305 .id = PLATFORM_DEVID_NONE,
306 .parent = &pdev->dev,
307 };
308 struct platform_device_info led_info = {
309 .name = "leds-gpio",
310 .id = PLATFORM_DEVID_NONE,
311 .parent = &pdev->dev,
312 };
313 struct p50_gpio *p50;
314 struct resource *res;
315 int ret;
316
317 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
318 if (!res) {
319 dev_err(&pdev->dev, "Cannot get I/O ports\n");
320 return -ENODEV;
321 }
322
323 if (!devm_request_region(&pdev->dev, res->start, resource_size(res), pdev->name)) {
324 dev_err(&pdev->dev, "Unable to reserve I/O region\n");
325 return -EBUSY;
326 }
327
328 p50 = devm_kzalloc(&pdev->dev, sizeof(*p50), GFP_KERNEL);
329 if (!p50)
330 return -ENOMEM;
331
332 platform_set_drvdata(pdev, p50);
333 mutex_init(&p50->lock);
334 p50->base = res->start;
335 p50->gc.owner = THIS_MODULE;
336 p50->gc.parent = &pdev->dev;
337 p50->gc.label = dev_name(&pdev->dev);
338 p50->gc.ngpio = ARRAY_SIZE(gpio_names);
339 p50->gc.names = gpio_names;
340 p50->gc.can_sleep = true;
341 p50->gc.base = -1;
342 p50->gc.get_direction = p50_gpio_get_direction;
343 p50->gc.get = p50_gpio_get;
344 p50->gc.set = p50_gpio_set;
345
346
347 /* reset mbox */
348 ret = p50_wait_mbox_idle(p50);
349 if (ret)
350 return ret;
351
352 ret = p50_write_mbox_reg(p50, P50_MBOX_REG_CMD, P50_MBOX_CMD_CLEAR);
353 if (ret)
354 return ret;
355
356 ret = p50_wait_mbox_idle(p50);
357 if (ret)
358 return ret;
359
360
361 ret = devm_gpiochip_add_data(&pdev->dev, &p50->gc, p50);
362 if (ret < 0) {
363 dev_err(&pdev->dev, "Could not register gpiochip: %d\n", ret);
364 return ret;
365 }
366
367 ret = software_node_register_node_group(p50_swnodes);
368 if (ret)
369 return dev_err_probe(&pdev->dev, ret, "failed to register software nodes");
370
371 led_info.fwnode = software_node_fwnode(&gpio_leds_node);
372 p50->leds_pdev = platform_device_register_full(&led_info);
373 if (IS_ERR(p50->leds_pdev)) {
374 ret = PTR_ERR(p50->leds_pdev);
375 dev_err(&pdev->dev, "Could not register leds-gpio: %d\n", ret);
376 goto err_leds;
377 }
378
379 key_info.fwnode = software_node_fwnode(&gpio_keys_node);
380 p50->keys_pdev = platform_device_register_full(&key_info);
381 if (IS_ERR(p50->keys_pdev)) {
382 ret = PTR_ERR(p50->keys_pdev);
383 dev_err(&pdev->dev, "Could not register gpio-keys-polled: %d\n", ret);
384 goto err_keys;
385 }
386
387 return 0;
388
389 err_keys:
390 platform_device_unregister(p50->leds_pdev);
391 err_leds:
392 software_node_unregister_node_group(p50_swnodes);
393
394 return ret;
395 }
396
p50_gpio_remove(struct platform_device * pdev)397 static void p50_gpio_remove(struct platform_device *pdev)
398 {
399 struct p50_gpio *p50 = platform_get_drvdata(pdev);
400
401 platform_device_unregister(p50->keys_pdev);
402 platform_device_unregister(p50->leds_pdev);
403
404 software_node_unregister_node_group(p50_swnodes);
405 }
406
407 static struct platform_driver p50_gpio_driver = {
408 .driver = {
409 .name = DRIVER_NAME,
410 },
411 .probe = p50_gpio_probe,
412 .remove = p50_gpio_remove,
413 };
414
415 /* Board setup */
416 static const struct dmi_system_id dmi_ids[] __initconst = {
417 {
418 .matches = {
419 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Barco"),
420 DMI_EXACT_MATCH(DMI_PRODUCT_FAMILY, "P50")
421 },
422 },
423 {}
424 };
425 MODULE_DEVICE_TABLE(dmi, dmi_ids);
426
p50_module_init(void)427 static int __init p50_module_init(void)
428 {
429 struct resource res = DEFINE_RES_IO(P50_GPIO_IO_PORT_BASE, P50_PORT_CMD + 1);
430 int ret;
431
432 if (!dmi_first_match(dmi_ids))
433 return -ENODEV;
434
435 ret = platform_driver_register(&p50_gpio_driver);
436 if (ret)
437 return ret;
438
439 gpio_pdev = platform_device_register_simple(DRIVER_NAME, PLATFORM_DEVID_NONE, &res, 1);
440 if (IS_ERR(gpio_pdev)) {
441 pr_err("failed registering %s: %ld\n", DRIVER_NAME, PTR_ERR(gpio_pdev));
442 platform_driver_unregister(&p50_gpio_driver);
443 return PTR_ERR(gpio_pdev);
444 }
445
446 return 0;
447 }
448
p50_module_exit(void)449 static void __exit p50_module_exit(void)
450 {
451 platform_device_unregister(gpio_pdev);
452 platform_driver_unregister(&p50_gpio_driver);
453 }
454
455 module_init(p50_module_init);
456 module_exit(p50_module_exit);
457
458 MODULE_AUTHOR("Santosh Kumar Yadav, Barco NV <santoshkumar.yadav@barco.com>");
459 MODULE_DESCRIPTION("Barco P50 identify GPIOs driver");
460 MODULE_LICENSE("GPL");
461