From b2f97cf279c54c51741539455116ec3393a871ea Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Fri, 18 Jul 2014 06:07:19 +0200 Subject: pwm, imx6: add support for pwm modul on imx6 add basic support for the pwm modul found on imx6. Pieces of this code are based on linux code from drivers/pwm/pwm-imx.c Commit "cd3de83f1476 Linux 3.16-rc4" Signed-off-by: Heiko Schocher Acked-by: Stefano Babic Cc: Wolfgang Denk diff --git a/README b/README index 4ac7399..a35b92c 100644 --- a/README +++ b/README @@ -1377,6 +1377,10 @@ The following options need to be configured: CONFIG_SH_ETHER_CACHE_WRITEBACK If this option is set, the driver enables cache flush. +- PWM Support: + CONFIG_PWM_IMX + Support for PWM modul on the imx6. + - TPM Support: CONFIG_TPM Support TPM devices. diff --git a/drivers/Makefile b/drivers/Makefile index b23076f..b22b109 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -15,3 +15,4 @@ obj-y += video/ obj-y += watchdog/ obj-$(CONFIG_QE) += qe/ obj-y += memory/ +obj-y += pwm/ diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile new file mode 100644 index 0000000..c0c4883 --- /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 0000000..f1d0b35 --- /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 + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include + +/* 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 0000000..45465c4 --- /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 0000000..40bf027 --- /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 +#include +#include +#include +#include +#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); +} -- cgit v0.10.2