1/* 2 * Copyright 2011 Analog Devices Inc. 3 * 4 * Licensed under the GPL-2. 5 * 6 */ 7 8#include <linux/kernel.h> 9#include <linux/module.h> 10#include <linux/platform_device.h> 11#include <linux/slab.h> 12#include <linux/interrupt.h> 13#include <linux/irq.h> 14#include <linux/delay.h> 15 16#include <asm/gptimers.h> 17#include <asm/portmux.h> 18 19#include <linux/iio/iio.h> 20#include <linux/iio/trigger.h> 21 22#include "iio-trig-bfin-timer.h" 23 24struct bfin_timer { 25 unsigned short id, bit; 26 unsigned long irqbit; 27 int irq; 28 int pin; 29}; 30 31/* 32 * this covers all hardware timer configurations on 33 * all Blackfin derivatives out there today 34 */ 35 36static struct bfin_timer iio_bfin_timer_code[MAX_BLACKFIN_GPTIMERS] = { 37 {TIMER0_id, TIMER0bit, TIMER_STATUS_TIMIL0, IRQ_TIMER0, P_TMR0}, 38 {TIMER1_id, TIMER1bit, TIMER_STATUS_TIMIL1, IRQ_TIMER1, P_TMR1}, 39 {TIMER2_id, TIMER2bit, TIMER_STATUS_TIMIL2, IRQ_TIMER2, P_TMR2}, 40#if (MAX_BLACKFIN_GPTIMERS > 3) 41 {TIMER3_id, TIMER3bit, TIMER_STATUS_TIMIL3, IRQ_TIMER3, P_TMR3}, 42 {TIMER4_id, TIMER4bit, TIMER_STATUS_TIMIL4, IRQ_TIMER4, P_TMR4}, 43 {TIMER5_id, TIMER5bit, TIMER_STATUS_TIMIL5, IRQ_TIMER5, P_TMR5}, 44 {TIMER6_id, TIMER6bit, TIMER_STATUS_TIMIL6, IRQ_TIMER6, P_TMR6}, 45 {TIMER7_id, TIMER7bit, TIMER_STATUS_TIMIL7, IRQ_TIMER7, P_TMR7}, 46#endif 47#if (MAX_BLACKFIN_GPTIMERS > 8) 48 {TIMER8_id, TIMER8bit, TIMER_STATUS_TIMIL8, IRQ_TIMER8, P_TMR8}, 49 {TIMER9_id, TIMER9bit, TIMER_STATUS_TIMIL9, IRQ_TIMER9, P_TMR9}, 50 {TIMER10_id, TIMER10bit, TIMER_STATUS_TIMIL10, IRQ_TIMER10, P_TMR10}, 51#if (MAX_BLACKFIN_GPTIMERS > 11) 52 {TIMER11_id, TIMER11bit, TIMER_STATUS_TIMIL11, IRQ_TIMER11, P_TMR11}, 53#endif 54#endif 55}; 56 57struct bfin_tmr_state { 58 struct iio_trigger *trig; 59 struct bfin_timer *t; 60 unsigned timer_num; 61 bool output_enable; 62 unsigned int duty; 63 int irq; 64}; 65 66static int iio_bfin_tmr_set_state(struct iio_trigger *trig, bool state) 67{ 68 struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig); 69 70 if (get_gptimer_period(st->t->id) == 0) 71 return -EINVAL; 72 73 if (state) 74 enable_gptimers(st->t->bit); 75 else 76 disable_gptimers(st->t->bit); 77 78 return 0; 79} 80 81static ssize_t iio_bfin_tmr_frequency_store(struct device *dev, 82 struct device_attribute *attr, const char *buf, size_t count) 83{ 84 struct iio_trigger *trig = to_iio_trigger(dev); 85 struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig); 86 unsigned int val; 87 bool enabled; 88 int ret; 89 90 ret = kstrtouint(buf, 10, &val); 91 if (ret) 92 return ret; 93 94 if (val > 100000) 95 return -EINVAL; 96 97 enabled = get_enabled_gptimers() & st->t->bit; 98 99 if (enabled) 100 disable_gptimers(st->t->bit); 101 102 if (val == 0) 103 return count; 104 105 val = get_sclk() / val; 106 if (val <= 4 || val <= st->duty) 107 return -EINVAL; 108 109 set_gptimer_period(st->t->id, val); 110 set_gptimer_pwidth(st->t->id, val - st->duty); 111 112 if (enabled) 113 enable_gptimers(st->t->bit); 114 115 return count; 116} 117 118static ssize_t iio_bfin_tmr_frequency_show(struct device *dev, 119 struct device_attribute *attr, 120 char *buf) 121{ 122 struct iio_trigger *trig = to_iio_trigger(dev); 123 struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig); 124 unsigned int period = get_gptimer_period(st->t->id); 125 unsigned long val; 126 127 if (period == 0) 128 val = 0; 129 else 130 val = get_sclk() / get_gptimer_period(st->t->id); 131 132 return sprintf(buf, "%lu\n", val); 133} 134 135static DEVICE_ATTR(frequency, S_IRUGO | S_IWUSR, iio_bfin_tmr_frequency_show, 136 iio_bfin_tmr_frequency_store); 137 138static struct attribute *iio_bfin_tmr_trigger_attrs[] = { 139 &dev_attr_frequency.attr, 140 NULL, 141}; 142 143static const struct attribute_group iio_bfin_tmr_trigger_attr_group = { 144 .attrs = iio_bfin_tmr_trigger_attrs, 145}; 146 147static const struct attribute_group *iio_bfin_tmr_trigger_attr_groups[] = { 148 &iio_bfin_tmr_trigger_attr_group, 149 NULL 150}; 151 152static irqreturn_t iio_bfin_tmr_trigger_isr(int irq, void *devid) 153{ 154 struct bfin_tmr_state *st = devid; 155 156 clear_gptimer_intr(st->t->id); 157 iio_trigger_poll(st->trig); 158 159 return IRQ_HANDLED; 160} 161 162static int iio_bfin_tmr_get_number(int irq) 163{ 164 int i; 165 166 for (i = 0; i < MAX_BLACKFIN_GPTIMERS; i++) 167 if (iio_bfin_timer_code[i].irq == irq) 168 return i; 169 170 return -ENODEV; 171} 172 173static const struct iio_trigger_ops iio_bfin_tmr_trigger_ops = { 174 .owner = THIS_MODULE, 175 .set_trigger_state = iio_bfin_tmr_set_state, 176}; 177 178static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev) 179{ 180 struct iio_bfin_timer_trigger_pdata *pdata = pdev->dev.platform_data; 181 struct bfin_tmr_state *st; 182 unsigned int config; 183 int ret; 184 185 st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL); 186 if (!st) 187 return -ENOMEM; 188 189 st->irq = platform_get_irq(pdev, 0); 190 if (!st->irq) { 191 dev_err(&pdev->dev, "No IRQs specified"); 192 return -ENODEV; 193 } 194 195 ret = iio_bfin_tmr_get_number(st->irq); 196 if (ret < 0) 197 return ret; 198 199 st->timer_num = ret; 200 st->t = &iio_bfin_timer_code[st->timer_num]; 201 202 st->trig = iio_trigger_alloc("bfintmr%d", st->timer_num); 203 if (!st->trig) 204 return -ENOMEM; 205 206 st->trig->ops = &iio_bfin_tmr_trigger_ops; 207 st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups; 208 iio_trigger_set_drvdata(st->trig, st); 209 ret = iio_trigger_register(st->trig); 210 if (ret) 211 goto out; 212 213 ret = request_irq(st->irq, iio_bfin_tmr_trigger_isr, 214 0, st->trig->name, st); 215 if (ret) { 216 dev_err(&pdev->dev, 217 "request IRQ-%d failed", st->irq); 218 goto out1; 219 } 220 221 config = PWM_OUT | PERIOD_CNT | IRQ_ENA; 222 223 if (pdata && pdata->output_enable) { 224 unsigned long long val; 225 226 st->output_enable = true; 227 228 ret = peripheral_request(st->t->pin, st->trig->name); 229 if (ret) 230 goto out_free_irq; 231 232 val = (unsigned long long)get_sclk() * pdata->duty_ns; 233 do_div(val, NSEC_PER_SEC); 234 st->duty = val; 235 236 /** 237 * The interrupt will be generated at the end of the period, 238 * since we want the interrupt to be generated at end of the 239 * pulse we invert both polarity and duty cycle, so that the 240 * pulse will be generated directly before the interrupt. 241 */ 242 if (pdata->active_low) 243 config |= PULSE_HI; 244 } else { 245 st->duty = 1; 246 config |= OUT_DIS; 247 } 248 249 set_gptimer_config(st->t->id, config); 250 251 dev_info(&pdev->dev, "iio trigger Blackfin TMR%d, IRQ-%d", 252 st->timer_num, st->irq); 253 platform_set_drvdata(pdev, st); 254 255 return 0; 256out_free_irq: 257 free_irq(st->irq, st); 258out1: 259 iio_trigger_unregister(st->trig); 260out: 261 iio_trigger_put(st->trig); 262 return ret; 263} 264 265static int iio_bfin_tmr_trigger_remove(struct platform_device *pdev) 266{ 267 struct bfin_tmr_state *st = platform_get_drvdata(pdev); 268 269 disable_gptimers(st->t->bit); 270 if (st->output_enable) 271 peripheral_free(st->t->pin); 272 free_irq(st->irq, st); 273 iio_trigger_unregister(st->trig); 274 iio_trigger_put(st->trig); 275 276 return 0; 277} 278 279static struct platform_driver iio_bfin_tmr_trigger_driver = { 280 .driver = { 281 .name = "iio_bfin_tmr_trigger", 282 }, 283 .probe = iio_bfin_tmr_trigger_probe, 284 .remove = iio_bfin_tmr_trigger_remove, 285}; 286 287module_platform_driver(iio_bfin_tmr_trigger_driver); 288 289MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); 290MODULE_DESCRIPTION("Blackfin system timer based trigger for the iio subsystem"); 291MODULE_LICENSE("GPL v2"); 292MODULE_ALIAS("platform:iio-trig-bfin-timer"); 293