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