[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