228 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2018 MediaTek Inc.4 * Author: Chunhui Dai <chunhui.dai@mediatek.com>5 */6 7#include "phy-mtk-hdmi.h"8#include "phy-mtk-io.h"9 10#define HDMI_CON0 0x0011#define RG_HDMITX_DRV_IBIAS_MASK GENMASK(5, 0)12#define RG_HDMITX_EN_SER_MASK GENMASK(15, 12)13#define RG_HDMITX_EN_SLDO_MASK GENMASK(19, 16)14#define RG_HDMITX_EN_PRED_MASK GENMASK(23, 20)15#define RG_HDMITX_EN_IMP_MASK GENMASK(27, 24)16#define RG_HDMITX_EN_DRV_MASK GENMASK(31, 28)17 18#define HDMI_CON1 0x0419#define RG_HDMITX_PRED_IBIAS_MASK GENMASK(21, 18)20#define RG_HDMITX_PRED_IMP BIT(22)21#define RG_HDMITX_DRV_IMP_MASK GENMASK(31, 26)22 23#define HDMI_CON2 0x0824#define RG_HDMITX_EN_TX_CKLDO BIT(0)25#define RG_HDMITX_EN_TX_POSDIV BIT(1)26#define RG_HDMITX_TX_POSDIV_MASK GENMASK(4, 3)27#define RG_HDMITX_EN_MBIAS BIT(6)28#define RG_HDMITX_MBIAS_LPF_EN BIT(7)29 30#define HDMI_CON4 0x1031#define RG_HDMITX_RESERVE_MASK GENMASK(31, 0)32 33#define HDMI_CON6 0x1834#define RG_HTPLL_BR_MASK GENMASK(1, 0)35#define RG_HTPLL_BC_MASK GENMASK(3, 2)36#define RG_HTPLL_BP_MASK GENMASK(7, 4)37#define RG_HTPLL_IR_MASK GENMASK(11, 8)38#define RG_HTPLL_IC_MASK GENMASK(15, 12)39#define RG_HTPLL_POSDIV_MASK GENMASK(17, 16)40#define RG_HTPLL_PREDIV_MASK GENMASK(19, 18)41#define RG_HTPLL_FBKSEL_MASK GENMASK(21, 20)42#define RG_HTPLL_RLH_EN BIT(22)43#define RG_HTPLL_FBKDIV_MASK GENMASK(30, 24)44#define RG_HTPLL_EN BIT(31)45 46#define HDMI_CON7 0x1c47#define RG_HTPLL_AUTOK_EN BIT(23)48#define RG_HTPLL_DIVEN_MASK GENMASK(30, 28)49 50static int mtk_hdmi_pll_prepare(struct clk_hw *hw)51{52 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);53 void __iomem *base = hdmi_phy->regs;54 55 mtk_phy_set_bits(base + HDMI_CON7, RG_HTPLL_AUTOK_EN);56 mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_RLH_EN);57 mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);58 mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_MBIAS);59 usleep_range(80, 100);60 mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_EN);61 mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);62 mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);63 usleep_range(80, 100);64 mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);65 mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_SER_MASK);66 mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_PRED_MASK);67 mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_DRV_MASK);68 usleep_range(80, 100);69 return 0;70}71 72static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)73{74 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);75 void __iomem *base = hdmi_phy->regs;76 77 mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_DRV_MASK);78 mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_PRED_MASK);79 mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_SER_MASK);80 mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);81 usleep_range(80, 100);82 mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);83 mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);84 mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_EN);85 usleep_range(80, 100);86 mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_EN_MBIAS);87 mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);88 mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_RLH_EN);89 mtk_phy_clear_bits(base + HDMI_CON7, RG_HTPLL_AUTOK_EN);90 usleep_range(80, 100);91}92 93static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,94 unsigned long *parent_rate)95{96 return rate;97}98 99static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,100 unsigned long parent_rate)101{102 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);103 void __iomem *base = hdmi_phy->regs;104 u32 pos_div;105 106 if (rate <= 64000000)107 pos_div = 3;108 else if (rate <= 128000000)109 pos_div = 2;110 else111 pos_div = 1;112 113 mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_PREDIV_MASK);114 mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);115 mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);116 mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_IC_MASK, 0x1);117 mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_IR_MASK, 0x1);118 mtk_phy_update_field(base + HDMI_CON2, RG_HDMITX_TX_POSDIV_MASK, pos_div);119 mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_FBKSEL_MASK, 1);120 mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_FBKDIV_MASK, 19);121 mtk_phy_update_field(base + HDMI_CON7, RG_HTPLL_DIVEN_MASK, 0x2);122 mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_BP_MASK, 0xc);123 mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_BC_MASK, 0x2);124 mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_BR_MASK, 0x1);125 126 mtk_phy_clear_bits(base + HDMI_CON1, RG_HDMITX_PRED_IMP);127 mtk_phy_update_field(base + HDMI_CON1, RG_HDMITX_PRED_IBIAS_MASK, 0x3);128 mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_IMP_MASK);129 mtk_phy_update_field(base + HDMI_CON1, RG_HDMITX_DRV_IMP_MASK, 0x28);130 mtk_phy_update_field(base + HDMI_CON4, RG_HDMITX_RESERVE_MASK, 0x28);131 mtk_phy_update_field(base + HDMI_CON0, RG_HDMITX_DRV_IBIAS_MASK, 0xa);132 return 0;133}134 135static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,136 unsigned long parent_rate)137{138 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);139 unsigned long out_rate, val;140 u32 tmp;141 142 tmp = readl(hdmi_phy->regs + HDMI_CON6);143 val = FIELD_GET(RG_HTPLL_PREDIV_MASK, tmp);144 switch (val) {145 case 0x00:146 out_rate = parent_rate;147 break;148 case 0x01:149 out_rate = parent_rate / 2;150 break;151 default:152 out_rate = parent_rate / 4;153 break;154 }155 156 val = FIELD_GET(RG_HTPLL_FBKDIV_MASK, tmp);157 out_rate *= (val + 1) * 2;158 159 tmp = readl(hdmi_phy->regs + HDMI_CON2);160 val = FIELD_GET(RG_HDMITX_TX_POSDIV_MASK, tmp);161 out_rate >>= val;162 163 if (tmp & RG_HDMITX_EN_TX_POSDIV)164 out_rate /= 5;165 166 return out_rate;167}168 169static const struct clk_ops mtk_hdmi_phy_pll_ops = {170 .prepare = mtk_hdmi_pll_prepare,171 .unprepare = mtk_hdmi_pll_unprepare,172 .set_rate = mtk_hdmi_pll_set_rate,173 .round_rate = mtk_hdmi_pll_round_rate,174 .recalc_rate = mtk_hdmi_pll_recalc_rate,175};176 177static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)178{179 void __iomem *base = hdmi_phy->regs;180 181 mtk_phy_set_bits(base + HDMI_CON7, RG_HTPLL_AUTOK_EN);182 mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_RLH_EN);183 mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);184 mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_MBIAS);185 usleep_range(80, 100);186 mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_EN);187 mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);188 mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);189 usleep_range(80, 100);190 mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);191 mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_SER_MASK);192 mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_PRED_MASK);193 mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_DRV_MASK);194 usleep_range(80, 100);195}196 197static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)198{199 void __iomem *base = hdmi_phy->regs;200 201 mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_DRV_MASK);202 mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_PRED_MASK);203 mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_SER_MASK);204 mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);205 usleep_range(80, 100);206 mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);207 mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);208 mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_EN);209 usleep_range(80, 100);210 mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_EN_MBIAS);211 mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);212 mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_RLH_EN);213 mtk_phy_clear_bits(base + HDMI_CON7, RG_HTPLL_AUTOK_EN);214 usleep_range(80, 100);215}216 217struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = {218 .flags = CLK_SET_RATE_GATE,219 .pll_default_off = true,220 .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,221 .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,222 .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,223};224 225MODULE_AUTHOR("Chunhui Dai <chunhui.dai@mediatek.com>");226MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");227MODULE_LICENSE("GPL v2");228