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/clk.h> 22 #include <linux/io.h> 23 #include <asm/sh_keysc.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 keys ^= ~0; 84 keys &= (1 << (sh_keysc_mode[pdata->mode].keyin * 85 sh_keysc_mode[pdata->mode].keyout)) - 1; 86 keys1 &= keys; 87 keys0 |= keys; 88 89 dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys); 90 91 } while (ioread16(priv->iomem_base + KYCR2_OFFS) & 0x01); 92 93 dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n", 94 priv->last_keys, keys0, keys1); 95 96 for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { 97 k = pdata->keycodes[i]; 98 if (!k) 99 continue; 100 101 mask = 1 << i; 102 103 if (!((priv->last_keys ^ keys0) & mask)) 104 continue; 105 106 if ((keys1 | keys0) & mask) { 107 input_event(priv->input, EV_KEY, k, 1); 108 priv->last_keys |= mask; 109 } 110 111 if (!(keys1 & mask)) { 112 input_event(priv->input, EV_KEY, k, 0); 113 priv->last_keys &= ~mask; 114 } 115 116 } 117 input_sync(priv->input); 118 119 return IRQ_HANDLED; 120 } 121 122 #define res_size(res) ((res)->end - (res)->start + 1) 123 124 static int __devinit sh_keysc_probe(struct platform_device *pdev) 125 { 126 struct sh_keysc_priv *priv; 127 struct sh_keysc_info *pdata; 128 struct resource *res; 129 struct input_dev *input; 130 char clk_name[8]; 131 int i; 132 int irq, error; 133 134 if (!pdev->dev.platform_data) { 135 dev_err(&pdev->dev, "no platform data defined\n"); 136 error = -EINVAL; 137 goto err0; 138 } 139 140 error = -ENXIO; 141 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 142 if (res == NULL) { 143 dev_err(&pdev->dev, "failed to get I/O memory\n"); 144 goto err0; 145 } 146 147 irq = platform_get_irq(pdev, 0); 148 if (irq < 0) { 149 dev_err(&pdev->dev, "failed to get irq\n"); 150 goto err0; 151 } 152 153 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 154 if (priv == NULL) { 155 dev_err(&pdev->dev, "failed to allocate driver data\n"); 156 error = -ENOMEM; 157 goto err0; 158 } 159 160 platform_set_drvdata(pdev, priv); 161 memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata)); 162 pdata = &priv->pdata; 163 164 priv->iomem_base = ioremap_nocache(res->start, res_size(res)); 165 if (priv->iomem_base == NULL) { 166 dev_err(&pdev->dev, "failed to remap I/O memory\n"); 167 error = -ENXIO; 168 goto err1; 169 } 170 171 snprintf(clk_name, sizeof(clk_name), "keysc%d", pdev->id); 172 priv->clk = clk_get(&pdev->dev, clk_name); 173 if (IS_ERR(priv->clk)) { 174 dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); 175 error = PTR_ERR(priv->clk); 176 goto err2; 177 } 178 179 priv->input = input_allocate_device(); 180 if (!priv->input) { 181 dev_err(&pdev->dev, "failed to allocate input device\n"); 182 error = -ENOMEM; 183 goto err3; 184 } 185 186 input = priv->input; 187 input->evbit[0] = BIT_MASK(EV_KEY); 188 189 input->name = pdev->name; 190 input->phys = "sh-keysc-keys/input0"; 191 input->dev.parent = &pdev->dev; 192 193 input->id.bustype = BUS_HOST; 194 input->id.vendor = 0x0001; 195 input->id.product = 0x0001; 196 input->id.version = 0x0100; 197 198 input->keycode = pdata->keycodes; 199 input->keycodesize = sizeof(pdata->keycodes[0]); 200 input->keycodemax = ARRAY_SIZE(pdata->keycodes); 201 202 error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); 203 if (error) { 204 dev_err(&pdev->dev, "failed to request IRQ\n"); 205 goto err4; 206 } 207 208 for (i = 0; i < SH_KEYSC_MAXKEYS; i++) 209 __set_bit(pdata->keycodes[i], input->keybit); 210 __clear_bit(KEY_RESERVED, input->keybit); 211 212 error = input_register_device(input); 213 if (error) { 214 dev_err(&pdev->dev, "failed to register input device\n"); 215 goto err5; 216 } 217 218 clk_enable(priv->clk); 219 220 iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) | 221 pdata->scan_timing, priv->iomem_base + KYCR1_OFFS); 222 iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); 223 iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); 224 225 device_init_wakeup(&pdev->dev, 1); 226 227 return 0; 228 229 err5: 230 free_irq(irq, pdev); 231 err4: 232 input_free_device(input); 233 err3: 234 clk_put(priv->clk); 235 err2: 236 iounmap(priv->iomem_base); 237 err1: 238 platform_set_drvdata(pdev, NULL); 239 kfree(priv); 240 err0: 241 return error; 242 } 243 244 static int __devexit sh_keysc_remove(struct platform_device *pdev) 245 { 246 struct sh_keysc_priv *priv = platform_get_drvdata(pdev); 247 248 iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS); 249 250 input_unregister_device(priv->input); 251 free_irq(platform_get_irq(pdev, 0), pdev); 252 iounmap(priv->iomem_base); 253 254 clk_disable(priv->clk); 255 clk_put(priv->clk); 256 257 platform_set_drvdata(pdev, NULL); 258 kfree(priv); 259 260 return 0; 261 } 262 263 static int sh_keysc_suspend(struct device *dev) 264 { 265 struct platform_device *pdev = to_platform_device(dev); 266 struct sh_keysc_priv *priv = platform_get_drvdata(pdev); 267 int irq = platform_get_irq(pdev, 0); 268 unsigned short value; 269 270 value = ioread16(priv->iomem_base + KYCR1_OFFS); 271 272 if (device_may_wakeup(dev)) { 273 value |= 0x80; 274 enable_irq_wake(irq); 275 } else { 276 value &= ~0x80; 277 } 278 279 iowrite16(value, priv->iomem_base + KYCR1_OFFS); 280 281 return 0; 282 } 283 284 static int sh_keysc_resume(struct device *dev) 285 { 286 struct platform_device *pdev = to_platform_device(dev); 287 int irq = platform_get_irq(pdev, 0); 288 289 if (device_may_wakeup(dev)) 290 disable_irq_wake(irq); 291 292 return 0; 293 } 294 295 static struct dev_pm_ops sh_keysc_dev_pm_ops = { 296 .suspend = sh_keysc_suspend, 297 .resume = sh_keysc_resume, 298 }; 299 300 struct platform_driver sh_keysc_device_driver = { 301 .probe = sh_keysc_probe, 302 .remove = __devexit_p(sh_keysc_remove), 303 .driver = { 304 .name = "sh_keysc", 305 .pm = &sh_keysc_dev_pm_ops, 306 } 307 }; 308 309 static int __init sh_keysc_init(void) 310 { 311 return platform_driver_register(&sh_keysc_device_driver); 312 } 313 314 static void __exit sh_keysc_exit(void) 315 { 316 platform_driver_unregister(&sh_keysc_device_driver); 317 } 318 319 module_init(sh_keysc_init); 320 module_exit(sh_keysc_exit); 321 322 MODULE_AUTHOR("Magnus Damm"); 323 MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver"); 324 MODULE_LICENSE("GPL"); 325