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

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
...@@ -46,16 +46,46 @@ struct imx_chip { ...@@ -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, ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment