summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/imx_pwm.c120
2 files changed, 121 insertions, 0 deletions
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 448b9cb..5bbafea 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -29,6 +29,7 @@ COBJS-$(CONFIG_ALI152X) += ali512x.o
COBJS-$(CONFIG_DS4510) += ds4510.o
COBJS-$(CONFIG_FSL_LAW) += fsl_law.o
COBJS-$(CONFIG_IMX_IIM) += imx_iim.o
+COBJS-$(CONFIG_IMX_PWM) += imx_pwm.o
COBJS-$(CONFIG_NS87308) += ns87308.o
COBJS-$(CONFIG_STATUS_LED) += status_led.o
COBJS-$(CONFIG_TWL4030_LED) += twl4030_led.o
diff --git a/drivers/misc/imx_pwm.c b/drivers/misc/imx_pwm.c
new file mode 100644
index 0000000..97c7df0
--- /dev/null
+++ b/drivers/misc/imx_pwm.c
@@ -0,0 +1,120 @@
+/*
+ * Porting to u-boot:
+ * Linux IMX PWM driver
+ *
+ * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/imx_pwm.h>
+#include <common.h>
+#include <div64.h>
+
+#define MX_PWMCR 0x00 /* PWM Control Register */
+#define MX_PWMSAR 0x0C /* PWM Sample Register */
+#define MX_PWMPR 0x10 /* PWM Period Register */
+#define MX_PWMCR_PRESCALER(x) (((x - 1) & 0xFFF) << 4)
+#define MX_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
+#define MX_PWMCR_CLKSRC_IPG (1 << 16)
+#define MX_PWMCR_EN (1 << 0)
+
+#define MX_PWMCR_STOPEN (1 << 25)
+#define MX_PWMCR_DOZEEN (1 << 24)
+#define MX_PWMCR_WAITEN (1 << 23)
+#define MX_PWMCR_DBGEN (1 << 22)
+#define MX_PWMCR_CLKSRC_IPG (1 << 16)
+#define MX_PWMCR_CLKSRC_IPG_32k (3 << 16)
+
+int imx_pwm_config(struct pwm_device pwm, int duty_ns, int period_ns)
+{
+ unsigned long long c;
+ unsigned long period_cycles, duty_cycles, prescale;
+ u32 cr;
+
+ if (period_ns == 0 || duty_ns > period_ns)
+ return -1;
+
+ pwm.mmio_base = pwm.pwm_id ? (unsigned long)IMX_PWM2_BASE:
+ (unsigned long)IMX_PWM1_BASE;
+
+ if (pwm.pwmo_invert)
+ duty_ns = period_ns - duty_ns;
+
+ c = mxc_get_clock(MXC_IPG_PERCLK);
+ c = c * period_ns;
+ do_div(c, 1000000000);
+ period_cycles = c;
+
+ prescale = period_cycles / 0x10000 + 1;
+
+ period_cycles /= prescale;
+ c = (unsigned long long)period_cycles * duty_ns;
+ do_div(c, period_ns);
+ duty_cycles = c;
+
+ writel(duty_cycles, pwm.mmio_base + MX_PWMSAR);
+ writel(period_cycles, pwm.mmio_base + MX_PWMPR);
+
+ cr = MX_PWMCR_PRESCALER(prescale) |
+ MX_PWMCR_STOPEN | MX_PWMCR_DOZEEN |
+ MX_PWMCR_WAITEN | MX_PWMCR_DBGEN;
+
+ cr |= MX_PWMCR_CLKSRC_IPG_HIGH;
+
+ writel(cr, pwm.mmio_base + MX_PWMCR);
+
+ return 0;
+}
+
+int imx_pwm_enable(struct pwm_device pwm)
+{
+ unsigned long reg;
+ int rc = 0;
+
+ if (pwm.enable_pwm_clk)
+ pwm.enable_pwm_clk();
+
+ pwm.mmio_base = pwm.pwm_id ? (unsigned long)IMX_PWM2_BASE:
+ (unsigned long)IMX_PWM1_BASE;
+
+ reg = readl(pwm.mmio_base + MX_PWMCR);
+ reg |= MX_PWMCR_EN;
+ writel(reg, pwm.mmio_base + MX_PWMCR);
+
+ if (pwm.enable_pwm_pad)
+ pwm.enable_pwm_pad();
+
+ return rc;
+}
+
+int imx_pwm_disable(struct pwm_device pwm)
+{
+ if (pwm.disable_pwm_pad)
+ pwm.disable_pwm_pad();
+
+ pwm.mmio_base = pwm.pwm_id ? (unsigned long)IMX_PWM2_BASE:
+ (unsigned long)IMX_PWM1_BASE;
+
+ writel(0, pwm.mmio_base + MX_PWMCR);
+
+ if (pwm.disable_pwm_clk)
+ pwm.disable_pwm_clk();
+
+ return 0;
+}