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 <sugu...@ti.com>
---
Changes since v2:
a) pwm_config_device callback is made more flexible.
b) pwm_request function code has been made more cleaner.
c) Sanity-check/warn has been included.

 arch/arm/mach-davinci/Makefile                   |    3 +
 arch/arm/mach-davinci/davinci_pwm.c              |  130 ++++++++++++++++++++++
 arch/arm/mach-davinci/include/mach/davinci_pwm.h |   32 ++++++
 3 files changed, 165 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..c2b8b9a
--- /dev/null
+++ b/arch/arm/mach-davinci/davinci_pwm.c
@@ -0,0 +1,130 @@
+/*
+ * 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;
+
+       return clk_enable(pwm->clk);
+}
+EXPORT_SYMBOL(pwm_enable);
+
+void pwm_disable(struct pwm_device *pwm)
+{
+       if (WARN_ON(!pwm))
+               return;
+
+       clk_disable(pwm->clk);
+}
+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..3b7a3c8
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h
@@ -0,0 +1,32 @@
+/*
+ * 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_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
Davinci-linux-open-source@linux.davincidsp.com
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to