diff options
Diffstat (limited to 'drivers/pwm/pwm-mediatek.c')
-rw-r--r-- | drivers/pwm/pwm-mediatek.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c index 7eaab5831499..6777c511622a 100644 --- a/drivers/pwm/pwm-mediatek.c +++ b/drivers/pwm/pwm-mediatek.c @@ -29,6 +29,7 @@ #define PWM45DWIDTH_FIXUP 0x30 #define PWMTHRES 0x30 #define PWM45THRES_FIXUP 0x34 +#define PWM_CK_26M_SEL_V3 0x74 #define PWM_CK_26M_SEL 0x210 #define PWM_CLK_DIV_MAX 7 @@ -36,7 +37,7 @@ struct pwm_mediatek_of_data { unsigned int num_pwms; bool pwm45_fixup; - bool has_ck_26m_sel; + u16 pwm_ck_26m_sel_reg; const unsigned int *reg_offset; }; @@ -64,6 +65,11 @@ static const unsigned int mtk_pwm_reg_offset_v2[] = { 0x0080, 0x00c0, 0x0100, 0x0140, 0x0180, 0x01c0, 0x0200, 0x0240 }; +/* PWM IP Version 3.0.2 */ +static const unsigned int mtk_pwm_reg_offset_v3[] = { + 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, 0x0800 +}; + static inline struct pwm_mediatek_chip * to_pwm_mediatek_chip(struct pwm_chip *chip) { @@ -130,12 +136,14 @@ static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm, return ret; clk_rate = clk_get_rate(pc->clk_pwms[pwm->hwpwm]); - if (!clk_rate) - return -EINVAL; + if (!clk_rate) { + ret = -EINVAL; + goto out; + } /* Make sure we use the bus clock and not the 26MHz clock */ - if (pc->soc->has_ck_26m_sel) - writel(0, pc->regs + PWM_CK_26M_SEL); + if (pc->soc->pwm_ck_26m_sel_reg) + writel(0, pc->regs + pc->soc->pwm_ck_26m_sel_reg); /* Using resolution in picosecond gets accuracy higher */ resolution = (u64)NSEC_PER_SEC * 1000; @@ -150,9 +158,9 @@ static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm, } if (clkdiv > PWM_CLK_DIV_MAX) { - pwm_mediatek_clk_disable(chip, pwm); dev_err(pwmchip_parent(chip), "period of %d ns not supported\n", period_ns); - return -EINVAL; + ret = -EINVAL; + goto out; } if (pc->soc->pwm45_fixup && pwm->hwpwm > 2) { @@ -169,9 +177,10 @@ static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm, pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, cnt_period); pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, cnt_duty); +out: pwm_mediatek_clk_disable(chip, pwm); - return 0; + return ret; } static int pwm_mediatek_enable(struct pwm_chip *chip, struct pwm_device *pwm) @@ -291,90 +300,92 @@ static int pwm_mediatek_probe(struct platform_device *pdev) static const struct pwm_mediatek_of_data mt2712_pwm_data = { .num_pwms = 8, .pwm45_fixup = false, - .has_ck_26m_sel = false, .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt6795_pwm_data = { .num_pwms = 7, .pwm45_fixup = false, - .has_ck_26m_sel = false, .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt7622_pwm_data = { .num_pwms = 6, .pwm45_fixup = false, - .has_ck_26m_sel = true, + .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL, .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt7623_pwm_data = { .num_pwms = 5, .pwm45_fixup = true, - .has_ck_26m_sel = false, .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt7628_pwm_data = { .num_pwms = 4, .pwm45_fixup = true, - .has_ck_26m_sel = false, .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt7629_pwm_data = { .num_pwms = 1, .pwm45_fixup = false, - .has_ck_26m_sel = false, .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt7981_pwm_data = { .num_pwms = 3, .pwm45_fixup = false, - .has_ck_26m_sel = true, + .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL, .reg_offset = mtk_pwm_reg_offset_v2, }; static const struct pwm_mediatek_of_data mt7986_pwm_data = { .num_pwms = 2, .pwm45_fixup = false, - .has_ck_26m_sel = true, + .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL, .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt7988_pwm_data = { .num_pwms = 8, .pwm45_fixup = false, - .has_ck_26m_sel = false, .reg_offset = mtk_pwm_reg_offset_v2, }; static const struct pwm_mediatek_of_data mt8183_pwm_data = { .num_pwms = 4, .pwm45_fixup = false, - .has_ck_26m_sel = true, + .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL, .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt8365_pwm_data = { .num_pwms = 3, .pwm45_fixup = false, - .has_ck_26m_sel = true, + .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL, .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt8516_pwm_data = { .num_pwms = 5, .pwm45_fixup = false, - .has_ck_26m_sel = true, + .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL, .reg_offset = mtk_pwm_reg_offset_v1, }; +static const struct pwm_mediatek_of_data mt6991_pwm_data = { + .num_pwms = 4, + .pwm45_fixup = false, + .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL_V3, + .reg_offset = mtk_pwm_reg_offset_v3, +}; + static const struct of_device_id pwm_mediatek_of_match[] = { { .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data }, { .compatible = "mediatek,mt6795-pwm", .data = &mt6795_pwm_data }, + { .compatible = "mediatek,mt6991-pwm", .data = &mt6991_pwm_data }, { .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data }, { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data }, { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data }, |