[linux-yocto] [[PATCH 1/1] pwm: Add freq_hz and duty_percent

chong.yi.chai at intel.com chong.yi.chai at intel.com
Wed Mar 30 20:17:07 PDT 2016


From: "Chai, Chong Yi" <chong.yi.chai at intel.com>

---
 features/soc/baytrail/baytrail.scc                 |   1 +
 .../pwm-Add-freq_hz-and-duty_percent.patch         | 312 +++++++++++++++++++++
 2 files changed, 313 insertions(+)
 create mode 100644 features/soc/baytrail/pwm-Add-freq_hz-and-duty_percent.patch

diff --git a/features/soc/baytrail/baytrail.scc b/features/soc/baytrail/baytrail.scc
index b61a2e7..4b71e0f 100644
--- a/features/soc/baytrail/baytrail.scc
+++ b/features/soc/baytrail/baytrail.scc
@@ -72,3 +72,4 @@ patch pinctrl-baytrail-unmap-interrupt-when-free-the-gpio-.patch
 patch pinctrl-baytrail-enable-platform-device-in-the-absen.patch
 patch pinctrl-baytrail-setup-IOAPIC-interrupt-for-GPIO-clu.patch
 patch pinctrl-baytrail-Serialize-GPIO-registers-access-wit.patch
+patch pwm-Add-freq_hz-and-duty_percent.patch
diff --git a/features/soc/baytrail/pwm-Add-freq_hz-and-duty_percent.patch b/features/soc/baytrail/pwm-Add-freq_hz-and-duty_percent.patch
new file mode 100644
index 0000000..9e3dc9d
--- /dev/null
+++ b/features/soc/baytrail/pwm-Add-freq_hz-and-duty_percent.patch
@@ -0,0 +1,312 @@
+From 15ff282bedbd1b870aeb12d1e3080fd15eb35fe7 Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad at intel.com>
+Date: Tue, 16 Jun 2015 11:17:21 +0800
+Subject: [PATCH 118/164] pwm: Add freq_hz and duty_percent
+
+Add new sysfs interface, freq_hz and duty_percent, together with their
+helper functions to the PWM framework. This patch will enable the
+duration to be configured in unit Hertz and the "on" duration to be
+configured as percentage.
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad at intel.com>
+---
+ drivers/pwm/core.c  |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++-
+ drivers/pwm/sysfs.c |   71 ++++++++++++++++++++++++++++++++++++++
+ include/linux/pwm.h |   50 +++++++++++++++++++++++++++
+ 3 files changed, 215 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
+index a804713..c0712ea 100644
+--- a/drivers/pwm/core.c
++++ b/drivers/pwm/core.c
+@@ -32,7 +32,8 @@
+ 
+ #include <dt-bindings/pwm/pwm.h>
+ 
+-#define MAX_PWMS 1024
++#define MAX_PWMS	1024
++#define NSECS_PER_SEC	1000000000UL
+ 
+ static DEFINE_MUTEX(pwm_lookup_lock);
+ static LIST_HEAD(pwm_lookup_list);
+@@ -197,6 +198,98 @@ static void of_pwmchip_remove(struct pwm_chip *chip)
+ }
+ 
+ /**
++  * pwm_freq_hz_to_period() - convert duration unit to ns
++  * @pwm: PWM device
++  * @freq_hz: number of cycles in duration of 1 second (Hertz)
++  *
++  */
++unsigned int pwm_freq_hz_to_period(struct pwm_device *pwm,
++				   unsigned int freq_hz)
++{
++	unsigned long long period_ns = NSECS_PER_SEC;
++	int remainder;
++
++	if (!freq_hz)
++		return 0;
++
++	remainder = do_div(period_ns, freq_hz);
++	if (remainder && (remainder >= (freq_hz >> 1)))
++		period_ns++;
++
++	return period_ns;
++
++}
++EXPORT_SYMBOL_GPL(pwm_freq_hz_to_period);
++
++/**
++  * pwm_period_to_freq_hz() - convert duration unit to Hertz
++  * @pwm: PWM device
++  * @period_ns: duration (in nanoseconds) of one cycle
++  *
++  */
++unsigned int pwm_period_to_freq_hz(struct pwm_device *pwm,
++				   unsigned int period_ns)
++{
++	unsigned long long freq_hz = NSECS_PER_SEC;
++	int remainder;
++
++	if (!period_ns)
++		return 0;
++
++	remainder = do_div(freq_hz, period_ns);
++	if (remainder && (remainder >= (period_ns >> 1)))
++		freq_hz++;
++
++	return freq_hz;
++}
++EXPORT_SYMBOL_GPL(pwm_period_to_freq_hz);
++
++/**
++  * pwm_duty_percent_to_duty_cycle() - convert "on" time unit to ns
++  * @pwm: PWM device
++  * @duty_percent: "on" time (in percentage)
++  *
++  */
++unsigned int pwm_duty_percent_to_duty_cycle(struct pwm_device *pwm,
++					    unsigned int duty_percent)
++{
++	unsigned long long duty_cycle;
++	int remainder;
++
++	duty_cycle = (pwm->period) * duty_percent;
++	remainder = do_div(duty_cycle, 100);
++	if (remainder && (remainder >= 50))
++		duty_cycle++;
++
++	return duty_cycle;
++}
++EXPORT_SYMBOL_GPL(pwm_duty_percent_to_duty_cycle);
++
++/**
++  * pwm_duty_cycle_to_duty_percent() - convert "on" time unit to percentage
++  * @pwm: PWM device
++  * @duty_cycle: "on" time (in nanoseconds)
++  *
++  */
++unsigned int pwm_duty_cycle_to_duty_percent(struct pwm_device *pwm,
++					    unsigned int duty_cycle)
++{
++	unsigned long long duty_percent;
++	int remainder;
++
++	if (!pwm->period)
++		return 0;
++
++	duty_percent = duty_cycle * 100;
++	remainder = do_div(duty_percent, pwm->period);
++	if (remainder && (remainder >= (pwm->period >> 1)))
++		duty_percent++;
++
++	return duty_percent;
++}
++EXPORT_SYMBOL_GPL(pwm_duty_cycle_to_duty_percent);
++
++/**
+  * pwm_set_chip_data() - set private chip data for a PWM
+  * @pwm: PWM device
+  * @data: pointer to chip-specific data
+diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
+index 4bd0c63..8987720 100644
+--- a/drivers/pwm/sysfs.c
++++ b/drivers/pwm/sysfs.c
+@@ -62,6 +62,10 @@ static ssize_t pwm_period_store(struct device *child,
+ 		return ret;
+ 
+ 	ret = pwm_config(pwm, pwm->duty_cycle, val);
++	if (0 == ret) {
++		val = pwm_period_to_freq_hz(pwm, val);
++		pwm_set_freq_hz(pwm, val);
++	}
+ 
+ 	return ret ? : size;
+ }
+@@ -88,6 +92,10 @@ static ssize_t pwm_duty_cycle_store(struct device *child,
+ 		return ret;
+ 
+ 	ret = pwm_config(pwm, val, pwm->period);
++	if (0 == ret) {
++		val = pwm_duty_cycle_to_duty_percent(pwm, val);
++		pwm_set_duty_percent(pwm, val);
++	}
+ 
+ 	return ret ? : size;
+ }
+@@ -157,16 +165,79 @@ static ssize_t pwm_polarity_store(struct device *child,
+ 	return ret ? : size;
+ }
+ 
++static ssize_t pwm_freq_hz_show(struct device *child,
++				struct device_attribute *attr,
++				char *buf)
++{
++	const struct pwm_device *pwm = child_to_pwm_device(child);
++
++	return sprintf(buf, "%u\n", pwm->freq_hz);
++}
++
++static ssize_t pwm_freq_hz_store(struct device *child,
++				 struct device_attribute *attr,
++				 const char *buf, size_t size)
++{
++	struct pwm_device *pwm = child_to_pwm_device(child);
++	unsigned int val, tmp_val;
++	int ret;
++
++	ret = kstrtouint(buf, 0, &val);
++	if (ret)
++		return ret;
++
++	tmp_val = pwm_freq_hz_to_period(pwm, val);
++	ret = pwm_config(pwm, pwm->duty_cycle, tmp_val);
++	if (0 == ret)
++		pwm_set_freq_hz(pwm, val);
++
++	return ret ? : size;
++}
++
++static ssize_t pwm_duty_percent_show(struct device *child,
++				     struct device_attribute *attr,
++				     char *buf)
++{
++	const struct pwm_device *pwm = child_to_pwm_device(child);
++
++	return sprintf(buf, "%u\n", pwm->duty_percent);
++}
++
++static ssize_t pwm_duty_percent_store(struct device *child,
++				      struct device_attribute *attr,
++				      const char *buf, size_t size)
++{
++	struct pwm_device *pwm = child_to_pwm_device(child);
++	unsigned int val, tmp_val;
++	int ret;
++
++	ret = kstrtouint(buf, 0, &val);
++	if (ret)
++		return ret;
++
++	tmp_val = pwm_duty_percent_to_duty_cycle(pwm, val);
++	ret = pwm_config(pwm, tmp_val, pwm->period);
++	if (0 == ret)
++		pwm_set_duty_percent(pwm, val);
++
++	return ret ? : size;
++}
++
+ static DEVICE_ATTR(period, 0644, pwm_period_show, pwm_period_store);
+ static DEVICE_ATTR(duty_cycle, 0644, pwm_duty_cycle_show, pwm_duty_cycle_store);
+ static DEVICE_ATTR(enable, 0644, pwm_enable_show, pwm_enable_store);
+ static DEVICE_ATTR(polarity, 0644, pwm_polarity_show, pwm_polarity_store);
++static DEVICE_ATTR(freq_hz, 0644, pwm_freq_hz_show, pwm_freq_hz_store);
++static DEVICE_ATTR(duty_percent, 0644, pwm_duty_percent_show,
++		   pwm_duty_percent_store);
+ 
+ static struct attribute *pwm_attrs[] = {
+ 	&dev_attr_period.attr,
+ 	&dev_attr_duty_cycle.attr,
+ 	&dev_attr_enable.attr,
+ 	&dev_attr_polarity.attr,
++	&dev_attr_freq_hz.attr,
++	&dev_attr_duty_percent.attr,
+ 	NULL
+ };
+ ATTRIBUTE_GROUPS(pwm);
+diff --git a/include/linux/pwm.h b/include/linux/pwm.h
+index f0feafd..f7d6dbb 100644
+--- a/include/linux/pwm.h
++++ b/include/linux/pwm.h
+@@ -89,6 +89,8 @@ struct pwm_device {
+ 
+ 	unsigned int		period; 	/* in nanoseconds */
+ 	unsigned int		duty_cycle;	/* in nanoseconds */
++	unsigned int		freq_hz;	/* in Hertz       */
++	unsigned int		duty_percent;	/* in percentage  */
+ 	enum pwm_polarity	polarity;
+ };
+ 
+@@ -114,11 +116,59 @@ static inline unsigned int pwm_get_duty_cycle(struct pwm_device *pwm)
+ 	return pwm ? pwm->duty_cycle : 0;
+ }
+ 
++static inline void pwm_set_freq_hz(struct pwm_device *pwm,
++				   unsigned int freq_hz)
++{
++	if (pwm)
++		pwm->freq_hz = freq_hz;
++}
++
++static inline unsigned int pwm_get_freq_hz(struct pwm_device *pwm)
++{
++	return pwm ? pwm->freq_hz : 0;
++}
++
++static inline void pwm_set_duty_percent(struct pwm_device *pwm,
++					unsigned int duty_percent)
++{
++	if (pwm)
++		pwm->duty_percent = duty_percent;
++}
++
++static inline unsigned int pwm_get_duty_percent(struct pwm_device *pwm)
++{
++	return pwm ? pwm->duty_percent : 0;
++}
++
+ /*
+  * pwm_set_polarity - configure the polarity of a PWM signal
+  */
+ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity);
+ 
++/*
++ * pwm_freq_hz_to_period() - convert duration unit to ns
++ */
++unsigned int pwm_freq_hz_to_period(struct pwm_device *pwm,
++				   unsigned int freq_hz);
++
++/*
++ * pwm_period_to_freq_hz() - convert duration unit to Hertz
++ */
++unsigned int pwm_period_to_freq_hz(struct pwm_device *pwm,
++				   unsigned int period_ns);
++
++/*
++ * pwm_duty_percent_to_duty_cycle() - convert "on" time unit to ns
++ */
++unsigned int pwm_duty_percent_to_duty_cycle(struct pwm_device *pwm,
++					    unsigned int duty_percent);
++
++/*
++ * pwm_duty_cycle_to_duty_percent() - convert "on" time unit to percentage
++ */
++unsigned int pwm_duty_cycle_to_duty_percent(struct pwm_device *pwm,
++					    unsigned int duty_cycle);
++
+ /**
+  * struct pwm_ops - PWM controller operations
+  * @request: optional hook for requesting a PWM
+-- 
+1.7.7.6
+
-- 
1.9.1



More information about the linux-yocto mailing list