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/io.h> 22 #include <asm/sh_keysc.h> 23 24 #define KYCR1_OFFS 0x00 25 #define KYCR2_OFFS 0x04 26 #define KYINDR_OFFS 0x08 27 #define KYOUTDR_OFFS 0x0c 28 29 #define KYCR2_IRQ_LEVEL 0x10 30 #define KYCR2_IRQ_DISABLED 0x00 31 32 static const struct { 33 unsigned char kymd, keyout, keyin; 34 } sh_keysc_mode[] = { 35 [SH_KEYSC_MODE_1] = { 0, 6, 5 }, 36 [SH_KEYSC_MODE_2] = { 1, 5, 6 }, 37 [SH_KEYSC_MODE_3] = { 2, 4, 7 }, 38 }; 39 40 struct sh_keysc_priv { 41 void __iomem *iomem_base; 42 unsigned long last_keys; 43 struct input_dev *input; 44 struct sh_keysc_info pdata; 45 }; 46 47 static irqreturn_t sh_keysc_isr(int irq, void *dev_id) 48 { 49 struct platform_device *pdev = dev_id; 50 struct sh_keysc_priv *priv = platform_get_drvdata(pdev); 51 struct sh_keysc_info *pdata = &priv->pdata; 52 unsigned long keys, keys1, keys0, mask; 53 unsigned char keyin_set, tmp; 54 int i, k; 55 56 dev_dbg(&pdev->dev, "isr!\n"); 57 58 keys1 = ~0; 59 keys0 = 0; 60 61 do { 62 keys = 0; 63 keyin_set = 0; 64 65 iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS); 66 67 for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) { 68 iowrite16(0xfff ^ (3 << (i * 2)), 69 priv->iomem_base + KYOUTDR_OFFS); 70 udelay(pdata->delay); 71 tmp = ioread16(priv->iomem_base + KYINDR_OFFS); 72 keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i); 73 tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1; 74 keyin_set |= tmp; 75 } 76 77 iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); 78 iowrite16(KYCR2_IRQ_LEVEL | (keyin_set << 8), 79 priv->iomem_base + KYCR2_OFFS); 80 81 keys ^= ~0; 82 keys &= (1 << (sh_keysc_mode[pdata->mode].keyin * 83 sh_keysc_mode[pdata->mode].keyout)) - 1; 84 keys1 &= keys; 85 keys0 |= keys; 86 87 dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys); 88 89 } while (ioread16(priv->iomem_base + KYCR2_OFFS) & 0x01); 90 91 dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n", 92 priv->last_keys, keys0, keys1); 93 94 for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { 95 k = pdata->keycodes[i]; 96 if (!k) 97 continue; 98 99 mask = 1 << i; 100 101 if (!((priv->last_keys ^ keys0) & mask)) 102 continue; 103 104 if ((keys1 | keys0) & mask) { 105 input_event(priv->input, EV_KEY, k, 1); 106 priv->last_keys |= mask; 107 } 108 109 if (!(keys1 & mask)) { 110 input_event(priv->input, EV_KEY, k, 0); 111 priv->last_keys &= ~mask; 112 } 113 114 } 115 input_sync(priv->input); 116 117 return IRQ_HANDLED; 118 } 119 120 #define res_size(res) ((res)->end - (res)->start + 1) 121 122 static int __devinit sh_keysc_probe(struct platform_device *pdev) 123 { 124 struct sh_keysc_priv *priv; 125 struct sh_keysc_info *pdata; 126 struct resource *res; 127 struct input_dev *input; 128 int i, k; 129 int irq, error; 130 131 if (!pdev->dev.platform_data) { 132 dev_err(&pdev->dev, "no platform data defined\n"); 133 error = -EINVAL; 134 goto err0; 135 } 136 137 error = -ENXIO; 138 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 139 if (res == NULL) { 140 dev_err(&pdev->dev, "failed to get I/O memory\n"); 141 goto err0; 142 } 143 144 irq = platform_get_irq(pdev, 0); 145 if (irq < 0) { 146 dev_err(&pdev->dev, "failed to get irq\n"); 147 goto err0; 148 } 149 150 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 151 if (priv == NULL) { 152 dev_err(&pdev->dev, "failed to allocate driver data\n"); 153 error = -ENOMEM; 154 goto err0; 155 } 156 157 platform_set_drvdata(pdev, priv); 158 memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata)); 159 pdata = &priv->pdata; 160 161 res = request_mem_region(res->start, res_size(res), pdev->name); 162 if (res == NULL) { 163 dev_err(&pdev->dev, "failed to request I/O memory\n"); 164 error = -EBUSY; 165 goto err1; 166 } 167 168 priv->iomem_base = ioremap_nocache(res->start, res_size(res)); 169 if (priv->iomem_base == NULL) { 170 dev_err(&pdev->dev, "failed to remap I/O memory\n"); 171 error = -ENXIO; 172 goto err2; 173 } 174 175 priv->input = input_allocate_device(); 176 if (!priv->input) { 177 dev_err(&pdev->dev, "failed to allocate input device\n"); 178 error = -ENOMEM; 179 goto err3; 180 } 181 182 input = priv->input; 183 input->evbit[0] = BIT_MASK(EV_KEY); 184 185 input->name = pdev->name; 186 input->phys = "sh-keysc-keys/input0"; 187 input->dev.parent = &pdev->dev; 188 189 input->id.bustype = BUS_HOST; 190 input->id.vendor = 0x0001; 191 input->id.product = 0x0001; 192 input->id.version = 0x0100; 193 194 error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); 195 if (error) { 196 dev_err(&pdev->dev, "failed to request IRQ\n"); 197 goto err4; 198 } 199 200 for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { 201 k = pdata->keycodes[i]; 202 if (k) 203 input_set_capability(input, EV_KEY, k); 204 } 205 206 error = input_register_device(input); 207 if (error) { 208 dev_err(&pdev->dev, "failed to register input device\n"); 209 goto err5; 210 } 211 212 iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) | 213 pdata->scan_timing, priv->iomem_base + KYCR1_OFFS); 214 iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); 215 iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); 216 return 0; 217 err5: 218 free_irq(irq, pdev); 219 err4: 220 input_free_device(input); 221 err3: 222 iounmap(priv->iomem_base); 223 err2: 224 release_mem_region(res->start, res_size(res)); 225 err1: 226 platform_set_drvdata(pdev, NULL); 227 kfree(priv); 228 err0: 229 return error; 230 } 231 232 static int __devexit sh_keysc_remove(struct platform_device *pdev) 233 { 234 struct sh_keysc_priv *priv = platform_get_drvdata(pdev); 235 struct resource *res; 236 237 iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS); 238 239 input_unregister_device(priv->input); 240 free_irq(platform_get_irq(pdev, 0), pdev); 241 iounmap(priv->iomem_base); 242 243 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 244 release_mem_region(res->start, res_size(res)); 245 246 platform_set_drvdata(pdev, NULL); 247 kfree(priv); 248 return 0; 249 } 250 251 252 #define sh_keysc_suspend NULL 253 #define sh_keysc_resume NULL 254 255 struct platform_driver sh_keysc_device_driver = { 256 .probe = sh_keysc_probe, 257 .remove = __devexit_p(sh_keysc_remove), 258 .suspend = sh_keysc_suspend, 259 .resume = sh_keysc_resume, 260 .driver = { 261 .name = "sh_keysc", 262 } 263 }; 264 265 static int __init sh_keysc_init(void) 266 { 267 return platform_driver_register(&sh_keysc_device_driver); 268 } 269 270 static void __exit sh_keysc_exit(void) 271 { 272 platform_driver_unregister(&sh_keysc_device_driver); 273 } 274 275 module_init(sh_keysc_init); 276 module_exit(sh_keysc_exit); 277 278 MODULE_AUTHOR("Magnus Damm"); 279 MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver"); 280 MODULE_LICENSE("GPL"); 281