get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2217558,
    "url": "http://patchwork.ozlabs.org/api/patches/2217558/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-pwm/patch/20260330-andes-pwm-v5-2-01c59a659d2c@andestech.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": "<20260330-andes-pwm-v5-2-01c59a659d2c@andestech.com>",
    "list_archive_url": null,
    "date": "2026-03-30T07:45:44",
    "name": "[v5,2/3] pwm: add Andes PWM driver support",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "6e0667e5b5b93174db987da29ef90144a747ce28",
    "submitter": {
        "id": 92477,
        "url": "http://patchwork.ozlabs.org/api/people/92477/?format=api",
        "name": "Ben Zong-You Xie via B4 Relay",
        "email": "devnull+ben717.andestech.com@kernel.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-pwm/patch/20260330-andes-pwm-v5-2-01c59a659d2c@andestech.com/mbox/",
    "series": [
        {
            "id": 497968,
            "url": "http://patchwork.ozlabs.org/api/series/497968/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-pwm/list/?series=497968",
            "date": "2026-03-30T07:45:42",
            "name": "pwm: add support for Andes platform",
            "version": 5,
            "mbox": "http://patchwork.ozlabs.org/series/497968/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2217558/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2217558/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-pwm+bounces-8408-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=BCExkV9q;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.105.105.114; helo=tor.lore.kernel.org;\n envelope-from=linux-pwm+bounces-8408-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=\"BCExkV9q\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"
        ],
        "Received": [
            "from tor.lore.kernel.org (tor.lore.kernel.org [172.105.105.114])\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 4fkjwc5N4Rz1y1q\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 30 Mar 2026 18:45:52 +1100 (AEDT)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id 79F993006513\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 30 Mar 2026 07:45:50 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 7F4E03A6B8B;\n\tMon, 30 Mar 2026 07:45:46 +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 DEA533A7585;\n\tMon, 30 Mar 2026 07:45:45 +0000 (UTC)",
            "by smtp.kernel.org (Postfix) with ESMTPS id 4F706C2BCB3;\n\tMon, 30 Mar 2026 07:45:45 +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 47314FF4956;\n\tMon, 30 Mar 2026 07:45:45 +0000 (UTC)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1774856746; cv=none;\n b=MjmM2ysk4F7B/9wbMUXly/W6RISD1udh7+zwssWqHvmy4yHk2b322aLnKy/K+rOS98WnfVSWyfVBZNyLF/Ed6ewhrZRVC6mtyt7ajZ5kc871evXimCh3RwMwyJxCpXMvdoJ9/6KzvTQ0Vy7TZcFKi1qsAJC3nQkhMzqW7/zo5c8=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1774856746; c=relaxed/simple;\n\tbh=zkNZgqriee8oDE85/0hw9dbAFsHYZugU0z6sxnVbyhQ=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=rwV/cTpprVhNoQsztZovgPEfvYT3yCjz9zpksmpcGXRSSAALO3ox+MforIvRrMZdZ0qTxy+PZe9E6ZhT79xTPdSAUSAj7FrWcMvT3ls/91Kwr+16t3rCpqze2qosBitip+xApWD96LKNxUgxKcHdYwzZuCjHfkRgbn3wEcuo2Eg=",
        "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=BCExkV9q; 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=1774856745;\n\tbh=zkNZgqriee8oDE85/0hw9dbAFsHYZugU0z6sxnVbyhQ=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From;\n\tb=BCExkV9qzbjsu1WRAPtqiOO6XFkOk4mRTuLkp/X6wJGaKGFZ4tDemyTX6tKTt3W8+\n\t OQ2cU81fuFgeyBDHFEFerR4T0Cpi5Ci/jS/C+YnjWoM6PDNE0G7GQ9xNaMajQZ4ptB\n\t SO4kcfAqStHH89ZPb5xKkzoOu2cT567Y9dvCycVXW1R5Gf5ZZa0AmGHXcdQBH9a9bJ\n\t 2ihyuhVsdaI8VygKFHu9pZ3GSfPuX/AP37QRm8XjYF3sfvH/RqkniexMzlfn7IACAc\n\t VCY9eJ4OhtNiXJnlx/bqZFESsWHPqwLy7p74N8eYTGd3RgrKE4gPROCUbI2GvG0Tg6\n\t tpNCGaes9z+Fg==",
        "From": "Ben Zong-You Xie via B4 Relay <devnull+ben717.andestech.com@kernel.org>",
        "Date": "Mon, 30 Mar 2026 15:45:44 +0800",
        "Subject": "[PATCH v5 2/3] pwm: add Andes PWM driver support",
        "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": "<20260330-andes-pwm-v5-2-01c59a659d2c@andestech.com>",
        "References": "<20260330-andes-pwm-v5-0-01c59a659d2c@andestech.com>",
        "In-Reply-To": "<20260330-andes-pwm-v5-0-01c59a659d2c@andestech.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>",
        "Cc": "linux-pwm@vger.kernel.org, devicetree@vger.kernel.org,\n linux-kernel@vger.kernel.org, Ben Zong-You Xie <ben717@andestech.com>",
        "X-Mailer": "b4 0.15-dev-47773",
        "X-Developer-Signature": "v=1; a=ed25519-sha256; t=1774856744; l=11929;\n i=ben717@andestech.com; s=20260120; h=from:subject:message-id;\n bh=GtWrGCOpQ0ivIMuJElmmZKWT7fHnuOYXiBw7/f54Xuo=;\n b=pdq+y6dC10PfMHKwH+XEbVTIxQlg/ShTuOGgLQmduLP2LwF+cC0maYeaoP+E2MjUnBCLxSSuI\n 4c6miwXMlCuCk4oyO+UCQJRyHUCA0oGUAZR/FhGFmbTTjp6EiiXU/G6",
        "X-Developer-Key": "i=ben717@andestech.com; a=ed25519;\n pk=nb8L7zQKGJpYk0yvrYKjViOZ34A36g1ZIsCmCsP518s=",
        "X-Endpoint-Received": "by B4 Relay for ben717@andestech.com/20260120 with\n auth_id=610",
        "X-Original-From": "Ben Zong-You Xie <ben717@andestech.com>",
        "Reply-To": "ben717@andestech.com"
    },
    "content": "From: Ben Zong-You Xie <ben717@andestech.com>\n\nAdd a driver for the PWM controller found in Andes AE350 platforms and\nQiLai SoCs.\n\nThe Andes PWM controller features:\n- 4 independent channels.\n- Dual clock source support (APB clock and external clock) to provide\n  a flexible range of frequencies.\n- Support for normal and inversed polarity.\n\nThe driver implements the .apply() and .get_state() callbacks. Since the\nclock source of each channel can be selected by programming the\nregister, clock selection logic is implemented to prioritize the\nexternal clock to maximize the supported period range, falling back to\nthe APB clock for higher frequency requirements.\n\nSigned-off-by: Ben Zong-You Xie <ben717@andestech.com>\n---\n drivers/pwm/Kconfig     |  10 ++\n drivers/pwm/Makefile    |   1 +\n drivers/pwm/pwm-andes.c | 306 ++++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 317 insertions(+)",
    "diff": "diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig\nindex 6f3147518376..b82f2c857ada 100644\n--- a/drivers/pwm/Kconfig\n+++ b/drivers/pwm/Kconfig\n@@ -73,6 +73,16 @@ config PWM_AIROHA\n \t  To compile this driver as a module, choose M here: the module\n \t  will be called pwm-airoha.\n \n+config PWM_ANDES\n+\ttristate \"Andes PWM support\"\n+\tdepends on ARCH_ANDES || COMPILE_TEST\n+\thelp\n+\t  Generic PWM framework driver for Andes platform, such as QiLai SoC\n+\t  and AE350 platform.\n+\n+\t  To compile this driver as a module, choose M here: the module\n+\t  will be called pwm-andes.\n+\n config PWM_APPLE\n \ttristate \"Apple SoC PWM support\"\n \tdepends on ARCH_APPLE || COMPILE_TEST\ndiff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile\nindex 0dc0d2b69025..858f225289cc 100644\n--- a/drivers/pwm/Makefile\n+++ b/drivers/pwm/Makefile\n@@ -3,6 +3,7 @@ obj-$(CONFIG_PWM)\t\t+= core.o\n obj-$(CONFIG_PWM_AB8500)\t+= pwm-ab8500.o\n obj-$(CONFIG_PWM_ADP5585)\t+= pwm-adp5585.o\n obj-$(CONFIG_PWM_AIROHA)\t+= pwm-airoha.o\n+obj-$(CONFIG_PWM_ANDES)\t\t+= pwm-andes.o\n obj-$(CONFIG_PWM_APPLE)\t\t+= pwm-apple.o\n obj-$(CONFIG_PWM_ARGON_FAN_HAT)\t+= pwm-argon-fan-hat.o\n obj-$(CONFIG_PWM_ATMEL)\t\t+= pwm-atmel.o\ndiff --git a/drivers/pwm/pwm-andes.c b/drivers/pwm/pwm-andes.c\nnew file mode 100644\nindex 000000000000..835c8db55987\n--- /dev/null\n+++ b/drivers/pwm/pwm-andes.c\n@@ -0,0 +1,306 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * Driver for Andes PWM, used in Andes AE350 platform and QiLai SoC\n+ *\n+ * Copyright (C) 2026 Andes Technology Corporation.\n+ *\n+ * Limitations:\n+ * - When disabling a channel, the current period will not be completed, and the\n+ *   output will be constant zero.\n+ * - The current period will be completed first if reconfiguring.\n+ * - Further, if the reconfiguration changes the clock source, the output will\n+ *   not be the old one nor the new one. And the output will be the new one\n+ *   until writing to the reload register.\n+ * - The hardware can neither do a 0% nor a 100% relative duty cycle.\n+ */\n+\n+#include <linux/bitfield.h>\n+#include <linux/clk.h>\n+#include <linux/err.h>\n+#include <linux/math64.h>\n+#include <linux/module.h>\n+#include <linux/of.h>\n+#include <linux/platform_device.h>\n+#include <linux/pwm.h>\n+#include <linux/regmap.h>\n+#include <linux/time.h>\n+#include <linux/types.h>\n+\n+#define ANDES_PWM_CH_ENABLE\t\t0x1C\n+#define ANDES_PWM_CH_ENABLE_PWM(ch)\tBIT(3 + (4 * (ch)))\n+\n+#define ANDES_PWM_CH_CTRL(ch)\t\t(0x20 + (0x10 * (ch)))\n+#define ANDES_PWM_CH_CTRL_MODE_PWM\tBIT(2)\n+#define ANDES_PWM_CH_CTRL_CLK\t\tBIT(3)\n+#define ANDES_PWM_CH_CTRL_PARK\t\tBIT(4)\n+#define ANDES_PWM_CH_CTRL_MASK\t\tGENMASK(4, 0)\n+\n+#define ANDES_PWM_CH_RELOAD(ch)\t\t(0x24 + (0x10 * (ch)))\n+#define ANDES_PWM_CH_RELOAD_HIGH\tGENMASK(31, 16)\n+#define ANDES_PWM_CH_RELOAD_LOW\t\tGENMASK(15, 0)\n+\n+#define ANDES_PWM_CH_COUNTER(ch)\t(0x28 + (0x10 * (ch)))\n+\n+#define ANDES_PWM_CH_MAX\t\t4\n+#define ANDES_PWM_CYCLE_MIN\t\t1\n+#define ANDES_PWM_CYCLE_MAX\t\t0x10000\n+\n+struct andes_pwm {\n+\tstruct regmap *regmap;\n+\tstruct clk *pclk;\n+\tstruct clk *extclk;\n+\tunsigned int pclk_rate;\n+\tunsigned int extclk_rate;\n+};\n+\n+static const struct regmap_config andes_pwm_regmap_config = {\n+\t.name = \"andes_pwm\",\n+\t.reg_bits = 32,\n+\t.reg_stride = 4,\n+\t.val_bits = 32,\n+\t.pad_bits = 0,\n+\t.max_register = ANDES_PWM_CH_COUNTER(ANDES_PWM_CH_MAX - 1),\n+\t.cache_type = REGCACHE_NONE,\n+};\n+\n+static inline struct andes_pwm *to_andes_pwm(struct pwm_chip *chip)\n+{\n+\treturn pwmchip_get_drvdata(chip);\n+}\n+\n+static int andes_pwm_enable(struct pwm_chip *chip, unsigned int channel,\n+\t\t\t    bool enable)\n+{\n+\tstruct andes_pwm *ap = to_andes_pwm(chip);\n+\n+\treturn regmap_assign_bits(ap->regmap, ANDES_PWM_CH_ENABLE,\n+\t\t\t\t  ANDES_PWM_CH_ENABLE_PWM(channel), enable);\n+}\n+\n+static int andes_pwm_config(struct pwm_chip *chip, unsigned int channel,\n+\t\t\t    const struct pwm_state *state)\n+{\n+\tstruct andes_pwm *ap = to_andes_pwm(chip);\n+\tunsigned int clk_rate = ap->extclk_rate;\n+\tunsigned int try = 2;\n+\tu64 high_ns = state->duty_cycle;\n+\tu64 low_ns = state->period - high_ns;\n+\tunsigned int ctrl = ANDES_PWM_CH_CTRL_MODE_PWM;\n+\tu64 high_cycles;\n+\tu64 low_cycles;\n+\tu32 reload;\n+\n+\t/*\n+\t * Reload register for PWM mode:\n+\t *\n+\t *\t\t31 : 16    15 : 0\n+\t *\t\tPWM16_Hi | PWM16_Lo\n+\t *\n+\t * The high duration is (PWM16_Hi + 1) cycles and the low duration is\n+\t * (PWM16_Lo + 1) cycles. For a duty cycle of 10 cycles and a total\n+\t * period of 30 cycles in normal polarity, PWM16_Hi is set to\n+\t * 9 (10 - 1) and PWM16_Lo to 19 (30 - 10 - 1). Also, PWM16_Hi is set to\n+\t * 19 and PWM16_Lo is set to 9 in inversed polarity.\n+\t *\n+\t * Because the register stores \"cycles - 1\", the valid range for\n+\t * each phase is 1 to 65536 (0x10000) cycles. This implies the hardware\n+\t * cannot achieve a true 0% or 100% duty cycle.\n+\t *\n+\t * The controller supports two clock sources: the APB clock and an\n+\t * external clock. The driver first attempts to use the external clock\n+\t * to widest possible range of supported periods. If the requests\n+\t * exceeds the valid range of the register, it falls back to the APB\n+\t * clock. The request is rejected if the timing cannot be met by either\n+\t * source.\n+\t */\n+\tif (state->polarity == PWM_POLARITY_INVERSED)\n+\t\tswap(high_ns, low_ns);\n+\n+\twhile (try) {\n+\t\thigh_cycles = mul_u64_u64_div_u64(clk_rate, high_ns,\n+\t\t\t\t\t\t  NSEC_PER_SEC);\n+\t\tlow_cycles = mul_u64_u64_div_u64(clk_rate, low_ns,\n+\t\t\t\t\t\t NSEC_PER_SEC);\n+\t\tif (high_cycles > ANDES_PWM_CYCLE_MAX)\n+\t\t\thigh_cycles = ANDES_PWM_CYCLE_MAX;\n+\n+\t\tif (low_cycles > ANDES_PWM_CYCLE_MAX)\n+\t\t\tlow_cycles = ANDES_PWM_CYCLE_MAX;\n+\n+\t\tif (high_cycles >= ANDES_PWM_CYCLE_MIN &&\n+\t\t    low_cycles >= ANDES_PWM_CYCLE_MIN)\n+\t\t\tbreak;\n+\n+\t\ttry--;\n+\t\tclk_rate = ap->pclk_rate;\n+\t}\n+\n+\t/*\n+\t * try == 0 : no clock is valid\n+\t * try == 1 : use APB clock\n+\t * try == 2 : use external clock\n+\t */\n+\tif (!try)\n+\t\treturn -EINVAL;\n+\n+\t/*\n+\t * If changing the clock source here, the output will not be the old one\n+\t * nor the new one. And the output will be the new one until writing to\n+\t * the reload register.\n+\t */\n+\tctrl |= (try == 1) ? ANDES_PWM_CH_CTRL_CLK : 0;\n+\tctrl |= (state->polarity == PWM_POLARITY_INVERSED) ?\n+\t\tANDES_PWM_CH_CTRL_PARK : 0;\n+\tregmap_update_bits(ap->regmap, ANDES_PWM_CH_CTRL(channel),\n+\t\t\t   ANDES_PWM_CH_CTRL_MASK, ctrl);\n+\treload = FIELD_PREP(ANDES_PWM_CH_RELOAD_HIGH, high_cycles - 1) |\n+\t\t FIELD_PREP(ANDES_PWM_CH_RELOAD_LOW, low_cycles - 1);\n+\n+\treturn regmap_write(ap->regmap, ANDES_PWM_CH_RELOAD(channel), reload);\n+}\n+\n+static int andes_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,\n+\t\t\t   const struct pwm_state *state)\n+{\n+\tunsigned int channel = pwm->hwpwm;\n+\tint ret;\n+\n+\tif (!state->enabled) {\n+\t\tif (pwm->state.enabled)\n+\t\t\tandes_pwm_enable(chip, channel, false);\n+\n+\t\treturn 0;\n+\t}\n+\n+\tret = andes_pwm_config(chip, channel, state);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn andes_pwm_enable(chip, channel, true);\n+}\n+\n+static int andes_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,\n+\t\t\t       struct pwm_state *state)\n+{\n+\tstruct andes_pwm *ap = to_andes_pwm(chip);\n+\tunsigned int channel = pwm->hwpwm;\n+\tunsigned int ctrl;\n+\tunsigned int clk_rate;\n+\tunsigned int reload;\n+\tu64 high_cycles;\n+\tu64 low_cycles;\n+\n+\tregmap_read(ap->regmap, ANDES_PWM_CH_CTRL(channel), &ctrl);\n+\tclk_rate = FIELD_GET(ANDES_PWM_CH_CTRL_CLK, ctrl) ? ap->pclk_rate\n+\t\t\t\t\t\t\t  : ap->extclk_rate;\n+\tstate->enabled = regmap_test_bits(ap->regmap, ANDES_PWM_CH_ENABLE,\n+\t\t\t\t\t  ANDES_PWM_CH_ENABLE_PWM(channel));\n+\tstate->polarity = regmap_test_bits(ap->regmap,\n+\t\t\t\t\t   ANDES_PWM_CH_CTRL(channel),\n+\t\t\t\t\t   ANDES_PWM_CH_CTRL_PARK);\n+\tregmap_read(ap->regmap, ANDES_PWM_CH_RELOAD(channel), &reload);\n+\thigh_cycles = FIELD_GET(ANDES_PWM_CH_RELOAD_HIGH, reload) + 1;\n+\tlow_cycles = FIELD_GET(ANDES_PWM_CH_RELOAD_LOW, reload) + 1;\n+\n+\t/*\n+\t * high_cycles and low_cycles are both 16 bits, and NSEC_PER_SEC is 30\n+\t * bits. Thus, the multiplication is safe from overflow\n+\t */\n+\tif (state->polarity == PWM_POLARITY_NORMAL) {\n+\t\tstate->duty_cycle = DIV_ROUND_UP_ULL(high_cycles * NSEC_PER_SEC,\n+\t\t\t\t\t\t     clk_rate);\n+\t\tstate->period = state->duty_cycle +\n+\t\t\t\tDIV_ROUND_UP_ULL(low_cycles * NSEC_PER_SEC,\n+\t\t\t\t\t\t clk_rate);\n+\t} else {\n+\t\tstate->duty_cycle = DIV_ROUND_UP_ULL(low_cycles * NSEC_PER_SEC,\n+\t\t\t\t\t\t     clk_rate);\n+\t\tstate->period = state->duty_cycle +\n+\t\t\t\tDIV_ROUND_UP_ULL(high_cycles * NSEC_PER_SEC,\n+\t\t\t\t\t\t clk_rate);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static const struct pwm_ops andes_pwm_ops = {\n+\t.apply = andes_pwm_apply,\n+\t.get_state = andes_pwm_get_state,\n+};\n+\n+static int andes_pwm_probe(struct platform_device *pdev)\n+{\n+\tstruct device *dev = &pdev->dev;\n+\tstruct pwm_chip *chip;\n+\tstruct andes_pwm *ap;\n+\tvoid __iomem *reg_base;\n+\tint ret;\n+\n+\tchip = devm_pwmchip_alloc(dev, ANDES_PWM_CH_MAX, sizeof(*ap));\n+\tif (IS_ERR(chip))\n+\t\treturn PTR_ERR(chip);\n+\n+\tap = to_andes_pwm(chip);\n+\treg_base = devm_platform_ioremap_resource(pdev, 0);\n+\tif (IS_ERR(reg_base))\n+\t\treturn dev_err_probe(dev, PTR_ERR(reg_base),\n+\t\t\t\t     \"failed to map I/O space\\n\");\n+\n+\tap->pclk = devm_clk_get_enabled(dev, \"pclk\");\n+\tif (IS_ERR(ap->pclk))\n+\t\treturn dev_err_probe(dev, PTR_ERR(ap->pclk),\n+\t\t\t\t     \"failed to get APB clock\\n\");\n+\n+\tap->extclk = devm_clk_get_optional_enabled(dev, \"extclk\");\n+\tif (IS_ERR(ap->extclk))\n+\t\treturn dev_err_probe(dev, PTR_ERR(ap->extclk),\n+\t\t\t\t     \"failed to get external clock\\n\");\n+\n+\t/*\n+\t * If the clock rate is greater than 10^9, there may be an overflow when\n+\t * calculating the cycles in andes_pwm_config()\n+\t */\n+\tap->pclk_rate = clk_get_rate(ap->pclk);\n+\tif (ap->pclk_rate > NSEC_PER_SEC)\n+\t\tap->pclk = NULL;\n+\n+\tap->extclk_rate = ap->extclk ? clk_get_rate(ap->extclk) : 0;\n+\tif (ap->extclk_rate > NSEC_PER_SEC)\n+\t\tap->extclk = NULL;\n+\n+\tif (!ap->pclk && !ap->extclk)\n+\t\treturn dev_err_probe(dev, -EINVAL, \"clocks are out of range\\n\");\n+\n+\tap->regmap = devm_regmap_init_mmio(dev, reg_base,\n+\t\t\t\t\t   &andes_pwm_regmap_config);\n+\tif (IS_ERR(ap->regmap)) {\n+\t\treturn dev_err_probe(dev, PTR_ERR(ap->regmap),\n+\t\t\t\t     \"failed to initialize regmap\\n\");\n+\t}\n+\n+\tchip->ops = &andes_pwm_ops;\n+\tret = devm_pwmchip_add(dev, chip);\n+\tif (ret)\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 andes_pwm_of_match[] = {\n+\t{ .compatible = \"andestech,ae350-pwm\" },\n+\t{ /* sentinel */ }\n+};\n+MODULE_DEVICE_TABLE(of, andes_pwm_of_match);\n+\n+static struct platform_driver andes_pwm_driver = {\n+\t.driver = {\n+\t\t.name = \"andes_pwm\",\n+\t\t.of_match_table = andes_pwm_of_match,\n+\t},\n+\t.probe = andes_pwm_probe,\n+};\n+module_platform_driver(andes_pwm_driver);\n+\n+MODULE_AUTHOR(\"Ben Zong-You Xie <ben717@andestech.com>\");\n+MODULE_DESCRIPTION(\"Andes PWM driver\");\n+MODULE_LICENSE(\"GPL\");\n",
    "prefixes": [
        "v5",
        "2/3"
    ]
}