Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.1-rc4 329 lines 9.1 kB view raw
1/* 2 * DaVinci Key Scan Driver for TI platforms 3 * 4 * Copyright (C) 2009 Texas Instruments, Inc 5 * 6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> 7 * 8 * Initial Code: Sandeep Paulraj <s-paulraj@ti.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 */ 24#include <linux/module.h> 25#include <linux/init.h> 26#include <linux/interrupt.h> 27#include <linux/types.h> 28#include <linux/input.h> 29#include <linux/kernel.h> 30#include <linux/delay.h> 31#include <linux/platform_device.h> 32#include <linux/errno.h> 33#include <linux/slab.h> 34 35#include <linux/platform_data/keyscan-davinci.h> 36 37/* Key scan registers */ 38#define DAVINCI_KEYSCAN_KEYCTRL 0x0000 39#define DAVINCI_KEYSCAN_INTENA 0x0004 40#define DAVINCI_KEYSCAN_INTFLAG 0x0008 41#define DAVINCI_KEYSCAN_INTCLR 0x000c 42#define DAVINCI_KEYSCAN_STRBWIDTH 0x0010 43#define DAVINCI_KEYSCAN_INTERVAL 0x0014 44#define DAVINCI_KEYSCAN_CONTTIME 0x0018 45#define DAVINCI_KEYSCAN_CURRENTST 0x001c 46#define DAVINCI_KEYSCAN_PREVSTATE 0x0020 47#define DAVINCI_KEYSCAN_EMUCTRL 0x0024 48#define DAVINCI_KEYSCAN_IODFTCTRL 0x002c 49 50/* Key Control Register (KEYCTRL) */ 51#define DAVINCI_KEYSCAN_KEYEN 0x00000001 52#define DAVINCI_KEYSCAN_PREVMODE 0x00000002 53#define DAVINCI_KEYSCAN_CHATOFF 0x00000004 54#define DAVINCI_KEYSCAN_AUTODET 0x00000008 55#define DAVINCI_KEYSCAN_SCANMODE 0x00000010 56#define DAVINCI_KEYSCAN_OUTTYPE 0x00000020 57 58/* Masks for the interrupts */ 59#define DAVINCI_KEYSCAN_INT_CONT 0x00000008 60#define DAVINCI_KEYSCAN_INT_OFF 0x00000004 61#define DAVINCI_KEYSCAN_INT_ON 0x00000002 62#define DAVINCI_KEYSCAN_INT_CHANGE 0x00000001 63#define DAVINCI_KEYSCAN_INT_ALL 0x0000000f 64 65struct davinci_ks { 66 struct input_dev *input; 67 struct davinci_ks_platform_data *pdata; 68 int irq; 69 void __iomem *base; 70 resource_size_t pbase; 71 size_t base_size; 72 unsigned short keymap[]; 73}; 74 75/* Initializing the kp Module */ 76static int __init davinci_ks_initialize(struct davinci_ks *davinci_ks) 77{ 78 struct device *dev = &davinci_ks->input->dev; 79 struct davinci_ks_platform_data *pdata = davinci_ks->pdata; 80 u32 matrix_ctrl; 81 82 /* Enable all interrupts */ 83 __raw_writel(DAVINCI_KEYSCAN_INT_ALL, 84 davinci_ks->base + DAVINCI_KEYSCAN_INTENA); 85 86 /* Clear interrupts if any */ 87 __raw_writel(DAVINCI_KEYSCAN_INT_ALL, 88 davinci_ks->base + DAVINCI_KEYSCAN_INTCLR); 89 90 /* Setup the scan period = strobe + interval */ 91 __raw_writel(pdata->strobe, 92 davinci_ks->base + DAVINCI_KEYSCAN_STRBWIDTH); 93 __raw_writel(pdata->interval, 94 davinci_ks->base + DAVINCI_KEYSCAN_INTERVAL); 95 __raw_writel(0x01, 96 davinci_ks->base + DAVINCI_KEYSCAN_CONTTIME); 97 98 /* Define matrix type */ 99 switch (pdata->matrix_type) { 100 case DAVINCI_KEYSCAN_MATRIX_4X4: 101 matrix_ctrl = 0; 102 break; 103 case DAVINCI_KEYSCAN_MATRIX_5X3: 104 matrix_ctrl = (1 << 6); 105 break; 106 default: 107 dev_err(dev->parent, "wrong matrix type\n"); 108 return -EINVAL; 109 } 110 111 /* Enable key scan module and set matrix type */ 112 __raw_writel(DAVINCI_KEYSCAN_AUTODET | DAVINCI_KEYSCAN_KEYEN | 113 matrix_ctrl, davinci_ks->base + DAVINCI_KEYSCAN_KEYCTRL); 114 115 return 0; 116} 117 118static irqreturn_t davinci_ks_interrupt(int irq, void *dev_id) 119{ 120 struct davinci_ks *davinci_ks = dev_id; 121 struct device *dev = &davinci_ks->input->dev; 122 unsigned short *keymap = davinci_ks->keymap; 123 int keymapsize = davinci_ks->pdata->keymapsize; 124 u32 prev_status, new_status, changed; 125 bool release; 126 int keycode = KEY_UNKNOWN; 127 int i; 128 129 /* Disable interrupt */ 130 __raw_writel(0x0, davinci_ks->base + DAVINCI_KEYSCAN_INTENA); 131 132 /* Reading previous and new status of the key scan */ 133 prev_status = __raw_readl(davinci_ks->base + DAVINCI_KEYSCAN_PREVSTATE); 134 new_status = __raw_readl(davinci_ks->base + DAVINCI_KEYSCAN_CURRENTST); 135 136 changed = prev_status ^ new_status; 137 138 if (changed) { 139 /* 140 * It goes through all bits in 'changed' to ensure 141 * that no key changes are being missed 142 */ 143 for (i = 0 ; i < keymapsize; i++) { 144 if ((changed>>i) & 0x1) { 145 keycode = keymap[i]; 146 release = (new_status >> i) & 0x1; 147 dev_dbg(dev->parent, "key %d %s\n", keycode, 148 release ? "released" : "pressed"); 149 input_report_key(davinci_ks->input, keycode, 150 !release); 151 input_sync(davinci_ks->input); 152 } 153 } 154 /* Clearing interrupt */ 155 __raw_writel(DAVINCI_KEYSCAN_INT_ALL, 156 davinci_ks->base + DAVINCI_KEYSCAN_INTCLR); 157 } 158 159 /* Enable interrupts */ 160 __raw_writel(0x1, davinci_ks->base + DAVINCI_KEYSCAN_INTENA); 161 162 return IRQ_HANDLED; 163} 164 165static int __init davinci_ks_probe(struct platform_device *pdev) 166{ 167 struct davinci_ks *davinci_ks; 168 struct input_dev *key_dev; 169 struct resource *res, *mem; 170 struct device *dev = &pdev->dev; 171 struct davinci_ks_platform_data *pdata = dev_get_platdata(dev); 172 int error, i; 173 174 if (pdata->device_enable) { 175 error = pdata->device_enable(dev); 176 if (error < 0) { 177 dev_dbg(dev, "device enable function failed\n"); 178 return error; 179 } 180 } 181 182 if (!pdata->keymap) { 183 dev_dbg(dev, "no keymap from pdata\n"); 184 return -EINVAL; 185 } 186 187 davinci_ks = kzalloc(sizeof(struct davinci_ks) + 188 sizeof(unsigned short) * pdata->keymapsize, GFP_KERNEL); 189 if (!davinci_ks) { 190 dev_dbg(dev, "could not allocate memory for private data\n"); 191 return -ENOMEM; 192 } 193 194 memcpy(davinci_ks->keymap, pdata->keymap, 195 sizeof(unsigned short) * pdata->keymapsize); 196 197 key_dev = input_allocate_device(); 198 if (!key_dev) { 199 dev_dbg(dev, "could not allocate input device\n"); 200 error = -ENOMEM; 201 goto fail1; 202 } 203 204 davinci_ks->input = key_dev; 205 206 davinci_ks->irq = platform_get_irq(pdev, 0); 207 if (davinci_ks->irq < 0) { 208 dev_err(dev, "no key scan irq\n"); 209 error = davinci_ks->irq; 210 goto fail2; 211 } 212 213 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 214 if (!res) { 215 dev_err(dev, "no mem resource\n"); 216 error = -EINVAL; 217 goto fail2; 218 } 219 220 davinci_ks->pbase = res->start; 221 davinci_ks->base_size = resource_size(res); 222 223 mem = request_mem_region(davinci_ks->pbase, davinci_ks->base_size, 224 pdev->name); 225 if (!mem) { 226 dev_err(dev, "key scan registers at %08x are not free\n", 227 davinci_ks->pbase); 228 error = -EBUSY; 229 goto fail2; 230 } 231 232 davinci_ks->base = ioremap(davinci_ks->pbase, davinci_ks->base_size); 233 if (!davinci_ks->base) { 234 dev_err(dev, "can't ioremap MEM resource.\n"); 235 error = -ENOMEM; 236 goto fail3; 237 } 238 239 /* Enable auto repeat feature of Linux input subsystem */ 240 if (pdata->rep) 241 __set_bit(EV_REP, key_dev->evbit); 242 243 /* Setup input device */ 244 __set_bit(EV_KEY, key_dev->evbit); 245 246 /* Setup the platform data */ 247 davinci_ks->pdata = pdata; 248 249 for (i = 0; i < davinci_ks->pdata->keymapsize; i++) 250 __set_bit(davinci_ks->pdata->keymap[i], key_dev->keybit); 251 252 key_dev->name = "davinci_keyscan"; 253 key_dev->phys = "davinci_keyscan/input0"; 254 key_dev->dev.parent = dev; 255 key_dev->id.bustype = BUS_HOST; 256 key_dev->id.vendor = 0x0001; 257 key_dev->id.product = 0x0001; 258 key_dev->id.version = 0x0001; 259 key_dev->keycode = davinci_ks->keymap; 260 key_dev->keycodesize = sizeof(davinci_ks->keymap[0]); 261 key_dev->keycodemax = davinci_ks->pdata->keymapsize; 262 263 error = input_register_device(davinci_ks->input); 264 if (error < 0) { 265 dev_err(dev, "unable to register davinci key scan device\n"); 266 goto fail4; 267 } 268 269 error = request_irq(davinci_ks->irq, davinci_ks_interrupt, 270 0, pdev->name, davinci_ks); 271 if (error < 0) { 272 dev_err(dev, "unable to register davinci key scan interrupt\n"); 273 goto fail5; 274 } 275 276 error = davinci_ks_initialize(davinci_ks); 277 if (error < 0) { 278 dev_err(dev, "unable to initialize davinci key scan device\n"); 279 goto fail6; 280 } 281 282 platform_set_drvdata(pdev, davinci_ks); 283 return 0; 284 285fail6: 286 free_irq(davinci_ks->irq, davinci_ks); 287fail5: 288 input_unregister_device(davinci_ks->input); 289 key_dev = NULL; 290fail4: 291 iounmap(davinci_ks->base); 292fail3: 293 release_mem_region(davinci_ks->pbase, davinci_ks->base_size); 294fail2: 295 input_free_device(key_dev); 296fail1: 297 kfree(davinci_ks); 298 299 return error; 300} 301 302static int davinci_ks_remove(struct platform_device *pdev) 303{ 304 struct davinci_ks *davinci_ks = platform_get_drvdata(pdev); 305 306 free_irq(davinci_ks->irq, davinci_ks); 307 308 input_unregister_device(davinci_ks->input); 309 310 iounmap(davinci_ks->base); 311 release_mem_region(davinci_ks->pbase, davinci_ks->base_size); 312 313 kfree(davinci_ks); 314 315 return 0; 316} 317 318static struct platform_driver davinci_ks_driver = { 319 .driver = { 320 .name = "davinci_keyscan", 321 }, 322 .remove = davinci_ks_remove, 323}; 324 325module_platform_driver_probe(davinci_ks_driver, davinci_ks_probe); 326 327MODULE_AUTHOR("Miguel Aguilar"); 328MODULE_DESCRIPTION("Texas Instruments DaVinci Key Scan Driver"); 329MODULE_LICENSE("GPL");