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 priv->iomem_base = ioremap_nocache(res->start, res_size(res)); 162 if (priv->iomem_base == NULL) { 163 dev_err(&pdev->dev, "failed to remap I/O memory\n"); 164 error = -ENXIO; 165 goto err1; 166 } 167 168 priv->input = input_allocate_device(); 169 if (!priv->input) { 170 dev_err(&pdev->dev, "failed to allocate input device\n"); 171 error = -ENOMEM; 172 goto err2; 173 } 174 175 input = priv->input; 176 input->evbit[0] = BIT_MASK(EV_KEY); 177 178 input->name = pdev->name; 179 input->phys = "sh-keysc-keys/input0"; 180 input->dev.parent = &pdev->dev; 181 182 input->id.bustype = BUS_HOST; 183 input->id.vendor = 0x0001; 184 input->id.product = 0x0001; 185 input->id.version = 0x0100; 186 187 error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); 188 if (error) { 189 dev_err(&pdev->dev, "failed to request IRQ\n"); 190 goto err3; 191 } 192 193 for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { 194 k = pdata->keycodes[i]; 195 if (k) 196 input_set_capability(input, EV_KEY, k); 197 } 198 199 error = input_register_device(input); 200 if (error) { 201 dev_err(&pdev->dev, "failed to register input device\n"); 202 goto err4; 203 } 204 205 iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) | 206 pdata->scan_timing, priv->iomem_base + KYCR1_OFFS); 207 iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); 208 iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); 209 return 0; 210 err4: 211 free_irq(irq, pdev); 212 err3: 213 input_free_device(input); 214 err2: 215 iounmap(priv->iomem_base); 216 err1: 217 platform_set_drvdata(pdev, NULL); 218 kfree(priv); 219 err0: 220 return error; 221 } 222 223 static int __devexit sh_keysc_remove(struct platform_device *pdev) 224 { 225 struct sh_keysc_priv *priv = platform_get_drvdata(pdev); 226 227 iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS); 228 229 input_unregister_device(priv->input); 230 free_irq(platform_get_irq(pdev, 0), pdev); 231 iounmap(priv->iomem_base); 232 233 platform_set_drvdata(pdev, NULL); 234 kfree(priv); 235 return 0; 236 } 237 238 239 #define sh_keysc_suspend NULL 240 #define sh_keysc_resume NULL 241 242 struct platform_driver sh_keysc_device_driver = { 243 .probe = sh_keysc_probe, 244 .remove = __devexit_p(sh_keysc_remove), 245 .suspend = sh_keysc_suspend, 246 .resume = sh_keysc_resume, 247 .driver = { 248 .name = "sh_keysc", 249 } 250 }; 251 252 static int __init sh_keysc_init(void) 253 { 254 return platform_driver_register(&sh_keysc_device_driver); 255 } 256 257 static void __exit sh_keysc_exit(void) 258 { 259 platform_driver_unregister(&sh_keysc_device_driver); 260 } 261 262 module_init(sh_keysc_init); 263 module_exit(sh_keysc_exit); 264 265 MODULE_AUTHOR("Magnus Damm"); 266 MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver"); 267 MODULE_LICENSE("GPL"); 268