From 5b79c57d5039649d7033d0b0ffe80b5dceb1cf78 Mon Sep 17 00:00:00 2001
From: Elias Bakken <elias.bakken@gmail.com>
Date: Tue, 2 Apr 2013 12:10:28 -0500
Subject: [PATCH 20/51] pwm: fix the pwm_test driver to work with device-tree

Hi, I have a patch for the pwm_test.c driver to make it work with device tree.

Signed-off-by: Elias Bakken <elias.bakken@gmail.com>
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
---
 drivers/pwm/pwm_test.c |  122 ++++++++++++++++++++++++++++--------------------
 1 file changed, 72 insertions(+), 50 deletions(-)

diff --git a/drivers/pwm/pwm_test.c b/drivers/pwm/pwm_test.c
index d9948db..1318d5d 100644
--- a/drivers/pwm/pwm_test.c
+++ b/drivers/pwm/pwm_test.c
@@ -26,13 +26,14 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
 
 struct pwm_test {
        struct pwm_device *pwm;
        int ret;
        struct class *pwm_test_class;
-       unsigned long period, duty, run, polarity, config, requested;
-       unsigned long period_s, duty_s, run_s, polarity_s, config_s, requested_s;
+       unsigned long period, duty, run, polarity, requested;
+       unsigned long period_s, duty_s, run_s, polarity_s, requested_s;
        struct device *dev;
 };
 
@@ -52,6 +53,17 @@ static ssize_t pwm_test_store_duty(struct device *dev,
        rc = kstrtoul(buf, 0, &pwm_test->duty_s);
        if (rc)
                return rc;
+
+       rc = pwm_config(pwm_test->pwm, pwm_test->duty_s, pwm_test->period);
+       if (rc) {
+               pr_err("Unable to set pwm duty %d\n", rc);
+               pwm_test->duty_s = pwm_test->duty;
+               pwm_test->period_s = pwm_test->period;
+               return rc;
+       }
+       pwm_test->duty = pwm_test->duty_s;
+       pwm_test->period = pwm_test->period_s;
+
        return count;
 }
 
@@ -73,50 +85,16 @@ static ssize_t pwm_test_store_period(struct device *dev,
        if (rc)
                return rc;
 
-       return count;
-}
-
-static ssize_t pwm_test_show_config(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct pwm_test *pwm_test = dev_get_drvdata(dev);
-       if (pwm_test->config)
-               return sprintf(buf, "config Done\n");
-       else
-               return sprintf(buf, "config Failed\n");
-}
-static ssize_t pwm_test_store_config(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct pwm_test *pwm_test = dev_get_drvdata(dev);
-       int ret;
-
-       if (pwm_test->duty_s == 0) {
-               ret = pwm_config(pwm_test->pwm, 0, pwm_test->period_s);
-               if (ret) {
-                       pwm_test->config = 0;
-                       pr_err("operation failed %d\n", ret);
-                       pwm_test->duty_s = pwm_test->duty;
-                       pwm_test->period_s = pwm_test->period;
-                       return ret;
-               }
-               pwm_test->duty = pwm_test->duty_s;
-               pwm_test->period = pwm_test->period_s;
-               pwm_test->config = 1;
-       } else {
-               ret = pwm_config(pwm_test->pwm, pwm_test->duty_s,
-                               pwm_test->period_s);
-               if (ret) {
-                       pwm_test->config = 0;
-                       pr_err("operation failed %d\n", ret);
-                       pwm_test->duty_s = pwm_test->duty;
-                       pwm_test->period_s = pwm_test->period;
-                       return ret;
-               }
-               pwm_test->duty = pwm_test->duty_s;
-               pwm_test->period = pwm_test->period_s;
-               pwm_test->config = 1;
+       rc = pwm_config(pwm_test->pwm, pwm_test->duty, pwm_test->period_s);
+       if (rc) {
+               pr_err("Unable to set pwm period %d\n", rc);
+               pwm_test->duty_s = pwm_test->duty;
+               pwm_test->period_s = pwm_test->period;
+               return rc;
        }
+       pwm_test->duty = pwm_test->duty_s;
+       pwm_test->period = pwm_test->period_s;
+
        return count;
 }
 
@@ -199,6 +177,9 @@ static ssize_t pwm_test_store_request(struct device *dev,
                return rc;
 
        if (pwm_test->requested_s) {
+               if(pwm_test->requested) // Allready requested
+                       return count;
+
                pwm_test->pwm = pwm_get(dev, NULL);
 
                if (IS_ERR(pwm_test->pwm)) {
@@ -212,12 +193,10 @@ static ssize_t pwm_test_store_request(struct device *dev,
                pwm_test->run = 0;
                pwm_test->duty = 0;
                pwm_test->period = 0;
-               pwm_test->config = 0;
                pwm_test->polarity_s = 0;
                pwm_test->run_s = 0;
                pwm_test->duty_s = 0;
                pwm_test->period_s = 0;
-               pwm_test->config_s = 0;
                rc = 0;
        }
 
@@ -235,14 +214,12 @@ static DEVICE_ATTR(duty, 0644, pwm_test_show_duty, pwm_test_store_duty);
 static DEVICE_ATTR(period, 0644, pwm_test_show_period, pwm_test_store_period);
 static DEVICE_ATTR(polarity, 0644, pwm_test_show_polarity,
                pwm_test_store_polarity);
-static DEVICE_ATTR(config, 0644 , pwm_test_show_config, pwm_test_store_config);
 static DEVICE_ATTR(run, 0644 , pwm_test_show_run, pwm_test_store_run);
 static DEVICE_ATTR(request, 0644 , pwm_test_show_request, pwm_test_store_request);
 
 static const struct attribute *pwm_attrs[] = {
        &dev_attr_duty.attr,
        &dev_attr_period.attr,
-       &dev_attr_config.attr,
        &dev_attr_run.attr,
        &dev_attr_request.attr,
        &dev_attr_polarity.attr,
@@ -263,6 +240,14 @@ static int __init pwm_test_class_init(struct device *dev)
 static int pwm_test_probe(struct platform_device *pdev)
 {
        struct pwm_test *pwm_test;
+       struct pinctrl *pinctrl;
+       struct device_node *node = (&pdev->dev)->of_node;
+       int rc;
+
+       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+       if (IS_ERR(pinctrl))
+               dev_warn(&pdev->dev, "unable to select pin group. PWM not muxed right\n");
+
 
        pwm_test = devm_kzalloc(&pdev->dev, sizeof(*pwm_test), GFP_KERNEL);
 
@@ -275,7 +260,43 @@ static int pwm_test_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "sysfs creation failed\n");
                return -EINVAL;
        }
-       dev_set_drvdata(&pdev->dev, pwm_test);
+
+       pwm_test->pwm = devm_pwm_get(&pdev->dev, NULL);
+       if (IS_ERR(pwm_test->pwm)) {
+               dev_err(&pdev->dev, "unable to request PWM\n");
+               return -EINVAL;
+       }
+
+       pwm_test->requested = 1;
+
+       pr_debug("pwm_test got PWM\n");
+
+       /* Get the properties of the pwm. This is set in the device driver (tiehrpwm) */
+       pwm_test->period = pwm_get_period(pwm_test->pwm);
+
+       /* Determine running or not from the device tree */
+       rc = of_property_read_u32(node, "enabled", (u32*) &(pwm_test->run));
+       if (rc < 0)
+               return rc;
+
+       if(pwm_test->run){
+               rc = pwm_enable(pwm_test->pwm);
+               if (rc < 0)
+                               return rc;
+       }
+
+       /* Determine the duty from the device tree */
+       rc = of_property_read_u32(node, "duty", (u32*) &(pwm_test->duty_s));
+       if (rc < 0)
+               return rc;
+
+       rc = pwm_config(pwm_test->pwm, pwm_test->duty_s, pwm_test->period);
+       if (rc) {
+               pr_err("Unable to set pwm duty %d\n", rc);
+               return rc;
+       }
+
+
        platform_set_drvdata(pdev, pwm_test);
        return 0;
 }
@@ -315,6 +336,7 @@ static struct platform_driver pwm_test_driver = {
        .remove         = pwm_test_remove,
 };
 
+
 module_platform_driver(pwm_test_driver);
 
 MODULE_DESCRIPTION("pwm_test Driver");
-- 
1.7.10.4