diff mbox

[v5,1/4] davinci: Add generic PWM support for PWM control

Message ID 1284968386-16898-1-git-send-email-sugumar@ti.com (mailing list archive)
State Superseded
Headers show

Commit Message

Sugumar Natarajan Sept. 20, 2010, 7:39 a.m. UTC
None
diff mbox

Patch

diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index a7a70d1..90ca821 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -39,3 +39,6 @@  obj-$(CONFIG_MACH_MITYOMAPL138)		+= board-mityomapl138.o
 obj-$(CONFIG_CPU_FREQ)			+= cpufreq.o
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
 obj-$(CONFIG_SUSPEND)			+= pm.o sleep.o
+
+# Generic PWM control support
+obj-$(CONFIG_HAVE_PWM)			+= davinci_pwm.o
diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c
new file mode 100644
index 0000000..8f3e8ad
--- /dev/null
+++ b/arch/arm/mach-davinci/davinci_pwm.c
@@ -0,0 +1,135 @@ 
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * 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 version 2.
+ *
+ * This program is distributed .as is. WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+#include <mach/davinci_pwm.h>
+
+int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+	unsigned int clock_freq;
+	unsigned int period_cycles;
+	unsigned int duty_cycle;
+	int ret = 0;
+
+	if (WARN_ON(!pwm))
+		return -EINVAL;
+
+	if (pwm->pwm_config_device) {
+		if (!period_ns || duty_ns > period_ns)
+			return -EINVAL;
+
+		clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC;
+		period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC;
+		duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC;
+
+		ret = pwm->pwm_config_device(pwm, period_cycles, duty_cycle);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(pwm_config);
+
+int pwm_enable(struct pwm_device *pwm)
+{
+	if (WARN_ON(!pwm))
+		return -EINVAL;
+
+	if (pwm->pwm_enable)
+		return pwm->pwm_enable(pwm);
+
+	return 0;
+}
+EXPORT_SYMBOL(pwm_enable);
+
+void pwm_disable(struct pwm_device *pwm)
+{
+	if (WARN_ON(!pwm))
+		return;
+
+	if (pwm->pwm_disable)
+		pwm->pwm_disable(pwm);
+}
+EXPORT_SYMBOL(pwm_disable);
+
+static DEFINE_MUTEX(pwm_lock);
+static LIST_HEAD(pwm_list);
+
+struct pwm_device *pwm_request(int pwm_id, const char *label)
+{
+	struct pwm_device *pwm, *tmp_pwm = ERR_PTR(-ENOENT);
+
+	mutex_lock(&pwm_lock);
+
+	list_for_each_entry(pwm, &pwm_list, node) {
+		if (pwm->pwm_id == pwm_id) {
+			if (pwm->use_count == 0) {
+				pwm->use_count++;
+				pwm->label = label;
+			} else {
+				pwm = ERR_PTR(-EBUSY);
+			}
+			tmp_pwm = pwm;
+			break;
+		}
+	}
+
+	mutex_unlock(&pwm_lock);
+	return tmp_pwm;
+}
+EXPORT_SYMBOL(pwm_request);
+
+void pwm_free(struct pwm_device *pwm)
+{
+	if (WARN_ON(!pwm))
+		return;
+
+	mutex_lock(&pwm_lock);
+
+	if (pwm->use_count) {
+		pwm->use_count--;
+		pwm->label = NULL;
+	} else {
+		dev_warn(&pwm->pdev->dev, "PWM device already freed\n");
+	}
+
+	mutex_unlock(&pwm_lock);
+}
+EXPORT_SYMBOL(pwm_free);
+
+void pwm_add(struct pwm_device *pwm)
+{
+	if (WARN_ON(!pwm))
+		return;
+
+	mutex_lock(&pwm_lock);
+	list_add_tail(&pwm->node, &pwm_list);
+	mutex_unlock(&pwm_lock);
+}
+EXPORT_SYMBOL(pwm_add);
+
+void pwm_remove(struct pwm_device *pwm)
+{
+	if (WARN_ON(!pwm))
+		return;
+
+	mutex_lock(&pwm_lock);
+	list_del(&pwm->node);
+	mutex_unlock(&pwm_lock);
+}
+EXPORT_SYMBOL(pwm_remove);
diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h
new file mode 100644
index 0000000..5762881
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h
@@ -0,0 +1,34 @@ 
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * 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 version 2.
+ *
+ * This program is distributed .as is. WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __DAVINCI_PWM_H
+#define __DAVINCI_PWM_H
+
+struct pwm_device {
+	struct list_head	node;
+	struct platform_device	*pdev;
+	int (*pwm_enable)(struct pwm_device *pwm);
+	void (*pwm_disable)(struct pwm_device *pwm);
+	int (*pwm_config_device)(struct pwm_device *pwm,
+		unsigned int period, unsigned int dutycycle);
+	const char	*label;
+	struct clk	*clk;
+	unsigned int	use_count;
+	unsigned int	pwm_id;
+};
+
+void pwm_add(struct pwm_device *pwm);
+void pwm_remove(struct pwm_device *pwm);
+
+#endif