linux/drivers/mfd/ezx-pcap.c
<<
>>
Prefs
   1/*
   2 * Driver for Motorola PCAP2 as present in EZX phones
   3 *
   4 * Copyright (C) 2006 Harald Welte <laforge@openezx.org>
   5 * Copyright (C) 2009 Daniel Ribeiro <drwyrm@gmail.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/kernel.h>
  15#include <linux/platform_device.h>
  16#include <linux/interrupt.h>
  17#include <linux/irq.h>
  18#include <linux/mfd/ezx-pcap.h>
  19#include <linux/spi/spi.h>
  20#include <linux/gpio.h>
  21#include <linux/slab.h>
  22
  23#define PCAP_ADC_MAXQ           8
  24struct pcap_adc_request {
  25        u8 bank;
  26        u8 ch[2];
  27        u32 flags;
  28        void (*callback)(void *, u16[]);
  29        void *data;
  30};
  31
  32struct pcap_adc_sync_request {
  33        u16 res[2];
  34        struct completion completion;
  35};
  36
  37struct pcap_chip {
  38        struct spi_device *spi;
  39
  40        /* IO */
  41        u32 buf;
  42        struct mutex io_mutex;
  43
  44        /* IRQ */
  45        unsigned int irq_base;
  46        u32 msr;
  47        struct work_struct isr_work;
  48        struct work_struct msr_work;
  49        struct workqueue_struct *workqueue;
  50
  51        /* ADC */
  52        struct pcap_adc_request *adc_queue[PCAP_ADC_MAXQ];
  53        u8 adc_head;
  54        u8 adc_tail;
  55        struct mutex adc_mutex;
  56};
  57
  58/* IO */
  59static int ezx_pcap_putget(struct pcap_chip *pcap, u32 *data)
  60{
  61        struct spi_transfer t;
  62        struct spi_message m;
  63        int status;
  64
  65        memset(&t, 0, sizeof t);
  66        spi_message_init(&m);
  67        t.len = sizeof(u32);
  68        spi_message_add_tail(&t, &m);
  69
  70        pcap->buf = *data;
  71        t.tx_buf = (u8 *) &pcap->buf;
  72        t.rx_buf = (u8 *) &pcap->buf;
  73        status = spi_sync(pcap->spi, &m);
  74
  75        if (status == 0)
  76                *data = pcap->buf;
  77
  78        return status;
  79}
  80
  81int ezx_pcap_write(struct pcap_chip *pcap, u8 reg_num, u32 value)
  82{
  83        int ret;
  84
  85        mutex_lock(&pcap->io_mutex);
  86        value &= PCAP_REGISTER_VALUE_MASK;
  87        value |= PCAP_REGISTER_WRITE_OP_BIT
  88                | (reg_num << PCAP_REGISTER_ADDRESS_SHIFT);
  89        ret = ezx_pcap_putget(pcap, &value);
  90        mutex_unlock(&pcap->io_mutex);
  91
  92        return ret;
  93}
  94EXPORT_SYMBOL_GPL(ezx_pcap_write);
  95
  96int ezx_pcap_read(struct pcap_chip *pcap, u8 reg_num, u32 *value)
  97{
  98        int ret;
  99
 100        mutex_lock(&pcap->io_mutex);
 101        *value = PCAP_REGISTER_READ_OP_BIT
 102                | (reg_num << PCAP_REGISTER_ADDRESS_SHIFT);
 103
 104        ret = ezx_pcap_putget(pcap, value);
 105        mutex_unlock(&pcap->io_mutex);
 106
 107        return ret;
 108}
 109EXPORT_SYMBOL_GPL(ezx_pcap_read);
 110
 111int ezx_pcap_set_bits(struct pcap_chip *pcap, u8 reg_num, u32 mask, u32 val)
 112{
 113        int ret;
 114        u32 tmp = PCAP_REGISTER_READ_OP_BIT |
 115                (reg_num << PCAP_REGISTER_ADDRESS_SHIFT);
 116
 117        mutex_lock(&pcap->io_mutex);
 118        ret = ezx_pcap_putget(pcap, &tmp);
 119        if (ret)
 120                goto out_unlock;
 121
 122        tmp &= (PCAP_REGISTER_VALUE_MASK & ~mask);
 123        tmp |= (val & mask) | PCAP_REGISTER_WRITE_OP_BIT |
 124                (reg_num << PCAP_REGISTER_ADDRESS_SHIFT);
 125
 126        ret = ezx_pcap_putget(pcap, &tmp);
 127out_unlock:
 128        mutex_unlock(&pcap->io_mutex);
 129
 130        return ret;
 131}
 132EXPORT_SYMBOL_GPL(ezx_pcap_set_bits);
 133
 134/* IRQ */
 135int irq_to_pcap(struct pcap_chip *pcap, int irq)
 136{
 137        return irq - pcap->irq_base;
 138}
 139EXPORT_SYMBOL_GPL(irq_to_pcap);
 140
 141int pcap_to_irq(struct pcap_chip *pcap, int irq)
 142{
 143        return pcap->irq_base + irq;
 144}
 145EXPORT_SYMBOL_GPL(pcap_to_irq);
 146
 147static void pcap_mask_irq(struct irq_data *d)
 148{
 149        struct pcap_chip *pcap = irq_data_get_irq_chip_data(d);
 150
 151        pcap->msr |= 1 << irq_to_pcap(pcap, d->irq);
 152        queue_work(pcap->workqueue, &pcap->msr_work);
 153}
 154
 155static void pcap_unmask_irq(struct irq_data *d)
 156{
 157        struct pcap_chip *pcap = irq_data_get_irq_chip_data(d);
 158
 159        pcap->msr &= ~(1 << irq_to_pcap(pcap, d->irq));
 160        queue_work(pcap->workqueue, &pcap->msr_work);
 161}
 162
 163static struct irq_chip pcap_irq_chip = {
 164        .name           = "pcap",
 165        .irq_disable    = pcap_mask_irq,
 166        .irq_mask       = pcap_mask_irq,
 167        .irq_unmask     = pcap_unmask_irq,
 168};
 169
 170static void pcap_msr_work(struct work_struct *work)
 171{
 172        struct pcap_chip *pcap = container_of(work, struct pcap_chip, msr_work);
 173
 174        ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr);
 175}
 176
 177static void pcap_isr_work(struct work_struct *work)
 178{
 179        struct pcap_chip *pcap = container_of(work, struct pcap_chip, isr_work);
 180        struct pcap_platform_data *pdata = pcap->spi->dev.platform_data;
 181        u32 msr, isr, int_sel, service;
 182        int irq;
 183
 184        do {
 185                ezx_pcap_read(pcap, PCAP_REG_MSR, &msr);
 186                ezx_pcap_read(pcap, PCAP_REG_ISR, &isr);
 187
 188                /* We can't service/ack irqs that are assigned to port 2 */
 189                if (!(pdata->config & PCAP_SECOND_PORT)) {
 190                        ezx_pcap_read(pcap, PCAP_REG_INT_SEL, &int_sel);
 191                        isr &= ~int_sel;
 192                }
 193
 194                ezx_pcap_write(pcap, PCAP_REG_MSR, isr | msr);
 195                ezx_pcap_write(pcap, PCAP_REG_ISR, isr);
 196
 197                local_irq_disable();
 198                service = isr & ~msr;
 199                for (irq = pcap->irq_base; service; service >>= 1, irq++) {
 200                        if (service & 1)
 201                                generic_handle_irq(irq);
 202                }
 203                local_irq_enable();
 204                ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr);
 205        } while (gpio_get_value(pdata->gpio));
 206}
 207
 208static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
 209{
 210        struct pcap_chip *pcap = irq_get_handler_data(irq);
 211
 212        desc->irq_data.chip->irq_ack(&desc->irq_data);
 213        queue_work(pcap->workqueue, &pcap->isr_work);
 214        return;
 215}
 216
 217/* ADC */
 218void pcap_set_ts_bits(struct pcap_chip *pcap, u32 bits)
 219{
 220        u32 tmp;
 221
 222        mutex_lock(&pcap->adc_mutex);
 223        ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp);
 224        tmp &= ~(PCAP_ADC_TS_M_MASK | PCAP_ADC_TS_REF_LOWPWR);
 225        tmp |= bits & (PCAP_ADC_TS_M_MASK | PCAP_ADC_TS_REF_LOWPWR);
 226        ezx_pcap_write(pcap, PCAP_REG_ADC, tmp);
 227        mutex_unlock(&pcap->adc_mutex);
 228}
 229EXPORT_SYMBOL_GPL(pcap_set_ts_bits);
 230
 231static void pcap_disable_adc(struct pcap_chip *pcap)
 232{
 233        u32 tmp;
 234
 235        ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp);
 236        tmp &= ~(PCAP_ADC_ADEN|PCAP_ADC_BATT_I_ADC|PCAP_ADC_BATT_I_POLARITY);
 237        ezx_pcap_write(pcap, PCAP_REG_ADC, tmp);
 238}
 239
 240static void pcap_adc_trigger(struct pcap_chip *pcap)
 241{
 242        u32 tmp;
 243        u8 head;
 244
 245        mutex_lock(&pcap->adc_mutex);
 246        head = pcap->adc_head;
 247        if (!pcap->adc_queue[head]) {
 248                /* queue is empty, save power */
 249                pcap_disable_adc(pcap);
 250                mutex_unlock(&pcap->adc_mutex);
 251                return;
 252        }
 253        /* start conversion on requested bank, save TS_M bits */
 254        ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp);
 255        tmp &= (PCAP_ADC_TS_M_MASK | PCAP_ADC_TS_REF_LOWPWR);
 256        tmp |= pcap->adc_queue[head]->flags | PCAP_ADC_ADEN;
 257
 258        if (pcap->adc_queue[head]->bank == PCAP_ADC_BANK_1)
 259                tmp |= PCAP_ADC_AD_SEL1;
 260
 261        ezx_pcap_write(pcap, PCAP_REG_ADC, tmp);
 262        mutex_unlock(&pcap->adc_mutex);
 263        ezx_pcap_write(pcap, PCAP_REG_ADR, PCAP_ADR_ASC);
 264}
 265
 266static irqreturn_t pcap_adc_irq(int irq, void *_pcap)
 267{
 268        struct pcap_chip *pcap = _pcap;
 269        struct pcap_adc_request *req;
 270        u16 res[2];
 271        u32 tmp;
 272
 273        mutex_lock(&pcap->adc_mutex);
 274        req = pcap->adc_queue[pcap->adc_head];
 275
 276        if (WARN(!req, "adc irq without pending request\n")) {
 277                mutex_unlock(&pcap->adc_mutex);
 278                return IRQ_HANDLED;
 279        }
 280
 281        /* read requested channels results */
 282        ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp);
 283        tmp &= ~(PCAP_ADC_ADA1_MASK | PCAP_ADC_ADA2_MASK);
 284        tmp |= (req->ch[0] << PCAP_ADC_ADA1_SHIFT);
 285        tmp |= (req->ch[1] << PCAP_ADC_ADA2_SHIFT);
 286        ezx_pcap_write(pcap, PCAP_REG_ADC, tmp);
 287        ezx_pcap_read(pcap, PCAP_REG_ADR, &tmp);
 288        res[0] = (tmp & PCAP_ADR_ADD1_MASK) >> PCAP_ADR_ADD1_SHIFT;
 289        res[1] = (tmp & PCAP_ADR_ADD2_MASK) >> PCAP_ADR_ADD2_SHIFT;
 290
 291        pcap->adc_queue[pcap->adc_head] = NULL;
 292        pcap->adc_head = (pcap->adc_head + 1) & (PCAP_ADC_MAXQ - 1);
 293        mutex_unlock(&pcap->adc_mutex);
 294
 295        /* pass the results and release memory */
 296        req->callback(req->data, res);
 297        kfree(req);
 298
 299        /* trigger next conversion (if any) on queue */
 300        pcap_adc_trigger(pcap);
 301
 302        return IRQ_HANDLED;
 303}
 304
 305int pcap_adc_async(struct pcap_chip *pcap, u8 bank, u32 flags, u8 ch[],
 306                                                void *callback, void *data)
 307{
 308        struct pcap_adc_request *req;
 309
 310        /* This will be freed after we have a result */
 311        req = kmalloc(sizeof(struct pcap_adc_request), GFP_KERNEL);
 312        if (!req)
 313                return -ENOMEM;
 314
 315        req->bank = bank;
 316        req->flags = flags;
 317        req->ch[0] = ch[0];
 318        req->ch[1] = ch[1];
 319        req->callback = callback;
 320        req->data = data;
 321
 322        mutex_lock(&pcap->adc_mutex);
 323        if (pcap->adc_queue[pcap->adc_tail]) {
 324                mutex_unlock(&pcap->adc_mutex);
 325                kfree(req);
 326                return -EBUSY;
 327        }
 328        pcap->adc_queue[pcap->adc_tail] = req;
 329        pcap->adc_tail = (pcap->adc_tail + 1) & (PCAP_ADC_MAXQ - 1);
 330        mutex_unlock(&pcap->adc_mutex);
 331
 332        /* start conversion */
 333        pcap_adc_trigger(pcap);
 334
 335        return 0;
 336}
 337EXPORT_SYMBOL_GPL(pcap_adc_async);
 338
 339static void pcap_adc_sync_cb(void *param, u16 res[])
 340{
 341        struct pcap_adc_sync_request *req = param;
 342
 343        req->res[0] = res[0];
 344        req->res[1] = res[1];
 345        complete(&req->completion);
 346}
 347
 348int pcap_adc_sync(struct pcap_chip *pcap, u8 bank, u32 flags, u8 ch[],
 349                                                                u16 res[])
 350{
 351        struct pcap_adc_sync_request sync_data;
 352        int ret;
 353
 354        init_completion(&sync_data.completion);
 355        ret = pcap_adc_async(pcap, bank, flags, ch, pcap_adc_sync_cb,
 356                                                                &sync_data);
 357        if (ret)
 358                return ret;
 359        wait_for_completion(&sync_data.completion);
 360        res[0] = sync_data.res[0];
 361        res[1] = sync_data.res[1];
 362
 363        return 0;
 364}
 365EXPORT_SYMBOL_GPL(pcap_adc_sync);
 366
 367/* subdevs */
 368static int pcap_remove_subdev(struct device *dev, void *unused)
 369{
 370        platform_device_unregister(to_platform_device(dev));
 371        return 0;
 372}
 373
 374static int pcap_add_subdev(struct pcap_chip *pcap,
 375                                                struct pcap_subdev *subdev)
 376{
 377        struct platform_device *pdev;
 378        int ret;
 379
 380        pdev = platform_device_alloc(subdev->name, subdev->id);
 381        if (!pdev)
 382                return -ENOMEM;
 383
 384        pdev->dev.parent = &pcap->spi->dev;
 385        pdev->dev.platform_data = subdev->platform_data;
 386
 387        ret = platform_device_add(pdev);
 388        if (ret)
 389                platform_device_put(pdev);
 390
 391        return ret;
 392}
 393
 394static int ezx_pcap_remove(struct spi_device *spi)
 395{
 396        struct pcap_chip *pcap = dev_get_drvdata(&spi->dev);
 397        struct pcap_platform_data *pdata = spi->dev.platform_data;
 398        int i, adc_irq;
 399
 400        /* remove all registered subdevs */
 401        device_for_each_child(&spi->dev, NULL, pcap_remove_subdev);
 402
 403        /* cleanup ADC */
 404        adc_irq = pcap_to_irq(pcap, (pdata->config & PCAP_SECOND_PORT) ?
 405                                PCAP_IRQ_ADCDONE2 : PCAP_IRQ_ADCDONE);
 406        free_irq(adc_irq, pcap);
 407        mutex_lock(&pcap->adc_mutex);
 408        for (i = 0; i < PCAP_ADC_MAXQ; i++)
 409                kfree(pcap->adc_queue[i]);
 410        mutex_unlock(&pcap->adc_mutex);
 411
 412        /* cleanup irqchip */
 413        for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++)
 414                irq_set_chip_and_handler(i, NULL, NULL);
 415
 416        destroy_workqueue(pcap->workqueue);
 417
 418        kfree(pcap);
 419
 420        return 0;
 421}
 422
 423static int ezx_pcap_probe(struct spi_device *spi)
 424{
 425        struct pcap_platform_data *pdata = spi->dev.platform_data;
 426        struct pcap_chip *pcap;
 427        int i, adc_irq;
 428        int ret = -ENODEV;
 429
 430        /* platform data is required */
 431        if (!pdata)
 432                goto ret;
 433
 434        pcap = kzalloc(sizeof(*pcap), GFP_KERNEL);
 435        if (!pcap) {
 436                ret = -ENOMEM;
 437                goto ret;
 438        }
 439
 440        mutex_init(&pcap->io_mutex);
 441        mutex_init(&pcap->adc_mutex);
 442        INIT_WORK(&pcap->isr_work, pcap_isr_work);
 443        INIT_WORK(&pcap->msr_work, pcap_msr_work);
 444        dev_set_drvdata(&spi->dev, pcap);
 445
 446        /* setup spi */
 447        spi->bits_per_word = 32;
 448        spi->mode = SPI_MODE_0 | (pdata->config & PCAP_CS_AH ? SPI_CS_HIGH : 0);
 449        ret = spi_setup(spi);
 450        if (ret)
 451                goto free_pcap;
 452
 453        pcap->spi = spi;
 454
 455        /* setup irq */
 456        pcap->irq_base = pdata->irq_base;
 457        pcap->workqueue = create_singlethread_workqueue("pcapd");
 458        if (!pcap->workqueue) {
 459                ret = -ENOMEM;
 460                dev_err(&spi->dev, "can't create pcap thread\n");
 461                goto free_pcap;
 462        }
 463
 464        /* redirect interrupts to AP, except adcdone2 */
 465        if (!(pdata->config & PCAP_SECOND_PORT))
 466                ezx_pcap_write(pcap, PCAP_REG_INT_SEL,
 467                                        (1 << PCAP_IRQ_ADCDONE2));
 468
 469        /* setup irq chip */
 470        for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) {
 471                irq_set_chip_and_handler(i, &pcap_irq_chip, handle_simple_irq);
 472                irq_set_chip_data(i, pcap);
 473#ifdef CONFIG_ARM
 474                set_irq_flags(i, IRQF_VALID);
 475#else
 476                irq_set_noprobe(i);
 477#endif
 478        }
 479
 480        /* mask/ack all PCAP interrupts */
 481        ezx_pcap_write(pcap, PCAP_REG_MSR, PCAP_MASK_ALL_INTERRUPT);
 482        ezx_pcap_write(pcap, PCAP_REG_ISR, PCAP_CLEAR_INTERRUPT_REGISTER);
 483        pcap->msr = PCAP_MASK_ALL_INTERRUPT;
 484
 485        irq_set_irq_type(spi->irq, IRQ_TYPE_EDGE_RISING);
 486        irq_set_handler_data(spi->irq, pcap);
 487        irq_set_chained_handler(spi->irq, pcap_irq_handler);
 488        irq_set_irq_wake(spi->irq, 1);
 489
 490        /* ADC */
 491        adc_irq = pcap_to_irq(pcap, (pdata->config & PCAP_SECOND_PORT) ?
 492                                        PCAP_IRQ_ADCDONE2 : PCAP_IRQ_ADCDONE);
 493
 494        ret = request_irq(adc_irq, pcap_adc_irq, 0, "ADC", pcap);
 495        if (ret)
 496                goto free_irqchip;
 497
 498        /* setup subdevs */
 499        for (i = 0; i < pdata->num_subdevs; i++) {
 500                ret = pcap_add_subdev(pcap, &pdata->subdevs[i]);
 501                if (ret)
 502                        goto remove_subdevs;
 503        }
 504
 505        /* board specific quirks */
 506        if (pdata->init)
 507                pdata->init(pcap);
 508
 509        return 0;
 510
 511remove_subdevs:
 512        device_for_each_child(&spi->dev, NULL, pcap_remove_subdev);
 513/* free_adc: */
 514        free_irq(adc_irq, pcap);
 515free_irqchip:
 516        for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++)
 517                irq_set_chip_and_handler(i, NULL, NULL);
 518/* destroy_workqueue: */
 519        destroy_workqueue(pcap->workqueue);
 520free_pcap:
 521        kfree(pcap);
 522ret:
 523        return ret;
 524}
 525
 526static struct spi_driver ezxpcap_driver = {
 527        .probe  = ezx_pcap_probe,
 528        .remove = ezx_pcap_remove,
 529        .driver = {
 530                .name   = "ezx-pcap",
 531                .owner  = THIS_MODULE,
 532        },
 533};
 534
 535static int __init ezx_pcap_init(void)
 536{
 537        return spi_register_driver(&ezxpcap_driver);
 538}
 539
 540static void __exit ezx_pcap_exit(void)
 541{
 542        spi_unregister_driver(&ezxpcap_driver);
 543}
 544
 545subsys_initcall(ezx_pcap_init);
 546module_exit(ezx_pcap_exit);
 547
 548MODULE_LICENSE("GPL");
 549MODULE_AUTHOR("Daniel Ribeiro / Harald Welte");
 550MODULE_DESCRIPTION("Motorola PCAP2 ASIC Driver");
 551MODULE_ALIAS("spi:ezx-pcap");
 552
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.