This patch adds generic PWM support where it maintains the
list of PWM control devices that can be added or removed.

The interface provides a list of functions that can be accessed
by the PWM control driver module and the generic PWM driver.

The PWM control driver module such as eCAP uses the interface to
register and add itself to the list as a PWM control device.
The generic PWM driver uses the interface to search for a PWM control
device and if present, uses the device for PWM control.

Signed-off-by: Sugumar Natarajan <[email protected]>
---
Changes since v4:
a) Conditional 'clk_enable' and 'clk_disable' has been added

 arch/arm/mach-davinci/Makefile                   |    3 +
 arch/arm/mach-davinci/davinci_pwm.c              |  140 ++++++++++++++++++++++
 arch/arm/mach-davinci/include/mach/davinci_pwm.h |   33 +++++
 3 files changed, 176 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-davinci/davinci_pwm.c
 create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h

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..5a5b332
--- /dev/null
+++ b/arch/arm/mach-davinci/davinci_pwm.c
@@ -0,0 +1,140 @@
+/*
+ * 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)
+{
+       int rc = 0;
+
+       if (WARN_ON(!pwm))
+               return -EINVAL;
+
+       if (!pwm->clk_enabled) {
+               rc = clk_enable(pwm->clk);
+               if (!rc)
+                       pwm->clk_enabled = 1;
+       }
+       return rc;
+}
+EXPORT_SYMBOL(pwm_enable);
+
+void pwm_disable(struct pwm_device *pwm)
+{
+       if (WARN_ON(!pwm))
+               return;
+
+       if (pwm->clk_enabled) {
+               clk_disable(pwm->clk);
+               pwm->clk_enabled = 0;
+       }
+}
+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..6dd8fb2
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h
@@ -0,0 +1,33 @@
+/*
+ * 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     clk_enabled;
+       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
-- 
1.5.6

_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to