static int ecap_pwm_request(struct pwm_device *p) { struct ecap_pwm *ep = to_ecap_pwm(p); p->tick_hz = clk_get_rate(ep->clk); return 0; }
static int ecap_pwm_config_duty(struct pwm_device *p) { unsigned long flags, v; struct ecap_pwm *ep = to_ecap_pwm(p); pm_runtime_get_sync(ep->dev); spin_lock_irqsave(&ep->lock, flags); v = readw(ep->mmio_base + CAPTURE_CTRL2_REG); v |= (ECTRL2_MDSL_ECAP | ECTRL2_SYNCOSEL_MASK); writew(v, ep->mmio_base + CAPTURE_CTRL2_REG); if (p->duty_ticks > 0) { writel(p->duty_ticks, ep->mmio_base + CAPTURE_4_REG); } else { writel(p->duty_ticks, ep->mmio_base + CAPTURE_2_REG); writel(0, ep->mmio_base + TIMER_CTR_REG); } spin_unlock_irqrestore(&ep->lock, flags); if (!pwm_is_running(p)) { v = readw(ep->mmio_base + CAPTURE_CTRL2_REG); v &= ~ECTRL2_MDSL_ECAP; writew(v, ep->mmio_base + CAPTURE_CTRL2_REG); } pm_runtime_put_sync(ep->dev); return 0; }
static int ecap_pwm_config_period(struct pwm_device *p) { unsigned long flags; struct ecap_pwm *ep = to_ecap_pwm(p); spin_lock_irqsave(&ep->lock, flags); __raw_writel((p->period_ticks) - 1, ep->mmio_base + CAPTURE_3_REG); spin_unlock_irqrestore(&ep->lock, flags); return 0; }
static int ecap_pwm_set_polarity(struct pwm_device *p, char pol) { unsigned long flags; struct ecap_pwm *ep = to_ecap_pwm(p); spin_lock_irqsave(&ep->lock, flags); __raw_writew((__raw_readw(ep->mmio_base + CAPTURE_CTRL2_REG) & ~ECTRL2_APWMPOL) | (!pol << 10), ep->mmio_base + CAPTURE_CTRL2_REG); spin_unlock_irqrestore(&ep->lock, flags); return 0; }
static int ecap_pwm_config_duty(struct pwm_device *p) { unsigned long flags; struct ecap_pwm *ep = to_ecap_pwm(p); spin_lock_irqsave(&ep->lock, flags); if (p->duty_ticks > 0) __raw_writel(p->duty_ticks, ep->mmio_base + CAPTURE_4_REG); else { __raw_writel(p->duty_ticks, ep->mmio_base + CAPTURE_2_REG); __raw_writel(0, ep->mmio_base + TIMER_CTR_REG); } spin_unlock_irqrestore(&ep->lock, flags); return 0; }
static int ecap_pwm_set_polarity(struct pwm_device *p, char pol) { unsigned long flags, v; struct ecap_pwm *ep = to_ecap_pwm(p); pm_runtime_get_sync(ep->dev); spin_lock_irqsave(&ep->lock, flags); v = readw(ep->mmio_base + CAPTURE_CTRL2_REG); v &= ~ECTRL2_PLSL_LOW; v |= pol << 10; writew(v, ep->mmio_base + CAPTURE_CTRL2_REG); spin_unlock_irqrestore(&ep->lock, flags); pm_runtime_put_sync(ep->dev); return 0; }
static int ecap_pwm_start(struct pwm_device *p) { int ret = 0; unsigned long flags; struct ecap_pwm *ep = to_ecap_pwm(p); if (!(p->flags & FLAG_RUNNING)) return 0; spin_lock_irqsave(&ep->lock, flags); __raw_writew(__raw_readw(ep->mmio_base + CAPTURE_CTRL2_REG) | ECTRL2_TSCTRSTOP, ep->mmio_base + CAPTURE_CTRL2_REG); spin_unlock_irqrestore(&ep->lock, flags); set_bit(FLAG_RUNNING, &p->flags); return ret; }
static int ecap_frequency_transition_cb(struct pwm_device *p) { struct ecap_pwm *ep = to_ecap_pwm(p); unsigned long duty_ns; p->tick_hz = clk_get_rate(ep->clk); duty_ns = p->duty_ns; if (pwm_is_running(p)) { pwm_stop(p); pwm_set_duty_ns(p, 0); pwm_set_period_ns(p, p->period_ns); pwm_set_duty_ns(p, duty_ns); pwm_start(p); } else { pwm_set_duty_ns(p, 0); pwm_set_period_ns(p, p->period_ns); pwm_set_duty_ns(p, duty_ns); } return 0; }
static int ecap_pwm_stop(struct pwm_device *p) { unsigned long flags, v; struct ecap_pwm *ep = to_ecap_pwm(p); /* Trying to stop a non-running PWM, not allowed */ if (!pwm_is_running(p)) return -EPERM; spin_lock_irqsave(&ep->lock, flags); v = readw(ep->mmio_base + CAPTURE_CTRL2_REG); v &= ~(ECTRL2_CTRSTP_FREERUN | ECTRL2_MDSL_ECAP); writew(v, ep->mmio_base + CAPTURE_CTRL2_REG); spin_unlock_irqrestore(&ep->lock, flags); /* For PWM clock should be disabled on stop */ pm_runtime_put_sync(ep->dev); clear_bit(FLAG_RUNNING, &p->flags); return 0; }
static int ecap_pwm_start(struct pwm_device *p) { int ret = 0; unsigned long flags, v; struct ecap_pwm *ep = to_ecap_pwm(p); /* Trying to start a running PWM, not allowed */ if (pwm_is_running(p)) return -EPERM; /* For PWM clock should be enabled on start */ pm_runtime_get_sync(ep->dev); spin_lock_irqsave(&ep->lock, flags); v = readw(ep->mmio_base + CAPTURE_CTRL2_REG); v |= (ECTRL2_CTRSTP_FREERUN | ECTRL2_MDSL_ECAP); writew(v, ep->mmio_base + CAPTURE_CTRL2_REG); spin_unlock_irqrestore(&ep->lock, flags); set_bit(FLAG_RUNNING, &p->flags); return ret; }