Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging:iio:trigger:bfintmr Add output support

Some converters require an external signal to start the conversion. This patch
adds support to the bfintmr trigger driver to generate such a signal.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>

authored by

Lars-Peter Clausen and committed by
Jonathan Cameron
587a5124 2aecc5b9

+80 -16
+56 -16
drivers/staging/iio/trigger/iio-trig-bfin-timer.c
··· 14 14 #include <linux/delay.h> 15 15 16 16 #include <asm/gptimers.h> 17 + #include <asm/portmux.h> 17 18 18 19 #include <linux/iio/iio.h> 19 20 #include <linux/iio/trigger.h> 21 + 22 + #include "iio-trig-bfin-timer.h" 20 23 21 24 struct bfin_timer { 22 25 unsigned short id, bit; 23 26 unsigned long irqbit; 24 27 int irq; 28 + int pin; 25 29 }; 26 30 27 31 /* ··· 34 30 */ 35 31 36 32 static struct bfin_timer iio_bfin_timer_code[MAX_BLACKFIN_GPTIMERS] = { 37 - {TIMER0_id, TIMER0bit, TIMER_STATUS_TIMIL0, IRQ_TIMER0}, 38 - {TIMER1_id, TIMER1bit, TIMER_STATUS_TIMIL1, IRQ_TIMER1}, 39 - {TIMER2_id, TIMER2bit, TIMER_STATUS_TIMIL2, IRQ_TIMER2}, 33 + {TIMER0_id, TIMER0bit, TIMER_STATUS_TIMIL0, IRQ_TIMER0, P_TMR0}, 34 + {TIMER1_id, TIMER1bit, TIMER_STATUS_TIMIL1, IRQ_TIMER1, P_TMR1}, 35 + {TIMER2_id, TIMER2bit, TIMER_STATUS_TIMIL2, IRQ_TIMER2, P_TMR2}, 40 36 #if (MAX_BLACKFIN_GPTIMERS > 3) 41 - {TIMER3_id, TIMER3bit, TIMER_STATUS_TIMIL3, IRQ_TIMER3}, 42 - {TIMER4_id, TIMER4bit, TIMER_STATUS_TIMIL4, IRQ_TIMER4}, 43 - {TIMER5_id, TIMER5bit, TIMER_STATUS_TIMIL5, IRQ_TIMER5}, 44 - {TIMER6_id, TIMER6bit, TIMER_STATUS_TIMIL6, IRQ_TIMER6}, 45 - {TIMER7_id, TIMER7bit, TIMER_STATUS_TIMIL7, IRQ_TIMER7}, 37 + {TIMER3_id, TIMER3bit, TIMER_STATUS_TIMIL3, IRQ_TIMER3, P_TMR3}, 38 + {TIMER4_id, TIMER4bit, TIMER_STATUS_TIMIL4, IRQ_TIMER4, P_TMR4}, 39 + {TIMER5_id, TIMER5bit, TIMER_STATUS_TIMIL5, IRQ_TIMER5, P_TMR5}, 40 + {TIMER6_id, TIMER6bit, TIMER_STATUS_TIMIL6, IRQ_TIMER6, P_TMR6}, 41 + {TIMER7_id, TIMER7bit, TIMER_STATUS_TIMIL7, IRQ_TIMER7, P_TMR7}, 46 42 #endif 47 43 #if (MAX_BLACKFIN_GPTIMERS > 8) 48 - {TIMER8_id, TIMER8bit, TIMER_STATUS_TIMIL8, IRQ_TIMER8}, 49 - {TIMER9_id, TIMER9bit, TIMER_STATUS_TIMIL9, IRQ_TIMER9}, 50 - {TIMER10_id, TIMER10bit, TIMER_STATUS_TIMIL10, IRQ_TIMER10}, 44 + {TIMER8_id, TIMER8bit, TIMER_STATUS_TIMIL8, IRQ_TIMER8, P_TMR8}, 45 + {TIMER9_id, TIMER9bit, TIMER_STATUS_TIMIL9, IRQ_TIMER9, P_TMR9}, 46 + {TIMER10_id, TIMER10bit, TIMER_STATUS_TIMIL10, IRQ_TIMER10, P_TMR10}, 51 47 #if (MAX_BLACKFIN_GPTIMERS > 11) 52 - {TIMER11_id, TIMER11bit, TIMER_STATUS_TIMIL11, IRQ_TIMER11}, 48 + {TIMER11_id, TIMER11bit, TIMER_STATUS_TIMIL11, IRQ_TIMER11, P_TMR11}, 53 49 #endif 54 50 #endif 55 51 }; ··· 58 54 struct iio_trigger *trig; 59 55 struct bfin_timer *t; 60 56 unsigned timer_num; 57 + bool output_enable; 58 + unsigned int duty; 61 59 int irq; 62 60 }; 63 61 ··· 83 77 { 84 78 struct iio_trigger *trig = to_iio_trigger(dev); 85 79 struct bfin_tmr_state *st = trig->private_data; 86 - long val; 80 + unsigned long val; 87 81 bool enabled; 88 82 int ret; 89 83 ··· 105 99 goto error_ret; 106 100 107 101 val = get_sclk() / val; 108 - if (val <= 4) { 102 + if (val <= 4 || val <= st->duty) { 109 103 ret = -EINVAL; 110 104 goto error_ret; 111 105 } 112 106 113 107 set_gptimer_period(st->t->id, val); 114 - set_gptimer_pwidth(st->t->id, 1); 108 + set_gptimer_pwidth(st->t->id, val - st->duty); 115 109 116 110 if (enabled) 117 111 enable_gptimers(st->t->bit); ··· 182 176 183 177 static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev) 184 178 { 179 + struct iio_bfin_timer_trigger_pdata *pdata = pdev->dev.platform_data; 185 180 struct bfin_tmr_state *st; 181 + unsigned int config; 186 182 int ret; 187 183 188 184 st = kzalloc(sizeof(*st), GFP_KERNEL); ··· 228 220 goto out4; 229 221 } 230 222 231 - set_gptimer_config(st->t->id, OUT_DIS | PWM_OUT | PERIOD_CNT | IRQ_ENA); 223 + config = PWM_OUT | PERIOD_CNT | IRQ_ENA; 224 + 225 + if (pdata && pdata->output_enable) { 226 + unsigned long long val; 227 + 228 + st->output_enable = true; 229 + 230 + ret = peripheral_request(st->t->pin, st->trig->name); 231 + if (ret) 232 + goto out_free_irq; 233 + 234 + val = (unsigned long long)get_sclk() * pdata->duty_ns; 235 + do_div(val, NSEC_PER_SEC); 236 + st->duty = val; 237 + 238 + /** 239 + * The interrupt will be generated at the end of the period, 240 + * since we want the interrupt to be generated at end of the 241 + * pulse we invert both polarity and duty cycle, so that the 242 + * pulse will be generated directly before the interrupt. 243 + */ 244 + if (pdata->active_low) 245 + config |= PULSE_HI; 246 + } else { 247 + st->duty = 1; 248 + config |= OUT_DIS; 249 + } 250 + 251 + set_gptimer_config(st->t->id, config); 232 252 233 253 dev_info(&pdev->dev, "iio trigger Blackfin TMR%d, IRQ-%d", 234 254 st->timer_num, st->irq); 235 255 platform_set_drvdata(pdev, st); 236 256 237 257 return 0; 258 + out_free_irq: 259 + free_irq(st->irq, st); 238 260 out4: 239 261 iio_trigger_unregister(st->trig); 240 262 out2: ··· 280 242 struct bfin_tmr_state *st = platform_get_drvdata(pdev); 281 243 282 244 disable_gptimers(st->t->bit); 245 + if (st->output_enable) 246 + peripheral_free(st->t->pin); 283 247 free_irq(st->irq, st); 284 248 iio_trigger_unregister(st->trig); 285 249 iio_trigger_put(st->trig);
+24
drivers/staging/iio/trigger/iio-trig-bfin-timer.h
··· 1 + #ifndef __IIO_BFIN_TIMER_TRIGGER_H__ 2 + #define __IIO_BFIN_TIMER_TRIGGER_H__ 3 + 4 + /** 5 + * struct iio_bfin_timer_trigger_pdata - timer trigger platform data 6 + * @output_enable: Enable external trigger pulse generation. 7 + * @active_low: Whether the trigger pulse is active low. 8 + * @duty_ns: Length of the trigger pulse in nanoseconds. 9 + * 10 + * This struct is used to configure the output pulse generation of the blackfin 11 + * timer trigger. If output_enable is set to true an external trigger signal 12 + * will generated on the pin corresponding to the timer. This is useful for 13 + * converters which needs an external signal to start conversion. active_low and 14 + * duty_ns are used to configure the type of the trigger pulse. If output_enable 15 + * is set to false no external trigger pulse will be generated and active_low 16 + * and duty_ns are ignored. 17 + **/ 18 + struct iio_bfin_timer_trigger_pdata { 19 + bool output_enable; 20 + bool active_low; 21 + unsigned int duty_ns; 22 + }; 23 + 24 + #endif