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