1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2015 MediaTek Inc.
6 #include "mtk_mipi_tx.h"
8 inline struct mtk_mipi_tx
*mtk_mipi_tx_from_clk_hw(struct clk_hw
*hw
)
10 return container_of(hw
, struct mtk_mipi_tx
, pll_hw
);
13 void mtk_mipi_tx_clear_bits(struct mtk_mipi_tx
*mipi_tx
, u32 offset
,
16 u32 temp
= readl(mipi_tx
->regs
+ offset
);
18 writel(temp
& ~bits
, mipi_tx
->regs
+ offset
);
21 void mtk_mipi_tx_set_bits(struct mtk_mipi_tx
*mipi_tx
, u32 offset
,
24 u32 temp
= readl(mipi_tx
->regs
+ offset
);
26 writel(temp
| bits
, mipi_tx
->regs
+ offset
);
29 void mtk_mipi_tx_update_bits(struct mtk_mipi_tx
*mipi_tx
, u32 offset
,
32 u32 temp
= readl(mipi_tx
->regs
+ offset
);
34 writel((temp
& ~mask
) | (data
& mask
), mipi_tx
->regs
+ offset
);
37 int mtk_mipi_tx_pll_set_rate(struct clk_hw
*hw
, unsigned long rate
,
38 unsigned long parent_rate
)
40 struct mtk_mipi_tx
*mipi_tx
= mtk_mipi_tx_from_clk_hw(hw
);
42 dev_dbg(mipi_tx
->dev
, "set rate: %lu Hz\n", rate
);
44 mipi_tx
->data_rate
= rate
;
49 unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw
*hw
,
50 unsigned long parent_rate
)
52 struct mtk_mipi_tx
*mipi_tx
= mtk_mipi_tx_from_clk_hw(hw
);
54 return mipi_tx
->data_rate
;
57 static int mtk_mipi_tx_power_on(struct phy
*phy
)
59 struct mtk_mipi_tx
*mipi_tx
= phy_get_drvdata(phy
);
62 /* Power up core and enable PLL */
63 ret
= clk_prepare_enable(mipi_tx
->pll
);
67 /* Enable DSI Lane LDO outputs, disable pad tie low */
68 mipi_tx
->driver_data
->mipi_tx_enable_signal(phy
);
72 static int mtk_mipi_tx_power_off(struct phy
*phy
)
74 struct mtk_mipi_tx
*mipi_tx
= phy_get_drvdata(phy
);
76 /* Enable pad tie low, disable DSI Lane LDO outputs */
77 mipi_tx
->driver_data
->mipi_tx_disable_signal(phy
);
79 /* Disable PLL and power down core */
80 clk_disable_unprepare(mipi_tx
->pll
);
85 static const struct phy_ops mtk_mipi_tx_ops
= {
86 .power_on
= mtk_mipi_tx_power_on
,
87 .power_off
= mtk_mipi_tx_power_off
,
91 static int mtk_mipi_tx_probe(struct platform_device
*pdev
)
93 struct device
*dev
= &pdev
->dev
;
94 struct mtk_mipi_tx
*mipi_tx
;
96 const char *ref_clk_name
;
98 struct clk_init_data clk_init
= {
100 .parent_names
= (const char * const *)&ref_clk_name
,
101 .flags
= CLK_SET_RATE_GATE
,
104 struct phy_provider
*phy_provider
;
107 mipi_tx
= devm_kzalloc(dev
, sizeof(*mipi_tx
), GFP_KERNEL
);
111 mipi_tx
->driver_data
= of_device_get_match_data(dev
);
113 mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
114 mipi_tx
->regs
= devm_ioremap_resource(dev
, mem
);
115 if (IS_ERR(mipi_tx
->regs
)) {
116 ret
= PTR_ERR(mipi_tx
->regs
);
117 dev_err(dev
, "Failed to get memory resource: %d\n", ret
);
121 ref_clk
= devm_clk_get(dev
, NULL
);
122 if (IS_ERR(ref_clk
)) {
123 ret
= PTR_ERR(ref_clk
);
124 dev_err(dev
, "Failed to get reference clock: %d\n", ret
);
128 ref_clk_name
= __clk_get_name(ref_clk
);
130 ret
= of_property_read_string(dev
->of_node
, "clock-output-names",
133 dev_err(dev
, "Failed to read clock-output-names: %d\n", ret
);
137 clk_init
.ops
= mipi_tx
->driver_data
->mipi_tx_clk_ops
;
139 mipi_tx
->pll_hw
.init
= &clk_init
;
140 mipi_tx
->pll
= devm_clk_register(dev
, &mipi_tx
->pll_hw
);
141 if (IS_ERR(mipi_tx
->pll
)) {
142 ret
= PTR_ERR(mipi_tx
->pll
);
143 dev_err(dev
, "Failed to register PLL: %d\n", ret
);
147 phy
= devm_phy_create(dev
, NULL
, &mtk_mipi_tx_ops
);
150 dev_err(dev
, "Failed to create MIPI D-PHY: %d\n", ret
);
153 phy_set_drvdata(phy
, mipi_tx
);
155 phy_provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
156 if (IS_ERR(phy_provider
)) {
157 ret
= PTR_ERR(phy_provider
);
163 return of_clk_add_provider(dev
->of_node
, of_clk_src_simple_get
,
167 static int mtk_mipi_tx_remove(struct platform_device
*pdev
)
169 of_clk_del_provider(pdev
->dev
.of_node
);
173 static const struct of_device_id mtk_mipi_tx_match
[] = {
174 { .compatible
= "mediatek,mt2701-mipi-tx",
175 .data
= &mt2701_mipitx_data
},
176 { .compatible
= "mediatek,mt8173-mipi-tx",
177 .data
= &mt8173_mipitx_data
},
178 { .compatible
= "mediatek,mt8183-mipi-tx",
179 .data
= &mt8183_mipitx_data
},
183 struct platform_driver mtk_mipi_tx_driver
= {
184 .probe
= mtk_mipi_tx_probe
,
185 .remove
= mtk_mipi_tx_remove
,
187 .name
= "mediatek-mipi-tx",
188 .of_match_table
= mtk_mipi_tx_match
,