Lines Matching +full:mipi +full:- +full:phy
1 // SPDX-License-Identifier: GPL-2.0
3 * Meson AXG MIPI DPHY driver
20 #include <linux/phy/phy.h>
23 /* [31] soft reset for the phy.
30 * [25] mipi dsi pll clock selection.
32 * [12] mipi HSbyteclk enable.
33 * [11] mipi divider clk selection.
34 * 1: select the mipi DDRCLKHS from clock divider.
36 * [10] mipi clock divider control.
38 * [9] mipi divider output enable.
39 * [8] mipi divider counter enable.
48 * [0] enalbe the MIPI DPHY TxDDRClk.
130 /* wait time to MIPI DIS analog ready. */
172 struct phy *analog;
183 static int phy_meson_axg_mipi_dphy_init(struct phy *phy) in phy_meson_axg_mipi_dphy_init() argument
185 struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy); in phy_meson_axg_mipi_dphy_init()
188 ret = phy_init(priv->analog); in phy_meson_axg_mipi_dphy_init()
192 ret = reset_control_reset(priv->reset); in phy_meson_axg_mipi_dphy_init()
199 static int phy_meson_axg_mipi_dphy_configure(struct phy *phy, in phy_meson_axg_mipi_dphy_configure() argument
202 struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy); in phy_meson_axg_mipi_dphy_configure()
205 ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy); in phy_meson_axg_mipi_dphy_configure()
209 ret = phy_configure(priv->analog, opts); in phy_meson_axg_mipi_dphy_configure()
213 memcpy(&priv->config, opts, sizeof(priv->config)); in phy_meson_axg_mipi_dphy_configure()
218 static int phy_meson_axg_mipi_dphy_power_on(struct phy *phy) in phy_meson_axg_mipi_dphy_power_on() argument
220 struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy); in phy_meson_axg_mipi_dphy_power_on()
224 ret = phy_power_on(priv->analog); in phy_meson_axg_mipi_dphy_power_on()
228 /* enable phy clock */ in phy_meson_axg_mipi_dphy_power_on()
229 regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, 0x1); in phy_meson_axg_mipi_dphy_power_on()
230 regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, in phy_meson_axg_mipi_dphy_power_on()
236 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(9), BIT(9)); in phy_meson_axg_mipi_dphy_power_on()
239 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(12), BIT(12)); in phy_meson_axg_mipi_dphy_power_on()
240 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), BIT(31)); in phy_meson_axg_mipi_dphy_power_on()
241 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), 0); in phy_meson_axg_mipi_dphy_power_on()
244 temp = (1000000 * 100) / (priv->config.hs_clk_rate / 1000); in phy_meson_axg_mipi_dphy_power_on()
247 regmap_write(priv->regmap, MIPI_DSI_CLK_TIM, in phy_meson_axg_mipi_dphy_power_on()
248 DIV_ROUND_UP(priv->config.clk_trail, temp) | in phy_meson_axg_mipi_dphy_power_on()
249 (DIV_ROUND_UP(priv->config.clk_post + in phy_meson_axg_mipi_dphy_power_on()
250 priv->config.hs_trail, temp) << 8) | in phy_meson_axg_mipi_dphy_power_on()
251 (DIV_ROUND_UP(priv->config.clk_zero, temp) << 16) | in phy_meson_axg_mipi_dphy_power_on()
252 (DIV_ROUND_UP(priv->config.clk_prepare, temp) << 24)); in phy_meson_axg_mipi_dphy_power_on()
253 regmap_write(priv->regmap, MIPI_DSI_CLK_TIM1, in phy_meson_axg_mipi_dphy_power_on()
254 DIV_ROUND_UP(priv->config.clk_pre, BITS_PER_BYTE)); in phy_meson_axg_mipi_dphy_power_on()
256 regmap_write(priv->regmap, MIPI_DSI_HS_TIM, in phy_meson_axg_mipi_dphy_power_on()
257 DIV_ROUND_UP(priv->config.hs_exit, temp) | in phy_meson_axg_mipi_dphy_power_on()
258 (DIV_ROUND_UP(priv->config.hs_trail, temp) << 8) | in phy_meson_axg_mipi_dphy_power_on()
259 (DIV_ROUND_UP(priv->config.hs_zero, temp) << 16) | in phy_meson_axg_mipi_dphy_power_on()
260 (DIV_ROUND_UP(priv->config.hs_prepare, temp) << 24)); in phy_meson_axg_mipi_dphy_power_on()
262 regmap_write(priv->regmap, MIPI_DSI_LP_TIM, in phy_meson_axg_mipi_dphy_power_on()
263 DIV_ROUND_UP(priv->config.lpx, temp) | in phy_meson_axg_mipi_dphy_power_on()
264 (DIV_ROUND_UP(priv->config.ta_sure, temp) << 8) | in phy_meson_axg_mipi_dphy_power_on()
265 (DIV_ROUND_UP(priv->config.ta_go, temp) << 16) | in phy_meson_axg_mipi_dphy_power_on()
266 (DIV_ROUND_UP(priv->config.ta_get, temp) << 24)); in phy_meson_axg_mipi_dphy_power_on()
268 regmap_write(priv->regmap, MIPI_DSI_ANA_UP_TIM, 0x0100); in phy_meson_axg_mipi_dphy_power_on()
269 regmap_write(priv->regmap, MIPI_DSI_INIT_TIM, in phy_meson_axg_mipi_dphy_power_on()
270 DIV_ROUND_UP(priv->config.init * NSEC_PER_MSEC, temp)); in phy_meson_axg_mipi_dphy_power_on()
271 regmap_write(priv->regmap, MIPI_DSI_WAKEUP_TIM, in phy_meson_axg_mipi_dphy_power_on()
272 DIV_ROUND_UP(priv->config.wakeup * NSEC_PER_MSEC, temp)); in phy_meson_axg_mipi_dphy_power_on()
273 regmap_write(priv->regmap, MIPI_DSI_LPOK_TIM, 0x7C); in phy_meson_axg_mipi_dphy_power_on()
274 regmap_write(priv->regmap, MIPI_DSI_ULPS_CHECK, 0x927C); in phy_meson_axg_mipi_dphy_power_on()
275 regmap_write(priv->regmap, MIPI_DSI_LP_WCHDOG, 0x1000); in phy_meson_axg_mipi_dphy_power_on()
276 regmap_write(priv->regmap, MIPI_DSI_TURN_WCHDOG, 0x1000); in phy_meson_axg_mipi_dphy_power_on()
279 switch (priv->config.lanes) { in phy_meson_axg_mipi_dphy_power_on()
281 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xe); in phy_meson_axg_mipi_dphy_power_on()
284 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xc); in phy_meson_axg_mipi_dphy_power_on()
287 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0x8); in phy_meson_axg_mipi_dphy_power_on()
291 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0); in phy_meson_axg_mipi_dphy_power_on()
296 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(1), BIT(1)); in phy_meson_axg_mipi_dphy_power_on()
301 static int phy_meson_axg_mipi_dphy_power_off(struct phy *phy) in phy_meson_axg_mipi_dphy_power_off() argument
303 struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy); in phy_meson_axg_mipi_dphy_power_off()
305 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xf); in phy_meson_axg_mipi_dphy_power_off()
306 regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31)); in phy_meson_axg_mipi_dphy_power_off()
308 phy_power_off(priv->analog); in phy_meson_axg_mipi_dphy_power_off()
313 static int phy_meson_axg_mipi_dphy_exit(struct phy *phy) in phy_meson_axg_mipi_dphy_exit() argument
315 struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy); in phy_meson_axg_mipi_dphy_exit()
318 ret = phy_exit(priv->analog); in phy_meson_axg_mipi_dphy_exit()
322 return reset_control_reset(priv->reset); in phy_meson_axg_mipi_dphy_exit()
336 struct device *dev = &pdev->dev; in phy_meson_axg_mipi_dphy_probe()
339 struct phy *phy; in phy_meson_axg_mipi_dphy_probe() local
345 return -ENOMEM; in phy_meson_axg_mipi_dphy_probe()
347 priv->dev = dev; in phy_meson_axg_mipi_dphy_probe()
354 priv->regmap = devm_regmap_init_mmio(dev, base, in phy_meson_axg_mipi_dphy_probe()
356 if (IS_ERR(priv->regmap)) in phy_meson_axg_mipi_dphy_probe()
357 return PTR_ERR(priv->regmap); in phy_meson_axg_mipi_dphy_probe()
359 priv->clk = devm_clk_get(dev, "pclk"); in phy_meson_axg_mipi_dphy_probe()
360 if (IS_ERR(priv->clk)) in phy_meson_axg_mipi_dphy_probe()
361 return PTR_ERR(priv->clk); in phy_meson_axg_mipi_dphy_probe()
363 priv->reset = devm_reset_control_get(dev, "phy"); in phy_meson_axg_mipi_dphy_probe()
364 if (IS_ERR(priv->reset)) in phy_meson_axg_mipi_dphy_probe()
365 return PTR_ERR(priv->reset); in phy_meson_axg_mipi_dphy_probe()
367 priv->analog = devm_phy_get(dev, "analog"); in phy_meson_axg_mipi_dphy_probe()
368 if (IS_ERR(priv->analog)) in phy_meson_axg_mipi_dphy_probe()
369 return PTR_ERR(priv->analog); in phy_meson_axg_mipi_dphy_probe()
371 ret = clk_prepare_enable(priv->clk); in phy_meson_axg_mipi_dphy_probe()
375 ret = reset_control_deassert(priv->reset); in phy_meson_axg_mipi_dphy_probe()
379 phy = devm_phy_create(dev, NULL, &phy_meson_axg_mipi_dphy_ops); in phy_meson_axg_mipi_dphy_probe()
380 if (IS_ERR(phy)) { in phy_meson_axg_mipi_dphy_probe()
381 ret = PTR_ERR(phy); in phy_meson_axg_mipi_dphy_probe()
382 if (ret != -EPROBE_DEFER) in phy_meson_axg_mipi_dphy_probe()
383 dev_err(dev, "failed to create PHY\n"); in phy_meson_axg_mipi_dphy_probe()
388 phy_set_drvdata(phy, priv); in phy_meson_axg_mipi_dphy_probe()
396 { .compatible = "amlogic,axg-mipi-dphy", },
404 .name = "phy-meson-axg-mipi-dphy",
411 MODULE_DESCRIPTION("Meson AXG MIPI DPHY driver");