if (!np)
return;
+ ret = of_property_read_u32(np, "capture-window-length", &pval);
+ if (!ret)
+ pwm->capture_win_len = pval;
+
ret = of_property_read_u32(np, "pwm-ramp-time", &pval);
if (!ret)
pwm->ramp_time = pval;
}
EXPORT_SYMBOL_GPL(pwm_set_double_pulse_period);
+/**
+ * pwm_set_capture_window_length(): Set PWM capture window length.
+ * @pwm: PWM device
+ * @window_length: Window length.
+ *
+ * Window lenght to capture the PWM signal.
+ *
+ * Returns 0 in success else negative error number in failure.
+ */
+int pwm_set_capture_window_length(struct pwm_device *pwm, int window_length)
+{
+ int err;
+
+ if (!pwm || window_length <= 0)
+ return -EINVAL;
+
+ if (!pwm->chip->ops->set_capture_window_length)
+ return -ENOTSUPP;
+
+ err = pwm->chip->ops->set_capture_window_length(pwm->chip, pwm,
+ window_length);
+ if (err)
+ return err;
+
+ pwm->capture_win_len = window_length;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pwm_set_capture_window_length);
+
+/**
+ * pwm_get_rpm(): Get PWM RPM.
+ * @pwm: PWM device
+ *
+ * Read PWM signal and return RPM value.
+ *
+ * Returns positive integer for valid RPM else negative error.
+ */
+int pwm_get_rpm(struct pwm_device *pwm)
+{
+ struct pwm_capture result;
+ int err;
+
+ err = pwm_capture(pwm, &result, 0);
+ if (err < 0)
+ return err;
+
+ return result.rpm;
+}
+EXPORT_SYMBOL_GPL(pwm_get_rpm);
+
static struct pwm_chip *of_node_to_pwmchip(struct device_node *np)
{
struct pwm_chip *chip;
return ret ? : size;
}
+static ssize_t capture_window_length_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_get_capture_window_length(pwm));
+}
+
+static ssize_t capture_window_length_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;
+ int ret;
+
+ ret = kstrtouint(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ ret = pwm_set_capture_window_length(pwm, val);
+
+ return ret ? : size;
+}
+
+static ssize_t rpm_show(struct device *child,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pwm_device *pwm = child_to_pwm_device(child);
+
+ return sprintf(buf, "%d\n", pwm_get_rpm(pwm));
+}
+
static DEVICE_ATTR_RW(period);
static DEVICE_ATTR_RW(duty_cycle);
static DEVICE_ATTR_RW(enable);
static DEVICE_ATTR_RW(polarity);
static DEVICE_ATTR_RW(double_period);
static DEVICE_ATTR_RW(ramp_time);
+static DEVICE_ATTR_RW(capture_window_length);
+static DEVICE_ATTR_RO(rpm);
static struct attribute *pwm_attrs[] = {
&dev_attr_period.attr,
&dev_attr_polarity.attr,
&dev_attr_double_period.attr,
&dev_attr_ramp_time.attr,
+ &dev_attr_capture_window_length.attr,
+ &dev_attr_rpm.attr,
NULL
};
ATTRIBUTE_GROUPS(pwm);
* Set double pulse period.
*/
int pwm_set_double_pulse_period(struct pwm_device *pwm, int period);
+
+/*
+ * Set PWM capture window length.
+ */
+int pwm_set_capture_window_length(struct pwm_device *pwm, int window_length);
+
+/*
+ * Get PWM RPM.
+ */
+int pwm_get_rpm(struct pwm_device *pwm);
+
#else
static inline struct pwm_device *pwm_request(int pwm_id, const char *label)
{
{
return -EINVAL;
}
+
+static inline int pwm_set_capture_window_length(struct pwm_device *pwm,
+ int window_length)
+{
+ return -EINVAL;
+}
+
+static inline int pwm_get_rpm(struct pwm_device *pwm)
+{
+ return -EINVAL;
+}
#endif
struct pwm_chip;
* @duty_cycle: duty cycle of the PWM signal (in nanoseconds)
* @double_period: Doble pulse period.
* @ramp_time: Ramp up/down time.
+ * @capture_win_len: Window length for captureing PWM signal.
* @polarity: polarity of the PWM signal
*/
struct pwm_device {
enum pwm_polarity polarity;
unsigned int double_period;
unsigned int ramp_time;
+ unsigned int capture_win_len;;
};
static inline bool pwm_is_enabled(const struct pwm_device *pwm)
return pwm ? pwm->ramp_time : 0;
}
+static inline unsigned int pwm_get_capture_window_length(
+ const struct pwm_device *pwm)
+{
+ return pwm ? pwm->capture_win_len : 0;
+}
+
/*
* pwm_set_polarity - configure the polarity of a PWM signal
*/
* @disable: disable PWM output toggling
* @set_ramp_time: Set PWM ramp up/down time.
* @set_double_pulse_period: Set double pulse period time.
+ * @set_capture_window_length: Set PWM capture window length.
* @dbg_show: optional routine to show contents in debugfs
* @owner: helps prevent removal of modules exporting active PWMs
*/
int (*set_double_pulse_period)(struct pwm_chip *chip,
struct pwm_device *pwm,
int period);
+ int (*set_capture_window_length)(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ int window_length);
#ifdef CONFIG_DEBUG_FS
void (*dbg_show)(struct pwm_chip *chip, struct seq_file *s);
#endif
* struct pwm_capture - PWM capture data
* @period: period of the PWM signal (in nanoseconds)
* @duty_cycle: duty cycle of the PWM signal (in nanoseconds)
+ * @rpm: Revolution per minute.
*/
struct pwm_capture {
unsigned int period;
unsigned int duty_cycle;
+ unsigned int rpm;
};
#if IS_ENABLED(CONFIG_PWM)