get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2220315,
    "url": "http://patchwork.ozlabs.org/api/1.1/patches/2220315/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-pwm/patch/20260406-ipq-pwm-v21-2-6ed1e868e4c2@outlook.com/",
    "project": {
        "id": 38,
        "url": "http://patchwork.ozlabs.org/api/1.1/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": ""
    },
    "msgid": "<20260406-ipq-pwm-v21-2-6ed1e868e4c2@outlook.com>",
    "date": "2026-04-06T20:24:39",
    "name": "[v21,2/6] pwm: driver for qualcomm ipq6018 pwm block",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "9ad71f312c7b110210af689634f32c96dd68b6a2",
    "submitter": {
        "id": 90538,
        "url": "http://patchwork.ozlabs.org/api/1.1/people/90538/?format=api",
        "name": "George Moussalem via B4 Relay",
        "email": "devnull+george.moussalem.outlook.com@kernel.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-pwm/patch/20260406-ipq-pwm-v21-2-6ed1e868e4c2@outlook.com/mbox/",
    "series": [
        {
            "id": 498895,
            "url": "http://patchwork.ozlabs.org/api/1.1/series/498895/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-pwm/list/?series=498895",
            "date": "2026-04-06T20:24:40",
            "name": "Add PWM support for IPQ chipsets",
            "version": 21,
            "mbox": "http://patchwork.ozlabs.org/series/498895/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2220315/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2220315/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "\n <linux-pwm+bounces-8500-incoming=patchwork.ozlabs.org@vger.kernel.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "linux-pwm@vger.kernel.org"
        ],
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=dKYd77b2;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org;\n envelope-from=linux-pwm+bounces-8500-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=\"dKYd77b2\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"
        ],
        "Received": [
            "from tor.lore.kernel.org (tor.lore.kernel.org\n [IPv6:2600:3c04:e001:36c::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fqLTm5Dzmz1yGn\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 07 Apr 2026 06:27:08 +1000 (AEST)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id DCBC4300AC3F\n\tfor <incoming@patchwork.ozlabs.org>; Mon,  6 Apr 2026 20:25:38 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id CBA753019BA;\n\tMon,  6 Apr 2026 20:25:37 +0000 (UTC)",
            "from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org\n [10.30.226.201])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id A3DE32ED843;\n\tMon,  6 Apr 2026 20:25:37 +0000 (UTC)",
            "by smtp.kernel.org (Postfix) with ESMTPS id 5EF39C19425;\n\tMon,  6 Apr 2026 20:25:37 +0000 (UTC)",
            "from aws-us-west-2-korg-lkml-1.web.codeaurora.org\n (localhost.localdomain [127.0.0.1])\n\tby smtp.lore.kernel.org (Postfix) with ESMTP id 5343AFB5168;\n\tMon,  6 Apr 2026 20:25:37 +0000 (UTC)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1775507137; cv=none;\n b=rSg1NjnmsruYmkX3R11W6k4Z8AtS38TZ+TqeYL720Tdv31TMvmKHDhnKxFF3tEIwgHWVheBySdmsHQ+TjnxpU5oSVZHZv22ih+8Aiy54O5TPR5z1YON6AsiVaBCkMkBlJ/jMUaSmVPHvRKFy9ayw1ZRvJkoI6VDG2UJjbwnNxG4=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775507137; c=relaxed/simple;\n\tbh=//4hFRzRx51KF8dy4TmLZTzuscwSckXo5IqSX/SPqZY=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=ArKzdfp/X7WMN4QtZSZyRhbAQp45YLQl6I5amOM+CrsyZ9gVl6Ig9XllK6FIsPUocURasHGcptv5FS/XwVHiC3l+roWqJXmNVv/U4DRwsgaL3Kc2MJhyHwPIV0yGbI1K/DDtF0ESVy/9H6z+VJfdpkob1whus00BilrEYX2k+OI=",
        "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=dKYd77b2; arc=none smtp.client-ip=10.30.226.201",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1775507137;\n\tbh=//4hFRzRx51KF8dy4TmLZTzuscwSckXo5IqSX/SPqZY=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From;\n\tb=dKYd77b2EVEbYFEoz8GlRUWt4QG2CKaZJdXDAMG7k2AgpxexfBmH0G8LoDmtRFgtY\n\t oVgXAZu50MD7faY9SaQ12xL84uf9+kwbnCDQrkjdvTOkopuA5J25KzYmsaKizbqSfm\n\t EEsih8WGBU/42qU+ti1nOOkawPiT7SbJD47IMI7a8YS10y+CBZUKQCqw7GOcEF3fW4\n\t EaX/Fwko1zH0NhYrlUyJaJNw82U4O1cQfa6aXVlbYE658InbuDfjyY4I6HZek9oMxo\n\t O5H++QXbopgbyTj8lEvNg+/vzQZRP8Q6jQVx7AfXjEWdzgNw9WdcbP3vtgeEmd18L1\n\t dJ2shBfGt8snQ==",
        "From": "George Moussalem via B4 Relay\n <devnull+george.moussalem.outlook.com@kernel.org>",
        "Date": "Mon, 06 Apr 2026 22:24:39 +0200",
        "Subject": "[PATCH v21 2/6] pwm: driver for qualcomm ipq6018 pwm block",
        "Precedence": "bulk",
        "X-Mailing-List": "linux-pwm@vger.kernel.org",
        "List-Id": "<linux-pwm.vger.kernel.org>",
        "List-Subscribe": "<mailto:linux-pwm+subscribe@vger.kernel.org>",
        "List-Unsubscribe": "<mailto:linux-pwm+unsubscribe@vger.kernel.org>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "<20260406-ipq-pwm-v21-2-6ed1e868e4c2@outlook.com>",
        "References": "<20260406-ipq-pwm-v21-0-6ed1e868e4c2@outlook.com>",
        "In-Reply-To": "<20260406-ipq-pwm-v21-0-6ed1e868e4c2@outlook.com>",
        "To": "=?utf-8?q?Uwe_Kleine-K=C3=B6nig?= <ukleinek@kernel.org>,\n  Rob Herring <robh@kernel.org>, Krzysztof Kozlowski <krzk+dt@kernel.org>,\n  Conor Dooley <conor+dt@kernel.org>, Bjorn Andersson <andersson@kernel.org>,\n  Konrad Dybcio <konradybcio@kernel.org>",
        "Cc": "linux-arm-msm@vger.kernel.org, linux-pwm@vger.kernel.org,\n devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,\n George Moussalem <george.moussalem@outlook.com>,\n Devi Priya <quic_devipriy@quicinc.com>,\n Baruch Siach <baruch.siach@siklu.com>",
        "X-Mailer": "b4 0.15.1",
        "X-Developer-Signature": "v=1; a=ed25519-sha256; t=1775507135; l=10191;\n i=george.moussalem@outlook.com; s=20260406; h=from:subject:message-id;\n bh=hCPxbSZuZ7s50wScexFoYf75FXO3O4WXi/g+V0VERTQ=;\n b=5g3ijef6uxDRL+31oDDnTpHKv8/sH7xFpw4FOJX8mXgdZCvjdLylG4wYYZQmPv04L5JCHRMUe\n vMVN6yfhxZ6BtrzjTUWbcFrNh+gAkfafTuwLYgBgS1WNbwObzcTF4Xd",
        "X-Developer-Key": "i=george.moussalem@outlook.com; a=ed25519;\n pk=uqspem3ahtBvPEBuxVbyyXT/0Vp3JNb/mo1EPbmBzWg=",
        "X-Endpoint-Received": "by B4 Relay for george.moussalem@outlook.com/20260406\n with auth_id=722",
        "X-Original-From": "George Moussalem <george.moussalem@outlook.com>",
        "Reply-To": "george.moussalem@outlook.com"
    },
    "content": "From: Devi Priya <quic_devipriy@quicinc.com>\n\nDriver for the PWM block in Qualcomm IPQ6018 line of SoCs. Based on\ndriver from downstream Codeaurora kernel tree. Removed support for older\n(V1) variants because I have no access to that hardware.\n\nTested on IPQ5018 and IPQ6010 based hardware.\n\nCo-developed-by: Baruch Siach <baruch.siach@siklu.com>\nSigned-off-by: Baruch Siach <baruch.siach@siklu.com>\nSigned-off-by: Devi Priya <quic_devipriy@quicinc.com>\nReviewed-by: Bjorn Andersson <andersson@kernel.org>\nSigned-off-by: George Moussalem <george.moussalem@outlook.com>\n---\n drivers/pwm/Kconfig   |  12 +++\n drivers/pwm/Makefile  |   1 +\n drivers/pwm/pwm-ipq.c | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 272 insertions(+)",
    "diff": "diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig\nindex 6f3147518376..e8886a9b64d9 100644\n--- a/drivers/pwm/Kconfig\n+++ b/drivers/pwm/Kconfig\n@@ -347,6 +347,18 @@ config PWM_INTEL_LGM\n \t  To compile this driver as a module, choose M here: the module\n \t  will be called pwm-intel-lgm.\n \n+config PWM_IPQ\n+\ttristate \"IPQ PWM support\"\n+\tdepends on ARCH_QCOM || COMPILE_TEST\n+\tdepends on HAVE_CLK && HAS_IOMEM\n+\thelp\n+\t  Generic PWM framework driver for IPQ PWM block which supports\n+\t  4 pwm channels. Each of the these channels can be configured\n+\t  independent of each other.\n+\n+\t  To compile this driver as a module, choose M here: the module\n+\t  will be called pwm-ipq.\n+\n config PWM_IQS620A\n \ttristate \"Azoteq IQS620A PWM support\"\n \tdepends on MFD_IQS62X || COMPILE_TEST\ndiff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile\nindex 0dc0d2b69025..5630a521a7cf 100644\n--- a/drivers/pwm/Makefile\n+++ b/drivers/pwm/Makefile\n@@ -29,6 +29,7 @@ obj-$(CONFIG_PWM_IMX1)\t\t+= pwm-imx1.o\n obj-$(CONFIG_PWM_IMX27)\t\t+= pwm-imx27.o\n obj-$(CONFIG_PWM_IMX_TPM)\t+= pwm-imx-tpm.o\n obj-$(CONFIG_PWM_INTEL_LGM)\t+= pwm-intel-lgm.o\n+obj-$(CONFIG_PWM_IPQ)\t\t+= pwm-ipq.o\n obj-$(CONFIG_PWM_IQS620A)\t+= pwm-iqs620a.o\n obj-$(CONFIG_PWM_JZ4740)\t+= pwm-jz4740.o\n obj-$(CONFIG_PWM_KEEMBAY)\t+= pwm-keembay.o\ndiff --git a/drivers/pwm/pwm-ipq.c b/drivers/pwm/pwm-ipq.c\nnew file mode 100644\nindex 000000000000..b79e5e457d1a\n--- /dev/null\n+++ b/drivers/pwm/pwm-ipq.c\n@@ -0,0 +1,259 @@\n+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0\n+/*\n+ * Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved.\n+ *\n+ * Hardware notes / Limitations:\n+ * - The PWM controller has no publicly available datasheet.\n+ * - Each of the four channels is programmed via two 32-bit registers\n+ *   (REG0 and REG1 at 8-byte stride).\n+ * - Period and duty-cycle reconfiguration is fully atomic: new divider,\n+ *   pre-divider, and high-duration values are latched by setting the\n+ *   UPDATE bit (bit 30 in REG1). The hardware applies the new settings\n+ *   at the beginning of the next period without disabling the output,\n+ *   so the currently running period is always completed.\n+ * - On disable (clearing the ENABLE bit 31 in REG1), the hardware\n+ *   finishes the current period before stopping the output. The pin\n+ *   is then driven to the inactive (low) level.\n+ * - Upon disabling, the hardware resets the pre-divider (PRE_DIV) and divider\n+ *   fields (PWM_DIV) in REG0 and REG1 to 0x0000 and 0x0001 respectively.\n+ * - Only normal polarity is supported.\n+ */\n+\n+#include <linux/module.h>\n+#include <linux/platform_device.h>\n+#include <linux/pwm.h>\n+#include <linux/clk.h>\n+#include <linux/io.h>\n+#include <linux/of.h>\n+#include <linux/math64.h>\n+#include <linux/of_device.h>\n+#include <linux/bitfield.h>\n+#include <linux/units.h>\n+\n+/* The frequency range supported is 1 Hz to 100 Mhz (clock rate) */\n+#define IPQ_PWM_MAX_PERIOD_NS\t((u64)NSEC_PER_SEC)\n+#define IPQ_PWM_MIN_PERIOD_NS\t10\n+\n+/*\n+ * Two 32-bit registers for each PWM: REG0, and REG1.\n+ * Base offset for PWM #i is at 8 * #i.\n+ */\n+#define IPQ_PWM_REG0\t\t\t0\n+#define IPQ_PWM_REG0_PWM_DIV\t\tGENMASK(15, 0)\n+#define IPQ_PWM_REG0_HI_DURATION\tGENMASK(31, 16)\n+\n+#define IPQ_PWM_REG1\t\t\t4\n+#define IPQ_PWM_REG1_PRE_DIV\t\tGENMASK(15, 0)\n+\n+/*\n+ * The max value specified for each field is based on the number of bits\n+ * in the pwm control register for that field (16-bit)\n+ */\n+#define IPQ_PWM_MAX_DIV\t\t\tFIELD_MAX(IPQ_PWM_REG0_PWM_DIV)\n+\n+/*\n+ * Enable bit is set to enable output toggling in pwm device.\n+ * Update bit is set to trigger the change and is unset automatically\n+ * to reflect the changed divider and high duration values in register.\n+ */\n+#define IPQ_PWM_REG1_UPDATE\t\tBIT(30)\n+#define IPQ_PWM_REG1_ENABLE\t\tBIT(31)\n+\n+struct ipq_pwm_chip {\n+\tvoid __iomem *mem;\n+\tunsigned long clk_rate;\n+};\n+\n+static struct ipq_pwm_chip *ipq_pwm_from_chip(struct pwm_chip *chip)\n+{\n+\treturn pwmchip_get_drvdata(chip);\n+}\n+\n+static unsigned int ipq_pwm_reg_read(struct pwm_device *pwm, unsigned int reg)\n+{\n+\tstruct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip);\n+\tunsigned int off = 8 * pwm->hwpwm + reg;\n+\n+\treturn readl(ipq_chip->mem + off);\n+}\n+\n+static void ipq_pwm_reg_write(struct pwm_device *pwm, unsigned int reg,\n+\t\t\t      unsigned int val)\n+{\n+\tstruct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip);\n+\tunsigned int off = 8 * pwm->hwpwm + reg;\n+\n+\twritel(val, ipq_chip->mem + off);\n+}\n+\n+static int ipq_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,\n+\t\t\t const struct pwm_state *state)\n+{\n+\tstruct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip);\n+\tunsigned int pre_div, pwm_div;\n+\tu64 period_ns, duty_ns;\n+\tunsigned long val = 0;\n+\tunsigned long hi_dur;\n+\n+\tif (state->polarity != PWM_POLARITY_NORMAL)\n+\t\treturn -EINVAL;\n+\n+\t/*\n+\t * Check the upper and lower bounds for the period as per\n+\t * hardware limits\n+\t */\n+\tperiod_ns = max(state->period, IPQ_PWM_MIN_PERIOD_NS);\n+\tperiod_ns = min(state->period, IPQ_PWM_MAX_PERIOD_NS);\n+\tduty_ns = min(state->duty_cycle, period_ns);\n+\n+\t/*\n+\t * Pick the maximal value for PWM_DIV that still allows a\n+\t * 100% relative duty cycle. This allows a fine grained\n+\t * selection of duty cycles.\n+\t */\n+\tpwm_div = IPQ_PWM_MAX_DIV - 1;\n+\n+\t/*\n+\t * although mul_u64_u64_div_u64 returns a u64, in practice it\n+\t * won't overflow due to above constraints. Take the max period\n+\t * of 10^9 (NSEC_PER_SEC) and the pwm_div + 1 (IPQ_PWM_MAX_DIV)\n+\t *  10^9 * 10^8\n+\t * ------------- => which fits well into a 32-bit unsigned int.\n+\t * 10^9 * 65,535\n+\t */\n+\tpre_div = mul_u64_u64_div_u64(period_ns, ipq_chip->clk_rate,\n+\t\t\t\t      (u64)NSEC_PER_SEC * (pwm_div + 1));\n+\n+\tif (!pre_div)\n+\t\treturn -ERANGE;\n+\n+\tpre_div -= 1;\n+\n+\tif (pre_div > IPQ_PWM_MAX_DIV)\n+\t\tpre_div = IPQ_PWM_MAX_DIV;\n+\n+\t/* pwm duty = HI_DUR * (PRE_DIV + 1) / clk_rate */\n+\thi_dur = mul_u64_u64_div_u64(duty_ns, ipq_chip->clk_rate,\n+\t\t\t\t     (u64)(pre_div + 1) * NSEC_PER_SEC);\n+\n+\tval = FIELD_PREP(IPQ_PWM_REG0_HI_DURATION, hi_dur) |\n+\t\tFIELD_PREP(IPQ_PWM_REG0_PWM_DIV, pwm_div);\n+\tipq_pwm_reg_write(pwm, IPQ_PWM_REG0, val);\n+\n+\tval = FIELD_PREP(IPQ_PWM_REG1_PRE_DIV, pre_div);\n+\tipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val);\n+\n+\t/* PWM enable toggle needs a separate write to REG1 */\n+\tval |= IPQ_PWM_REG1_UPDATE;\n+\tif (state->enabled)\n+\t\tval |= IPQ_PWM_REG1_ENABLE;\n+\tipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val);\n+\n+\treturn 0;\n+}\n+\n+static int ipq_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,\n+\t\t\t     struct pwm_state *state)\n+{\n+\tstruct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip);\n+\tunsigned int pre_div, pwm_div, hi_dur;\n+\tu64 effective_div, hi_div;\n+\tu32 reg0, reg1;\n+\n+\treg1 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG1);\n+\tstate->enabled = reg1 & IPQ_PWM_REG1_ENABLE;\n+\n+\tif (!state->enabled)\n+\t\treturn 0;\n+\n+\treg0 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG0);\n+\n+\tstate->polarity = PWM_POLARITY_NORMAL;\n+\n+\tpwm_div = FIELD_GET(IPQ_PWM_REG0_PWM_DIV, reg0);\n+\thi_dur = FIELD_GET(IPQ_PWM_REG0_HI_DURATION, reg0);\n+\tpre_div = FIELD_GET(IPQ_PWM_REG1_PRE_DIV, reg1);\n+\n+\teffective_div = (u64)(pre_div + 1) * (pwm_div + 1);\n+\n+\t/*\n+\t * effective_div <= 0x100000000, so the multiplication doesn't overflow.\n+\t */\n+\tstate->period = DIV64_U64_ROUND_UP(effective_div * NSEC_PER_SEC,\n+\t\t\t\t\t   ipq_chip->clk_rate);\n+\n+\thi_div = hi_dur * (pre_div + 1);\n+\tstate->duty_cycle = DIV64_U64_ROUND_UP(hi_div * NSEC_PER_SEC,\n+\t\t\t\t\t       ipq_chip->clk_rate);\n+\n+\t/*\n+\t * ensure a valid config is passed back to PWM core in case duty_cycle\n+\t * is > period (>100%)\n+\t */\n+\tstate->duty_cycle = min(state->duty_cycle, state->period);\n+\n+\treturn 0;\n+}\n+\n+static const struct pwm_ops ipq_pwm_ops = {\n+\t.apply = ipq_pwm_apply,\n+\t.get_state = ipq_pwm_get_state,\n+};\n+\n+static int ipq_pwm_probe(struct platform_device *pdev)\n+{\n+\tstruct device *dev = &pdev->dev;\n+\tstruct ipq_pwm_chip *pwm;\n+\tstruct pwm_chip *chip;\n+\tstruct clk *clk;\n+\tint ret;\n+\n+\tchip = devm_pwmchip_alloc(dev, 4, sizeof(*pwm));\n+\tif (IS_ERR(chip))\n+\t\treturn PTR_ERR(chip);\n+\tpwm = ipq_pwm_from_chip(chip);\n+\n+\tpwm->mem = devm_platform_ioremap_resource(pdev, 0);\n+\tif (IS_ERR(pwm->mem))\n+\t\treturn dev_err_probe(dev, PTR_ERR(pwm->mem),\n+\t\t\t\t     \"Failed to acquire resource\\n\");\n+\n+\tclk = devm_clk_get_enabled(dev, NULL);\n+\tif (IS_ERR(clk))\n+\t\treturn dev_err_probe(dev, PTR_ERR(clk),\n+\t\t\t\t     \"Failed to get clock\\n\");\n+\n+\tret = devm_clk_rate_exclusive_get(dev, clk);\n+\tif (ret)\n+\t\treturn dev_err_probe(dev, ret, \"Failed to lock clock rate\\n\");\n+\n+\tpwm->clk_rate = clk_get_rate(clk);\n+\tif (!pwm->clk_rate)\n+\t\treturn dev_err_probe(dev, -EINVAL, \"Failed due to clock rate being zero\\n\");\n+\n+\tchip->ops = &ipq_pwm_ops;\n+\n+\tret = devm_pwmchip_add(dev, chip);\n+\tif (ret < 0)\n+\t\treturn dev_err_probe(dev, ret, \"Failed to add pwm chip\\n\");\n+\n+\treturn 0;\n+}\n+\n+static const struct of_device_id pwm_ipq_dt_match[] = {\n+\t{ .compatible = \"qcom,ipq6018-pwm\", },\n+\t{}\n+};\n+MODULE_DEVICE_TABLE(of, pwm_ipq_dt_match);\n+\n+static struct platform_driver ipq_pwm_driver = {\n+\t.driver = {\n+\t\t.name = \"ipq-pwm\",\n+\t\t.of_match_table = pwm_ipq_dt_match,\n+\t},\n+\t.probe = ipq_pwm_probe,\n+};\n+\n+module_platform_driver(ipq_pwm_driver);\n+\n+MODULE_LICENSE(\"GPL\");\n",
    "prefixes": [
        "v21",
        "2/6"
    ]
}