static void pwm_config_ns_to_ticks(struct pwm_device *p, struct pwm_config *c) { if (test_bit(PWM_CONFIG_PERIOD_NS, &c->config_mask)) { c->period_ticks = pwm_ns_to_ticks(p, c->period_ns); clear_bit(PWM_CONFIG_PERIOD_NS, &c->config_mask); set_bit(PWM_CONFIG_PERIOD_TICKS, &c->config_mask); } if (test_bit(PWM_CONFIG_DUTY_NS, &c->config_mask)) { c->duty_ticks = pwm_ns_to_ticks(p, c->duty_ns); clear_bit(PWM_CONFIG_DUTY_NS, &c->config_mask); set_bit(PWM_CONFIG_DUTY_TICKS, &c->config_mask); } }
int pwm_set_period_ns(struct pwm_device *p, unsigned long period_ns) { struct pwm_config c = { .config_mask = BIT(PWM_CONFIG_PERIOD_TICKS), .period_ticks = pwm_ns_to_ticks(p, period_ns), }; spin_lock(&p->pwm_lock); p->period_ns = period_ns; spin_unlock(&p->pwm_lock); return pwm_config(p, &c); } EXPORT_SYMBOL(pwm_set_period_ns); unsigned long pwm_get_period_ns(struct pwm_device *p) { return pwm_ticks_to_ns(p, p->period_ticks); } EXPORT_SYMBOL(pwm_get_period_ns); int pwm_set_frequency(struct pwm_device *p, unsigned long freq) { struct pwm_config c; if (!freq) return -EINVAL; c.config_mask = BIT(PWM_CONFIG_PERIOD_TICKS), c.period_ticks = pwm_ns_to_ticks(p, (NSEC_PER_SEC / freq)), spin_lock(&p->pwm_lock); p->period_ns = NSEC_PER_SEC / freq; spin_unlock(&p->pwm_lock); return pwm_config(p, &c); } EXPORT_SYMBOL(pwm_set_frequency); unsigned long pwm_get_frequency(struct pwm_device *p) { unsigned long period_ns; period_ns = pwm_ticks_to_ns(p, p->period_ticks); if (!period_ns) { pr_debug("%s: frequency is zero\n", dev_name(p->dev)); return 0; } return NSEC_PER_SEC / period_ns; }
int ehrpwm_db_set_delay(struct pwm_device *p, unsigned char edge, enum config_mask cfgmask, unsigned long delay) { struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p); unsigned long delay_ticks; unsigned char offset = 0; if (!ehrpwm) return -EINVAL; if (edge == RISING_EDGE_DELAY) offset = DBRED; else if (edge == FALLING_EDGE_DELAY) offset = DBFED; else return -EINVAL; if (cfgmask == CONFIG_TICKS) { delay = delay / ehrpwm->prescale_val; if (delay > 0x3ff) return -EINVAL; ehrpwm_write(ehrpwm, offset, delay); } else if (cfgmask == CONFIG_NS) { delay_ticks = pwm_ns_to_ticks(p, delay); delay_ticks = delay_ticks / ehrpwm->prescale_val; if (delay_ticks > 0x3ff) { ehrpwm_db_get_max_delay(p, CONFIG_NS, &delay_ticks); dev_dbg(p->dev, "%s: Expected delay cannot be" " attained setting the maximum possible delay of" " %lu ns", __func__, delay_ticks); delay_ticks = 0x3ff; } debug("\n delay ticks is %lu", delay_ticks); ehrpwm_write(ehrpwm, offset, delay_ticks); } else { return -EINVAL; } return 0; }
static int ehrpwm_probe(struct platform_device *pdev) { struct ehrpwm_pwm *ehrpwm = NULL; struct resource *r; int ret = 0; int chan = 0; struct pwmss_platform_data *pdata = (&pdev->dev)->platform_data; int ch_mask = 0; int val; char con_id[PWM_CON_ID_STRING_LENGTH] = "epwmss"; ehrpwm = kzalloc(sizeof(*ehrpwm), GFP_KERNEL); if (!ehrpwm) { dev_err(&pdev->dev, "failed to allocate memory\n"); ret = -ENOMEM; goto err_mem_failure; } ehrpwm->version = pdata->version; if (ehrpwm->version == PWM_VERSION_1) { sprintf(con_id, "%s%d_%s", con_id, pdev->id, "fck"); ehrpwm->clk = clk_get(&pdev->dev, con_id); } else ehrpwm->clk = clk_get(&pdev->dev, "ehrpwm"); pm_runtime_enable(&pdev->dev); ehrpwm->dev = &pdev->dev; if (IS_ERR(ehrpwm->clk)) { ret = PTR_ERR(ehrpwm->clk); goto err_clock_failure; } if (ehrpwm->version == PWM_VERSION_1) { r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { dev_err(&pdev->dev, "no memory resource defined\n"); ret = -ENOMEM; goto err_resource_mem_failure; } ehrpwm->config_mem_base = ioremap(r->start, resource_size(r)); if (!ehrpwm->config_mem_base) { dev_err(&pdev->dev, "failed to ioremap() registers\n"); ret = -ENODEV; goto err_free_mem_config; } pm_runtime_get_sync(ehrpwm->dev); val = readw(ehrpwm->config_mem_base + PWMSS_CLKCONFIG); val |= BIT(EPWM_CLK_EN); writew(val, ehrpwm->config_mem_base + PWMSS_CLKCONFIG); pm_runtime_put_sync(ehrpwm->dev); } else ch_mask = pdata->channel_mask; spin_lock_init(&ehrpwm->lock); ehrpwm->ops.config = ehrpwm_pwm_config; ehrpwm->ops.request = ehrpwm_pwm_request; ehrpwm->ops.freq_transition_notifier_cb = ehrpwm_freq_transition_cb; ehrpwm->prescale_val = 1; if (ehrpwm->version == PWM_VERSION_1) r = platform_get_resource(pdev, IORESOURCE_MEM, 1); else r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { dev_err(&pdev->dev, "no memory resource defined\n"); ret = -ENODEV; goto err_resource_mem2_failiure; } r = request_mem_region(r->start, resource_size(r), pdev->name); if (!r) { dev_err(&pdev->dev, "failed to request memory resource\n"); ret = -EBUSY; goto err_request_mem2_failure; } ehrpwm->mmio_base = ioremap(r->start, resource_size(r)); if (!ehrpwm->mmio_base) { dev_err(&pdev->dev, "failed to ioremap() registers\n"); ret = -ENODEV; goto err_free_mem2; } ehrpwm->irq[0] = platform_get_irq(pdev, 0); if (ehrpwm->irq[0] == -ENXIO) { dev_err(&pdev->dev, "No IRQ resource\n"); ret = -ENXIO; goto err_free_io; } ret = request_irq(ehrpwm->irq[0], ehrpwm_trip_zone_irq_handler, 0, "ehrpwmTZ", ehrpwm); if (ret) goto err_free_io; ehrpwm->irq[1] = platform_get_irq(pdev, 1); if (ehrpwm->irq[1] == -ENXIO) { dev_err(&pdev->dev, "No IRQ resource\n"); ret = -ENXIO; goto err_request_irq; } ret = request_irq(ehrpwm->irq[1], ehrpwm_event_irq_handler, 0, "ehrpwm_evt", ehrpwm); if (ret) goto err_request_irq; for (chan = 0; chan < NCHAN; chan++) { ehrpwm->pwm[chan].ops = &ehrpwm->ops; pwm_set_drvdata(&ehrpwm->pwm[chan], ehrpwm); ehrpwm->pwm[chan].tick_hz = clk_get_rate(ehrpwm->clk); if (pdata->chan_attrib[chan].max_freq) { int period_ns = NSEC_PER_SEC / pdata->chan_attrib[chan].max_freq; ehrpwm->pwm[chan].max_period_ticks = pwm_ns_to_ticks(&ehrpwm->pwm[chan], period_ns); } if (!(ehrpwm->version == PWM_VERSION_1)) { if (!(ch_mask & (0x1 << chan))) continue; } ret = pwm_register(&ehrpwm->pwm[chan], &pdev->dev, chan); if (ret) goto err_pwm_register; } platform_set_drvdata(pdev, ehrpwm); return 0; err_pwm_register: for (chan = 0; chan < NCHAN; chan++) { if (pwm_is_registered(&ehrpwm->pwm[chan])) pwm_unregister(&ehrpwm->pwm[chan]); } err_request_irq: if (ehrpwm->irq[0] != -ENXIO) free_irq(ehrpwm->irq[0], ehrpwm); err_free_io: iounmap(ehrpwm->mmio_base); err_free_mem2: release_mem_region(r->start, resource_size(r)); err_request_mem2_failure: err_resource_mem2_failiure: if (ehrpwm->version == PWM_VERSION_1) { iounmap(ehrpwm->config_mem_base); ehrpwm->config_mem_base = NULL; } err_free_mem_config: err_resource_mem_failure: clk_put(ehrpwm->clk); pm_runtime_disable(ehrpwm->dev); err_clock_failure: kfree(ehrpwm); err_mem_failure: return ret; }