linux/drivers/input/touchscreen/atmel_tsadcc.c
<<
>>
Prefs
   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
 344