brintos

brintos / linux-shallow public Read only

0
0
Text · 7.8 KiB · e51b2d1 Raw
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