Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19e73333 authored by Sascha Hauer's avatar Sascha Hauer Committed by Thierry Reding
Browse files

pwm: i.MX: factor out SoC specific functions



To cleanup the code and to make it easier to support different
SoCs.

Signed-off-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
Reviewed-by: default avatarShawn Guo <shawn.guo@linaro.org>
Reviewed-by: default avatarBenoît Thébaudeau <benoit.thebaudeau@advansee.com>
Signed-off-by: default avatarThierry Reding <thierry.reding@avionic-design.de>
parent daa5629b
Loading
Loading
Loading
Loading
+83 −63
Original line number Original line Diff line number Diff line
@@ -46,16 +46,46 @@ struct imx_chip {
	void __iomem	*mmio_base;
	void __iomem	*mmio_base;


	struct pwm_chip	chip;
	struct pwm_chip	chip;

	int (*config)(struct pwm_chip *chip,
		struct pwm_device *pwm, int duty_ns, int period_ns);
};
};


#define to_imx_chip(chip)	container_of(chip, struct imx_chip, chip)
#define to_imx_chip(chip)	container_of(chip, struct imx_chip, chip)


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


	if (!(cpu_is_mx1() || cpu_is_mx21())) {
	/*
	 * 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 = max * duty_ns / period_ns;
	writel(max - p, imx->mmio_base + MX1_PWMS);

	return 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 long c;
	unsigned long period_cycles, duty_cycles, prescale;
	unsigned long period_cycles, duty_cycles, prescale;
	u32 cr;
	u32 cr;
@@ -94,33 +124,18 @@ static int imx_pwm_config(struct pwm_chip *chip,
		cr |= MX3_PWMCR_CLKSRC_IPG_HIGH;
		cr |= MX3_PWMCR_CLKSRC_IPG_HIGH;


	writel(cr, imx->mmio_base + MX3_PWMCR);
	writel(cr, imx->mmio_base + MX3_PWMCR);
	} else if (cpu_is_mx1() || cpu_is_mx21()) {
		/* 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 = max * duty_ns / period_ns;
		writel(max - p, imx->mmio_base + MX1_PWMS);
	} else {
		BUG();
	}


	return 0;
	return 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);

	return imx->config(chip, pwm, duty_ns, period_ns);
}

static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
{
{
	struct imx_chip *imx = to_imx_chip(chip);
	struct imx_chip *imx = to_imx_chip(chip);
@@ -187,6 +202,11 @@ static int __devinit imx_pwm_probe(struct platform_device *pdev)
	if (imx->mmio_base == NULL)
	if (imx->mmio_base == NULL)
		return -EADDRNOTAVAIL;
		return -EADDRNOTAVAIL;


	if (cpu_is_mx1() || cpu_is_mx21())
		imx->config = imx_pwm_config_v1;
	else
		imx->config = imx_pwm_config_v2;

	ret = pwmchip_add(&imx->chip);
	ret = pwmchip_add(&imx->chip);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;