1 /* 2 * SPEAr Keyboard Driver 3 * Based on omap-keypad driver 4 * 5 * Copyright (C) 2010 ST Microelectronics 6 * Rajeev Kumar<rajeev-dlh.kumar@st.com> 7 * 8 * This file is licensed under the terms of the GNU General Public 9 * License version 2. This program is licensed "as is" without any 10 * warranty of any kind, whether express or implied. 11 */ 12 13 #include <linux/clk.h> 14 #include <linux/errno.h> 15 #include <linux/init.h> 16 #include <linux/interrupt.h> 17 #include <linux/input.h> 18 #include <linux/io.h> 19 #include <linux/irq.h> 20 #include <linux/kernel.h> 21 #include <linux/module.h> 22 #include <linux/platform_device.h> 23 #include <linux/pm_wakeup.h> 24 #include <linux/slab.h> 25 #include <linux/types.h> 26 #include <plat/keyboard.h> 27 28 /* Keyboard Registers */ 29 #define MODE_REG 0x00 /* 16 bit reg */ 30 #define STATUS_REG 0x0C /* 2 bit reg */ 31 #define DATA_REG 0x10 /* 8 bit reg */ 32 #define INTR_MASK 0x54 33 34 /* Register Values */ 35 /* 36 * pclk freq mask = (APB FEQ -1)= 82 MHZ.Programme bit 15-9 in mode 37 * control register as 1010010(82MHZ) 38 */ 39 #define PCLK_FREQ_MSK 0xA400 /* 82 MHz */ 40 #define START_SCAN 0x0100 41 #define SCAN_RATE_10 0x0000 42 #define SCAN_RATE_20 0x0004 43 #define SCAN_RATE_40 0x0008 44 #define SCAN_RATE_80 0x000C 45 #define MODE_KEYBOARD 0x0002 46 #define DATA_AVAIL 0x2 47 48 #define KEY_MASK 0xFF000000 49 #define KEY_VALUE 0x00FFFFFF 50 #define ROW_MASK 0xF0 51 #define COLUMN_MASK 0x0F 52 #define ROW_SHIFT 4 53 #define KEY_MATRIX_SHIFT 6 54 55 struct spear_kbd { 56 struct input_dev *input; 57 struct resource *res; 58 void __iomem *io_base; 59 struct clk *clk; 60 unsigned int irq; 61 unsigned int mode; 62 unsigned short last_key; 63 unsigned short keycodes[256]; 64 }; 65 66 static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id) 67 { 68 struct spear_kbd *kbd = dev_id; 69 struct input_dev *input = kbd->input; 70 unsigned int key; 71 u8 sts, val; 72 73 sts = readb(kbd->io_base + STATUS_REG); 74 if (!(sts & DATA_AVAIL)) 75 return IRQ_NONE; 76 77 if (kbd->last_key != KEY_RESERVED) { 78 input_report_key(input, kbd->last_key, 0); 79 kbd->last_key = KEY_RESERVED; 80 } 81 82 /* following reads active (row, col) pair */ 83 val = readb(kbd->io_base + DATA_REG); 84 key = kbd->keycodes[val]; 85 86 input_event(input, EV_MSC, MSC_SCAN, val); 87 input_report_key(input, key, 1); 88 input_sync(input); 89 90 kbd->last_key = key; 91 92 /* clear interrupt */ 93 writeb(0, kbd->io_base + STATUS_REG); 94 95 return IRQ_HANDLED; 96 } 97 98 static int spear_kbd_open(struct input_dev *dev) 99 { 100 struct spear_kbd *kbd = input_get_drvdata(dev); 101 int error; 102 u16 val; 103 104 kbd->last_key = KEY_RESERVED; 105 106 error = clk_enable(kbd->clk); 107 if (error) 108 return error; 109 110 /* program keyboard */ 111 val = SCAN_RATE_80 | MODE_KEYBOARD | PCLK_FREQ_MSK | 112 (kbd->mode << KEY_MATRIX_SHIFT); 113 writew(val, kbd->io_base + MODE_REG); 114 writeb(1, kbd->io_base + STATUS_REG); 115 116 /* start key scan */ 117 val = readw(kbd->io_base + MODE_REG); 118 val |= START_SCAN; 119 writew(val, kbd->io_base + MODE_REG); 120 121 return 0; 122 } 123 124 static void spear_kbd_close(struct input_dev *dev) 125 { 126 struct spear_kbd *kbd = input_get_drvdata(dev); 127 u16 val; 128 129 /* stop key scan */ 130 val = readw(kbd->io_base + MODE_REG); 131 val &= ~START_SCAN; 132 writew(val, kbd->io_base + MODE_REG); 133 134 clk_disable(kbd->clk); 135 136 kbd->last_key = KEY_RESERVED; 137 } 138 139 static int __devinit spear_kbd_probe(struct platform_device *pdev) 140 { 141 const struct kbd_platform_data *pdata = pdev->dev.platform_data; 142 const struct matrix_keymap_data *keymap; 143 struct spear_kbd *kbd; 144 struct input_dev *input_dev; 145 struct resource *res; 146 int irq; 147 int error; 148 149 if (!pdata) { 150 dev_err(&pdev->dev, "Invalid platform data\n"); 151 return -EINVAL; 152 } 153 154 keymap = pdata->keymap; 155 if (!keymap) { 156 dev_err(&pdev->dev, "no keymap defined\n"); 157 return -EINVAL; 158 } 159 160 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 161 if (!res) { 162 dev_err(&pdev->dev, "no keyboard resource defined\n"); 163 return -EBUSY; 164 } 165 166 irq = platform_get_irq(pdev, 0); 167 if (irq < 0) { 168 dev_err(&pdev->dev, "not able to get irq for the device\n"); 169 return irq; 170 } 171 172 kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); 173 input_dev = input_allocate_device(); 174 if (!kbd || !input_dev) { 175 dev_err(&pdev->dev, "out of memory\n"); 176 error = -ENOMEM; 177 goto err_free_mem; 178 } 179 180 kbd->input = input_dev; 181 kbd->irq = irq; 182 kbd->mode = pdata->mode; 183 184 kbd->res = request_mem_region(res->start, resource_size(res), 185 pdev->name); 186 if (!kbd->res) { 187 dev_err(&pdev->dev, "keyboard region already claimed\n"); 188 error = -EBUSY; 189 goto err_free_mem; 190 } 191 192 kbd->io_base = ioremap(res->start, resource_size(res)); 193 if (!kbd->io_base) { 194 dev_err(&pdev->dev, "ioremap failed for kbd_region\n"); 195 error = -ENOMEM; 196 goto err_release_mem_region; 197 } 198 199 kbd->clk = clk_get(&pdev->dev, NULL); 200 if (IS_ERR(kbd->clk)) { 201 error = PTR_ERR(kbd->clk); 202 goto err_iounmap; 203 } 204 205 input_dev->name = "Spear Keyboard"; 206 input_dev->phys = "keyboard/input0"; 207 input_dev->dev.parent = &pdev->dev; 208 input_dev->id.bustype = BUS_HOST; 209 input_dev->id.vendor = 0x0001; 210 input_dev->id.product = 0x0001; 211 input_dev->id.version = 0x0100; 212 input_dev->open = spear_kbd_open; 213 input_dev->close = spear_kbd_close; 214 215 __set_bit(EV_KEY, input_dev->evbit); 216 if (pdata->rep) 217 __set_bit(EV_REP, input_dev->evbit); 218 input_set_capability(input_dev, EV_MSC, MSC_SCAN); 219 220 input_dev->keycode = kbd->keycodes; 221 input_dev->keycodesize = sizeof(kbd->keycodes[0]); 222 input_dev->keycodemax = ARRAY_SIZE(kbd->keycodes); 223 224 matrix_keypad_build_keymap(keymap, ROW_SHIFT, 225 input_dev->keycode, input_dev->keybit); 226 227 input_set_drvdata(input_dev, kbd); 228 229 error = request_irq(irq, spear_kbd_interrupt, 0, "keyboard", kbd); 230 if (error) { 231 dev_err(&pdev->dev, "request_irq fail\n"); 232 goto err_put_clk; 233 } 234 235 error = input_register_device(input_dev); 236 if (error) { 237 dev_err(&pdev->dev, "Unable to register keyboard device\n"); 238 goto err_free_irq; 239 } 240 241 device_init_wakeup(&pdev->dev, 1); 242 platform_set_drvdata(pdev, kbd); 243 244 return 0; 245 246 err_free_irq: 247 free_irq(kbd->irq, kbd); 248 err_put_clk: 249 clk_put(kbd->clk); 250 err_iounmap: 251 iounmap(kbd->io_base); 252 err_release_mem_region: 253 release_mem_region(res->start, resource_size(res)); 254 err_free_mem: 255 input_free_device(input_dev); 256 kfree(kbd); 257 258 return error; 259 } 260 261 static int __devexit spear_kbd_remove(struct platform_device *pdev) 262 { 263 struct spear_kbd *kbd = platform_get_drvdata(pdev); 264 265 free_irq(kbd->irq, kbd); 266 input_unregister_device(kbd->input); 267 clk_put(kbd->clk); 268 iounmap(kbd->io_base); 269 release_mem_region(kbd->res->start, resource_size(kbd->res)); 270 kfree(kbd); 271 272 device_init_wakeup(&pdev->dev, 1); 273 platform_set_drvdata(pdev, NULL); 274 275 return 0; 276 } 277 278 #ifdef CONFIG_PM 279 static int spear_kbd_suspend(struct device *dev) 280 { 281 struct platform_device *pdev = to_platform_device(dev); 282 struct spear_kbd *kbd = platform_get_drvdata(pdev); 283 struct input_dev *input_dev = kbd->input; 284 285 mutex_lock(&input_dev->mutex); 286 287 if (input_dev->users) 288 clk_enable(kbd->clk); 289 290 if (device_may_wakeup(&pdev->dev)) 291 enable_irq_wake(kbd->irq); 292 293 mutex_unlock(&input_dev->mutex); 294 295 return 0; 296 } 297 298 static int spear_kbd_resume(struct device *dev) 299 { 300 struct platform_device *pdev = to_platform_device(dev); 301 struct spear_kbd *kbd = platform_get_drvdata(pdev); 302 struct input_dev *input_dev = kbd->input; 303 304 mutex_lock(&input_dev->mutex); 305 306 if (device_may_wakeup(&pdev->dev)) 307 disable_irq_wake(kbd->irq); 308 309 if (input_dev->users) 310 clk_enable(kbd->clk); 311 312 mutex_unlock(&input_dev->mutex); 313 314 return 0; 315 } 316 #endif 317 318 static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, spear_kbd_suspend, spear_kbd_resume); 319 320 static struct platform_driver spear_kbd_driver = { 321 .probe = spear_kbd_probe, 322 .remove = __devexit_p(spear_kbd_remove), 323 .driver = { 324 .name = "keyboard", 325 .owner = THIS_MODULE, 326 .pm = &spear_kbd_pm_ops, 327 }, 328 }; 329 module_platform_driver(spear_kbd_driver); 330 331 MODULE_AUTHOR("Rajeev Kumar"); 332 MODULE_DESCRIPTION("SPEAr Keyboard Driver"); 333 MODULE_LICENSE("GPL"); 334