• Home
  • Raw
  • Download

Lines Matching +full:dphy +full:- +full:cfg

1 // SPDX-License-Identifier: GPL-2.0+
8 #include <linux/clk-provider.h>
19 /* DPHY registers */
47 ((x) < 32) ? 0xe0 | ((x) - 16) : \
48 ((x) < 64) ? 0xc0 | ((x) - 32) : \
49 ((x) < 128) ? 0x80 | ((x) - 64) : \
50 ((x) - 128))
51 #define CN(x) (((x) == 1) ? 0x1f : (((CN_BUF) >> ((x) - 1)) & 0x1f))
52 #define CO(x) ((CO_BUF) >> (8 - (x)) & 0x03)
81 /* DPHY PLL parameters */
85 /* DPHY register values */
96 struct mixel_dphy_cfg cfg; member
107 .name = "mipi-dphy",
115 ret = regmap_write(priv->regmap, reg, value); in phy_write()
117 dev_err(&phy->dev, "Failed to write DPHY reg %d: %d\n", reg, in phy_write()
146 c = a - (b * whole); in get_best_ratio()
156 struct mixel_dphy_cfg *cfg) in mixel_dphy_config_from_opts() argument
158 struct mixel_dphy_priv *priv = dev_get_drvdata(phy->dev.parent); in mixel_dphy_config_from_opts()
159 unsigned long ref_clk = clk_get_rate(priv->phy_ref_clk); in mixel_dphy_config_from_opts()
165 if (dphy_opts->hs_clk_rate > DATA_RATE_MAX_SPEED || in mixel_dphy_config_from_opts()
166 dphy_opts->hs_clk_rate < DATA_RATE_MIN_SPEED) in mixel_dphy_config_from_opts()
167 return -EINVAL; in mixel_dphy_config_from_opts()
169 numerator = dphy_opts->hs_clk_rate; in mixel_dphy_config_from_opts()
173 dev_err(&phy->dev, "Invalid %d/%d for %ld/%ld\n", in mixel_dphy_config_from_opts()
175 dphy_opts->hs_clk_rate, ref_clk); in mixel_dphy_config_from_opts()
176 return -EINVAL; in mixel_dphy_config_from_opts()
191 cfg->cn = denominator >> i; in mixel_dphy_config_from_opts()
192 cfg->co = 1 << i; in mixel_dphy_config_from_opts()
193 cfg->cm = numerator; in mixel_dphy_config_from_opts()
195 if (cfg->cm < 16 || cfg->cm > 255 || in mixel_dphy_config_from_opts()
196 cfg->cn < 1 || cfg->cn > 32 || in mixel_dphy_config_from_opts()
197 cfg->co < 1 || cfg->co > 8) { in mixel_dphy_config_from_opts()
198 dev_err(&phy->dev, "Invalid CM/CN/CO values: %u/%u/%u\n", in mixel_dphy_config_from_opts()
199 cfg->cm, cfg->cn, cfg->co); in mixel_dphy_config_from_opts()
200 dev_err(&phy->dev, "for hs_clk/ref_clk=%ld/%ld ~ %d/%d\n", in mixel_dphy_config_from_opts()
201 dphy_opts->hs_clk_rate, ref_clk, in mixel_dphy_config_from_opts()
203 return -EINVAL; in mixel_dphy_config_from_opts()
206 dev_dbg(&phy->dev, "hs_clk/ref_clk=%ld/%ld ~ %d/%d\n", in mixel_dphy_config_from_opts()
207 dphy_opts->hs_clk_rate, ref_clk, numerator, denominator); in mixel_dphy_config_from_opts()
211 do_div(tmp, dphy_opts->lp_clk_rate); /* ps */ in mixel_dphy_config_from_opts()
213 return -EINVAL; in mixel_dphy_config_from_opts()
216 dev_dbg(&phy->dev, "LP clock %lu, period: %u ps\n", in mixel_dphy_config_from_opts()
217 dphy_opts->lp_clk_rate, lp_t); in mixel_dphy_config_from_opts()
220 if (2 * dphy_opts->hs_prepare > 5 * lp_t) { in mixel_dphy_config_from_opts()
221 dev_err(&phy->dev, in mixel_dphy_config_from_opts()
223 dphy_opts->hs_prepare, lp_t); in mixel_dphy_config_from_opts()
224 return -EINVAL; in mixel_dphy_config_from_opts()
227 if (dphy_opts->hs_prepare < lp_t) { in mixel_dphy_config_from_opts()
230 tmp = 2 * (dphy_opts->hs_prepare - lp_t); in mixel_dphy_config_from_opts()
234 cfg->m_prg_hs_prepare = n; in mixel_dphy_config_from_opts()
237 if (2 * dphy_opts->clk_prepare > 3 * lp_t) { in mixel_dphy_config_from_opts()
238 dev_err(&phy->dev, in mixel_dphy_config_from_opts()
240 dphy_opts->clk_prepare, lp_t); in mixel_dphy_config_from_opts()
241 return -EINVAL; in mixel_dphy_config_from_opts()
244 cfg->mc_prg_hs_prepare = dphy_opts->clk_prepare > lp_t ? 1 : 0; in mixel_dphy_config_from_opts()
247 n = (144 * (dphy_opts->hs_clk_rate / 1000000) - 47500) / 10000; in mixel_dphy_config_from_opts()
248 cfg->m_prg_hs_zero = n < 1 ? 1 : n; in mixel_dphy_config_from_opts()
251 n = (34 * (dphy_opts->hs_clk_rate / 1000000) - 2500) / 1000; in mixel_dphy_config_from_opts()
252 cfg->mc_prg_hs_zero = n < 1 ? 1 : n; in mixel_dphy_config_from_opts()
255 n = (103 * (dphy_opts->hs_clk_rate / 1000000) + 10000) / 10000; in mixel_dphy_config_from_opts()
260 cfg->m_prg_hs_trail = n; in mixel_dphy_config_from_opts()
261 cfg->mc_prg_hs_trail = n; in mixel_dphy_config_from_opts()
264 if (dphy_opts->hs_clk_rate < MBPS(80)) in mixel_dphy_config_from_opts()
265 cfg->rxhs_settle = 0x0d; in mixel_dphy_config_from_opts()
266 else if (dphy_opts->hs_clk_rate < MBPS(90)) in mixel_dphy_config_from_opts()
267 cfg->rxhs_settle = 0x0c; in mixel_dphy_config_from_opts()
268 else if (dphy_opts->hs_clk_rate < MBPS(125)) in mixel_dphy_config_from_opts()
269 cfg->rxhs_settle = 0x0b; in mixel_dphy_config_from_opts()
270 else if (dphy_opts->hs_clk_rate < MBPS(150)) in mixel_dphy_config_from_opts()
271 cfg->rxhs_settle = 0x0a; in mixel_dphy_config_from_opts()
272 else if (dphy_opts->hs_clk_rate < MBPS(225)) in mixel_dphy_config_from_opts()
273 cfg->rxhs_settle = 0x09; in mixel_dphy_config_from_opts()
274 else if (dphy_opts->hs_clk_rate < MBPS(500)) in mixel_dphy_config_from_opts()
275 cfg->rxhs_settle = 0x08; in mixel_dphy_config_from_opts()
277 cfg->rxhs_settle = 0x07; in mixel_dphy_config_from_opts()
279 dev_dbg(&phy->dev, "phy_config: %u %u %u %u %u %u %u\n", in mixel_dphy_config_from_opts()
280 cfg->m_prg_hs_prepare, cfg->mc_prg_hs_prepare, in mixel_dphy_config_from_opts()
281 cfg->m_prg_hs_zero, cfg->mc_prg_hs_zero, in mixel_dphy_config_from_opts()
282 cfg->m_prg_hs_trail, cfg->mc_prg_hs_trail, in mixel_dphy_config_from_opts()
283 cfg->rxhs_settle); in mixel_dphy_config_from_opts()
292 phy_write(phy, priv->cfg.m_prg_hs_prepare, DPHY_M_PRG_HS_PREPARE); in mixel_phy_set_hs_timings()
293 phy_write(phy, priv->cfg.mc_prg_hs_prepare, DPHY_MC_PRG_HS_PREPARE); in mixel_phy_set_hs_timings()
294 phy_write(phy, priv->cfg.m_prg_hs_zero, DPHY_M_PRG_HS_ZERO); in mixel_phy_set_hs_timings()
295 phy_write(phy, priv->cfg.mc_prg_hs_zero, DPHY_MC_PRG_HS_ZERO); in mixel_phy_set_hs_timings()
296 phy_write(phy, priv->cfg.m_prg_hs_trail, DPHY_M_PRG_HS_TRAIL); in mixel_phy_set_hs_timings()
297 phy_write(phy, priv->cfg.mc_prg_hs_trail, DPHY_MC_PRG_HS_TRAIL); in mixel_phy_set_hs_timings()
298 phy_write(phy, priv->cfg.rxhs_settle, priv->devdata->reg_rxhs_settle); in mixel_phy_set_hs_timings()
303 struct mixel_dphy_priv *priv = dev_get_drvdata(phy->dev.parent); in mixel_dphy_set_pll_params()
305 if (priv->cfg.cm < 16 || priv->cfg.cm > 255 || in mixel_dphy_set_pll_params()
306 priv->cfg.cn < 1 || priv->cfg.cn > 32 || in mixel_dphy_set_pll_params()
307 priv->cfg.co < 1 || priv->cfg.co > 8) { in mixel_dphy_set_pll_params()
308 dev_err(&phy->dev, "Invalid CM/CN/CO values! (%u/%u/%u)\n", in mixel_dphy_set_pll_params()
309 priv->cfg.cm, priv->cfg.cn, priv->cfg.co); in mixel_dphy_set_pll_params()
310 return -EINVAL; in mixel_dphy_set_pll_params()
312 dev_dbg(&phy->dev, "Using CM:%u CN:%u CO:%u\n", in mixel_dphy_set_pll_params()
313 priv->cfg.cm, priv->cfg.cn, priv->cfg.co); in mixel_dphy_set_pll_params()
314 phy_write(phy, CM(priv->cfg.cm), DPHY_CM); in mixel_dphy_set_pll_params()
315 phy_write(phy, CN(priv->cfg.cn), DPHY_CN); in mixel_dphy_set_pll_params()
316 phy_write(phy, CO(priv->cfg.co), DPHY_CO); in mixel_dphy_set_pll_params()
323 struct mixel_dphy_cfg cfg = { 0 }; in mixel_dphy_configure() local
326 ret = mixel_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg); in mixel_dphy_configure()
331 memcpy(&priv->cfg, &cfg, sizeof(struct mixel_dphy_cfg)); in mixel_dphy_configure()
334 phy_write(phy, 0x01, priv->devdata->reg_tx_rcal); in mixel_dphy_configure()
335 phy_write(phy, 0x00, priv->devdata->reg_auto_pd_en); in mixel_dphy_configure()
336 phy_write(phy, 0x02, priv->devdata->reg_rxlprp); in mixel_dphy_configure()
337 phy_write(phy, 0x02, priv->devdata->reg_rxcdrp); in mixel_dphy_configure()
351 struct mixel_dphy_cfg cfg = { 0 }; in mixel_dphy_validate() local
354 return -EINVAL; in mixel_dphy_validate()
356 return mixel_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg); in mixel_dphy_validate()
382 ret = clk_prepare_enable(priv->phy_ref_clk); in mixel_dphy_power_on()
387 ret = regmap_read_poll_timeout(priv->regmap, DPHY_LOCK, locked, in mixel_dphy_power_on()
391 dev_err(&phy->dev, "Could not get DPHY lock (%d)!\n", ret); in mixel_dphy_power_on()
398 clk_disable_unprepare(priv->phy_ref_clk); in mixel_dphy_power_on()
409 clk_disable_unprepare(priv->phy_ref_clk); in mixel_dphy_power_off()
425 { .compatible = "fsl,imx8mq-mipi-dphy",
433 struct device *dev = &pdev->dev; in mixel_dphy_probe()
434 struct device_node *np = dev->of_node; in mixel_dphy_probe()
442 return -ENODEV; in mixel_dphy_probe()
446 return -ENOMEM; in mixel_dphy_probe()
448 priv->devdata = of_device_get_match_data(&pdev->dev); in mixel_dphy_probe()
449 if (!priv->devdata) in mixel_dphy_probe()
450 return -EINVAL; in mixel_dphy_probe()
457 priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, in mixel_dphy_probe()
459 if (IS_ERR(priv->regmap)) { in mixel_dphy_probe()
460 dev_err(dev, "Couldn't create the DPHY regmap\n"); in mixel_dphy_probe()
461 return PTR_ERR(priv->regmap); in mixel_dphy_probe()
464 priv->phy_ref_clk = devm_clk_get(&pdev->dev, "phy_ref"); in mixel_dphy_probe()
465 if (IS_ERR(priv->phy_ref_clk)) { in mixel_dphy_probe()
467 return PTR_ERR(priv->phy_ref_clk); in mixel_dphy_probe()
470 clk_get_rate(priv->phy_ref_clk)); in mixel_dphy_probe()
489 .name = "mixel-mipi-dphy",
496 MODULE_DESCRIPTION("Mixel MIPI-DSI PHY driver");