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