From 061ff0854baad667e7870187bed9bcc6d8778715 Mon Sep 17 00:00:00 2001
From: Jason Kridner <jdk@ti.com>
Date: Mon, 8 Apr 2013 00:21:25 +0000
Subject: [PATCH] pwm_test: add support for devicetree overlay

* Utilize pinctrl to configure the pinmuxes
* Include devicetree overlay files for each of the PWM pins on
  BeagleBone, starting with P8_13

Signed-off-by: Elias Bakken <elias.bakken@gmail.com>
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
Signed-off-by: Jason Kridner <jdk@ti.com>
---
 drivers/pwm/pwm_test.c            |  117 +++++++++++++++++++++----------------
 firmware/Makefile                 |    1 +
 firmware/capes/pwm_P8_13-00A0.dts |   53 +++++++++++++++++
 3 files changed, 121 insertions(+), 50 deletions(-)
 create mode 100644 firmware/capes/pwm_P8_13-00A0.dts

diff --git a/drivers/pwm/pwm_test.c b/drivers/pwm/pwm_test.c
index d9948db..1cf35a9d 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,15 @@ 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. Err %d, (duty, period) = (%lu, %lu)\n",
+			rc, pwm_test->duty_s, pwm_test->period);
+		return rc;
+	}
+	pwm_test->duty = pwm_test->duty_s;
+
 	return count;
 }
 
@@ -73,50 +83,13 @@ 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);
+		return rc;
 	}
+	pwm_test->period = pwm_test->period_s;
+
 	return count;
 }
 
@@ -199,6 +172,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 +188,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 +209,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 +235,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 +255,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 +331,7 @@ static struct platform_driver pwm_test_driver = {
 	.remove		= pwm_test_remove,
 };
 
+
 module_platform_driver(pwm_test_driver);
 
 MODULE_DESCRIPTION("pwm_test Driver");
diff --git a/firmware/Makefile b/firmware/Makefile
index f9f0294..5c27e68 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -154,6 +154,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
 	cape-bone-pinmux-test-00A0.dtbo \
 	cape-bone-exptest-00A0.dtbo \
 	cape-bone-mrf24j40-00A0.dtbo \
+	pwm_P8_13-00A0.dtbo \
 	BB-BONELT-BT-00A0.dtbo
 
 # the geiger cape
diff --git a/firmware/capes/pwm_P8_13-00A0.dts b/firmware/capes/pwm_P8_13-00A0.dts
new file mode 100644
index 0000000..b739e04
--- /dev/null
+++ b/firmware/capes/pwm_P8_13-00A0.dts
@@ -0,0 +1,53 @@
+/*
+* Copyright (C) 2013 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 version 2 as
+* published by the Free Software Foundation.
+*/
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	part-number = "pwm_P8_13";
+	version = "00A0";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pin_P8_13: pinmux_pwm_P8_13 {
+				pinctrl-single,pins = <
+					0x024  0x4	/* gpmc_ad9 = ehrpwm2B | MODE 4 */
+				>;
+			};						
+		};
+	};
+
+	fragment@1 {
+		target = <&ehrpwm2>;
+		__overlay__ {			
+			status = "okay";			
+		};
+	};
+
+	fragment@2 {
+		target = <&ocp>;
+		__overlay__ {			
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			P8_13 {
+				compatible      = "pwm_test";
+				pinctrl-names   = "default";
+				pinctrl-0       = <&pin_P8_13>;
+				pwms 		= <&ehrpwm2 1 500000 1>;
+				pwm-names 	= "P8_13";
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
-- 
1.7.8.6

