From patchwork Tue May 22 12:07:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudiu Beznea X-Patchwork-Id: 918247 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=microchip.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40qvf13cMNz9s76 for ; Tue, 22 May 2018 22:12:09 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751454AbeEVMMI (ORCPT ); Tue, 22 May 2018 08:12:08 -0400 Received: from esa4.microchip.iphmx.com ([68.232.154.123]:23173 "EHLO esa4.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751729AbeEVMIU (ORCPT ); Tue, 22 May 2018 08:08:20 -0400 X-IronPort-AV: E=Sophos;i="5.49,430,1520924400"; d="scan'208";a="14214832" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 22 May 2018 05:08:19 -0700 Received: from m18063-ThinkPad-T460p.microchip.com (10.10.76.4) by chn-sv-exch05.mchp-main.com (10.10.76.106) with Microsoft SMTP Server id 14.3.352.0; Tue, 22 May 2018 05:08:18 -0700 From: Claudiu Beznea To: , , , , , , CC: , , , Claudiu Beznea Subject: [PATCH v5 1/9] pwm: extend PWM framework with PWM modes Date: Tue, 22 May 2018 15:07:05 +0300 Message-ID: <1526990833-30707-2-git-send-email-claudiu.beznea@microchip.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> References: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Add basic PWM modes: normal and complementary. These modes should differentiate the single output PWM channels from two outputs PWM channels. These modes could be set as follow: 1. PWM channels with one output per channel: - normal mode 2. PWM channels with two outputs per channel: - normal mode - complementary mode Since users could use a PWM channel with two output as one output PWM channel, the PWM normal mode is allowed to be set for PWM channels with two outputs; in fact PWM normal mode should be supported by all PWMs. The PWM capabilities were implemented per PWM channel. Every PWM controller will register a function to get PWM capabilities. If this is not explicitly set by the driver a default function will be used to retrieve the PWM capabilities (in this case the PWM capabilities will contain only PWM normal mode). This function is set in pwmchip_add_with_polarity() as a member of "struct pwm_chip". To retrieve capabilities the pwm_get_caps() function could be used. Every PWM channel have associated a mode in the PWM state. Proper support was added to get/set PWM mode. The mode could also be set from DT via flag cells. The valid DT modes are located in include/dt-bindings/pwm/pwm.h. Only modes supported by PWM channel could be set. If nothing is specified for a PWM channel, via DT, the first available mode will be used (normally, this will be PWM normal mode). Signed-off-by: Claudiu Beznea --- drivers/pwm/core.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++-- drivers/pwm/sysfs.c | 61 ++++++++++++++++++++++++++ include/linux/pwm.h | 39 +++++++++++++++++ 3 files changed, 221 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 1581f6ab1b1f..59a9df9120de 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -136,6 +136,7 @@ struct pwm_device * of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args) { struct pwm_device *pwm; + int modebit; /* check, whether the driver supports a third cell for flags */ if (pc->of_pwm_n_cells < 3) @@ -154,9 +155,23 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args) pwm->args.period = args->args[1]; pwm->args.polarity = PWM_POLARITY_NORMAL; + pwm->args.mode = pwm_mode_get_valid(pc, pwm); - if (args->args_count > 2 && args->args[2] & PWM_POLARITY_INVERTED) - pwm->args.polarity = PWM_POLARITY_INVERSED; + if (args->args_count > 2) { + if (args->args[2] & PWM_POLARITY_INVERTED) + pwm->args.polarity = PWM_POLARITY_INVERSED; + + for (modebit = PWMC_MODE_COMPLEMENTARY_BIT; + modebit < PWMC_MODE_CNT; modebit++) { + unsigned long mode = BIT(modebit); + + if ((args->args[2] & mode) && + pwm_mode_valid(pwm, mode)) { + pwm->args.mode = mode; + break; + } + } + } return pwm; } @@ -183,6 +198,7 @@ of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) return pwm; pwm->args.period = args->args[1]; + pwm->args.mode = pwm_mode_get_valid(pc, pwm); return pwm; } @@ -250,6 +266,97 @@ static bool pwm_ops_check(const struct pwm_ops *ops) } /** + * pwm_get_caps() - get PWM capabilities of a PWM device + * @chip: PWM chip + * @pwm: PWM device to get the capabilities for + * @caps: returned capabilities + * + * Returns: 0 on success or a negative error code on failure + */ +int pwm_get_caps(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_caps *caps) +{ + if (!chip || !pwm || !caps) + return -EINVAL; + + if (chip->ops && chip->ops->get_caps) + pwm->chip->ops->get_caps(chip, pwm, caps); + else if (chip->get_default_caps) + chip->get_default_caps(caps); + + return 0; +} +EXPORT_SYMBOL_GPL(pwm_get_caps); + +static void pwmchip_get_default_caps(struct pwm_caps *caps) +{ + static const struct pwm_caps default_caps = { + .modes = PWMC_MODE(NORMAL), + }; + + if (!caps) + return; + + *caps = default_caps; +} + +/** + * pwm_mode_get_valid() - get the first available valid mode for PWM + * @chip: PWM chip + * @pwm: PWM device to get the valid mode for + * + * Returns: first valid mode for PWM device + */ +unsigned long pwm_mode_get_valid(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct pwm_caps caps; + + if (pwm_get_caps(chip, pwm, &caps)) + return PWMC_MODE(NORMAL); + + return BIT(ffs(caps.modes) - 1); +} +EXPORT_SYMBOL_GPL(pwm_mode_get_valid); + +/** + * pwm_mode_valid() - check if mode is valid for PWM device + * @pwm: PWM device + * @mode: PWM mode to check if valid + * + * Returns: true if mode is valid and false otherwise + */ +bool pwm_mode_valid(struct pwm_device *pwm, unsigned long mode) +{ + struct pwm_caps caps; + + if (!pwm || !mode) + return false; + + if (hweight_long(mode) != 1 || ffs(mode) - 1 >= PWMC_MODE_CNT) + return false; + + if (pwm_get_caps(pwm->chip, pwm, &caps)) + return false; + + return (caps.modes & mode); +} +EXPORT_SYMBOL_GPL(pwm_mode_valid); + +const char *pwm_mode_desc(struct pwm_device *pwm, unsigned long mode) +{ + static const char * const modes[] = { + "invalid", + "normal", + "complementary", + }; + + if (!pwm_mode_valid(pwm, mode)) + return modes[0]; + + return modes[ffs(mode)]; +} + +/** * pwmchip_add_with_polarity() - register a new PWM chip * @chip: the PWM chip to add * @polarity: initial polarity of PWM channels @@ -275,6 +382,8 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip, mutex_lock(&pwm_lock); + chip->get_default_caps = pwmchip_get_default_caps; + ret = alloc_pwms(chip->base, chip->npwm); if (ret < 0) goto out; @@ -294,6 +403,7 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip, pwm->pwm = chip->base + i; pwm->hwpwm = i; pwm->state.polarity = polarity; + pwm->state.mode = pwm_mode_get_valid(chip, pwm); if (chip->ops->get_state) chip->ops->get_state(chip, pwm, &pwm->state); @@ -469,7 +579,8 @@ int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state) int err; if (!pwm || !state || !state->period || - state->duty_cycle > state->period) + state->duty_cycle > state->period || + !pwm_mode_valid(pwm, state->mode)) return -EINVAL; if (!memcmp(state, &pwm->state, sizeof(*state))) @@ -530,6 +641,9 @@ int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state) pwm->state.enabled = state->enabled; } + + /* No mode support for non-atomic PWM. */ + pwm->state.mode = state->mode; } return 0; @@ -579,6 +693,8 @@ int pwm_adjust_config(struct pwm_device *pwm) pwm_get_args(pwm, &pargs); pwm_get_state(pwm, &state); + state.mode = pargs.mode; + /* * If the current period is zero it means that either the PWM driver * does not support initial state retrieval or the PWM has not yet @@ -850,6 +966,7 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id) pwm->args.period = chosen->period; pwm->args.polarity = chosen->polarity; + pwm->args.mode = pwm_mode_get_valid(chip, pwm); return pwm; } @@ -999,6 +1116,7 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) seq_printf(s, " duty: %u ns", state.duty_cycle); seq_printf(s, " polarity: %s", state.polarity ? "inverse" : "normal"); + seq_printf(s, " mode: %s", pwm_mode_desc(pwm, state.mode)); seq_puts(s, "\n"); } diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 83f2b0b15712..785eda0b1e67 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -223,11 +223,71 @@ static ssize_t capture_show(struct device *child, return sprintf(buf, "%u %u\n", result.period, result.duty_cycle); } +static ssize_t mode_show(struct device *child, + struct device_attribute *attr, + char *buf) +{ + struct pwm_device *pwm = child_to_pwm_device(child); + struct pwm_state state; + unsigned long mode; + int modebit, len = 0; + + pwm_get_state(pwm, &state); + + for (modebit = PWMC_MODE_NORMAL_BIT; + modebit < PWMC_MODE_CNT; modebit++) { + mode = BIT(modebit); + if (pwm_mode_valid(pwm, mode)) { + if (state.mode == mode) + len += scnprintf(buf + len, + PAGE_SIZE - len, "[%s] ", + pwm_mode_desc(pwm, mode)); + else + len += scnprintf(buf + len, + PAGE_SIZE - len, "%s ", + pwm_mode_desc(pwm, mode)); + } + } + + len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); + return len; +} + +static ssize_t mode_store(struct device *child, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct pwm_export *export = child_to_pwm_export(child); + struct pwm_device *pwm = export->pwm; + struct pwm_state state; + unsigned long mode; + int modebit, ret; + + for (modebit = PWMC_MODE_NORMAL_BIT; + modebit < PWMC_MODE_CNT; modebit++) { + mode = BIT(modebit); + if (sysfs_streq(buf, pwm_mode_desc(pwm, mode))) + break; + } + + if (modebit == PWMC_MODE_CNT) + return -EINVAL; + + mutex_lock(&export->lock); + pwm_get_state(pwm, &state); + state.mode = mode; + ret = pwm_apply_state(pwm, &state); + mutex_unlock(&export->lock); + + return ret ? : size; +} + static DEVICE_ATTR_RW(period); static DEVICE_ATTR_RW(duty_cycle); static DEVICE_ATTR_RW(enable); static DEVICE_ATTR_RW(polarity); static DEVICE_ATTR_RO(capture); +static DEVICE_ATTR_RW(mode); static struct attribute *pwm_attrs[] = { &dev_attr_period.attr, @@ -235,6 +295,7 @@ static struct attribute *pwm_attrs[] = { &dev_attr_enable.attr, &dev_attr_polarity.attr, &dev_attr_capture.attr, + &dev_attr_mode.attr, NULL }; ATTRIBUTE_GROUPS(pwm); diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 56518adc31dd..a4ce4ad7edf0 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -26,9 +26,32 @@ enum pwm_polarity { }; /** + * PWM modes capabilities + * @PWMC_MODE_NORMAL_BIT: PWM has one output + * @PWMC_MODE_COMPLEMENTARY_BIT: PWM has 2 outputs with opposite polarities + * @PWMC_MODE_CNT: PWM modes count + */ +enum { + PWMC_MODE_NORMAL_BIT, + PWMC_MODE_COMPLEMENTARY_BIT, + PWMC_MODE_CNT, +}; + +#define PWMC_MODE(name) BIT(PWMC_MODE_##name##_BIT) + +/** + * struct pwm_caps - PWM capabilities + * @modes: PWM modes + */ +struct pwm_caps { + unsigned long modes; +}; + +/** * struct pwm_args - board-dependent PWM arguments * @period: reference period * @polarity: reference polarity + * @mode: reference mode * * This structure describes board-dependent arguments attached to a PWM * device. These arguments are usually retrieved from the PWM lookup table or @@ -41,6 +64,7 @@ enum pwm_polarity { struct pwm_args { unsigned int period; enum pwm_polarity polarity; + unsigned long mode; }; enum { @@ -53,12 +77,14 @@ enum { * @period: PWM period (in nanoseconds) * @duty_cycle: PWM duty cycle (in nanoseconds) * @polarity: PWM polarity + * @mode: PWM mode * @enabled: PWM enabled status */ struct pwm_state { unsigned int period; unsigned int duty_cycle; enum pwm_polarity polarity; + unsigned long mode; bool enabled; }; @@ -181,6 +207,7 @@ static inline void pwm_init_state(const struct pwm_device *pwm, state->period = args.period; state->polarity = args.polarity; state->duty_cycle = 0; + state->mode = args.mode; } /** @@ -254,6 +281,7 @@ pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle, * @get_state: get the current PWM state. This function is only * called once per PWM device when the PWM chip is * registered. + * @get_caps: get PWM capabilities. * @dbg_show: optional routine to show contents in debugfs * @owner: helps prevent removal of modules exporting active PWMs */ @@ -272,6 +300,8 @@ struct pwm_ops { struct pwm_state *state); void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state); + void (*get_caps)(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_caps *caps); #ifdef CONFIG_DEBUG_FS void (*dbg_show)(struct pwm_chip *chip, struct seq_file *s); #endif @@ -287,6 +317,7 @@ struct pwm_ops { * @npwm: number of PWMs controlled by this chip * @pwms: array of PWM devices allocated by the framework * @of_xlate: request a PWM device given a device tree PWM specifier + * @get_default_caps: get default PWM capabilities * @of_pwm_n_cells: number of cells expected in the device tree PWM specifier */ struct pwm_chip { @@ -300,6 +331,7 @@ struct pwm_chip { struct pwm_device * (*of_xlate)(struct pwm_chip *pc, const struct of_phandle_args *args); + void (*get_default_caps)(struct pwm_caps *caps); unsigned int of_pwm_n_cells; }; @@ -438,6 +470,12 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, unsigned int index, const char *label); +int pwm_get_caps(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_caps *caps); +unsigned long pwm_mode_get_valid(struct pwm_chip *chip, + struct pwm_device *pwm); +bool pwm_mode_valid(struct pwm_device *pwm, unsigned long mode); +const char *pwm_mode_desc(struct pwm_device *pwm, unsigned long mode); struct pwm_device *of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args); @@ -592,6 +630,7 @@ static inline void pwm_apply_args(struct pwm_device *pwm) state.enabled = false; state.polarity = pwm->args.polarity; state.period = pwm->args.period; + state.mode = pwm->args.mode; pwm_apply_state(pwm, &state); } From patchwork Tue May 22 12:07:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudiu Beznea X-Patchwork-Id: 918245 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=microchip.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40qvdT6lzKz9s76 for ; Tue, 22 May 2018 22:11:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752776AbeEVMI0 (ORCPT ); Tue, 22 May 2018 08:08:26 -0400 Received: from esa6.microchip.iphmx.com ([216.71.154.253]:24301 "EHLO esa6.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751456AbeEVMIW (ORCPT ); Tue, 22 May 2018 08:08:22 -0400 X-IronPort-AV: E=Sophos;i="5.49,430,1520924400"; d="scan'208";a="11781815" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa6.microchip.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 22 May 2018 05:08:22 -0700 Received: from m18063-ThinkPad-T460p.microchip.com (10.10.76.4) by chn-sv-exch05.mchp-main.com (10.10.76.106) with Microsoft SMTP Server id 14.3.352.0; Tue, 22 May 2018 05:08:21 -0700 From: Claudiu Beznea To: , , , , , , CC: , , , Claudiu Beznea Subject: [PATCH v5 2/9] pwm: clps711x: populate PWM mode in of_xlate function Date: Tue, 22 May 2018 15:07:06 +0300 Message-ID: <1526990833-30707-3-git-send-email-claudiu.beznea@microchip.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> References: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Populate PWM mode in of_xlate function to avoid pwm_apply_state() failure. Signed-off-by: Claudiu Beznea --- drivers/pwm/pwm-clps711x.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c index 26ec24e457b1..d742e8e375c7 100644 --- a/drivers/pwm/pwm-clps711x.c +++ b/drivers/pwm/pwm-clps711x.c @@ -109,10 +109,18 @@ static const struct pwm_ops clps711x_pwm_ops = { static struct pwm_device *clps711x_pwm_xlate(struct pwm_chip *chip, const struct of_phandle_args *args) { + struct pwm_device *pwm; + if (args->args[0] >= chip->npwm) return ERR_PTR(-EINVAL); - return pwm_request_from_chip(chip, args->args[0], NULL); + pwm = pwm_request_from_chip(chip, args->args[0], NULL); + if (IS_ERR(pwm)) + return pwm; + + pwm->args.mode = pwm_mode_get_valid(chip, pwm); + + return pwm; } static int clps711x_pwm_probe(struct platform_device *pdev) From patchwork Tue May 22 12:07:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudiu Beznea X-Patchwork-Id: 918244 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=microchip.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40qvd646Pnz9s7C for ; Tue, 22 May 2018 22:11:22 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752968AbeEVMI2 (ORCPT ); Tue, 22 May 2018 08:08:28 -0400 Received: from esa4.microchip.iphmx.com ([68.232.154.123]:23173 "EHLO esa4.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752807AbeEVMIZ (ORCPT ); Tue, 22 May 2018 08:08:25 -0400 X-IronPort-AV: E=Sophos;i="5.49,430,1520924400"; d="scan'208";a="14214837" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 22 May 2018 05:08:25 -0700 Received: from m18063-ThinkPad-T460p.microchip.com (10.10.76.4) by chn-sv-exch05.mchp-main.com (10.10.76.106) with Microsoft SMTP Server id 14.3.352.0; Tue, 22 May 2018 05:08:24 -0700 From: Claudiu Beznea To: , , , , , , CC: , , , Claudiu Beznea Subject: [PATCH v5 3/9] pwm: cros-ec: populate PWM mode in of_xlate function Date: Tue, 22 May 2018 15:07:07 +0300 Message-ID: <1526990833-30707-4-git-send-email-claudiu.beznea@microchip.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> References: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Populate PWM mode in of_xlate function to avoid pwm_apply_state() failure. Signed-off-by: Claudiu Beznea --- drivers/pwm/pwm-cros-ec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c index 9c13694eaa24..78d28d60a468 100644 --- a/drivers/pwm/pwm-cros-ec.c +++ b/drivers/pwm/pwm-cros-ec.c @@ -147,6 +147,7 @@ cros_ec_pwm_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) /* The EC won't let us change the period */ pwm->args.period = EC_PWM_MAX_DUTY; + pwm->args.mode = pwm_mode_get_valid(pc, pwm); return pwm; } From patchwork Tue May 22 12:07:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudiu Beznea X-Patchwork-Id: 918243 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=microchip.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40qvd55rqKz9s76 for ; Tue, 22 May 2018 22:11:21 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752136AbeEVMLU (ORCPT ); Tue, 22 May 2018 08:11:20 -0400 Received: from esa6.microchip.iphmx.com ([216.71.154.253]:24301 "EHLO esa6.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752970AbeEVMI2 (ORCPT ); Tue, 22 May 2018 08:08:28 -0400 X-IronPort-AV: E=Sophos;i="5.49,430,1520924400"; d="scan'208";a="11781816" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa6.microchip.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 22 May 2018 05:08:28 -0700 Received: from m18063-ThinkPad-T460p.microchip.com (10.10.76.4) by chn-sv-exch05.mchp-main.com (10.10.76.106) with Microsoft SMTP Server id 14.3.352.0; Tue, 22 May 2018 05:08:27 -0700 From: Claudiu Beznea To: , , , , , , CC: , , , Claudiu Beznea Subject: [PATCH v5 4/9] pwm: pxa: populate PWM mode in of_xlate function Date: Tue, 22 May 2018 15:07:08 +0300 Message-ID: <1526990833-30707-5-git-send-email-claudiu.beznea@microchip.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> References: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Populate PWM mode in of_xlate function to avoid pwm_apply_state() failure. Signed-off-by: Claudiu Beznea --- drivers/pwm/pwm-pxa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c index 4143a46684d2..4c88cb47d6ba 100644 --- a/drivers/pwm/pwm-pxa.c +++ b/drivers/pwm/pwm-pxa.c @@ -161,6 +161,7 @@ pxa_pwm_of_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) return pwm; pwm->args.period = args->args[0]; + pwm->args.mode = pwm_mode_get_valid(pc, pwm); return pwm; } From patchwork Tue May 22 12:07:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudiu Beznea X-Patchwork-Id: 918240 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=microchip.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40qvcK5Zy6z9s7C for ; Tue, 22 May 2018 22:10:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751511AbeEVMIf (ORCPT ); Tue, 22 May 2018 08:08:35 -0400 Received: from esa4.microchip.iphmx.com ([68.232.154.123]:24928 "EHLO esa4.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752978AbeEVMIc (ORCPT ); Tue, 22 May 2018 08:08:32 -0400 X-IronPort-AV: E=Sophos;i="5.49,430,1520924400"; d="scan'208";a="14214841" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 22 May 2018 05:08:31 -0700 Received: from m18063-ThinkPad-T460p.microchip.com (10.10.76.4) by chn-sv-exch05.mchp-main.com (10.10.76.106) with Microsoft SMTP Server id 14.3.352.0; Tue, 22 May 2018 05:08:30 -0700 From: Claudiu Beznea To: , , , , , , CC: , , , Claudiu Beznea Subject: [PATCH v5 5/9] pwm: add PWM modes Date: Tue, 22 May 2018 15:07:09 +0300 Message-ID: <1526990833-30707-6-git-send-email-claudiu.beznea@microchip.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> References: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Add PWM normal and complementary modes. Signed-off-by: Claudiu Beznea --- Documentation/devicetree/bindings/pwm/pwm.txt | 9 +++++++-- Documentation/pwm.txt | 26 +++++++++++++++++++++++--- include/dt-bindings/pwm/pwm.h | 1 + 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/pwm/pwm.txt b/Documentation/devicetree/bindings/pwm/pwm.txt index 8556263b8502..7c8aaac43f92 100644 --- a/Documentation/devicetree/bindings/pwm/pwm.txt +++ b/Documentation/devicetree/bindings/pwm/pwm.txt @@ -46,11 +46,16 @@ period in nanoseconds. Optionally, the pwm-specifier can encode a number of flags (defined in ) in a third cell: - PWM_POLARITY_INVERTED: invert the PWM signal polarity +- PWM_MODE_COMPLEMENTARY: PWM complementary working mode (for PWM channels +with two outputs); if not specified, the default for PWM channel will be +used -Example with optional PWM specifier for inverse polarity +Example with optional PWM specifier for inverse polarity and complementary +mode: bl: backlight { - pwms = <&pwm 0 5000000 PWM_POLARITY_INVERTED>; + pwms = <&pwm 0 5000000 + (PWM_MODE_COMPLEMENTARY | PWM_POLARITY_INVERTED)>; pwm-names = "backlight"; }; diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt index 8fbf0aa3ba2d..912c43da8b48 100644 --- a/Documentation/pwm.txt +++ b/Documentation/pwm.txt @@ -61,9 +61,9 @@ In addition to the PWM state, the PWM API also exposes PWM arguments, which are the reference PWM config one should use on this PWM. PWM arguments are usually platform-specific and allows the PWM user to only care about dutycycle relatively to the full period (like, duty = 50% of the -period). struct pwm_args contains 2 fields (period and polarity) and should -be used to set the initial PWM config (usually done in the probe function -of the PWM user). PWM arguments are retrieved with pwm_get_args(). +period). struct pwm_args contains 3 fields (period, polarity and mode) and +should be used to set the initial PWM config (usually done in the probe +function of the PWM user). PWM arguments are retrieved with pwm_get_args(). Using PWMs with the sysfs interface ----------------------------------- @@ -110,6 +110,26 @@ channel that was exported. The following properties will then be available: - 0 - disabled - 1 - enabled + mode + Get/set PWM channel working mode. + + Normal mode - for PWM channels with one output; this should be the + default working mode for every PWM channel; output waveforms looks + like this: + __ __ __ __ + PWM __| |__| |__| |__| |__ + <--T--> + + Complementary mode - for PWM channels with two outputs; output waveforms + looks line this: + __ __ __ __ + PWMH1 __| |__| |__| |__| |__ + __ __ __ __ __ + PWML1 |__| |__| |__| |__| + <--T--> + + Where T is the signal period. + Implementing a PWM driver ------------------------- diff --git a/include/dt-bindings/pwm/pwm.h b/include/dt-bindings/pwm/pwm.h index ab9a077e3c7d..b82279cc1787 100644 --- a/include/dt-bindings/pwm/pwm.h +++ b/include/dt-bindings/pwm/pwm.h @@ -11,5 +11,6 @@ #define _DT_BINDINGS_PWM_PWM_H #define PWM_POLARITY_INVERTED (1 << 0) +#define PWM_MODE_COMPLEMENTARY (1 << 1) #endif From patchwork Tue May 22 12:07:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudiu Beznea X-Patchwork-Id: 918241 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=microchip.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40qvcM41tbz9s76 for ; Tue, 22 May 2018 22:10:43 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752276AbeEVMKm (ORCPT ); Tue, 22 May 2018 08:10:42 -0400 Received: from esa6.microchip.iphmx.com ([216.71.154.253]:49885 "EHLO esa6.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753005AbeEVMIf (ORCPT ); Tue, 22 May 2018 08:08:35 -0400 X-IronPort-AV: E=Sophos;i="5.49,430,1520924400"; d="scan'208";a="11781821" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa6.microchip.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 22 May 2018 05:08:34 -0700 Received: from m18063-ThinkPad-T460p.microchip.com (10.10.76.4) by chn-sv-exch05.mchp-main.com (10.10.76.106) with Microsoft SMTP Server id 14.3.352.0; Tue, 22 May 2018 05:08:33 -0700 From: Claudiu Beznea To: , , , , , , CC: , , , Claudiu Beznea Subject: [PATCH v5 6/9] pwm: atmel: add pwm capabilities Date: Tue, 22 May 2018 15:07:10 +0300 Message-ID: <1526990833-30707-7-git-send-email-claudiu.beznea@microchip.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> References: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Add pwm capabilities for Atmel/Microchip PWM controllers. Signed-off-by: Claudiu Beznea --- drivers/pwm/pwm-atmel.c | 80 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index 530d7dc5f1b5..87ef54bd492c 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -65,11 +65,16 @@ struct atmel_pwm_registers { u8 duty_upd; }; +struct atmel_pwm_data { + struct atmel_pwm_registers regs; + struct pwm_caps caps; +}; + struct atmel_pwm_chip { struct pwm_chip chip; struct clk *clk; void __iomem *base; - const struct atmel_pwm_registers *regs; + const struct atmel_pwm_data *data; unsigned int updated_pwms; /* ISR is cleared when read, ensure only one thread does that */ @@ -150,15 +155,15 @@ static void atmel_pwm_update_cdty(struct pwm_chip *chip, struct pwm_device *pwm, struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); u32 val; - if (atmel_pwm->regs->duty_upd == - atmel_pwm->regs->period_upd) { + if (atmel_pwm->data->regs.duty_upd == + atmel_pwm->data->regs.period_upd) { val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR); val &= ~PWM_CMR_UPD_CDTY; atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val); } atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, - atmel_pwm->regs->duty_upd, cdty); + atmel_pwm->data->regs.duty_upd, cdty); } static void atmel_pwm_set_cprd_cdty(struct pwm_chip *chip, @@ -168,9 +173,9 @@ static void atmel_pwm_set_cprd_cdty(struct pwm_chip *chip, struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, - atmel_pwm->regs->duty, cdty); + atmel_pwm->data->regs.duty, cdty); atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, - atmel_pwm->regs->period, cprd); + atmel_pwm->data->regs.period, cprd); } static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm, @@ -225,7 +230,7 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, cstate.polarity == state->polarity && cstate.period == state->period) { cprd = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, - atmel_pwm->regs->period); + atmel_pwm->data->regs.period); atmel_pwm_calculate_cdty(state, cprd, &cdty); atmel_pwm_update_cdty(chip, pwm, cdty); return 0; @@ -272,32 +277,51 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } +static void atmel_pwm_get_caps(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_caps *caps) +{ + struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); + + *caps = atmel_pwm->data->caps; +} + static const struct pwm_ops atmel_pwm_ops = { .apply = atmel_pwm_apply, + .get_caps = atmel_pwm_get_caps, .owner = THIS_MODULE, }; -static const struct atmel_pwm_registers atmel_pwm_regs_v1 = { - .period = PWMV1_CPRD, - .period_upd = PWMV1_CUPD, - .duty = PWMV1_CDTY, - .duty_upd = PWMV1_CUPD, +static const struct atmel_pwm_data atmel_pwm_data_v1 = { + .regs = { + .period = PWMV1_CPRD, + .period_upd = PWMV1_CUPD, + .duty = PWMV1_CDTY, + .duty_upd = PWMV1_CUPD, + }, + .caps = { + .modes = PWMC_MODE(NORMAL), + }, }; -static const struct atmel_pwm_registers atmel_pwm_regs_v2 = { - .period = PWMV2_CPRD, - .period_upd = PWMV2_CPRDUPD, - .duty = PWMV2_CDTY, - .duty_upd = PWMV2_CDTYUPD, +static const struct atmel_pwm_data atmel_pwm_data_v2 = { + .regs = { + .period = PWMV2_CPRD, + .period_upd = PWMV2_CPRDUPD, + .duty = PWMV2_CDTY, + .duty_upd = PWMV2_CDTYUPD, + }, + .caps = { + .modes = PWMC_MODE(NORMAL) | PWMC_MODE(COMPLEMENTARY), + }, }; static const struct platform_device_id atmel_pwm_devtypes[] = { { .name = "at91sam9rl-pwm", - .driver_data = (kernel_ulong_t)&atmel_pwm_regs_v1, + .driver_data = (kernel_ulong_t)&atmel_pwm_data_v1, }, { .name = "sama5d3-pwm", - .driver_data = (kernel_ulong_t)&atmel_pwm_regs_v2, + .driver_data = (kernel_ulong_t)&atmel_pwm_data_v2, }, { /* sentinel */ }, @@ -307,20 +331,20 @@ MODULE_DEVICE_TABLE(platform, atmel_pwm_devtypes); static const struct of_device_id atmel_pwm_dt_ids[] = { { .compatible = "atmel,at91sam9rl-pwm", - .data = &atmel_pwm_regs_v1, + .data = &atmel_pwm_data_v1, }, { .compatible = "atmel,sama5d3-pwm", - .data = &atmel_pwm_regs_v2, + .data = &atmel_pwm_data_v2, }, { .compatible = "atmel,sama5d2-pwm", - .data = &atmel_pwm_regs_v2, + .data = &atmel_pwm_data_v2, }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, atmel_pwm_dt_ids); -static inline const struct atmel_pwm_registers * +static inline const struct atmel_pwm_data * atmel_pwm_get_driver_data(struct platform_device *pdev) { const struct platform_device_id *id; @@ -330,18 +354,18 @@ atmel_pwm_get_driver_data(struct platform_device *pdev) id = platform_get_device_id(pdev); - return (struct atmel_pwm_registers *)id->driver_data; + return (struct atmel_pwm_data *)id->driver_data; } static int atmel_pwm_probe(struct platform_device *pdev) { - const struct atmel_pwm_registers *regs; + const struct atmel_pwm_data *data; struct atmel_pwm_chip *atmel_pwm; struct resource *res; int ret; - regs = atmel_pwm_get_driver_data(pdev); - if (!regs) + data = atmel_pwm_get_driver_data(pdev); + if (!data) return -ENODEV; atmel_pwm = devm_kzalloc(&pdev->dev, sizeof(*atmel_pwm), GFP_KERNEL); @@ -373,7 +397,7 @@ static int atmel_pwm_probe(struct platform_device *pdev) atmel_pwm->chip.base = -1; atmel_pwm->chip.npwm = 4; - atmel_pwm->regs = regs; + atmel_pwm->data = data; atmel_pwm->updated_pwms = 0; mutex_init(&atmel_pwm->isr_lock); From patchwork Tue May 22 12:07:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudiu Beznea X-Patchwork-Id: 918239 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=microchip.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40qvbv1DPYz9s76 for ; Tue, 22 May 2018 22:10:19 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751499AbeEVMIl (ORCPT ); Tue, 22 May 2018 08:08:41 -0400 Received: from esa4.microchip.iphmx.com ([68.232.154.123]:32405 "EHLO esa4.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753023AbeEVMIi (ORCPT ); Tue, 22 May 2018 08:08:38 -0400 X-IronPort-AV: E=Sophos;i="5.49,430,1520924400"; d="scan'208";a="14214844" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 22 May 2018 05:08:37 -0700 Received: from m18063-ThinkPad-T460p.microchip.com (10.10.76.4) by chn-sv-exch05.mchp-main.com (10.10.76.106) with Microsoft SMTP Server id 14.3.352.0; Tue, 22 May 2018 05:08:36 -0700 From: Claudiu Beznea To: , , , , , , CC: , , , Claudiu Beznea Subject: [PATCH v5 7/9] pwm: add push-pull mode support Date: Tue, 22 May 2018 15:07:11 +0300 Message-ID: <1526990833-30707-8-git-send-email-claudiu.beznea@microchip.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> References: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Add push-pull mode support. In push-pull mode the channels' outputs have same polarities and the edges are complementary delayed for one period. Signed-off-by: Claudiu Beznea --- drivers/pwm/core.c | 1 + include/linux/pwm.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 59a9df9120de..5fde2e685ca7 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -348,6 +348,7 @@ const char *pwm_mode_desc(struct pwm_device *pwm, unsigned long mode) "invalid", "normal", "complementary", + "push-pull", }; if (!pwm_mode_valid(pwm, mode)) diff --git a/include/linux/pwm.h b/include/linux/pwm.h index a4ce4ad7edf0..eb170e2ab431 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -29,11 +29,14 @@ enum pwm_polarity { * PWM modes capabilities * @PWMC_MODE_NORMAL_BIT: PWM has one output * @PWMC_MODE_COMPLEMENTARY_BIT: PWM has 2 outputs with opposite polarities + * @PWMC_MODE_PUSH_PULL_BIT: PWM has 2 outputs with same polarities and the + * edges are complementary delayed for one period * @PWMC_MODE_CNT: PWM modes count */ enum { PWMC_MODE_NORMAL_BIT, PWMC_MODE_COMPLEMENTARY_BIT, + PWMC_MODE_PUSH_PULL_BIT, PWMC_MODE_CNT, }; From patchwork Tue May 22 12:07:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudiu Beznea X-Patchwork-Id: 918238 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=microchip.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40qvbq3fzGz9s76 for ; Tue, 22 May 2018 22:10:15 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752574AbeEVMKB (ORCPT ); Tue, 22 May 2018 08:10:01 -0400 Received: from esa6.microchip.iphmx.com ([216.71.154.253]:62583 "EHLO esa6.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753033AbeEVMIl (ORCPT ); Tue, 22 May 2018 08:08:41 -0400 X-IronPort-AV: E=Sophos;i="5.49,430,1520924400"; d="scan'208";a="11781826" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa6.microchip.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 22 May 2018 05:08:41 -0700 Received: from m18063-ThinkPad-T460p.microchip.com (10.10.76.4) by chn-sv-exch05.mchp-main.com (10.10.76.106) with Microsoft SMTP Server id 14.3.352.0; Tue, 22 May 2018 05:08:40 -0700 From: Claudiu Beznea To: , , , , , , CC: , , , Claudiu Beznea Subject: [PATCH v5 8/9] pwm: add documentation for pwm push-pull mode Date: Tue, 22 May 2018 15:07:12 +0300 Message-ID: <1526990833-30707-9-git-send-email-claudiu.beznea@microchip.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> References: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Add documentation for PWM push-pull mode. Signed-off-by: Claudiu Beznea Reviewed-by: Rob Herring --- Documentation/devicetree/bindings/pwm/pwm.txt | 2 ++ Documentation/pwm.txt | 16 ++++++++++++++++ include/dt-bindings/pwm/pwm.h | 1 + 3 files changed, 19 insertions(+) diff --git a/Documentation/devicetree/bindings/pwm/pwm.txt b/Documentation/devicetree/bindings/pwm/pwm.txt index 7c8aaac43f92..6a60c0fca112 100644 --- a/Documentation/devicetree/bindings/pwm/pwm.txt +++ b/Documentation/devicetree/bindings/pwm/pwm.txt @@ -49,6 +49,8 @@ Optionally, the pwm-specifier can encode a number of flags (defined in - PWM_MODE_COMPLEMENTARY: PWM complementary working mode (for PWM channels with two outputs); if not specified, the default for PWM channel will be used +- PWM_MODE_PUSH_PULL: PWM push-pull working modes (for PWM channels with +two outputs); if not specified the default for PWM channel will be used Example with optional PWM specifier for inverse polarity and complementary mode: diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt index 912c43da8b48..675f9351fed1 100644 --- a/Documentation/pwm.txt +++ b/Documentation/pwm.txt @@ -128,6 +128,22 @@ channel that was exported. The following properties will then be available: PWML1 |__| |__| |__| |__| <--T--> + Push-pull mode - for PWM channels with two outputs; output waveforms + for a PWM channel in push-pull mode, with normal polarity looks like + this: + __ __ + PWMH __| |________| |________ + __ __ + PWML ________| |________| |__ + <--T--> + + If polarity is inversed: + __ ________ ________ + PWMH |__| |__| + ________ ________ __ + PWML |__| |__| + <--T--> + Where T is the signal period. Implementing a PWM driver diff --git a/include/dt-bindings/pwm/pwm.h b/include/dt-bindings/pwm/pwm.h index b82279cc1787..cd4265bce968 100644 --- a/include/dt-bindings/pwm/pwm.h +++ b/include/dt-bindings/pwm/pwm.h @@ -12,5 +12,6 @@ #define PWM_POLARITY_INVERTED (1 << 0) #define PWM_MODE_COMPLEMENTARY (1 << 1) +#define PWM_MODE_PUSH_PULL (1 << 2) #endif From patchwork Tue May 22 12:07:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudiu Beznea X-Patchwork-Id: 918235 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=microchip.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40qvb16t9Cz9s76 for ; Tue, 22 May 2018 22:09:33 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753051AbeEVMIs (ORCPT ); Tue, 22 May 2018 08:08:48 -0400 Received: from esa4.microchip.iphmx.com ([68.232.154.123]:11439 "EHLO esa4.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751415AbeEVMIp (ORCPT ); Tue, 22 May 2018 08:08:45 -0400 X-IronPort-AV: E=Sophos;i="5.49,430,1520924400"; d="scan'208";a="14214849" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 22 May 2018 05:08:44 -0700 Received: from m18063-ThinkPad-T460p.microchip.com (10.10.76.4) by chn-sv-exch05.mchp-main.com (10.10.76.106) with Microsoft SMTP Server id 14.3.352.0; Tue, 22 May 2018 05:08:43 -0700 From: Claudiu Beznea To: , , , , , , CC: , , , Claudiu Beznea Subject: [PATCH v5 9/9] pwm: atmel: add push-pull mode support Date: Tue, 22 May 2018 15:07:13 +0300 Message-ID: <1526990833-30707-10-git-send-email-claudiu.beznea@microchip.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> References: <1526990833-30707-1-git-send-email-claudiu.beznea@microchip.com> MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Add support for PWM push-pull mode. This is only supported by SAMA5D2 SoCs. Signed-off-by: Claudiu Beznea --- drivers/pwm/pwm-atmel.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index 87ef54bd492c..aaafc4dd30f2 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -33,8 +33,11 @@ #define PWM_CMR 0x0 /* Bit field in CMR */ -#define PWM_CMR_CPOL (1 << 9) -#define PWM_CMR_UPD_CDTY (1 << 10) +#define PWM_CMR_CPOL BIT(9) +#define PWM_CMR_UPD_CDTY BIT(10) +#define PWM_CMR_DTHI BIT(17) +#define PWM_CMR_DTLI BIT(18) +#define PWM_CMR_PPM BIT(19) #define PWM_CMR_CPRE_MSK 0xF /* The following registers for PWM v1 */ @@ -219,16 +222,19 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, { struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); struct pwm_state cstate; + struct pwm_caps caps; unsigned long cprd, cdty; u32 pres, val; int ret; pwm_get_state(pwm, &cstate); + pwm_get_caps(chip, pwm, &caps); if (state->enabled) { if (cstate.enabled && cstate.polarity == state->polarity && - cstate.period == state->period) { + cstate.period == state->period && + cstate.mode == state->mode) { cprd = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, atmel_pwm->data->regs.period); atmel_pwm_calculate_cdty(state, cprd, &cdty); @@ -263,6 +269,18 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, val &= ~PWM_CMR_CPOL; else val |= PWM_CMR_CPOL; + + /* PWM mode. */ + if (caps.modes & PWMC_MODE(PUSH_PULL)) { + if (state->mode == PWMC_MODE(PUSH_PULL)) { + val |= PWM_CMR_PPM | PWM_CMR_DTLI; + val &= ~PWM_CMR_DTHI; + } else { + val &= ~(PWM_CMR_PPM | PWM_CMR_DTLI | + PWM_CMR_DTHI); + } + } + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val); atmel_pwm_set_cprd_cdty(chip, pwm, cprd, cdty); mutex_lock(&atmel_pwm->isr_lock); @@ -315,6 +333,20 @@ static const struct atmel_pwm_data atmel_pwm_data_v2 = { }, }; +static const struct atmel_pwm_data atmel_pwm_data_v3 = { + .regs = { + .period = PWMV2_CPRD, + .period_upd = PWMV2_CPRDUPD, + .duty = PWMV2_CDTY, + .duty_upd = PWMV2_CDTYUPD, + }, + .caps = { + .modes = PWMC_MODE(NORMAL) | + PWMC_MODE(COMPLEMENTARY) | + PWMC_MODE(PUSH_PULL), + }, +}; + static const struct platform_device_id atmel_pwm_devtypes[] = { { .name = "at91sam9rl-pwm", @@ -337,7 +369,7 @@ static const struct of_device_id atmel_pwm_dt_ids[] = { .data = &atmel_pwm_data_v2, }, { .compatible = "atmel,sama5d2-pwm", - .data = &atmel_pwm_data_v2, + .data = &atmel_pwm_data_v3, }, { /* sentinel */ },