From: "Chai, Chong Yi" <chong.yi.c...@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.moha...@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.moha...@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 -- _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto