lkml.org 
[lkml]   [2016]   [Oct]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4/6] pwm: imx: Provide atomic PWM support for IMXv2 PWM
    Date
    This commit provides apply() callback implementation for IMX's PWMv2.

    Suggested-by: Stefan Agner <stefan@agner.ch>
    Suggested-by: Boris Brezillon <boris.brezillon@free-electrons.com>
    Signed-off-by: Lukasz Majewski <l.majewski@majess.pl>
    ---
    drivers/pwm/pwm-imx.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 79 insertions(+)

    diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
    index f3577c5..df25379 100644
    --- a/drivers/pwm/pwm-imx.c
    +++ b/drivers/pwm/pwm-imx.c
    @@ -171,6 +171,84 @@ static void imx_pwm_wait_fifo_slot(struct pwm_chip *chip,
    }
    }

    +static int imx_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm,
    + struct pwm_state *state)
    +{
    + unsigned long period_cycles, duty_cycles, prescale;
    + struct imx_chip *imx = to_imx_chip(chip);
    + struct pwm_state cstate;
    + unsigned long long c;
    + u32 cr = 0;
    + int ret;
    +
    + ret = clk_prepare_enable(imx->clk_ipg);
    + if (ret)
    + return ret;
    +
    + pwm_get_state(pwm, &cstate);
    +
    + c = clk_get_rate(imx->clk_per);
    + c *= state->period;
    +
    + do_div(c, 1000000000);
    + period_cycles = c;
    +
    + prescale = period_cycles / 0x10000 + 1;
    +
    + period_cycles /= prescale;
    + c = (unsigned long long)period_cycles * state->duty_cycle;
    + do_div(c, state->period);
    + duty_cycles = c;
    +
    + /*
    + * according to imx pwm RM, the real period value should be
    + * PERIOD value in PWMPR plus 2.
    + */
    + if (period_cycles > 2)
    + period_cycles -= 2;
    + else
    + period_cycles = 0;
    +
    + /* Enable the clock if the PWM is being enabled. */
    + if (state->enabled && !cstate.enabled) {
    + ret = clk_prepare_enable(imx->clk_per);
    + if (ret)
    + return ret;
    + }
    +
    + /*
    + * Wait for a free FIFO slot if the PWM is already enabled, and flush
    + * the FIFO if the PWM was disabled and is about to be enabled.
    + */
    + if (cstate.enabled)
    + imx_pwm_wait_fifo_slot(chip, pwm);
    + else if (state->enabled)
    + imx_pwm_sw_reset(chip);
    +
    + writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
    + writel(period_cycles, imx->mmio_base + MX3_PWMPR);
    +
    + cr |= MX3_PWMCR_PRESCALER(prescale) |
    + MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
    + MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH;
    +
    + if (state->enabled)
    + cr |= MX3_PWMCR_EN;
    +
    + if (state->polarity == PWM_POLARITY_INVERSED)
    + cr |= MX3_PWMCR_POUTC;
    +
    + writel(cr, imx->mmio_base + MX3_PWMCR);
    +
    + /* Disable the clock if the PWM is being disabled. */
    + if (!state->enabled && cstate.enabled)
    + clk_disable_unprepare(imx->clk_per);
    +
    + clk_disable_unprepare(imx->clk_ipg);
    +
    + return 0;
    +}
    +
    static int imx_pwm_config_v2(struct pwm_chip *chip,
    struct pwm_device *pwm, int duty_ns, int period_ns)
    {
    @@ -322,6 +400,7 @@ static struct pwm_ops imx_pwm_ops_v2 = {
    .disable = imx_pwm_disable,
    .set_polarity = imx_pwm_set_polarity,
    .config = imx_pwm_config,
    + .apply = imx_pwm_apply_v2,
    .owner = THIS_MODULE,
    };

    --
    2.1.4
    \
     
     \ /
      Last update: 2016-10-23 23:57    [W:5.206 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site