diff options
Diffstat (limited to 'drivers/pwm')
-rw-r--r-- | drivers/pwm/Makefile | 13 | ||||
-rw-r--r-- | drivers/pwm/pwm-imx-util.c | 73 | ||||
-rw-r--r-- | drivers/pwm/pwm-imx-util.h | 16 | ||||
-rw-r--r-- | drivers/pwm/pwm-imx.c | 59 |
4 files changed, 161 insertions, 0 deletions
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile new file mode 100644 index 00000000000..c0c48833173 --- /dev/null +++ b/drivers/pwm/Makefile @@ -0,0 +1,13 @@ +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2001 +# Erik Theisen, Wave 7 Optics, etheisen@mindspring.com. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +#ccflags-y += -DDEBUG + +obj-$(CONFIG_PWM_IMX) += pwm-imx.o pwm-imx-util.o diff --git a/drivers/pwm/pwm-imx-util.c b/drivers/pwm/pwm-imx-util.c new file mode 100644 index 00000000000..f1d0b35d277 --- /dev/null +++ b/drivers/pwm/pwm-imx-util.c @@ -0,0 +1,73 @@ +/* + * (C) Copyright 2014 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * Basic support for the pwm modul on imx6. + * + * Based on linux:drivers/pwm/pwm-imx.c + * from + * Sascha Hauer <s.hauer@pengutronix.de> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <div64.h> +#include <asm/arch/imx-regs.h> + +/* pwm_id from 0..3 */ +struct pwm_regs *pwm_id_to_reg(int pwm_id) +{ + switch (pwm_id) { + case 0: + return (struct pwm_regs *)PWM1_BASE_ADDR; + break; + case 1: + return (struct pwm_regs *)PWM2_BASE_ADDR; + break; + case 2: + return (struct pwm_regs *)PWM3_BASE_ADDR; + break; + case 3: + return (struct pwm_regs *)PWM4_BASE_ADDR; + break; + default: + printf("unknown pwm_id: %d\n", pwm_id); + break; + } + return NULL; +} + +int pwm_imx_get_parms(int period_ns, int duty_ns, unsigned long *period_c, + unsigned long *duty_c, unsigned long *prescale) +{ + unsigned long long c; + + /* + * we have not yet a clock framework for imx6, so add the clock + * value here as a define. Replace it when we have the clock + * framework. + */ + c = CONFIG_IMX6_PWM_PER_CLK; + c = c * period_ns; + do_div(c, 1000000000); + *period_c = c; + + *prescale = *period_c / 0x10000 + 1; + + *period_c /= *prescale; + c = (unsigned long long)(*period_c * duty_ns); + do_div(c, period_ns); + *duty_c = c; + + /* + * according to imx pwm RM, the real period value should be + * PERIOD value in PWMPR plus 2. + */ + if (*period_c > 2) + *period_c -= 2; + else + *period_c = 0; + + return 0; +} diff --git a/drivers/pwm/pwm-imx-util.h b/drivers/pwm/pwm-imx-util.h new file mode 100644 index 00000000000..45465c4fde5 --- /dev/null +++ b/drivers/pwm/pwm-imx-util.h @@ -0,0 +1,16 @@ +/* + * (C) Copyright 2014 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * Basic support for the pwm modul on imx6. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _pwm_imx_util_h_ +#define _pwm_imx_util_h_ + +struct pwm_regs *pwm_id_to_reg(int pwm_id); +int pwm_imx_get_parms(int period_ns, int duty_ns, unsigned long *period_c, + unsigned long *duty_c, unsigned long *prescale); +#endif diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c new file mode 100644 index 00000000000..40bf0275437 --- /dev/null +++ b/drivers/pwm/pwm-imx.c @@ -0,0 +1,59 @@ +/* + * (C) Copyright 2014 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * Basic support for the pwm modul on imx6. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <pwm.h> +#include <asm/arch/imx-regs.h> +#include <asm/io.h> +#include "pwm-imx-util.h" + +int pwm_init(int pwm_id, int div, int invert) +{ + struct pwm_regs *pwm = (struct pwm_regs *)pwm_id_to_reg(pwm_id); + + writel(0, &pwm->ir); + return 0; +} + +int pwm_config(int pwm_id, int duty_ns, int period_ns) +{ + struct pwm_regs *pwm = (struct pwm_regs *)pwm_id_to_reg(pwm_id); + unsigned long period_cycles, duty_cycles, prescale; + u32 cr; + + pwm_imx_get_parms(period_ns, duty_ns, &period_cycles, &duty_cycles, + &prescale); + + cr = PWMCR_PRESCALER(prescale) | + PWMCR_DOZEEN | PWMCR_WAITEN | + PWMCR_DBGEN | PWMCR_CLKSRC_IPG_HIGH; + + writel(cr, &pwm->cr); + /* set duty cycles */ + writel(duty_cycles, &pwm->sar); + /* set period cycles */ + writel(period_cycles, &pwm->pr); + return 0; +} + +int pwm_enable(int pwm_id) +{ + struct pwm_regs *pwm = (struct pwm_regs *)pwm_id_to_reg(pwm_id); + + setbits_le32(&pwm->cr, PWMCR_EN); + return 0; +} + +void pwm_disable(int pwm_id) +{ + struct pwm_regs *pwm = (struct pwm_regs *)pwm_id_to_reg(pwm_id); + + clrbits_le32(&pwm->cr, PWMCR_EN); +} |