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