aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/ezx-pcap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/ezx-pcap.c')
-rw-r--r--drivers/mfd/ezx-pcap.c105
1 files changed, 74 insertions, 31 deletions
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
index c1de4afa89a6..016be4938e4c 100644
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -17,6 +17,7 @@
17#include <linux/irq.h> 17#include <linux/irq.h>
18#include <linux/mfd/ezx-pcap.h> 18#include <linux/mfd/ezx-pcap.h>
19#include <linux/spi/spi.h> 19#include <linux/spi/spi.h>
20#include <linux/gpio.h>
20 21
21#define PCAP_ADC_MAXQ 8 22#define PCAP_ADC_MAXQ 8
22struct pcap_adc_request { 23struct pcap_adc_request {
@@ -106,11 +107,35 @@ int ezx_pcap_read(struct pcap_chip *pcap, u8 reg_num, u32 *value)
106} 107}
107EXPORT_SYMBOL_GPL(ezx_pcap_read); 108EXPORT_SYMBOL_GPL(ezx_pcap_read);
108 109
110int ezx_pcap_set_bits(struct pcap_chip *pcap, u8 reg_num, u32 mask, u32 val)
111{
112 int ret;
113 u32 tmp = PCAP_REGISTER_READ_OP_BIT |
114 (reg_num << PCAP_REGISTER_ADDRESS_SHIFT);
115
116 mutex_lock(&pcap->io_mutex);
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 mutex_unlock(&pcap->io_mutex);
128
129 return ret;
130}
131EXPORT_SYMBOL_GPL(ezx_pcap_set_bits);
132
109/* IRQ */ 133/* IRQ */
110static inline unsigned int irq2pcap(struct pcap_chip *pcap, int irq) 134int irq_to_pcap(struct pcap_chip *pcap, int irq)
111{ 135{
112 return 1 << (irq - pcap->irq_base); 136 return irq - pcap->irq_base;
113} 137}
138EXPORT_SYMBOL_GPL(irq_to_pcap);
114 139
115int pcap_to_irq(struct pcap_chip *pcap, int irq) 140int pcap_to_irq(struct pcap_chip *pcap, int irq)
116{ 141{
@@ -122,7 +147,7 @@ static void pcap_mask_irq(unsigned int irq)
122{ 147{
123 struct pcap_chip *pcap = get_irq_chip_data(irq); 148 struct pcap_chip *pcap = get_irq_chip_data(irq);
124 149
125 pcap->msr |= irq2pcap(pcap, irq); 150 pcap->msr |= 1 << irq_to_pcap(pcap, irq);
126 queue_work(pcap->workqueue, &pcap->msr_work); 151 queue_work(pcap->workqueue, &pcap->msr_work);
127} 152}
128 153
@@ -130,7 +155,7 @@ static void pcap_unmask_irq(unsigned int irq)
130{ 155{
131 struct pcap_chip *pcap = get_irq_chip_data(irq); 156 struct pcap_chip *pcap = get_irq_chip_data(irq);
132 157
133 pcap->msr &= ~irq2pcap(pcap, irq); 158 pcap->msr &= ~(1 << irq_to_pcap(pcap, irq));
134 queue_work(pcap->workqueue, &pcap->msr_work); 159 queue_work(pcap->workqueue, &pcap->msr_work);
135} 160}
136 161
@@ -154,34 +179,38 @@ static void pcap_isr_work(struct work_struct *work)
154 u32 msr, isr, int_sel, service; 179 u32 msr, isr, int_sel, service;
155 int irq; 180 int irq;
156 181
157 ezx_pcap_read(pcap, PCAP_REG_MSR, &msr); 182 do {
158 ezx_pcap_read(pcap, PCAP_REG_ISR, &isr); 183 ezx_pcap_read(pcap, PCAP_REG_MSR, &msr);
184 ezx_pcap_read(pcap, PCAP_REG_ISR, &isr);
159 185
160 /* We cant service/ack irqs that are assigned to port 2 */ 186 /* We cant service/ack irqs that are assigned to port 2 */
161 if (!(pdata->config & PCAP_SECOND_PORT)) { 187 if (!(pdata->config & PCAP_SECOND_PORT)) {
162 ezx_pcap_read(pcap, PCAP_REG_INT_SEL, &int_sel); 188 ezx_pcap_read(pcap, PCAP_REG_INT_SEL, &int_sel);
163 isr &= ~int_sel; 189 isr &= ~int_sel;
164 } 190 }
165 ezx_pcap_write(pcap, PCAP_REG_ISR, isr);
166 191
167 local_irq_disable(); 192 ezx_pcap_write(pcap, PCAP_REG_MSR, isr | msr);
168 service = isr & ~msr; 193 ezx_pcap_write(pcap, PCAP_REG_ISR, isr);
169 194
170 for (irq = pcap->irq_base; service; service >>= 1, irq++) { 195 local_irq_disable();
171 if (service & 1) { 196 service = isr & ~msr;
172 struct irq_desc *desc = irq_to_desc(irq); 197 for (irq = pcap->irq_base; service; service >>= 1, irq++) {
198 if (service & 1) {
199 struct irq_desc *desc = irq_to_desc(irq);
173 200
174 if (WARN(!desc, KERN_WARNING 201 if (WARN(!desc, KERN_WARNING
175 "Invalid PCAP IRQ %d\n", irq)) 202 "Invalid PCAP IRQ %d\n", irq))
176 break; 203 break;
177 204
178 if (desc->status & IRQ_DISABLED) 205 if (desc->status & IRQ_DISABLED)
179 note_interrupt(irq, desc, IRQ_NONE); 206 note_interrupt(irq, desc, IRQ_NONE);
180 else 207 else
181 desc->handle_irq(irq, desc); 208 desc->handle_irq(irq, desc);
209 }
182 } 210 }
183 } 211 local_irq_enable();
184 local_irq_enable(); 212 ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr);
213 } while (gpio_get_value(irq_to_gpio(pcap->spi->irq)));
185} 214}
186 215
187static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc) 216static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
@@ -194,6 +223,19 @@ static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
194} 223}
195 224
196/* ADC */ 225/* ADC */
226void pcap_set_ts_bits(struct pcap_chip *pcap, u32 bits)
227{
228 u32 tmp;
229
230 mutex_lock(&pcap->adc_mutex);
231 ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp);
232 tmp &= ~(PCAP_ADC_TS_M_MASK | PCAP_ADC_TS_REF_LOWPWR);
233 tmp |= bits & (PCAP_ADC_TS_M_MASK | PCAP_ADC_TS_REF_LOWPWR);
234 ezx_pcap_write(pcap, PCAP_REG_ADC, tmp);
235 mutex_unlock(&pcap->adc_mutex);
236}
237EXPORT_SYMBOL_GPL(pcap_set_ts_bits);
238
197static void pcap_disable_adc(struct pcap_chip *pcap) 239static void pcap_disable_adc(struct pcap_chip *pcap)
198{ 240{
199 u32 tmp; 241 u32 tmp;
@@ -216,15 +258,16 @@ static void pcap_adc_trigger(struct pcap_chip *pcap)
216 mutex_unlock(&pcap->adc_mutex); 258 mutex_unlock(&pcap->adc_mutex);
217 return; 259 return;
218 } 260 }
219 mutex_unlock(&pcap->adc_mutex); 261 /* start conversion on requested bank, save TS_M bits */
220 262 ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp);
221 /* start conversion on requested bank */ 263 tmp &= (PCAP_ADC_TS_M_MASK | PCAP_ADC_TS_REF_LOWPWR);
222 tmp = pcap->adc_queue[head]->flags | PCAP_ADC_ADEN; 264 tmp |= pcap->adc_queue[head]->flags | PCAP_ADC_ADEN;
223 265
224 if (pcap->adc_queue[head]->bank == PCAP_ADC_BANK_1) 266 if (pcap->adc_queue[head]->bank == PCAP_ADC_BANK_1)
225 tmp |= PCAP_ADC_AD_SEL1; 267 tmp |= PCAP_ADC_AD_SEL1;
226 268
227 ezx_pcap_write(pcap, PCAP_REG_ADC, tmp); 269 ezx_pcap_write(pcap, PCAP_REG_ADC, tmp);
270 mutex_unlock(&pcap->adc_mutex);
228 ezx_pcap_write(pcap, PCAP_REG_ADR, PCAP_ADR_ASC); 271 ezx_pcap_write(pcap, PCAP_REG_ADR, PCAP_ADR_ASC);
229} 272}
230 273
@@ -499,7 +542,7 @@ static void __exit ezx_pcap_exit(void)
499 spi_unregister_driver(&ezxpcap_driver); 542 spi_unregister_driver(&ezxpcap_driver);
500} 543}
501 544
502module_init(ezx_pcap_init); 545subsys_initcall(ezx_pcap_init);
503module_exit(ezx_pcap_exit); 546module_exit(ezx_pcap_exit);
504 547
505MODULE_LICENSE("GPL"); 548MODULE_LICENSE("GPL");