Path: blob/master/drivers/input/keyboard/opencores-kbd.c
15111 views
/*1* OpenCores Keyboard Controller Driver2* http://www.opencores.org/project,keyboardcontroller3*4* Copyright 2007-2009 HV Sistemas S.L.5*6* Licensed under the GPL-2 or later.7*/89#include <linux/input.h>10#include <linux/interrupt.h>11#include <linux/io.h>12#include <linux/ioport.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/platform_device.h>16#include <linux/slab.h>1718struct opencores_kbd {19struct input_dev *input;20struct resource *addr_res;21void __iomem *addr;22int irq;23unsigned short keycodes[128];24};2526static irqreturn_t opencores_kbd_isr(int irq, void *dev_id)27{28struct opencores_kbd *opencores_kbd = dev_id;29struct input_dev *input = opencores_kbd->input;30unsigned char c;3132c = readb(opencores_kbd->addr);33input_report_key(input, c & 0x7f, c & 0x80 ? 0 : 1);34input_sync(input);3536return IRQ_HANDLED;37}3839static int __devinit opencores_kbd_probe(struct platform_device *pdev)40{41struct input_dev *input;42struct opencores_kbd *opencores_kbd;43struct resource *res;44int irq, i, error;4546res = platform_get_resource(pdev, IORESOURCE_MEM, 0);47if (!res) {48dev_err(&pdev->dev, "missing board memory resource\n");49return -EINVAL;50}5152irq = platform_get_irq(pdev, 0);53if (irq < 0) {54dev_err(&pdev->dev, "missing board IRQ resource\n");55return -EINVAL;56}5758opencores_kbd = kzalloc(sizeof(*opencores_kbd), GFP_KERNEL);59input = input_allocate_device();60if (!opencores_kbd || !input) {61dev_err(&pdev->dev, "failed to allocate device structures\n");62error = -ENOMEM;63goto err_free_mem;64}6566opencores_kbd->addr_res = res;67res = request_mem_region(res->start, resource_size(res), pdev->name);68if (!res) {69dev_err(&pdev->dev, "failed to request I/O memory\n");70error = -EBUSY;71goto err_free_mem;72}7374opencores_kbd->addr = ioremap(res->start, resource_size(res));75if (!opencores_kbd->addr) {76dev_err(&pdev->dev, "failed to remap I/O memory\n");77error = -ENXIO;78goto err_rel_mem;79}8081opencores_kbd->input = input;82opencores_kbd->irq = irq;8384input->name = pdev->name;85input->phys = "opencores-kbd/input0";86input->dev.parent = &pdev->dev;8788input_set_drvdata(input, opencores_kbd);8990input->id.bustype = BUS_HOST;91input->id.vendor = 0x0001;92input->id.product = 0x0001;93input->id.version = 0x0100;9495input->keycode = opencores_kbd->keycodes;96input->keycodesize = sizeof(opencores_kbd->keycodes[0]);97input->keycodemax = ARRAY_SIZE(opencores_kbd->keycodes);9899__set_bit(EV_KEY, input->evbit);100101for (i = 0; i < ARRAY_SIZE(opencores_kbd->keycodes); i++) {102/*103* OpenCores controller happens to have scancodes match104* our KEY_* definitions.105*/106opencores_kbd->keycodes[i] = i;107__set_bit(opencores_kbd->keycodes[i], input->keybit);108}109__clear_bit(KEY_RESERVED, input->keybit);110111error = request_irq(irq, &opencores_kbd_isr,112IRQF_TRIGGER_RISING, pdev->name, opencores_kbd);113if (error) {114dev_err(&pdev->dev, "unable to claim irq %d\n", irq);115goto err_unmap_mem;116}117118error = input_register_device(input);119if (error) {120dev_err(&pdev->dev, "unable to register input device\n");121goto err_free_irq;122}123124platform_set_drvdata(pdev, opencores_kbd);125126return 0;127128err_free_irq:129free_irq(irq, opencores_kbd);130err_unmap_mem:131iounmap(opencores_kbd->addr);132err_rel_mem:133release_mem_region(res->start, resource_size(res));134err_free_mem:135input_free_device(input);136kfree(opencores_kbd);137138return error;139}140141static int __devexit opencores_kbd_remove(struct platform_device *pdev)142{143struct opencores_kbd *opencores_kbd = platform_get_drvdata(pdev);144145free_irq(opencores_kbd->irq, opencores_kbd);146147iounmap(opencores_kbd->addr);148release_mem_region(opencores_kbd->addr_res->start,149resource_size(opencores_kbd->addr_res));150input_unregister_device(opencores_kbd->input);151kfree(opencores_kbd);152153platform_set_drvdata(pdev, NULL);154155return 0;156}157158static struct platform_driver opencores_kbd_device_driver = {159.probe = opencores_kbd_probe,160.remove = __devexit_p(opencores_kbd_remove),161.driver = {162.name = "opencores-kbd",163},164};165166static int __init opencores_kbd_init(void)167{168return platform_driver_register(&opencores_kbd_device_driver);169}170module_init(opencores_kbd_init);171172static void __exit opencores_kbd_exit(void)173{174platform_driver_unregister(&opencores_kbd_device_driver);175}176module_exit(opencores_kbd_exit);177178MODULE_LICENSE("GPL");179MODULE_AUTHOR("Javier Herrero <[email protected]>");180MODULE_DESCRIPTION("Keyboard driver for OpenCores Keyboard Controller");181182183