1 /* 2 * SuperH KEYSC Keypad Driver 3 * 4 * Copyright (C) 2008 Magnus Damm 5 * 6 * Based on gpio_keys.c, Copyright 2005 Phil Blundell 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/init.h> 16 #include <linux/interrupt.h> 17 #include <linux/irq.h> 18 #include <linux/delay.h> 19 #include <linux/platform_device.h> 20 #include <linux/input.h> 21 #include <linux/input/sh_keysc.h> 22 #include <linux/clk.h> 23 #include <linux/io.h> 24 25 #define KYCR1_OFFS 0x00 26 #define KYCR2_OFFS 0x04 27 #define KYINDR_OFFS 0x08 28 #define KYOUTDR_OFFS 0x0c 29 30 #define KYCR2_IRQ_LEVEL 0x10 31 #define KYCR2_IRQ_DISABLED 0x00 32 33 static const struct { 34 unsigned char kymd, keyout, keyin; 35 } sh_keysc_mode[] = { 36 [SH_KEYSC_MODE_1] = { 0, 6, 5 }, 37 [SH_KEYSC_MODE_2] = { 1, 5, 6 }, 38 [SH_KEYSC_MODE_3] = { 2, 4, 7 }, 39 }; 40 41 struct sh_keysc_priv { 42 void __iomem *iomem_base; 43 struct clk *clk; 44 unsigned long last_keys; 45 struct input_dev *input; 46 struct sh_keysc_info pdata; 47 }; 48 49 static irqreturn_t sh_keysc_isr(int irq, void *dev_id) 50 { 51 struct platform_device *pdev = dev_id; 52 struct sh_keysc_priv *priv = platform_get_drvdata(pdev); 53 struct sh_keysc_info *pdata = &priv->pdata; 54 unsigned long keys, keys1, keys0, mask; 55 unsigned char keyin_set, tmp; 56 int i, k; 57 58 dev_dbg(&pdev->dev, "isr!\n"); 59 60 keys1 = ~0; 61 keys0 = 0; 62 63 do { 64 keys = 0; 65 keyin_set = 0; 66 67 iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS); 68 69 for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) { 70 iowrite16(0xfff ^ (3 << (i * 2)), 71 priv->iomem_base + KYOUTDR_OFFS); 72 udelay(pdata->delay); 73 tmp = ioread16(priv->iomem_base + KYINDR_OFFS); 74 keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i); 75 tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1; 76 keyin_set |= tmp; 77 } 78 79 iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); 80 iowrite16(KYCR2_IRQ_LEVEL | (keyin_set << 8), 81 priv->iomem_base + KYCR2_OFFS); 82 83 if (pdata->kycr2_delay) 84 udelay(pdata->kycr2_delay); 85 86 keys ^= ~0; 87 keys &= (1 << (sh_keysc_mode[pdata->mode].keyin * 88 sh_keysc_mode[pdata->mode].keyout)) - 1; 89 keys1 &= keys; 90 keys0 |= keys; 91 92 dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys); 93 94 } while (ioread16(priv->iomem_base + KYCR2_OFFS) & 0x01); 95 96 dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n", 97 priv->last_keys, keys0, keys1); 98 99 for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { 100 k = pdata->keycodes[i]; 101 if (!k) 102 continue; 103 104 mask = 1 << i; 105 106 if (!((priv->last_keys ^ keys0) & mask)) 107 continue; 108 109 if ((keys1 | keys0) & mask) { 110 input_event(priv->input, EV_KEY, k, 1); 111 priv->last_keys |= mask; 112 } 113 114 if (!(keys1 & mask)) { 115 input_event(priv->input, EV_KEY, k, 0); 116 priv->last_keys &= ~mask; 117 } 118 119 } 120 input_sync(priv->input); 121 122 return IRQ_HANDLED; 123 } 124 125 #define res_size(res) ((res)->end - (res)->start + 1) 126 127 static int __devinit sh_keysc_probe(struct platform_device *pdev) 128 { 129 struct sh_keysc_priv *priv; 130 struct sh_keysc_info *pdata; 131 struct resource *res; 132 struct input_dev *input; 133 char clk_name[8]; 134 int i; 135 int irq, error; 136 137 if (!pdev->dev.platform_data) { 138 dev_err(&pdev->dev, "no platform data defined\n"); 139 error = -EINVAL; 140 goto err0; 141 } 142 143 error = -ENXIO; 144 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 145 if (res == NULL) { 146 dev_err(&pdev->dev, "failed to get I/O memory\n"); 147 goto err0; 148 } 149 150 irq = platform_get_irq(pdev, 0); 151 if (irq < 0) { 152 dev_err(&pdev->dev, "failed to get irq\n"); 153 goto err0; 154 } 155 156 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 157 if (priv == NULL) { 158 dev_err(&pdev->dev, "failed to allocate driver data\n"); 159 error = -ENOMEM; 160 goto err0; 161 } 162 163 platform_set_drvdata(pdev, priv); 164 memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata)); 165 pdata = &priv->pdata; 166 167 priv->iomem_base = ioremap_nocache(res->start, res_size(res)); 168 if (priv->iomem_base == NULL) { 169 dev_err(&pdev->dev, "failed to remap I/O memory\n"); 170 error = -ENXIO; 171 goto err1; 172 } 173 174 snprintf(clk_name, sizeof(clk_name), "keysc%d", pdev->id); 175 priv->clk = clk_get(&pdev->dev, clk_name); 176 if (IS_ERR(priv->clk)) { 177 dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); 178 error = PTR_ERR(priv->clk); 179 goto err2; 180 } 181 182 priv->input = input_allocate_device(); 183 if (!priv->input) { 184 dev_err(&pdev->dev, "failed to allocate input device\n"); 185 error = -ENOMEM; 186 goto err3; 187 } 188 189 input = priv->input; 190 input->evbit[0] = BIT_MASK(EV_KEY); 191 192 input->name = pdev->name; 193 input->phys = "sh-keysc-keys/input0"; 194 input->dev.parent = &pdev->dev; 195 196 input->id.bustype = BUS_HOST; 197 input->id.vendor = 0x0001; 198 input->id.product = 0x0001; 199 input->id.version = 0x0100; 200 201 input->keycode = pdata->keycodes; 202 input->keycodesize = sizeof(pdata->keycodes[0]); 203 input->keycodemax = ARRAY_SIZE(pdata->keycodes); 204 205 error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); 206 if (error) { 207 dev_err(&pdev->dev, "failed to request IRQ\n"); 208 goto err4; 209 } 210 211 for (i = 0; i < SH_KEYSC_MAXKEYS; i++) 212 __set_bit(pdata->keycodes[i], input->keybit); 213 __clear_bit(KEY_RESERVED, input->keybit); 214 215 error = input_register_device(input); 216 if (error) { 217 dev_err(&pdev->dev, "failed to register input device\n"); 218 goto err5; 219 } 220 221 clk_enable(priv->clk); 222 223 iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) | 224 pdata->scan_timing, priv->iomem_base + KYCR1_OFFS); 225 iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); 226 iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); 227 228 device_init_wakeup(&pdev->dev, 1); 229 230 return 0; 231 232 err5: 233 free_irq(irq, pdev); 234 err4: 235 input_free_device(input); 236 err3: 237 clk_put(priv->clk); 238 err2: 239 iounmap(priv->iomem_base); 240 err1: 241 platform_set_drvdata(pdev, NULL); 242 kfree(priv); 243 err0: 244 return error; 245 } 246 247 static int __devexit sh_keysc_remove(struct platform_device *pdev) 248 { 249 struct sh_keysc_priv *priv = platform_get_drvdata(pdev); 250 251 iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS); 252 253 input_unregister_device(priv->input); 254 free_irq(platform_get_irq(pdev, 0), pdev); 255 iounmap(priv->iomem_base); 256 257 clk_disable(priv->clk); 258 clk_put(priv->clk); 259 260 platform_set_drvdata(pdev, NULL); 261 kfree(priv); 262 263 return 0; 264 } 265 266 static int sh_keysc_suspend(struct device *dev) 267 { 268 struct platform_device *pdev = to_platform_device(dev); 269 struct sh_keysc_priv *priv = platform_get_drvdata(pdev); 270 int irq = platform_get_irq(pdev, 0); 271 unsigned short value; 272 273 value = ioread16(priv->iomem_base + KYCR1_OFFS); 274 275 if (device_may_wakeup(dev)) { 276 value |= 0x80; 277 enable_irq_wake(irq); 278 } else { 279 value &= ~0x80; 280 } 281 282 iowrite16(value, priv->iomem_base + KYCR1_OFFS); 283 284 return 0; 285 } 286 287 static int sh_keysc_resume(struct device *dev) 288 { 289 struct platform_device *pdev = to_platform_device(dev); 290 int irq = platform_get_irq(pdev, 0); 291 292 if (device_may_wakeup(dev)) 293 disable_irq_wake(irq); 294 295 return 0; 296 } 297 298 static const struct dev_pm_ops sh_keysc_dev_pm_ops = { 299 .suspend = sh_keysc_suspend, 300 .resume = sh_keysc_resume, 301 }; 302 303 struct platform_driver sh_keysc_device_driver = { 304 .probe = sh_keysc_probe, 305 .remove = __devexit_p(sh_keysc_remove), 306 .driver = { 307 .name = "sh_keysc", 308 .pm = &sh_keysc_dev_pm_ops, 309 } 310 }; 311 312 static int __init sh_keysc_init(void) 313 { 314 return platform_driver_register(&sh_keysc_device_driver); 315 } 316 317 static void __exit sh_keysc_exit(void) 318 { 319 platform_driver_unregister(&sh_keysc_device_driver); 320 } 321 322 module_init(sh_keysc_init); 323 module_exit(sh_keysc_exit); 324 325 MODULE_AUTHOR("Magnus Damm"); 326 MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver"); 327 MODULE_LICENSE("GPL"); 328