diff options
Diffstat (limited to 'drivers/input/serio')
-rw-r--r-- | drivers/input/serio/q40kbd.c | 89 |
1 files changed, 57 insertions, 32 deletions
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index b44d255596c2..d3827c5fe119 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c | |||
@@ -75,13 +75,13 @@ static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
75 | 75 | ||
76 | static void q40kbd_flush(void) | 76 | static void q40kbd_flush(void) |
77 | { | 77 | { |
78 | int maxread = 100; | 78 | int maxread = 100; |
79 | unsigned long flags; | 79 | unsigned long flags; |
80 | 80 | ||
81 | spin_lock_irqsave(&q40kbd_lock, flags); | 81 | spin_lock_irqsave(&q40kbd_lock, flags); |
82 | 82 | ||
83 | while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))) | 83 | while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))) |
84 | master_inb(KEYCODE_REG); | 84 | master_inb(KEYCODE_REG); |
85 | 85 | ||
86 | spin_unlock_irqrestore(&q40kbd_lock, flags); | 86 | spin_unlock_irqrestore(&q40kbd_lock, flags); |
87 | } | 87 | } |
@@ -97,14 +97,14 @@ static int q40kbd_open(struct serio *port) | |||
97 | 97 | ||
98 | if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) { | 98 | if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) { |
99 | printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD); | 99 | printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD); |
100 | return -1; | 100 | return -EBUSY; |
101 | } | 101 | } |
102 | 102 | ||
103 | /* off we go */ | 103 | /* off we go */ |
104 | master_outb(-1, KEYBOARD_UNLOCK_REG); | 104 | master_outb(-1, KEYBOARD_UNLOCK_REG); |
105 | master_outb(1, KEY_IRQ_ENABLE_REG); | 105 | master_outb(1, KEY_IRQ_ENABLE_REG); |
106 | 106 | ||
107 | return 0; | 107 | return 0; |
108 | } | 108 | } |
109 | 109 | ||
110 | static void q40kbd_close(struct serio *port) | 110 | static void q40kbd_close(struct serio *port) |
@@ -116,48 +116,73 @@ static void q40kbd_close(struct serio *port) | |||
116 | q40kbd_flush(); | 116 | q40kbd_flush(); |
117 | } | 117 | } |
118 | 118 | ||
119 | static struct serio * __init q40kbd_allocate_port(void) | 119 | static int __devinit q40kbd_probe(struct platform_device *dev) |
120 | { | 120 | { |
121 | struct serio *serio; | 121 | q40kbd_port = kzalloc(sizeof(struct serio), GFP_KERNEL); |
122 | 122 | if (!q40kbd_port) | |
123 | serio = kmalloc(sizeof(struct serio), GFP_KERNEL); | 123 | return -ENOMEM; |
124 | if (serio) { | 124 | |
125 | memset(serio, 0, sizeof(struct serio)); | 125 | q40kbd_port->id.type = SERIO_8042; |
126 | serio->id.type = SERIO_8042; | 126 | q40kbd_port->open = q40kbd_open; |
127 | serio->open = q40kbd_open; | 127 | q40kbd_port->close = q40kbd_close; |
128 | serio->close = q40kbd_close; | 128 | q40kbd_port->dev.parent = &dev->dev; |
129 | serio->dev.parent = &q40kbd_device->dev; | 129 | strlcpy(q40kbd_port->name, "Q40 Kbd Port", sizeof(q40kbd_port->name)); |
130 | strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name)); | 130 | strlcpy(q40kbd_port->phys, "Q40", sizeof(q40kbd_port->phys)); |
131 | strlcpy(serio->phys, "Q40", sizeof(serio->phys)); | 131 | |
132 | } | 132 | serio_register_port(q40kbd_port); |
133 | printk(KERN_INFO "serio: Q40 kbd registered\n"); | ||
133 | 134 | ||
134 | return serio; | 135 | return 0; |
135 | } | 136 | } |
136 | 137 | ||
138 | static int __devexit q40kbd_remove(struct platform_device *dev) | ||
139 | { | ||
140 | serio_unregister_port(q40kbd_port); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static struct platform_driver q40kbd_driver = { | ||
146 | .driver = { | ||
147 | .name = "q40kbd", | ||
148 | .owner = THIS_MODULE, | ||
149 | }, | ||
150 | .probe = q40kbd_probe, | ||
151 | .remove = __devexit_p(q40kbd_remove), | ||
152 | }; | ||
153 | |||
137 | static int __init q40kbd_init(void) | 154 | static int __init q40kbd_init(void) |
138 | { | 155 | { |
156 | int error; | ||
157 | |||
139 | if (!MACH_IS_Q40) | 158 | if (!MACH_IS_Q40) |
140 | return -EIO; | 159 | return -EIO; |
141 | 160 | ||
142 | q40kbd_device = platform_device_register_simple("q40kbd", -1, NULL, 0); | 161 | error = platform_driver_register(&q40kbd_driver); |
143 | if (IS_ERR(q40kbd_device)) | 162 | if (error) |
144 | return PTR_ERR(q40kbd_device); | 163 | return error; |
145 | 164 | ||
146 | if (!(q40kbd_port = q40kbd_allocate_port())) { | 165 | q40kbd_device = platform_device_alloc("q40kbd", -1); |
147 | platform_device_unregister(q40kbd_device); | 166 | if (!q40kbd_device) |
148 | return -ENOMEM; | 167 | goto err_unregister_driver; |
149 | } | ||
150 | 168 | ||
151 | serio_register_port(q40kbd_port); | 169 | error = platform_device_add(q40kbd_device); |
152 | printk(KERN_INFO "serio: Q40 kbd registered\n"); | 170 | if (error) |
171 | goto err_free_device; | ||
153 | 172 | ||
154 | return 0; | 173 | return 0; |
174 | |||
175 | err_free_device: | ||
176 | platform_device_put(q40kbd_device); | ||
177 | err_unregister_driver: | ||
178 | platform_driver_unregister(&q40kbd_driver); | ||
179 | return error; | ||
155 | } | 180 | } |
156 | 181 | ||
157 | static void __exit q40kbd_exit(void) | 182 | static void __exit q40kbd_exit(void) |
158 | { | 183 | { |
159 | serio_unregister_port(q40kbd_port); | ||
160 | platform_device_unregister(q40kbd_device); | 184 | platform_device_unregister(q40kbd_device); |
185 | platform_driver_unregister(&q40kbd_driver); | ||
161 | } | 186 | } |
162 | 187 | ||
163 | module_init(q40kbd_init); | 188 | module_init(q40kbd_init); |