0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0012
0013 #include <linux/delay.h>
0014 #include <linux/dmi.h>
0015 #include <linux/err.h>
0016 #include <linux/io.h>
0017 #include <linux/kernel.h>
0018 #include <linux/leds.h>
0019 #include <linux/module.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/gpio_keys.h>
0022 #include <linux/gpio/driver.h>
0023 #include <linux/gpio/machine.h>
0024 #include <linux/input.h>
0025
0026
0027 #define DRIVER_NAME "barco-p50-gpio"
0028
0029
0030 #define P50_GPIO_LINE_LED 0
0031 #define P50_GPIO_LINE_BTN 1
0032
0033
0034 #define P50_GPIO_IO_PORT_BASE 0x299
0035
0036 #define P50_PORT_DATA 0x00
0037 #define P50_PORT_CMD 0x01
0038
0039 #define P50_STATUS_OBF 0x01
0040 #define P50_STATUS_IBF 0x02
0041
0042 #define P50_CMD_READ 0xa0
0043 #define P50_CMD_WRITE 0x50
0044
0045
0046 #define P50_MBOX_REG_CMD 0x00
0047 #define P50_MBOX_REG_STATUS 0x01
0048 #define P50_MBOX_REG_PARAM 0x02
0049 #define P50_MBOX_REG_DATA 0x03
0050
0051 #define P50_MBOX_CMD_READ_GPIO 0x11
0052 #define P50_MBOX_CMD_WRITE_GPIO 0x12
0053 #define P50_MBOX_CMD_CLEAR 0xff
0054
0055 #define P50_MBOX_STATUS_SUCCESS 0x01
0056
0057 #define P50_MBOX_PARAM_LED 0x12
0058 #define P50_MBOX_PARAM_BTN 0x13
0059
0060
0061 struct p50_gpio {
0062 struct gpio_chip gc;
0063 struct mutex lock;
0064 unsigned long base;
0065 struct platform_device *leds_pdev;
0066 struct platform_device *keys_pdev;
0067 };
0068
0069 static struct platform_device *gpio_pdev;
0070
0071 static int gpio_params[] = {
0072 [P50_GPIO_LINE_LED] = P50_MBOX_PARAM_LED,
0073 [P50_GPIO_LINE_BTN] = P50_MBOX_PARAM_BTN,
0074 };
0075
0076 static const char * const gpio_names[] = {
0077 [P50_GPIO_LINE_LED] = "identify-led",
0078 [P50_GPIO_LINE_BTN] = "identify-button",
0079 };
0080
0081
0082 static struct gpiod_lookup_table p50_gpio_led_table = {
0083 .dev_id = "leds-gpio",
0084 .table = {
0085 GPIO_LOOKUP_IDX(DRIVER_NAME, P50_GPIO_LINE_LED, NULL, 0, GPIO_ACTIVE_HIGH),
0086 {}
0087 }
0088 };
0089
0090
0091 static struct gpio_led leds[] = {
0092 { .name = "identify" }
0093 };
0094
0095 static struct gpio_led_platform_data leds_pdata = {
0096 .num_leds = ARRAY_SIZE(leds),
0097 .leds = leds,
0098 };
0099
0100
0101 static struct gpio_keys_button buttons[] = {
0102 {
0103 .code = KEY_VENDOR,
0104 .gpio = P50_GPIO_LINE_BTN,
0105 .active_low = 1,
0106 .type = EV_KEY,
0107 .value = 1,
0108 },
0109 };
0110
0111 static struct gpio_keys_platform_data keys_pdata = {
0112 .buttons = buttons,
0113 .nbuttons = ARRAY_SIZE(buttons),
0114 .poll_interval = 100,
0115 .rep = 0,
0116 .name = "identify",
0117 };
0118
0119
0120
0121
0122 static int p50_wait_ec(struct p50_gpio *p50, int mask, int expected)
0123 {
0124 int i, val;
0125
0126 for (i = 0; i < 100; i++) {
0127 val = inb(p50->base + P50_PORT_CMD) & mask;
0128 if (val == expected)
0129 return 0;
0130 usleep_range(500, 2000);
0131 }
0132
0133 dev_err(p50->gc.parent, "Timed out waiting for EC (0x%x)\n", val);
0134 return -ETIMEDOUT;
0135 }
0136
0137
0138 static int p50_read_mbox_reg(struct p50_gpio *p50, int reg)
0139 {
0140 int ret;
0141
0142 ret = p50_wait_ec(p50, P50_STATUS_IBF, 0);
0143 if (ret)
0144 return ret;
0145
0146
0147 inb(p50->base + P50_PORT_DATA);
0148
0149
0150 outb(P50_CMD_READ | reg, p50->base + P50_PORT_CMD);
0151
0152 ret = p50_wait_ec(p50, P50_STATUS_OBF, P50_STATUS_OBF);
0153 if (ret)
0154 return ret;
0155
0156 return inb(p50->base + P50_PORT_DATA);
0157 }
0158
0159 static int p50_write_mbox_reg(struct p50_gpio *p50, int reg, int val)
0160 {
0161 int ret;
0162
0163 ret = p50_wait_ec(p50, P50_STATUS_IBF, 0);
0164 if (ret)
0165 return ret;
0166
0167
0168 outb(P50_CMD_WRITE | reg, p50->base + P50_PORT_CMD);
0169
0170 ret = p50_wait_ec(p50, P50_STATUS_IBF, 0);
0171 if (ret)
0172 return ret;
0173
0174
0175 outb(val, p50->base + P50_PORT_DATA);
0176
0177 return 0;
0178 }
0179
0180
0181
0182
0183 static int p50_wait_mbox_idle(struct p50_gpio *p50)
0184 {
0185 int i, val;
0186
0187 for (i = 0; i < 1000; i++) {
0188 val = p50_read_mbox_reg(p50, P50_MBOX_REG_CMD);
0189
0190 if (val <= 0)
0191 return val;
0192
0193 usleep_range(500, 2000);
0194 }
0195
0196 dev_err(p50->gc.parent, "Timed out waiting for EC mbox idle (CMD: 0x%x)\n", val);
0197
0198 return -ETIMEDOUT;
0199 }
0200
0201 static int p50_send_mbox_cmd(struct p50_gpio *p50, int cmd, int param, int data)
0202 {
0203 int ret;
0204
0205 ret = p50_wait_mbox_idle(p50);
0206 if (ret)
0207 return ret;
0208
0209 ret = p50_write_mbox_reg(p50, P50_MBOX_REG_DATA, data);
0210 if (ret)
0211 return ret;
0212
0213 ret = p50_write_mbox_reg(p50, P50_MBOX_REG_PARAM, param);
0214 if (ret)
0215 return ret;
0216
0217 ret = p50_write_mbox_reg(p50, P50_MBOX_REG_CMD, cmd);
0218 if (ret)
0219 return ret;
0220
0221 ret = p50_wait_mbox_idle(p50);
0222 if (ret)
0223 return ret;
0224
0225 ret = p50_read_mbox_reg(p50, P50_MBOX_REG_STATUS);
0226 if (ret < 0)
0227 return ret;
0228
0229 if (ret == P50_MBOX_STATUS_SUCCESS)
0230 return 0;
0231
0232 dev_err(p50->gc.parent, "Mbox command failed (CMD=0x%x STAT=0x%x PARAM=0x%x DATA=0x%x)\n",
0233 cmd, ret, param, data);
0234
0235 return -EIO;
0236 }
0237
0238
0239
0240
0241 static int p50_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
0242 {
0243 switch (offset) {
0244 case P50_GPIO_LINE_BTN:
0245 return GPIO_LINE_DIRECTION_IN;
0246
0247 case P50_GPIO_LINE_LED:
0248 return GPIO_LINE_DIRECTION_OUT;
0249
0250 default:
0251 return -EINVAL;
0252 }
0253 }
0254
0255 static int p50_gpio_get(struct gpio_chip *gc, unsigned int offset)
0256 {
0257 struct p50_gpio *p50 = gpiochip_get_data(gc);
0258 int ret;
0259
0260 mutex_lock(&p50->lock);
0261
0262 ret = p50_send_mbox_cmd(p50, P50_MBOX_CMD_READ_GPIO, gpio_params[offset], 0);
0263 if (ret == 0)
0264 ret = p50_read_mbox_reg(p50, P50_MBOX_REG_DATA);
0265
0266 mutex_unlock(&p50->lock);
0267
0268 return ret;
0269 }
0270
0271 static void p50_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
0272 {
0273 struct p50_gpio *p50 = gpiochip_get_data(gc);
0274
0275 mutex_lock(&p50->lock);
0276
0277 p50_send_mbox_cmd(p50, P50_MBOX_CMD_WRITE_GPIO, gpio_params[offset], value);
0278
0279 mutex_unlock(&p50->lock);
0280 }
0281
0282 static int p50_gpio_probe(struct platform_device *pdev)
0283 {
0284 struct p50_gpio *p50;
0285 struct resource *res;
0286 int ret;
0287
0288 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
0289 if (!res) {
0290 dev_err(&pdev->dev, "Cannot get I/O ports\n");
0291 return -ENODEV;
0292 }
0293
0294 if (!devm_request_region(&pdev->dev, res->start, resource_size(res), pdev->name)) {
0295 dev_err(&pdev->dev, "Unable to reserve I/O region\n");
0296 return -EBUSY;
0297 }
0298
0299 p50 = devm_kzalloc(&pdev->dev, sizeof(*p50), GFP_KERNEL);
0300 if (!p50)
0301 return -ENOMEM;
0302
0303 platform_set_drvdata(pdev, p50);
0304 mutex_init(&p50->lock);
0305 p50->base = res->start;
0306 p50->gc.owner = THIS_MODULE;
0307 p50->gc.parent = &pdev->dev;
0308 p50->gc.label = dev_name(&pdev->dev);
0309 p50->gc.ngpio = ARRAY_SIZE(gpio_names);
0310 p50->gc.names = gpio_names;
0311 p50->gc.can_sleep = true;
0312 p50->gc.base = -1;
0313 p50->gc.get_direction = p50_gpio_get_direction;
0314 p50->gc.get = p50_gpio_get;
0315 p50->gc.set = p50_gpio_set;
0316
0317
0318
0319 ret = p50_wait_mbox_idle(p50);
0320 if (ret)
0321 return ret;
0322
0323 ret = p50_write_mbox_reg(p50, P50_MBOX_REG_CMD, P50_MBOX_CMD_CLEAR);
0324 if (ret)
0325 return ret;
0326
0327 ret = p50_wait_mbox_idle(p50);
0328 if (ret)
0329 return ret;
0330
0331
0332 ret = devm_gpiochip_add_data(&pdev->dev, &p50->gc, p50);
0333 if (ret < 0) {
0334 dev_err(&pdev->dev, "Could not register gpiochip: %d\n", ret);
0335 return ret;
0336 }
0337
0338 gpiod_add_lookup_table(&p50_gpio_led_table);
0339
0340 p50->leds_pdev = platform_device_register_data(&pdev->dev,
0341 "leds-gpio", PLATFORM_DEVID_NONE, &leds_pdata, sizeof(leds_pdata));
0342
0343 if (IS_ERR(p50->leds_pdev)) {
0344 ret = PTR_ERR(p50->leds_pdev);
0345 dev_err(&pdev->dev, "Could not register leds-gpio: %d\n", ret);
0346 goto err_leds;
0347 }
0348
0349
0350 buttons[0].gpio += p50->gc.base;
0351
0352 p50->keys_pdev =
0353 platform_device_register_data(&pdev->dev, "gpio-keys-polled",
0354 PLATFORM_DEVID_NONE,
0355 &keys_pdata, sizeof(keys_pdata));
0356
0357 if (IS_ERR(p50->keys_pdev)) {
0358 ret = PTR_ERR(p50->keys_pdev);
0359 dev_err(&pdev->dev, "Could not register gpio-keys-polled: %d\n", ret);
0360 goto err_keys;
0361 }
0362
0363 return 0;
0364
0365 err_keys:
0366 platform_device_unregister(p50->leds_pdev);
0367 err_leds:
0368 gpiod_remove_lookup_table(&p50_gpio_led_table);
0369
0370 return ret;
0371 }
0372
0373 static int p50_gpio_remove(struct platform_device *pdev)
0374 {
0375 struct p50_gpio *p50 = platform_get_drvdata(pdev);
0376
0377 platform_device_unregister(p50->keys_pdev);
0378 platform_device_unregister(p50->leds_pdev);
0379
0380 gpiod_remove_lookup_table(&p50_gpio_led_table);
0381
0382 return 0;
0383 }
0384
0385 static struct platform_driver p50_gpio_driver = {
0386 .driver = {
0387 .name = DRIVER_NAME,
0388 },
0389 .probe = p50_gpio_probe,
0390 .remove = p50_gpio_remove,
0391 };
0392
0393
0394 static const struct dmi_system_id dmi_ids[] __initconst = {
0395 {
0396 .matches = {
0397 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Barco"),
0398 DMI_EXACT_MATCH(DMI_PRODUCT_FAMILY, "P50")
0399 },
0400 },
0401 {}
0402 };
0403 MODULE_DEVICE_TABLE(dmi, dmi_ids);
0404
0405 static int __init p50_module_init(void)
0406 {
0407 struct resource res = DEFINE_RES_IO(P50_GPIO_IO_PORT_BASE, P50_PORT_CMD + 1);
0408 int ret;
0409
0410 if (!dmi_first_match(dmi_ids))
0411 return -ENODEV;
0412
0413 ret = platform_driver_register(&p50_gpio_driver);
0414 if (ret)
0415 return ret;
0416
0417 gpio_pdev = platform_device_register_simple(DRIVER_NAME, PLATFORM_DEVID_NONE, &res, 1);
0418 if (IS_ERR(gpio_pdev)) {
0419 pr_err("failed registering %s: %ld\n", DRIVER_NAME, PTR_ERR(gpio_pdev));
0420 platform_driver_unregister(&p50_gpio_driver);
0421 return PTR_ERR(gpio_pdev);
0422 }
0423
0424 return 0;
0425 }
0426
0427 static void __exit p50_module_exit(void)
0428 {
0429 platform_device_unregister(gpio_pdev);
0430 platform_driver_unregister(&p50_gpio_driver);
0431 }
0432
0433 module_init(p50_module_init);
0434 module_exit(p50_module_exit);
0435
0436 MODULE_AUTHOR("Santosh Kumar Yadav, Barco NV <santoshkumar.yadav@barco.com>");
0437 MODULE_DESCRIPTION("Barco P50 identify GPIOs driver");
0438 MODULE_LICENSE("GPL");