summaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pwm/pwm-imx.c')
-rw-r--r--drivers/pwm/pwm-imx.c62
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,