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