diff options
Diffstat (limited to 'drivers/pwm/pwm-imx.c')
-rw-r--r-- | drivers/pwm/pwm-imx.c | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c index 609765d895..c9db4aef34 100644 --- a/drivers/pwm/pwm-imx.c +++ b/drivers/pwm/pwm-imx.c @@ -36,7 +36,7 @@ #define MX3_PWMCR_EN (1 << 0) struct imx_chip { - struct clk *clk_per; + struct clk *clk_per, *clk_ipg; void __iomem *mmio_base; @@ -93,14 +93,42 @@ static void imx_pwm_set_enable_v1(struct pwm_chip *chip, bool enable) writel(val, imx->mmio_base + MX1_PWMC); } +static int imx_pwm_clk_enable_v2(struct imx_chip *imx) +{ + int ret; + + ret = clk_enable(imx->clk_ipg); + if (ret) + return ret; + + ret = clk_prepare_enable(imx->clk_per); + if (ret) { + clk_disable_unprepare(imx->clk_ipg); + return ret; + } + + return 0; +} + +static void imx_pwm_clk_disable_v2(struct imx_chip *imx) +{ + clk_disable_unprepare(imx->clk_per); + clk_disable_unprepare(imx->clk_ipg); +} + static int imx_pwm_config_v2(struct pwm_chip *chip, int duty_ns, int period_ns) { struct imx_chip *imx = to_imx_chip(chip); unsigned long long c; unsigned long period_cycles, duty_cycles, prescale; + int ret; u32 cr; + ret = imx_pwm_clk_enable_v2(imx); + if (ret) + return ret; + c = clk_get_rate(imx->clk_per); c = c * period_ns; do_div(c, 1000000000); @@ -134,6 +162,9 @@ static int imx_pwm_config_v2(struct pwm_chip *chip, writel(cr, imx->mmio_base + MX3_PWMCR); + if (!chip->state.p_enable) + imx_pwm_clk_disable_v2(imx); + return 0; } @@ -141,6 +172,11 @@ static void imx_pwm_set_enable_v2(struct pwm_chip *chip, bool enable) { struct imx_chip *imx = to_imx_chip(chip); u32 val; + int ret; + + ret = imx_pwm_clk_enable_v2(imx); + if (WARN_ON(ret)) + return; val = readl(imx->mmio_base + MX3_PWMCR); @@ -150,6 +186,9 @@ static void imx_pwm_set_enable_v2(struct pwm_chip *chip, bool enable) val &= ~MX3_PWMCR_EN; writel(val, imx->mmio_base + MX3_PWMCR); + + if (!enable) + imx_pwm_clk_disable_v2(imx); } static int imx_pwm_apply(struct pwm_chip *chip, const struct pwm_state *state) @@ -200,13 +239,14 @@ static struct of_device_id imx_pwm_dt_ids[] = { { .compatible = "fsl,imx27-pwm", .data = &imx_pwm_data_v2, }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, imx_pwm_dt_ids); -static int imx_pwm_probe(struct device_d *dev) +static int imx_pwm_probe(struct device *dev) { struct resource *iores; const struct imx_pwm_data *data; struct imx_chip *imx; - int ret = 0; + int ret; ret = dev_get_drvdata(dev, (const void **)&data); if (ret) @@ -214,6 +254,10 @@ static int imx_pwm_probe(struct device_d *dev) imx = xzalloc(sizeof(*imx)); + imx->clk_ipg = clk_get_optional(dev, "ipg"); + if (IS_ERR(imx->clk_ipg)) + return PTR_ERR(imx->clk_ipg); + imx->clk_per = clk_get(dev, "per"); if (IS_ERR(imx->clk_per)) return PTR_ERR(imx->clk_per); @@ -224,8 +268,8 @@ static int imx_pwm_probe(struct device_d *dev) imx->mmio_base = IOMEM(iores->start); imx->chip.ops = &imx_pwm_ops; - if (dev->device_node) { - imx->chip.devname = of_alias_get(dev->device_node); + if (dev->of_node) { + imx->chip.devname = of_alias_get(dev->of_node); if (!imx->chip.devname) imx->chip.devname = basprintf("pwm_%p", imx->mmio_base); @@ -236,14 +280,10 @@ static int imx_pwm_probe(struct device_d *dev) imx->config = data->config; imx->set_enable = data->set_enable; - ret = pwmchip_add(&imx->chip, dev); - if (ret < 0) - return ret; - - return 0; + return pwmchip_add(&imx->chip, dev);; } -static struct driver_d imx_pwm_driver = { +static struct driver imx_pwm_driver = { .name = "imx-pwm", .of_compatible = imx_pwm_dt_ids, .probe = imx_pwm_probe, |