From 3542ee9d1f463fd39912548515dbb8ca48414a77 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 10 Mar 2023 19:57:18 +0000 Subject: [PATCH] mediatek: add PWM support for MT7981 SoC Add patch to support PWM on the MT7981 SoC. This patch will also be submitted to upstream Linux soon. Signed-off-by: Daniel Golle --- ...-pwm-mediatek-Add-support-for-MT7981.patch | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 target/linux/mediatek/patches-5.15/811-pwm-mediatek-Add-support-for-MT7981.patch diff --git a/target/linux/mediatek/patches-5.15/811-pwm-mediatek-Add-support-for-MT7981.patch b/target/linux/mediatek/patches-5.15/811-pwm-mediatek-Add-support-for-MT7981.patch new file mode 100644 index 0000000000..ab465a7582 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/811-pwm-mediatek-Add-support-for-MT7981.patch @@ -0,0 +1,212 @@ +From 947b535ebfe161e1725f1030a09de10d1460371c Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 23 Jan 2023 20:47:34 +0000 +Subject: [PATCH] pwm: mediatek: Add support for MT7981 + +The PWM unit on MT7981 uses different register offsets than previous +MediaTek PWM units. Add support for these new offsets and add support +for PWM on MT7981 which has 3 PWM channels, one of them is typically +used for a temperature controlled fan. + +Signed-off-by: Daniel Golle +--- + drivers/pwm/pwm-mediatek.c | 54 ++++++++++++++++++++++++++++++++------ + 1 file changed, 46 insertions(+), 8 deletions(-) + +--- a/drivers/pwm/pwm-mediatek.c ++++ b/drivers/pwm/pwm-mediatek.c +@@ -34,10 +34,14 @@ + + #define PWM_CLK_DIV_MAX 7 + ++#define REG_V1 1 ++#define REG_V2 2 ++ + struct pwm_mediatek_of_data { + unsigned int num_pwms; + bool pwm45_fixup; + bool has_ck_26m_sel; ++ u8 reg_ver; + }; + + /** +@@ -59,10 +63,14 @@ struct pwm_mediatek_chip { + const struct pwm_mediatek_of_data *soc; + }; + +-static const unsigned int pwm_mediatek_reg_offset[] = { ++static const unsigned int mtk_pwm_reg_offset_v1[] = { + 0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220 + }; + ++static const unsigned int mtk_pwm_reg_offset_v2[] = { ++ 0x0080, 0x00c0, 0x0100, 0x0140, 0x0180, 0x1c0, 0x200, 0x0240 ++}; ++ + static inline struct pwm_mediatek_chip * + to_pwm_mediatek_chip(struct pwm_chip *chip) + { +@@ -111,7 +119,19 @@ static inline void pwm_mediatek_writel(s + unsigned int num, unsigned int offset, + u32 value) + { +- writel(value, chip->regs + pwm_mediatek_reg_offset[num] + offset); ++ u32 pwm_offset; ++ ++ switch (chip->soc->reg_ver) { ++ case REG_V2: ++ pwm_offset = mtk_pwm_reg_offset_v2[num]; ++ break; ++ ++ case REG_V1: ++ default: ++ pwm_offset = mtk_pwm_reg_offset_v1[num]; ++ } ++ ++ writel(value, chip->regs + pwm_offset + offset); + } + + static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm, +@@ -146,7 +166,7 @@ static int pwm_mediatek_config(struct pw + + if (clkdiv > PWM_CLK_DIV_MAX) { + pwm_mediatek_clk_disable(chip, pwm); +- dev_err(chip->dev, "period %d not supported\n", period_ns); ++ dev_err(chip->dev, "period of %d ns not supported\n", period_ns); + return -EINVAL; + } + +@@ -221,24 +241,20 @@ static int pwm_mediatek_probe(struct pla + if (IS_ERR(pc->regs)) + return PTR_ERR(pc->regs); + +- pc->clk_pwms = devm_kcalloc(&pdev->dev, pc->soc->num_pwms, ++ pc->clk_pwms = devm_kmalloc_array(&pdev->dev, pc->soc->num_pwms, + sizeof(*pc->clk_pwms), GFP_KERNEL); + if (!pc->clk_pwms) + return -ENOMEM; + + pc->clk_top = devm_clk_get(&pdev->dev, "top"); +- if (IS_ERR(pc->clk_top)) { +- dev_err(&pdev->dev, "clock: top fail: %ld\n", +- PTR_ERR(pc->clk_top)); +- return PTR_ERR(pc->clk_top); +- } ++ if (IS_ERR(pc->clk_top)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_top), ++ "Failed to get top clock\n"); + + pc->clk_main = devm_clk_get(&pdev->dev, "main"); +- if (IS_ERR(pc->clk_main)) { +- dev_err(&pdev->dev, "clock: main fail: %ld\n", +- PTR_ERR(pc->clk_main)); +- return PTR_ERR(pc->clk_main); +- } ++ if (IS_ERR(pc->clk_main)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_main), ++ "Failed to get main clock\n"); + + for (i = 0; i < pc->soc->num_pwms; i++) { + char name[8]; +@@ -246,11 +262,9 @@ static int pwm_mediatek_probe(struct pla + snprintf(name, sizeof(name), "pwm%d", i + 1); + + pc->clk_pwms[i] = devm_clk_get(&pdev->dev, name); +- if (IS_ERR(pc->clk_pwms[i])) { +- dev_err(&pdev->dev, "clock: %s fail: %ld\n", +- name, PTR_ERR(pc->clk_pwms[i])); +- return PTR_ERR(pc->clk_pwms[i]); +- } ++ if (IS_ERR(pc->clk_pwms[i])) ++ return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_pwms[i]), ++ "Failed to get %s clock\n", name); + } + + pc->chip.dev = &pdev->dev; +@@ -258,10 +272,8 @@ static int pwm_mediatek_probe(struct pla + pc->chip.npwm = pc->soc->num_pwms; + + ret = devm_pwmchip_add(&pdev->dev, &pc->chip); +- if (ret < 0) { +- dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); +- return ret; +- } ++ if (ret < 0) ++ return dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n"); + + return 0; + } +@@ -270,48 +282,63 @@ static const struct pwm_mediatek_of_data + .num_pwms = 8, + .pwm45_fixup = false, + .has_ck_26m_sel = false, ++ .reg_ver = REG_V1, + }; + + static const struct pwm_mediatek_of_data mt7622_pwm_data = { + .num_pwms = 6, + .pwm45_fixup = false, + .has_ck_26m_sel = true, ++ .reg_ver = REG_V1, + }; + + static const struct pwm_mediatek_of_data mt7623_pwm_data = { + .num_pwms = 5, + .pwm45_fixup = true, + .has_ck_26m_sel = false, ++ .reg_ver = REG_V1, + }; + + static const struct pwm_mediatek_of_data mt7628_pwm_data = { + .num_pwms = 4, + .pwm45_fixup = true, + .has_ck_26m_sel = false, ++ .reg_ver = REG_V1, + }; + + static const struct pwm_mediatek_of_data mt7629_pwm_data = { + .num_pwms = 1, + .pwm45_fixup = false, + .has_ck_26m_sel = false, ++ .reg_ver = REG_V1, + }; + +-static const struct pwm_mediatek_of_data mt8183_pwm_data = { +- .num_pwms = 4, ++static const struct pwm_mediatek_of_data mt7981_pwm_data = { ++ .num_pwms = 3, + .pwm45_fixup = false, + .has_ck_26m_sel = true, ++ .reg_ver = REG_V2, + }; + + static const struct pwm_mediatek_of_data mt7986_pwm_data = { + .num_pwms = 2, + .pwm45_fixup = false, + .has_ck_26m_sel = true, ++ .reg_ver = REG_V1, ++}; ++ ++static const struct pwm_mediatek_of_data mt8183_pwm_data = { ++ .num_pwms = 4, ++ .pwm45_fixup = false, ++ .has_ck_26m_sel = true, ++ .reg_ver = REG_V1, + }; + + static const struct pwm_mediatek_of_data mt8516_pwm_data = { + .num_pwms = 5, + .pwm45_fixup = false, + .has_ck_26m_sel = true, ++ .reg_ver = REG_V1, + }; + + static const struct of_device_id pwm_mediatek_of_match[] = { +@@ -320,6 +347,7 @@ static const struct of_device_id pwm_med + { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data }, + { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data }, + { .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data }, ++ { .compatible = "mediatek,mt7981-pwm", .data = &mt7981_pwm_data }, + { .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data }, + { .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data }, + { .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data }, -- 2.30.2