get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/806474/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 806474,
    "url": "http://patchwork.ozlabs.org/api/patches/806474/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-pwm/patch/1503914654-19963-5-git-send-email-fabrice.gasnier@st.com/",
    "project": {
        "id": 38,
        "url": "http://patchwork.ozlabs.org/api/projects/38/?format=api",
        "name": "Linux PWM development",
        "link_name": "linux-pwm",
        "list_id": "linux-pwm.vger.kernel.org",
        "list_email": "linux-pwm@vger.kernel.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<1503914654-19963-5-git-send-email-fabrice.gasnier@st.com>",
    "list_archive_url": null,
    "date": "2017-08-28T10:04:09",
    "name": "[RESEND,v3,4/9] pwm: Add STM32 LPTimer PWM driver",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "74c2b91436be5a3c16bf81769770a2ea51dc9cf3",
    "submitter": {
        "id": 65902,
        "url": "http://patchwork.ozlabs.org/api/people/65902/?format=api",
        "name": "Fabrice Gasnier",
        "email": "fabrice.gasnier@st.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-pwm/patch/1503914654-19963-5-git-send-email-fabrice.gasnier@st.com/mbox/",
    "series": [
        {
            "id": 122,
            "url": "http://patchwork.ozlabs.org/api/series/122/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-pwm/list/?series=122",
            "date": "2017-08-28T10:04:06",
            "name": "Add STM32 LPTimer: PWM, trigger and counter",
            "version": 3,
            "mbox": "http://patchwork.ozlabs.org/series/122/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/806474/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/806474/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<linux-pwm-owner@vger.kernel.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org",
        "Authentication-Results": "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=linux-pwm-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)",
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xgnVS4WXmz9sNr\n\tfor <incoming@patchwork.ozlabs.org>;\n\tMon, 28 Aug 2017 20:06:40 +1000 (AEST)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751412AbdH1KFY (ORCPT <rfc822;incoming@patchwork.ozlabs.org>);\n\tMon, 28 Aug 2017 06:05:24 -0400",
            "from mx07-00178001.pphosted.com ([62.209.51.94]:47135 \"EHLO\n\tmx07-00178001.pphosted.com\" rhost-flags-OK-OK-OK-OK)\n\tby vger.kernel.org with ESMTP id S1751436AbdH1KFR (ORCPT\n\t<rfc822; linux-pwm@vger.kernel.org>); Mon, 28 Aug 2017 06:05:17 -0400",
            "from pps.filterd (m0046037.ppops.net [127.0.0.1])\n\tby mx07-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id\n\tv7SA4TDw028034; Mon, 28 Aug 2017 12:04:39 +0200",
            "from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35])\n\tby mx07-.pphosted.com with ESMTP id 2cjxrqscsw-1\n\t(version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT);\n\tMon, 28 Aug 2017 12:04:39 +0200",
            "from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9])\n\tby beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 7E55931;\n\tMon, 28 Aug 2017 10:04:38 +0000 (GMT)",
            "from Webmail-eu.st.com (sfhdag5node3.st.com [10.75.127.15])\n\tby zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 5B2751FE8;\n\tMon, 28 Aug 2017 10:04:38 +0000 (GMT)",
            "from localhost (10.75.127.50) by SFHDAG5NODE3.st.com (10.75.127.15)\n\twith Microsoft SMTP Server (TLS) id 15.0.1178.4;\n\tMon, 28 Aug 2017 12:04:37 +0200"
        ],
        "From": "Fabrice Gasnier <fabrice.gasnier@st.com>",
        "To": "<lee.jones@linaro.org>, <benjamin.gaignard@linaro.org>,\n\t<jic23@kernel.org>, <thierry.reding@gmail.com>, <robh+dt@kernel.org>",
        "CC": "<mark.rutland@arm.com>, <alexandre.torgue@st.com>,\n\t<mcoquelin.stm32@gmail.com>, <fabrice.gasnier@st.com>,\n\t<benjamin.gaignard@st.com>, <linux-iio@vger.kernel.org>,\n\t<devicetree@vger.kernel.org>, <linux-arm-kernel@lists.infradead.org>,\n\t<linux-kernel@vger.kernel.org>, <linux-pwm@vger.kernel.org>,\n\t<vilhelm.gray@gmail.com>",
        "Subject": "[RESEND PATCH v3 4/9] pwm: Add STM32 LPTimer PWM driver",
        "Date": "Mon, 28 Aug 2017 12:04:09 +0200",
        "Message-ID": "<1503914654-19963-5-git-send-email-fabrice.gasnier@st.com>",
        "X-Mailer": "git-send-email 1.9.1",
        "In-Reply-To": "<1503914654-19963-1-git-send-email-fabrice.gasnier@st.com>",
        "References": "<1503914654-19963-1-git-send-email-fabrice.gasnier@st.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[10.75.127.50]",
        "X-ClientProxiedBy": "SFHDAG4NODE3.st.com (10.75.127.12) To SFHDAG5NODE3.st.com\n\t(10.75.127.15)",
        "X-Proofpoint-Virus-Version": "vendor=fsecure engine=2.50.10432:, ,\n\tdefinitions=2017-08-28_06:, , signatures=0",
        "Sender": "linux-pwm-owner@vger.kernel.org",
        "Precedence": "bulk",
        "List-ID": "<linux-pwm.vger.kernel.org>",
        "X-Mailing-List": "linux-pwm@vger.kernel.org"
    },
    "content": "Add support for single PWM channel on Low-Power Timer, that can be\nfound on some STM32 platforms.\n\nSigned-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>\nAcked-by: Thierry Reding <thierry.reding@gmail.com>\n---\nChanges in v3:\n- remove prescalers[] array, use power-of-2 presc directly\n- Update following Thierry's comments:\n- fix issue using FIELD_GET() macro\n- Add get_state() callback\n- remove some checks in probe\n- slight rework 'reenable' flag\n- use more common method to disable pwm in remove()\n\nChanges in v2:\n- s/Low Power/Low-Power\n- update few comment lines\n---\n drivers/pwm/Kconfig        |  10 ++\n drivers/pwm/Makefile       |   1 +\n drivers/pwm/pwm-stm32-lp.c | 246 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 257 insertions(+)\n create mode 100644 drivers/pwm/pwm-stm32-lp.c",
    "diff": "diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig\nindex 313c107..7cb982b 100644\n--- a/drivers/pwm/Kconfig\n+++ b/drivers/pwm/Kconfig\n@@ -417,6 +417,16 @@ config PWM_STM32\n \t  To compile this driver as a module, choose M here: the module\n \t  will be called pwm-stm32.\n \n+config PWM_STM32_LP\n+\ttristate \"STMicroelectronics STM32 PWM LP\"\n+\tdepends on MFD_STM32_LPTIMER || COMPILE_TEST\n+\thelp\n+\t  Generic PWM framework driver for STMicroelectronics STM32 SoCs\n+\t  with Low-Power Timer (LPTIM).\n+\n+\t  To compile this driver as a module, choose M here: the module\n+\t  will be called pwm-stm32-lp.\n+\n config PWM_STMPE\n \tbool \"STMPE expander PWM export\"\n \tdepends on MFD_STMPE\ndiff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile\nindex 93da1f7..a3a4bee 100644\n--- a/drivers/pwm/Makefile\n+++ b/drivers/pwm/Makefile\n@@ -40,6 +40,7 @@ obj-$(CONFIG_PWM_SAMSUNG)\t+= pwm-samsung.o\n obj-$(CONFIG_PWM_SPEAR)\t\t+= pwm-spear.o\n obj-$(CONFIG_PWM_STI)\t\t+= pwm-sti.o\n obj-$(CONFIG_PWM_STM32)\t\t+= pwm-stm32.o\n+obj-$(CONFIG_PWM_STM32_LP)\t+= pwm-stm32-lp.o\n obj-$(CONFIG_PWM_STMPE)\t\t+= pwm-stmpe.o\n obj-$(CONFIG_PWM_SUN4I)\t\t+= pwm-sun4i.o\n obj-$(CONFIG_PWM_TEGRA)\t\t+= pwm-tegra.o\ndiff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c\nnew file mode 100644\nindex 0000000..9793b29\n--- /dev/null\n+++ b/drivers/pwm/pwm-stm32-lp.c\n@@ -0,0 +1,246 @@\n+/*\n+ * STM32 Low-Power Timer PWM driver\n+ *\n+ * Copyright (C) STMicroelectronics 2017\n+ *\n+ * Author: Gerald Baeza <gerald.baeza@st.com>\n+ *\n+ * License terms: GNU General Public License (GPL), version 2\n+ *\n+ * Inspired by Gerald Baeza's pwm-stm32 driver\n+ */\n+\n+#include <linux/bitfield.h>\n+#include <linux/mfd/stm32-lptimer.h>\n+#include <linux/module.h>\n+#include <linux/of.h>\n+#include <linux/platform_device.h>\n+#include <linux/pwm.h>\n+\n+struct stm32_pwm_lp {\n+\tstruct pwm_chip chip;\n+\tstruct clk *clk;\n+\tstruct regmap *regmap;\n+};\n+\n+static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)\n+{\n+\treturn container_of(chip, struct stm32_pwm_lp, chip);\n+}\n+\n+/* STM32 Low-Power Timer is preceded by a configurable power-of-2 prescaler */\n+#define STM32_LPTIM_MAX_PRESCALER\t128\n+\n+static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,\n+\t\t\t      struct pwm_state *state)\n+{\n+\tstruct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);\n+\tunsigned long long prd, div, dty;\n+\tstruct pwm_state cstate;\n+\tu32 val, mask, cfgr, presc = 0;\n+\tbool reenable;\n+\tint ret;\n+\n+\tpwm_get_state(pwm, &cstate);\n+\treenable = !cstate.enabled;\n+\n+\tif (!state->enabled) {\n+\t\tif (cstate.enabled) {\n+\t\t\t/* Disable LP timer */\n+\t\t\tret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t\t/* disable clock to PWM counter */\n+\t\t\tclk_disable(priv->clk);\n+\t\t}\n+\t\treturn 0;\n+\t}\n+\n+\t/* Calculate the period and prescaler value */\n+\tdiv = (unsigned long long)clk_get_rate(priv->clk) * state->period;\n+\tdo_div(div, NSEC_PER_SEC);\n+\tprd = div;\n+\twhile (div > STM32_LPTIM_MAX_ARR) {\n+\t\tpresc++;\n+\t\tif ((1 << presc) > STM32_LPTIM_MAX_PRESCALER) {\n+\t\t\tdev_err(priv->chip.dev, \"max prescaler exceeded\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tdiv = prd >> presc;\n+\t}\n+\tprd = div;\n+\n+\t/* Calculate the duty cycle */\n+\tdty = prd * state->duty_cycle;\n+\tdo_div(dty, state->period);\n+\n+\tif (!cstate.enabled) {\n+\t\t/* enable clock to drive PWM counter */\n+\t\tret = clk_enable(priv->clk);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\tret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);\n+\tif (ret)\n+\t\tgoto err;\n+\n+\tif ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) ||\n+\t    (FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity)) {\n+\t\tval = FIELD_PREP(STM32_LPTIM_PRESC, presc);\n+\t\tval |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity);\n+\t\tmask = STM32_LPTIM_PRESC | STM32_LPTIM_WAVPOL;\n+\n+\t\t/* Must disable LP timer to modify CFGR */\n+\t\treenable = true;\n+\t\tret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);\n+\t\tif (ret)\n+\t\t\tgoto err;\n+\n+\t\tret = regmap_update_bits(priv->regmap, STM32_LPTIM_CFGR, mask,\n+\t\t\t\t\t val);\n+\t\tif (ret)\n+\t\t\tgoto err;\n+\t}\n+\n+\tif (reenable) {\n+\t\t/* Must (re)enable LP timer to modify CMP & ARR */\n+\t\tret = regmap_write(priv->regmap, STM32_LPTIM_CR,\n+\t\t\t\t   STM32_LPTIM_ENABLE);\n+\t\tif (ret)\n+\t\t\tgoto err;\n+\t}\n+\n+\tret = regmap_write(priv->regmap, STM32_LPTIM_ARR, prd - 1);\n+\tif (ret)\n+\t\tgoto err;\n+\n+\tret = regmap_write(priv->regmap, STM32_LPTIM_CMP, prd - (1 + dty));\n+\tif (ret)\n+\t\tgoto err;\n+\n+\t/* ensure CMP & ARR registers are properly written */\n+\tret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val,\n+\t\t\t\t       (val & STM32_LPTIM_CMPOK_ARROK),\n+\t\t\t\t       100, 1000);\n+\tif (ret) {\n+\t\tdev_err(priv->chip.dev, \"ARR/CMP registers write issue\\n\");\n+\t\tgoto err;\n+\t}\n+\tret = regmap_write(priv->regmap, STM32_LPTIM_ICR,\n+\t\t\t   STM32_LPTIM_CMPOKCF_ARROKCF);\n+\tif (ret)\n+\t\tgoto err;\n+\n+\tif (reenable) {\n+\t\t/* Start LP timer in continuous mode */\n+\t\tret = regmap_update_bits(priv->regmap, STM32_LPTIM_CR,\n+\t\t\t\t\t STM32_LPTIM_CNTSTRT,\n+\t\t\t\t\t STM32_LPTIM_CNTSTRT);\n+\t\tif (ret) {\n+\t\t\tregmap_write(priv->regmap, STM32_LPTIM_CR, 0);\n+\t\t\tgoto err;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+err:\n+\tif (!cstate.enabled)\n+\t\tclk_disable(priv->clk);\n+\n+\treturn ret;\n+}\n+\n+static void stm32_pwm_lp_get_state(struct pwm_chip *chip,\n+\t\t\t\t   struct pwm_device *pwm,\n+\t\t\t\t   struct pwm_state *state)\n+{\n+\tstruct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);\n+\tunsigned long rate = clk_get_rate(priv->clk);\n+\tu32 val, presc, prd;\n+\tu64 tmp;\n+\n+\tregmap_read(priv->regmap, STM32_LPTIM_CR, &val);\n+\tstate->enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val);\n+\t/* Keep PWM counter clock refcount in sync with PWM initial state */\n+\tif (state->enabled)\n+\t\tclk_enable(priv->clk);\n+\n+\tregmap_read(priv->regmap, STM32_LPTIM_CFGR, &val);\n+\tpresc = FIELD_GET(STM32_LPTIM_PRESC, val);\n+\tstate->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val);\n+\n+\tregmap_read(priv->regmap, STM32_LPTIM_ARR, &prd);\n+\ttmp = prd + 1;\n+\ttmp = (tmp << presc) * NSEC_PER_SEC;\n+\tstate->period = DIV_ROUND_CLOSEST_ULL(tmp, rate);\n+\n+\tregmap_read(priv->regmap, STM32_LPTIM_CMP, &val);\n+\ttmp = prd - val;\n+\ttmp = (tmp << presc) * NSEC_PER_SEC;\n+\tstate->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate);\n+}\n+\n+static const struct pwm_ops stm32_pwm_lp_ops = {\n+\t.owner = THIS_MODULE,\n+\t.apply = stm32_pwm_lp_apply,\n+\t.get_state = stm32_pwm_lp_get_state,\n+};\n+\n+static int stm32_pwm_lp_probe(struct platform_device *pdev)\n+{\n+\tstruct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent);\n+\tstruct stm32_pwm_lp *priv;\n+\tint ret;\n+\n+\tpriv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);\n+\tif (!priv)\n+\t\treturn -ENOMEM;\n+\n+\tpriv->regmap = ddata->regmap;\n+\tpriv->clk = ddata->clk;\n+\tpriv->chip.base = -1;\n+\tpriv->chip.dev = &pdev->dev;\n+\tpriv->chip.ops = &stm32_pwm_lp_ops;\n+\tpriv->chip.npwm = 1;\n+\n+\tret = pwmchip_add(&priv->chip);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tplatform_set_drvdata(pdev, priv);\n+\n+\treturn 0;\n+}\n+\n+static int stm32_pwm_lp_remove(struct platform_device *pdev)\n+{\n+\tstruct stm32_pwm_lp *priv = platform_get_drvdata(pdev);\n+\tunsigned int i;\n+\n+\tfor (i = 0; i < priv->chip.npwm; i++)\n+\t\tif (pwm_is_enabled(&priv->chip.pwms[i]))\n+\t\t\tpwm_disable(&priv->chip.pwms[i]);\n+\n+\treturn pwmchip_remove(&priv->chip);\n+}\n+\n+static const struct of_device_id stm32_pwm_lp_of_match[] = {\n+\t{ .compatible = \"st,stm32-pwm-lp\", },\n+\t{},\n+};\n+MODULE_DEVICE_TABLE(of, stm32_pwm_lp_of_match);\n+\n+static struct platform_driver stm32_pwm_lp_driver = {\n+\t.probe\t= stm32_pwm_lp_probe,\n+\t.remove\t= stm32_pwm_lp_remove,\n+\t.driver\t= {\n+\t\t.name = \"stm32-pwm-lp\",\n+\t\t.of_match_table = of_match_ptr(stm32_pwm_lp_of_match),\n+\t},\n+};\n+module_platform_driver(stm32_pwm_lp_driver);\n+\n+MODULE_ALIAS(\"platform:stm32-pwm-lp\");\n+MODULE_DESCRIPTION(\"STMicroelectronics STM32 PWM LP driver\");\n+MODULE_LICENSE(\"GPL v2\");\n",
    "prefixes": [
        "RESEND",
        "v3",
        "4/9"
    ]
}