0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/bitfield.h>
0011 #include <linux/bitops.h>
0012 #include <linux/bits.h>
0013 #include <linux/clk.h>
0014 #include <linux/delay.h>
0015 #include <linux/io.h>
0016 #include <linux/module.h>
0017 #include <linux/of_device.h>
0018 #include <linux/regmap.h>
0019 #include <linux/reset.h>
0020 #include <linux/phy/phy.h>
0021 #include <linux/platform_device.h>
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 #define MIPI_DSI_PHY_CTRL 0x0
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 #define MIPI_DSI_CHAN_CTRL 0x4
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 #define MIPI_DSI_CHAN_STS 0x8
0108
0109
0110
0111
0112
0113
0114 #define MIPI_DSI_CLK_TIM 0xc
0115
0116
0117
0118
0119
0120
0121 #define MIPI_DSI_HS_TIM 0x10
0122
0123
0124
0125
0126
0127
0128 #define MIPI_DSI_LP_TIM 0x14
0129
0130
0131 #define MIPI_DSI_ANA_UP_TIM 0x18
0132
0133
0134 #define MIPI_DSI_INIT_TIM 0x1c
0135
0136
0137 #define MIPI_DSI_WAKEUP_TIM 0x20
0138
0139
0140
0141
0142 #define MIPI_DSI_LPOK_TIM 0x24
0143
0144
0145 #define MIPI_DSI_LP_WCHDOG 0x28
0146
0147
0148
0149
0150 #define MIPI_DSI_ANA_CTRL 0x2c
0151
0152
0153
0154
0155 #define MIPI_DSI_CLK_TIM1 0x30
0156
0157
0158 #define MIPI_DSI_TURN_WCHDOG 0x34
0159
0160
0161
0162
0163 #define MIPI_DSI_ULPS_CHECK 0x38
0164 #define MIPI_DSI_TEST_CTRL0 0x3c
0165 #define MIPI_DSI_TEST_CTRL1 0x40
0166
0167 struct phy_meson_axg_mipi_dphy_priv {
0168 struct device *dev;
0169 struct regmap *regmap;
0170 struct clk *clk;
0171 struct reset_control *reset;
0172 struct phy *analog;
0173 struct phy_configure_opts_mipi_dphy config;
0174 };
0175
0176 static const struct regmap_config phy_meson_axg_mipi_dphy_regmap_conf = {
0177 .reg_bits = 8,
0178 .val_bits = 32,
0179 .reg_stride = 4,
0180 .max_register = MIPI_DSI_TEST_CTRL1,
0181 };
0182
0183 static int phy_meson_axg_mipi_dphy_init(struct phy *phy)
0184 {
0185 struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
0186 int ret;
0187
0188 ret = phy_init(priv->analog);
0189 if (ret)
0190 return ret;
0191
0192 ret = reset_control_reset(priv->reset);
0193 if (ret)
0194 return ret;
0195
0196 return 0;
0197 }
0198
0199 static int phy_meson_axg_mipi_dphy_configure(struct phy *phy,
0200 union phy_configure_opts *opts)
0201 {
0202 struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
0203 int ret;
0204
0205 ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);
0206 if (ret)
0207 return ret;
0208
0209 ret = phy_configure(priv->analog, opts);
0210 if (ret)
0211 return ret;
0212
0213 memcpy(&priv->config, opts, sizeof(priv->config));
0214
0215 return 0;
0216 }
0217
0218 static int phy_meson_axg_mipi_dphy_power_on(struct phy *phy)
0219 {
0220 struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
0221 int ret;
0222 unsigned long temp;
0223
0224 ret = phy_power_on(priv->analog);
0225 if (ret)
0226 return ret;
0227
0228
0229 regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, 0x1);
0230 regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL,
0231 BIT(0) |
0232 BIT(7) |
0233 BIT(8));
0234
0235
0236 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(9), BIT(9));
0237
0238
0239 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(12), BIT(12));
0240 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), BIT(31));
0241 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), 0);
0242
0243
0244 temp = (1000000 * 100) / (priv->config.hs_clk_rate / 1000);
0245 temp = temp * 8 * 10;
0246
0247 regmap_write(priv->regmap, MIPI_DSI_CLK_TIM,
0248 DIV_ROUND_UP(priv->config.clk_trail, temp) |
0249 (DIV_ROUND_UP(priv->config.clk_post +
0250 priv->config.hs_trail, temp) << 8) |
0251 (DIV_ROUND_UP(priv->config.clk_zero, temp) << 16) |
0252 (DIV_ROUND_UP(priv->config.clk_prepare, temp) << 24));
0253 regmap_write(priv->regmap, MIPI_DSI_CLK_TIM1,
0254 DIV_ROUND_UP(priv->config.clk_pre, BITS_PER_BYTE));
0255
0256 regmap_write(priv->regmap, MIPI_DSI_HS_TIM,
0257 DIV_ROUND_UP(priv->config.hs_exit, temp) |
0258 (DIV_ROUND_UP(priv->config.hs_trail, temp) << 8) |
0259 (DIV_ROUND_UP(priv->config.hs_zero, temp) << 16) |
0260 (DIV_ROUND_UP(priv->config.hs_prepare, temp) << 24));
0261
0262 regmap_write(priv->regmap, MIPI_DSI_LP_TIM,
0263 DIV_ROUND_UP(priv->config.lpx, temp) |
0264 (DIV_ROUND_UP(priv->config.ta_sure, temp) << 8) |
0265 (DIV_ROUND_UP(priv->config.ta_go, temp) << 16) |
0266 (DIV_ROUND_UP(priv->config.ta_get, temp) << 24));
0267
0268 regmap_write(priv->regmap, MIPI_DSI_ANA_UP_TIM, 0x0100);
0269 regmap_write(priv->regmap, MIPI_DSI_INIT_TIM,
0270 DIV_ROUND_UP(priv->config.init * NSEC_PER_MSEC, temp));
0271 regmap_write(priv->regmap, MIPI_DSI_WAKEUP_TIM,
0272 DIV_ROUND_UP(priv->config.wakeup * NSEC_PER_MSEC, temp));
0273 regmap_write(priv->regmap, MIPI_DSI_LPOK_TIM, 0x7C);
0274 regmap_write(priv->regmap, MIPI_DSI_ULPS_CHECK, 0x927C);
0275 regmap_write(priv->regmap, MIPI_DSI_LP_WCHDOG, 0x1000);
0276 regmap_write(priv->regmap, MIPI_DSI_TURN_WCHDOG, 0x1000);
0277
0278
0279 switch (priv->config.lanes) {
0280 case 1:
0281 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xe);
0282 break;
0283 case 2:
0284 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xc);
0285 break;
0286 case 3:
0287 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0x8);
0288 break;
0289 case 4:
0290 default:
0291 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0);
0292 break;
0293 }
0294
0295
0296 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(1), BIT(1));
0297
0298 return 0;
0299 }
0300
0301 static int phy_meson_axg_mipi_dphy_power_off(struct phy *phy)
0302 {
0303 struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
0304
0305 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xf);
0306 regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31));
0307
0308 phy_power_off(priv->analog);
0309
0310 return 0;
0311 }
0312
0313 static int phy_meson_axg_mipi_dphy_exit(struct phy *phy)
0314 {
0315 struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
0316 int ret;
0317
0318 ret = phy_exit(priv->analog);
0319 if (ret)
0320 return ret;
0321
0322 return reset_control_reset(priv->reset);
0323 }
0324
0325 static const struct phy_ops phy_meson_axg_mipi_dphy_ops = {
0326 .configure = phy_meson_axg_mipi_dphy_configure,
0327 .init = phy_meson_axg_mipi_dphy_init,
0328 .exit = phy_meson_axg_mipi_dphy_exit,
0329 .power_on = phy_meson_axg_mipi_dphy_power_on,
0330 .power_off = phy_meson_axg_mipi_dphy_power_off,
0331 .owner = THIS_MODULE,
0332 };
0333
0334 static int phy_meson_axg_mipi_dphy_probe(struct platform_device *pdev)
0335 {
0336 struct device *dev = &pdev->dev;
0337 struct phy_provider *phy_provider;
0338 struct resource *res;
0339 struct phy_meson_axg_mipi_dphy_priv *priv;
0340 struct phy *phy;
0341 void __iomem *base;
0342 int ret;
0343
0344 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0345 if (!priv)
0346 return -ENOMEM;
0347
0348 priv->dev = dev;
0349 platform_set_drvdata(pdev, priv);
0350
0351 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0352 base = devm_ioremap_resource(dev, res);
0353 if (IS_ERR(base))
0354 return PTR_ERR(base);
0355
0356 priv->regmap = devm_regmap_init_mmio(dev, base,
0357 &phy_meson_axg_mipi_dphy_regmap_conf);
0358 if (IS_ERR(priv->regmap))
0359 return PTR_ERR(priv->regmap);
0360
0361 priv->clk = devm_clk_get(dev, "pclk");
0362 if (IS_ERR(priv->clk))
0363 return PTR_ERR(priv->clk);
0364
0365 priv->reset = devm_reset_control_get(dev, "phy");
0366 if (IS_ERR(priv->reset))
0367 return PTR_ERR(priv->reset);
0368
0369 priv->analog = devm_phy_get(dev, "analog");
0370 if (IS_ERR(priv->analog))
0371 return PTR_ERR(priv->analog);
0372
0373 ret = clk_prepare_enable(priv->clk);
0374 if (ret)
0375 return ret;
0376
0377 ret = reset_control_deassert(priv->reset);
0378 if (ret)
0379 return ret;
0380
0381 phy = devm_phy_create(dev, NULL, &phy_meson_axg_mipi_dphy_ops);
0382 if (IS_ERR(phy)) {
0383 ret = PTR_ERR(phy);
0384 if (ret != -EPROBE_DEFER)
0385 dev_err(dev, "failed to create PHY\n");
0386
0387 return ret;
0388 }
0389
0390 phy_set_drvdata(phy, priv);
0391
0392 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0393
0394 return PTR_ERR_OR_ZERO(phy_provider);
0395 }
0396
0397 static const struct of_device_id phy_meson_axg_mipi_dphy_of_match[] = {
0398 { .compatible = "amlogic,axg-mipi-dphy", },
0399 { },
0400 };
0401 MODULE_DEVICE_TABLE(of, phy_meson_axg_mipi_dphy_of_match);
0402
0403 static struct platform_driver phy_meson_axg_mipi_dphy_driver = {
0404 .probe = phy_meson_axg_mipi_dphy_probe,
0405 .driver = {
0406 .name = "phy-meson-axg-mipi-dphy",
0407 .of_match_table = phy_meson_axg_mipi_dphy_of_match,
0408 },
0409 };
0410 module_platform_driver(phy_meson_axg_mipi_dphy_driver);
0411
0412 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
0413 MODULE_DESCRIPTION("Meson AXG MIPI DPHY driver");
0414 MODULE_LICENSE("GPL v2");