xref: /linux/drivers/platform/x86/barco-p50-gpio.c (revision e3966940559d52aa1800a008dcfeec218dd31f88)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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