static void bfin_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { case CLOCK_EVT_MODE_PERIODIC: { set_gptimer_config(TIMER0_id, \ TIMER_OUT_DIS | TIMER_IRQ_ENA | \ TIMER_PERIOD_CNT | TIMER_MODE_PWM); set_gptimer_period(TIMER0_id, get_sclk() / HZ); set_gptimer_pwidth(TIMER0_id, get_sclk() / HZ - 1); enable_gptimers(TIMER0bit); break; } case CLOCK_EVT_MODE_ONESHOT: disable_gptimers(TIMER0bit); set_gptimer_config(TIMER0_id, \ TIMER_OUT_DIS | TIMER_IRQ_ENA | TIMER_MODE_PWM); set_gptimer_period(TIMER0_id, 0); break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: disable_gptimers(TIMER0bit); break; case CLOCK_EVT_MODE_RESUME: break; } }
int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) { unsigned long period, duty; unsigned long long val; if (duty_ns < 0 || duty_ns > period_ns) return -EINVAL; val = (unsigned long long)get_sclk() * period_ns; do_div(val, NSEC_PER_SEC); period = val; val = (unsigned long long)period * duty_ns; do_div(val, period_ns); duty = period - val; if (duty >= period) duty = period - 1; set_gptimer_config(pwm->id, TIMER_MODE_PWM | TIMER_PERIOD_CNT); set_gptimer_pwidth(pwm->id, duty); set_gptimer_period(pwm->id, period); return 0; }
static ssize_t iio_bfin_tmr_frequency_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct iio_trigger *trig = dev_get_drvdata(dev); struct bfin_tmr_state *st = trig->private_data; long val; int ret; ret = strict_strtoul(buf, 10, &val); if (ret) goto error_ret; if (val > 100000) { ret = -EINVAL; goto error_ret; } disable_gptimers(st->t->bit); if (!val) goto error_ret; val = get_sclk() / val; if (val <= 4) { ret = -EINVAL; goto error_ret; } set_gptimer_period(st->t->id, val); set_gptimer_pwidth(st->t->id, 1); enable_gptimers(st->t->bit); error_ret: return ret ? ret : count; }
void __init setup_gptimer0(void) { disable_gptimers(TIMER0bit); set_gptimer_config(TIMER0_id, \ TIMER_OUT_DIS | TIMER_PERIOD_CNT | TIMER_MODE_PWM); set_gptimer_period(TIMER0_id, -1); set_gptimer_pwidth(TIMER0_id, -2); SSYNC(); enable_gptimers(TIMER0bit); }
void __init setup_system_timer0(void) { /* Power down the core timer, just to play safe. */ bfin_write_TCNTL(0); disable_gptimers(TIMER0bit); set_gptimer_status(0, TIMER_STATUS_TRUN0); while (get_gptimer_status(0) & TIMER_STATUS_TRUN0) udelay(10); set_gptimer_config(0, 0x59); /* IRQ enable, periodic, PWM_OUT, SCLKed, OUT PAD disabled */ set_gptimer_period(TIMER0_id, get_sclk() / HZ); set_gptimer_pwidth(TIMER0_id, 1); SSYNC(); enable_gptimers(TIMER0bit); }
static ssize_t iio_bfin_tmr_frequency_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct iio_trigger *trig = to_iio_trigger(dev); struct bfin_tmr_state *st = trig->private_data; unsigned long val; bool enabled; int ret; ret = strict_strtoul(buf, 10, &val); if (ret) goto error_ret; if (val > 100000) { ret = -EINVAL; goto error_ret; } enabled = get_enabled_gptimers() & st->t->bit; if (enabled) disable_gptimers(st->t->bit); if (!val) goto error_ret; val = get_sclk() / val; if (val <= 4 || val <= st->duty) { ret = -EINVAL; goto error_ret; } set_gptimer_period(st->t->id, val); set_gptimer_pwidth(st->t->id, val - st->duty); if (enabled) enable_gptimers(st->t->bit); error_ret: return ret ? ret : count; }
static int bfin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, int duty_ns, int period_ns) { struct bfin_pwm *priv = pwm_get_chip_data(pwm); unsigned long period, duty; unsigned long long val; val = (unsigned long long)get_sclk() * period_ns; do_div(val, NSEC_PER_SEC); period = val; val = (unsigned long long)period * duty_ns; do_div(val, period_ns); duty = period - val; if (duty >= period) duty = period - 1; set_gptimer_config(priv->pin, TIMER_MODE_PWM | TIMER_PERIOD_CNT); set_gptimer_pwidth(priv->pin, duty); set_gptimer_period(priv->pin, period); return 0; }
static ssize_t iio_bfin_tmr_frequency_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct iio_trigger *trig = to_iio_trigger(dev); struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig); unsigned int val; bool enabled; int ret; ret = kstrtouint(buf, 10, &val); if (ret) return ret; if (val > 100000) return -EINVAL; enabled = get_enabled_gptimers() & st->t->bit; if (enabled) disable_gptimers(st->t->bit); if (val == 0) return count; val = get_sclk() / val; if (val <= 4 || val <= st->duty) return -EINVAL; set_gptimer_period(st->t->id, val); set_gptimer_pwidth(st->t->id, val - st->duty); if (enabled) enable_gptimers(st->t->bit); return count; }