drm/i915: use linux/stddef.h due to "isystem: trim/fixup stdarg.h and other headers"
[linux-2.6-microblaze.git] / drivers / phy / mediatek / phy-mtk-mipi-dsi.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2015 MediaTek Inc.
4  */
5
6 #include "phy-mtk-mipi-dsi.h"
7
8 inline struct mtk_mipi_tx *mtk_mipi_tx_from_clk_hw(struct clk_hw *hw)
9 {
10         return container_of(hw, struct mtk_mipi_tx, pll_hw);
11 }
12
13 void mtk_mipi_tx_clear_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
14                             u32 bits)
15 {
16         u32 temp = readl(mipi_tx->regs + offset);
17
18         writel(temp & ~bits, mipi_tx->regs + offset);
19 }
20
21 void mtk_mipi_tx_set_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
22                           u32 bits)
23 {
24         u32 temp = readl(mipi_tx->regs + offset);
25
26         writel(temp | bits, mipi_tx->regs + offset);
27 }
28
29 void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
30                              u32 mask, u32 data)
31 {
32         u32 temp = readl(mipi_tx->regs + offset);
33
34         writel((temp & ~mask) | (data & mask), mipi_tx->regs + offset);
35 }
36
37 int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
38                              unsigned long parent_rate)
39 {
40         struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
41
42         dev_dbg(mipi_tx->dev, "set rate: %lu Hz\n", rate);
43
44         mipi_tx->data_rate = rate;
45
46         return 0;
47 }
48
49 unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw,
50                                           unsigned long parent_rate)
51 {
52         struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
53
54         return mipi_tx->data_rate;
55 }
56
57 static int mtk_mipi_tx_power_on(struct phy *phy)
58 {
59         struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
60         int ret;
61
62         /* Power up core and enable PLL */
63         ret = clk_prepare_enable(mipi_tx->pll);
64         if (ret < 0)
65                 return ret;
66
67         /* Enable DSI Lane LDO outputs, disable pad tie low */
68         mipi_tx->driver_data->mipi_tx_enable_signal(phy);
69         return 0;
70 }
71
72 static int mtk_mipi_tx_power_off(struct phy *phy)
73 {
74         struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
75
76         /* Enable pad tie low, disable DSI Lane LDO outputs */
77         mipi_tx->driver_data->mipi_tx_disable_signal(phy);
78
79         /* Disable PLL and power down core */
80         clk_disable_unprepare(mipi_tx->pll);
81
82         return 0;
83 }
84
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,
88         .owner = THIS_MODULE,
89 };
90
91 static void mtk_mipi_tx_get_calibration_datal(struct mtk_mipi_tx *mipi_tx)
92 {
93         struct nvmem_cell *cell;
94         size_t len;
95         u32 *buf;
96
97         cell = nvmem_cell_get(mipi_tx->dev, "calibration-data");
98         if (IS_ERR(cell)) {
99                 dev_info(mipi_tx->dev, "can't get nvmem_cell_get, ignore it\n");
100                 return;
101         }
102         buf = (u32 *)nvmem_cell_read(cell, &len);
103         nvmem_cell_put(cell);
104
105         if (IS_ERR(buf)) {
106                 dev_info(mipi_tx->dev, "can't get data, ignore it\n");
107                 return;
108         }
109
110         if (len < 3 * sizeof(u32)) {
111                 dev_info(mipi_tx->dev, "invalid calibration data\n");
112                 kfree(buf);
113                 return;
114         }
115
116         mipi_tx->rt_code[0] = ((buf[0] >> 6 & 0x1f) << 5) |
117                                (buf[0] >> 11 & 0x1f);
118         mipi_tx->rt_code[1] = ((buf[1] >> 27 & 0x1f) << 5) |
119                                (buf[0] >> 1 & 0x1f);
120         mipi_tx->rt_code[2] = ((buf[1] >> 17 & 0x1f) << 5) |
121                                (buf[1] >> 22 & 0x1f);
122         mipi_tx->rt_code[3] = ((buf[1] >> 7 & 0x1f) << 5) |
123                                (buf[1] >> 12 & 0x1f);
124         mipi_tx->rt_code[4] = ((buf[2] >> 27 & 0x1f) << 5) |
125                                (buf[1] >> 2 & 0x1f);
126         kfree(buf);
127 }
128
129 static int mtk_mipi_tx_probe(struct platform_device *pdev)
130 {
131         struct device *dev = &pdev->dev;
132         struct mtk_mipi_tx *mipi_tx;
133         struct resource *mem;
134         const char *ref_clk_name;
135         struct clk *ref_clk;
136         struct clk_init_data clk_init = {
137                 .num_parents = 1,
138                 .parent_names = (const char * const *)&ref_clk_name,
139                 .flags = CLK_SET_RATE_GATE,
140         };
141         struct phy *phy;
142         struct phy_provider *phy_provider;
143         int ret;
144
145         mipi_tx = devm_kzalloc(dev, sizeof(*mipi_tx), GFP_KERNEL);
146         if (!mipi_tx)
147                 return -ENOMEM;
148
149         mipi_tx->driver_data = of_device_get_match_data(dev);
150
151         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
152         mipi_tx->regs = devm_ioremap_resource(dev, mem);
153         if (IS_ERR(mipi_tx->regs)) {
154                 return PTR_ERR(mipi_tx->regs);
155         }
156
157         ref_clk = devm_clk_get(dev, NULL);
158         if (IS_ERR(ref_clk)) {
159                 ret = PTR_ERR(ref_clk);
160                 dev_err(dev, "Failed to get reference clock: %d\n", ret);
161                 return ret;
162         }
163
164         ret = of_property_read_u32(dev->of_node, "drive-strength-microamp",
165                                    &mipi_tx->mipitx_drive);
166         /* If can't get the "mipi_tx->mipitx_drive", set it default 0x8 */
167         if (ret < 0)
168                 mipi_tx->mipitx_drive = 4600;
169
170         /* check the mipitx_drive valid */
171         if (mipi_tx->mipitx_drive > 6000 || mipi_tx->mipitx_drive < 3000) {
172                 dev_warn(dev, "drive-strength-microamp is invalid %d, not in 3000 ~ 6000\n",
173                          mipi_tx->mipitx_drive);
174                 mipi_tx->mipitx_drive = clamp_val(mipi_tx->mipitx_drive, 3000,
175                                                   6000);
176         }
177
178         ref_clk_name = __clk_get_name(ref_clk);
179
180         ret = of_property_read_string(dev->of_node, "clock-output-names",
181                                       &clk_init.name);
182         if (ret < 0) {
183                 dev_err(dev, "Failed to read clock-output-names: %d\n", ret);
184                 return ret;
185         }
186
187         clk_init.ops = mipi_tx->driver_data->mipi_tx_clk_ops;
188
189         mipi_tx->pll_hw.init = &clk_init;
190         mipi_tx->pll = devm_clk_register(dev, &mipi_tx->pll_hw);
191         if (IS_ERR(mipi_tx->pll)) {
192                 ret = PTR_ERR(mipi_tx->pll);
193                 dev_err(dev, "Failed to register PLL: %d\n", ret);
194                 return ret;
195         }
196
197         phy = devm_phy_create(dev, NULL, &mtk_mipi_tx_ops);
198         if (IS_ERR(phy)) {
199                 ret = PTR_ERR(phy);
200                 dev_err(dev, "Failed to create MIPI D-PHY: %d\n", ret);
201                 return ret;
202         }
203         phy_set_drvdata(phy, mipi_tx);
204
205         phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
206         if (IS_ERR(phy_provider)) {
207                 ret = PTR_ERR(phy_provider);
208                 return ret;
209         }
210
211         mipi_tx->dev = dev;
212
213         mtk_mipi_tx_get_calibration_datal(mipi_tx);
214
215         return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
216                                    mipi_tx->pll);
217 }
218
219 static int mtk_mipi_tx_remove(struct platform_device *pdev)
220 {
221         of_clk_del_provider(pdev->dev.of_node);
222         return 0;
223 }
224
225 static const struct of_device_id mtk_mipi_tx_match[] = {
226         { .compatible = "mediatek,mt2701-mipi-tx",
227           .data = &mt2701_mipitx_data },
228         { .compatible = "mediatek,mt8173-mipi-tx",
229           .data = &mt8173_mipitx_data },
230         { .compatible = "mediatek,mt8183-mipi-tx",
231           .data = &mt8183_mipitx_data },
232         { },
233 };
234 MODULE_DEVICE_TABLE(of, mtk_mipi_tx_match);
235
236 static struct platform_driver mtk_mipi_tx_driver = {
237         .probe = mtk_mipi_tx_probe,
238         .remove = mtk_mipi_tx_remove,
239         .driver = {
240                 .name = "mediatek-mipi-tx",
241                 .of_match_table = mtk_mipi_tx_match,
242         },
243 };
244 module_platform_driver(mtk_mipi_tx_driver);
245
246 MODULE_DESCRIPTION("MediaTek MIPI TX Driver");
247 MODULE_LICENSE("GPL v2");