Example #1
0
static int imx_pwm_config_v1(struct pwm_chip *chip,
		struct pwm_device *pwm, int duty_ns, int period_ns)
{
	struct imx_chip *imx = to_imx_chip(chip);

	/*
	 * The PWM subsystem allows for exact frequencies. However,
	 * I cannot connect a scope on my device to the PWM line and
	 * thus cannot provide the program the PWM controller
	 * exactly. Instead, I'm relying on the fact that the
	 * Bootloader (u-boot or WinCE+haret) has programmed the PWM
	 * function group already. So I'll just modify the PWM sample
	 * register to follow the ratio of duty_ns vs. period_ns
	 * accordingly.
	 *
	 * This is good enough for programming the brightness of
	 * the LCD backlight.
	 *
	 * The real implementation would divide PERCLK[0] first by
	 * both the prescaler (/1 .. /128) and then by CLKSEL
	 * (/2 .. /16).
	 */
	u32 max = readl(imx->mmio_base + MX1_PWMP);
	u32 p = udiv32(max * duty_ns, period_ns);
	writel(max - p, imx->mmio_base + MX1_PWMS);

	return 0;
}
Example #2
0
static void imx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
{
	struct imx_chip *imx = to_imx_chip(chip);

	imx->set_enable(chip, false);

	/* clk_disable_unprepare(imx->clk_per); */
}
Example #3
0
static int imx_pwm_enable(struct pwm_chip *chip)
{
	struct imx_chip *imx = to_imx_chip(chip);

	imx->set_enable(chip, true);

	return 0;
}
Example #4
0
static int imx_pwm_config(struct pwm_chip *chip,
		int duty_ns, int period_ns)
{
	struct imx_chip *imx = to_imx_chip(chip);
	int ret;

	ret = imx->config(chip, duty_ns, period_ns);

	return ret;
}
Example #5
0
static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
{
	struct imx_chip *imx = to_imx_chip(chip);
	int ret;

	ret = clk_prepare_enable(imx->clk_per);
	if (ret)
		return ret;

	imx->set_enable(chip, true);

	return 0;
}
Example #6
0
static void imx_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
{
	struct imx_chip *imx = to_imx_chip(chip);
	u32 val;

	val = readl(imx->mmio_base + MX3_PWMCR);

	if (enable)
		val |= MX3_PWMCR_EN;
	else
		val &= ~MX3_PWMCR_EN;

	writel(val, imx->mmio_base + MX3_PWMCR);
}
Example #7
0
static int imx_pwm_config(struct pwm_chip *chip,
		struct pwm_device *pwm, int duty_ns, int period_ns)
{
	struct imx_chip *imx = to_imx_chip(chip);
	int ret;

	ret = clk_prepare_enable(imx->clk_ipg);
	if (ret)
		return ret;

	ret = imx->config(chip, pwm, duty_ns, period_ns);

	/* clk_disable_unprepare(imx->clk_ipg); */

	return ret;
}
Example #8
0
static int imx_pwm_config_v2(struct pwm_chip *chip,
		struct pwm_device *pwm, 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;
	u32 cr;

	c = clk_get_rate(imx->clk_per);
	c = c * period_ns;
	c = udiv64(c, 1000000000);
	period_cycles = c;

	prescale = period_cycles / 0x10000 + 1;

	period_cycles = udiv32(period_cycles, prescale);
	c = (unsigned long long)period_cycles * duty_ns;
	c = udiv64(c, period_ns);
	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;

	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 (test_bit(PWMF_ENABLED, &pwm->flags))
		cr |= MX3_PWMCR_EN;

	writel(cr, imx->mmio_base + MX3_PWMCR);

	return 0;
}
Example #9
0
static void imx_pwm_disable(struct pwm_chip *chip)
{
	struct imx_chip *imx = to_imx_chip(chip);

	imx->set_enable(chip, false);
}