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 v2.6.30 343 lines 11 kB view raw
1/* 2 * Atmel Touch Screen Driver 3 * 4 * Copyright (c) 2008 ATMEL 5 * Copyright (c) 2008 Dan Liang 6 * Copyright (c) 2008 TimeSys Corporation 7 * Copyright (c) 2008 Justin Waters 8 * 9 * Based on touchscreen code from Atmel Corporation. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 */ 15#include <linux/init.h> 16#include <linux/err.h> 17#include <linux/kernel.h> 18#include <linux/module.h> 19#include <linux/input.h> 20#include <linux/slab.h> 21#include <linux/interrupt.h> 22#include <linux/clk.h> 23#include <linux/platform_device.h> 24#include <linux/io.h> 25 26/* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */ 27 28#define ATMEL_TSADCC_CR 0x00 /* Control register */ 29#define ATMEL_TSADCC_SWRST (1 << 0) /* Software Reset*/ 30#define ATMEL_TSADCC_START (1 << 1) /* Start conversion */ 31 32#define ATMEL_TSADCC_MR 0x04 /* Mode register */ 33#define ATMEL_TSADCC_TSAMOD (3 << 0) /* ADC mode */ 34#define ATMEL_TSADCC_TSAMOD_ADC_ONLY_MODE (0x0) /* ADC Mode */ 35#define ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE (0x1) /* Touch Screen Only Mode */ 36#define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */ 37#define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */ 38#define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */ 39#define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */ 40#define ATMEL_TSADCC_STARTUP (0x7f << 16) /* Start Up time */ 41#define ATMEL_TSADCC_SHTIM (0xf << 24) /* Sample & Hold time */ 42#define ATMEL_TSADCC_PENDBC (0xf << 28) /* Pen Detect debouncing time */ 43 44#define ATMEL_TSADCC_TRGR 0x08 /* Trigger register */ 45#define ATMEL_TSADCC_TRGMOD (7 << 0) /* Trigger mode */ 46#define ATMEL_TSADCC_TRGMOD_NONE (0 << 0) 47#define ATMEL_TSADCC_TRGMOD_EXT_RISING (1 << 0) 48#define ATMEL_TSADCC_TRGMOD_EXT_FALLING (2 << 0) 49#define ATMEL_TSADCC_TRGMOD_EXT_ANY (3 << 0) 50#define ATMEL_TSADCC_TRGMOD_PENDET (4 << 0) 51#define ATMEL_TSADCC_TRGMOD_PERIOD (5 << 0) 52#define ATMEL_TSADCC_TRGMOD_CONTINUOUS (6 << 0) 53#define ATMEL_TSADCC_TRGPER (0xffff << 16) /* Trigger period */ 54 55#define ATMEL_TSADCC_TSR 0x0C /* Touch Screen register */ 56#define ATMEL_TSADCC_TSFREQ (0xf << 0) /* TS Frequency in Interleaved mode */ 57#define ATMEL_TSADCC_TSSHTIM (0xf << 24) /* Sample & Hold time */ 58 59#define ATMEL_TSADCC_CHER 0x10 /* Channel Enable register */ 60#define ATMEL_TSADCC_CHDR 0x14 /* Channel Disable register */ 61#define ATMEL_TSADCC_CHSR 0x18 /* Channel Status register */ 62#define ATMEL_TSADCC_CH(n) (1 << (n)) /* Channel number */ 63 64#define ATMEL_TSADCC_SR 0x1C /* Status register */ 65#define ATMEL_TSADCC_EOC(n) (1 << ((n)+0)) /* End of conversion for channel N */ 66#define ATMEL_TSADCC_OVRE(n) (1 << ((n)+8)) /* Overrun error for channel N */ 67#define ATMEL_TSADCC_DRDY (1 << 16) /* Data Ready */ 68#define ATMEL_TSADCC_GOVRE (1 << 17) /* General Overrun Error */ 69#define ATMEL_TSADCC_ENDRX (1 << 18) /* End of RX Buffer */ 70#define ATMEL_TSADCC_RXBUFF (1 << 19) /* TX Buffer full */ 71#define ATMEL_TSADCC_PENCNT (1 << 20) /* Pen contact */ 72#define ATMEL_TSADCC_NOCNT (1 << 21) /* No contact */ 73 74#define ATMEL_TSADCC_LCDR 0x20 /* Last Converted Data register */ 75#define ATMEL_TSADCC_DATA (0x3ff << 0) /* Channel data */ 76 77#define ATMEL_TSADCC_IER 0x24 /* Interrupt Enable register */ 78#define ATMEL_TSADCC_IDR 0x28 /* Interrupt Disable register */ 79#define ATMEL_TSADCC_IMR 0x2C /* Interrupt Mask register */ 80#define ATMEL_TSADCC_CDR0 0x30 /* Channel Data 0 */ 81#define ATMEL_TSADCC_CDR1 0x34 /* Channel Data 1 */ 82#define ATMEL_TSADCC_CDR2 0x38 /* Channel Data 2 */ 83#define ATMEL_TSADCC_CDR3 0x3C /* Channel Data 3 */ 84#define ATMEL_TSADCC_CDR4 0x40 /* Channel Data 4 */ 85#define ATMEL_TSADCC_CDR5 0x44 /* Channel Data 5 */ 86 87#define ADC_CLOCK 1000000 88 89struct atmel_tsadcc { 90 struct input_dev *input; 91 char phys[32]; 92 struct clk *clk; 93 int irq; 94 unsigned int prev_absx; 95 unsigned int prev_absy; 96 unsigned char bufferedmeasure; 97}; 98 99static void __iomem *tsc_base; 100 101#define atmel_tsadcc_read(reg) __raw_readl(tsc_base + (reg)) 102#define atmel_tsadcc_write(reg, val) __raw_writel((val), tsc_base + (reg)) 103 104static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) 105{ 106 struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev; 107 struct input_dev *input_dev = ts_dev->input; 108 109 unsigned int status; 110 unsigned int reg; 111 112 status = atmel_tsadcc_read(ATMEL_TSADCC_SR); 113 status &= atmel_tsadcc_read(ATMEL_TSADCC_IMR); 114 115 if (status & ATMEL_TSADCC_NOCNT) { 116 /* Contact lost */ 117 reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC; 118 119 atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); 120 atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE); 121 atmel_tsadcc_write(ATMEL_TSADCC_IDR, 122 ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT); 123 atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); 124 125 input_report_key(input_dev, BTN_TOUCH, 0); 126 ts_dev->bufferedmeasure = 0; 127 input_sync(input_dev); 128 129 } else if (status & ATMEL_TSADCC_PENCNT) { 130 /* Pen detected */ 131 reg = atmel_tsadcc_read(ATMEL_TSADCC_MR); 132 reg &= ~ATMEL_TSADCC_PENDBC; 133 134 atmel_tsadcc_write(ATMEL_TSADCC_IDR, ATMEL_TSADCC_PENCNT); 135 atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); 136 atmel_tsadcc_write(ATMEL_TSADCC_IER, 137 ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT); 138 atmel_tsadcc_write(ATMEL_TSADCC_TRGR, 139 ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FFF << 16)); 140 141 } else if (status & ATMEL_TSADCC_EOC(3)) { 142 /* Conversion finished */ 143 144 if (ts_dev->bufferedmeasure) { 145 /* Last measurement is always discarded, since it can 146 * be erroneous. 147 * Always report previous measurement */ 148 input_report_abs(input_dev, ABS_X, ts_dev->prev_absx); 149 input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy); 150 input_report_key(input_dev, BTN_TOUCH, 1); 151 input_sync(input_dev); 152 } else 153 ts_dev->bufferedmeasure = 1; 154 155 /* Now make new measurement */ 156 ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10; 157 ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2); 158 159 ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10; 160 ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0); 161 } 162 163 return IRQ_HANDLED; 164} 165 166/* 167 * The functions for inserting/removing us as a module. 168 */ 169 170static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) 171{ 172 struct atmel_tsadcc *ts_dev; 173 struct input_dev *input_dev; 174 struct resource *res; 175 int err = 0; 176 unsigned int prsc; 177 unsigned int reg; 178 179 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 180 if (!res) { 181 dev_err(&pdev->dev, "no mmio resource defined.\n"); 182 return -ENXIO; 183 } 184 185 /* Allocate memory for device */ 186 ts_dev = kzalloc(sizeof(struct atmel_tsadcc), GFP_KERNEL); 187 if (!ts_dev) { 188 dev_err(&pdev->dev, "failed to allocate memory.\n"); 189 return -ENOMEM; 190 } 191 platform_set_drvdata(pdev, ts_dev); 192 193 input_dev = input_allocate_device(); 194 if (!input_dev) { 195 dev_err(&pdev->dev, "failed to allocate input device.\n"); 196 err = -EBUSY; 197 goto err_free_mem; 198 } 199 200 ts_dev->irq = platform_get_irq(pdev, 0); 201 if (ts_dev->irq < 0) { 202 dev_err(&pdev->dev, "no irq ID is designated.\n"); 203 err = -ENODEV; 204 goto err_free_dev; 205 } 206 207 if (!request_mem_region(res->start, res->end - res->start + 1, 208 "atmel tsadcc regs")) { 209 dev_err(&pdev->dev, "resources is unavailable.\n"); 210 err = -EBUSY; 211 goto err_free_dev; 212 } 213 214 tsc_base = ioremap(res->start, res->end - res->start + 1); 215 if (!tsc_base) { 216 dev_err(&pdev->dev, "failed to map registers.\n"); 217 err = -ENOMEM; 218 goto err_release_mem; 219 } 220 221 err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, IRQF_DISABLED, 222 pdev->dev.driver->name, ts_dev); 223 if (err) { 224 dev_err(&pdev->dev, "failed to allocate irq.\n"); 225 goto err_unmap_regs; 226 } 227 228 ts_dev->clk = clk_get(&pdev->dev, "tsc_clk"); 229 if (IS_ERR(ts_dev->clk)) { 230 dev_err(&pdev->dev, "failed to get ts_clk\n"); 231 err = PTR_ERR(ts_dev->clk); 232 goto err_free_irq; 233 } 234 235 ts_dev->input = input_dev; 236 ts_dev->bufferedmeasure = 0; 237 238 snprintf(ts_dev->phys, sizeof(ts_dev->phys), 239 "%s/input0", dev_name(&pdev->dev)); 240 241 input_dev->name = "atmel touch screen controller"; 242 input_dev->phys = ts_dev->phys; 243 input_dev->dev.parent = &pdev->dev; 244 245 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 246 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 247 248 input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0); 249 input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0); 250 251 /* clk_enable() always returns 0, no need to check it */ 252 clk_enable(ts_dev->clk); 253 254 prsc = clk_get_rate(ts_dev->clk); 255 dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc); 256 257 prsc = prsc / ADC_CLOCK / 2 - 1; 258 259 reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE | 260 ((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* Normal Mode */ 261 ((0x01 << 6) & ATMEL_TSADCC_PENDET) | /* Enable Pen Detect */ 262 ((prsc << 8) & ATMEL_TSADCC_PRESCAL) | /* PRESCAL */ 263 ((0x13 << 16) & ATMEL_TSADCC_STARTUP) | /* STARTUP */ 264 ((0x0F << 28) & ATMEL_TSADCC_PENDBC); /* PENDBC */ 265 266 atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST); 267 atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); 268 atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE); 269 atmel_tsadcc_write(ATMEL_TSADCC_TSR, (0x3 << 24) & ATMEL_TSADCC_TSSHTIM); 270 271 atmel_tsadcc_read(ATMEL_TSADCC_SR); 272 atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); 273 274 /* All went ok, so register to the input system */ 275 err = input_register_device(input_dev); 276 if (err) 277 goto err_fail; 278 279 return 0; 280 281err_fail: 282 clk_disable(ts_dev->clk); 283 clk_put(ts_dev->clk); 284err_free_irq: 285 free_irq(ts_dev->irq, ts_dev); 286err_unmap_regs: 287 iounmap(tsc_base); 288err_release_mem: 289 release_mem_region(res->start, res->end - res->start + 1); 290err_free_dev: 291 input_free_device(ts_dev->input); 292err_free_mem: 293 kfree(ts_dev); 294 return err; 295} 296 297static int __devexit atmel_tsadcc_remove(struct platform_device *pdev) 298{ 299 struct atmel_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev); 300 struct resource *res; 301 302 free_irq(ts_dev->irq, ts_dev); 303 304 input_unregister_device(ts_dev->input); 305 306 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 307 iounmap(tsc_base); 308 release_mem_region(res->start, res->end - res->start + 1); 309 310 clk_disable(ts_dev->clk); 311 clk_put(ts_dev->clk); 312 313 kfree(ts_dev); 314 315 return 0; 316} 317 318static struct platform_driver atmel_tsadcc_driver = { 319 .probe = atmel_tsadcc_probe, 320 .remove = __devexit_p(atmel_tsadcc_remove), 321 .driver = { 322 .name = "atmel_tsadcc", 323 }, 324}; 325 326static int __init atmel_tsadcc_init(void) 327{ 328 return platform_driver_register(&atmel_tsadcc_driver); 329} 330 331static void __exit atmel_tsadcc_exit(void) 332{ 333 platform_driver_unregister(&atmel_tsadcc_driver); 334} 335 336module_init(atmel_tsadcc_init); 337module_exit(atmel_tsadcc_exit); 338 339 340MODULE_LICENSE("GPL"); 341MODULE_DESCRIPTION("Atmel TouchScreen Driver"); 342MODULE_AUTHOR("Dan Liang <dan.liang@atmel.com>"); 343