1 /* 2 * Copyright (C) 2013 NVIDIA Corporation 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23 #include <linux/clk.h> 24 #include <linux/host1x.h> 25 #include <linux/io.h> 26 #include <linux/iopoll.h> 27 #include <linux/of_platform.h> 28 #include <linux/platform_device.h> 29 #include <linux/slab.h> 30 #include <linux/tegra-mipi-cal.h> 31 32 #include "dev.h" 33 34 #define MIPI_CAL_CTRL 0x00 35 #define MIPI_CAL_CTRL_NOISE_FILTER(x) (((x) & 0xf) << 26) 36 #define MIPI_CAL_CTRL_PRESCALE(x) (((x) & 0x3) << 24) 37 #define MIPI_CAL_CTRL_CLKEN_OVR BIT(4) 38 #define MIPI_CAL_CTRL_START BIT(0) 39 40 #define MIPI_CAL_AUTOCAL_CTRL 0x01 41 42 #define MIPI_CAL_STATUS 0x02 43 #define MIPI_CAL_STATUS_DONE BIT(16) 44 #define MIPI_CAL_STATUS_ACTIVE BIT(0) 45 46 #define MIPI_CAL_CONFIG_CSIA 0x05 47 #define MIPI_CAL_CONFIG_CSIB 0x06 48 #define MIPI_CAL_CONFIG_CSIC 0x07 49 #define MIPI_CAL_CONFIG_CSID 0x08 50 #define MIPI_CAL_CONFIG_CSIE 0x09 51 #define MIPI_CAL_CONFIG_CSIF 0x0a 52 #define MIPI_CAL_CONFIG_DSIA 0x0e 53 #define MIPI_CAL_CONFIG_DSIB 0x0f 54 #define MIPI_CAL_CONFIG_DSIC 0x10 55 #define MIPI_CAL_CONFIG_DSID 0x11 56 57 #define MIPI_CAL_CONFIG_DSIA_CLK 0x19 58 #define MIPI_CAL_CONFIG_DSIB_CLK 0x1a 59 #define MIPI_CAL_CONFIG_CSIAB_CLK 0x1b 60 #define MIPI_CAL_CONFIG_DSIC_CLK 0x1c 61 #define MIPI_CAL_CONFIG_CSICD_CLK 0x1c 62 #define MIPI_CAL_CONFIG_DSID_CLK 0x1d 63 #define MIPI_CAL_CONFIG_CSIE_CLK 0x1d 64 65 /* for data and clock lanes */ 66 #define MIPI_CAL_CONFIG_SELECT BIT(21) 67 68 /* for data lanes */ 69 #define MIPI_CAL_CONFIG_HSPDOS(x) (((x) & 0x1f) << 16) 70 #define MIPI_CAL_CONFIG_HSPUOS(x) (((x) & 0x1f) << 8) 71 #define MIPI_CAL_CONFIG_TERMOS(x) (((x) & 0x1f) << 0) 72 73 /* for clock lanes */ 74 #define MIPI_CAL_CONFIG_HSCLKPDOSD(x) (((x) & 0x1f) << 8) 75 #define MIPI_CAL_CONFIG_HSCLKPUOSD(x) (((x) & 0x1f) << 0) 76 77 #define MIPI_CAL_BIAS_PAD_CFG0 0x16 78 #define MIPI_CAL_BIAS_PAD_PDVCLAMP BIT(1) 79 #define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF BIT(0) 80 81 #define MIPI_CAL_BIAS_PAD_CFG1 0x17 82 #define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16) 83 #define MIPI_CAL_BIAS_PAD_DRV_UP_REF(x) (((x) & 0x7) << 8) 84 85 #define MIPI_CAL_BIAS_PAD_CFG2 0x18 86 #define MIPI_CAL_BIAS_PAD_VCLAMP(x) (((x) & 0x7) << 16) 87 #define MIPI_CAL_BIAS_PAD_VAUXP(x) (((x) & 0x7) << 4) 88 #define MIPI_CAL_BIAS_PAD_PDVREG BIT(1) 89 90 struct tegra_mipi_pad { 91 unsigned long data; 92 unsigned long clk; 93 }; 94 95 struct tegra_mipi_soc { 96 bool has_clk_lane; 97 const struct tegra_mipi_pad *pads; 98 unsigned int num_pads; 99 100 bool clock_enable_override; 101 bool needs_vclamp_ref; 102 103 /* bias pad configuration settings */ 104 u8 pad_drive_down_ref; 105 u8 pad_drive_up_ref; 106 107 u8 pad_vclamp_level; 108 u8 pad_vauxp_level; 109 110 /* calibration settings for data lanes */ 111 u8 hspdos; 112 u8 hspuos; 113 u8 termos; 114 115 /* calibration settings for clock lanes */ 116 u8 hsclkpdos; 117 u8 hsclkpuos; 118 }; 119 120 struct tegra_mipi { 121 const struct tegra_mipi_soc *soc; 122 struct device *dev; 123 void __iomem *regs; 124 struct mutex lock; /* for register access */ 125 struct clk *clk; 126 127 unsigned long usage_count; 128 }; 129 130 static inline u32 tegra_mipi_readl(struct tegra_mipi *mipi, 131 unsigned long offset) 132 { 133 return readl(mipi->regs + (offset << 2)); 134 } 135 136 static inline void tegra_mipi_writel(struct tegra_mipi *mipi, u32 value, 137 unsigned long offset) 138 { 139 writel(value, mipi->regs + (offset << 2)); 140 } 141 142 static int tegra114_mipi_power_up(struct tegra_mipi *mipi) 143 { 144 u32 value; 145 int err; 146 147 err = clk_enable(mipi->clk); 148 if (err < 0) 149 return err; 150 151 value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0); 152 value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP; 153 154 if (mipi->soc->needs_vclamp_ref) 155 value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF; 156 157 tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0); 158 159 value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2); 160 value &= ~MIPI_CAL_BIAS_PAD_PDVREG; 161 tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2); 162 163 clk_disable(mipi->clk); 164 165 return 0; 166 } 167 168 static int tegra114_mipi_power_down(struct tegra_mipi *mipi) 169 { 170 u32 value; 171 int err; 172 173 err = clk_enable(mipi->clk); 174 if (err < 0) 175 return err; 176 177 /* 178 * The MIPI_CAL_BIAS_PAD_PDVREG controls a voltage regulator that 179 * supplies the DSI pads. This must be kept enabled until none of the 180 * DSI lanes are used anymore. 181 */ 182 value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2); 183 value |= MIPI_CAL_BIAS_PAD_PDVREG; 184 tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2); 185 186 /* 187 * MIPI_CAL_BIAS_PAD_PDVCLAMP and MIPI_CAL_BIAS_PAD_E_VCLAMP_REF 188 * control a regulator that supplies current to the pre-driver logic. 189 * Powering down this regulator causes DSI to fail, so it must remain 190 * powered on until none of the DSI lanes are used anymore. 191 */ 192 value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0); 193 194 if (mipi->soc->needs_vclamp_ref) 195 value &= ~MIPI_CAL_BIAS_PAD_E_VCLAMP_REF; 196 197 value |= MIPI_CAL_BIAS_PAD_PDVCLAMP; 198 tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0); 199 200 return 0; 201 } 202 203 static int tegra114_mipi_enable(struct tegra_mipi_device *mipidev) 204 { 205 struct tegra_mipi *mipi = platform_get_drvdata(mipidev->pdev); 206 int err = 0; 207 208 mutex_lock(&mipi->lock); 209 210 if (mipi->usage_count++ == 0) 211 err = tegra114_mipi_power_up(mipi); 212 213 mutex_unlock(&mipi->lock); 214 215 return err; 216 } 217 218 static int tegra114_mipi_disable(struct tegra_mipi_device *mipidev) 219 { 220 struct tegra_mipi *mipi = platform_get_drvdata(mipidev->pdev); 221 int err = 0; 222 223 mutex_lock(&mipi->lock); 224 225 if (--mipi->usage_count == 0) 226 err = tegra114_mipi_power_down(mipi); 227 228 mutex_unlock(&mipi->lock); 229 230 return err; 231 } 232 233 static int tegra114_mipi_finish_calibration(struct tegra_mipi_device *mipidev) 234 { 235 struct tegra_mipi *mipi = platform_get_drvdata(mipidev->pdev); 236 void __iomem *status_reg = mipi->regs + (MIPI_CAL_STATUS << 2); 237 u32 value; 238 int err; 239 240 err = readl_relaxed_poll_timeout(status_reg, value, 241 !(value & MIPI_CAL_STATUS_ACTIVE) && 242 (value & MIPI_CAL_STATUS_DONE), 50, 243 250000); 244 mutex_unlock(&mipi->lock); 245 clk_disable(mipi->clk); 246 247 return err; 248 } 249 250 static int tegra114_mipi_start_calibration(struct tegra_mipi_device *mipidev) 251 { 252 struct tegra_mipi *mipi = platform_get_drvdata(mipidev->pdev); 253 const struct tegra_mipi_soc *soc = mipi->soc; 254 unsigned int i; 255 u32 value; 256 int err; 257 258 err = clk_enable(mipi->clk); 259 if (err < 0) 260 return err; 261 262 mutex_lock(&mipi->lock); 263 264 value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) | 265 MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref); 266 tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG1); 267 268 value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2); 269 value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7); 270 value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7); 271 value |= MIPI_CAL_BIAS_PAD_VCLAMP(soc->pad_vclamp_level); 272 value |= MIPI_CAL_BIAS_PAD_VAUXP(soc->pad_vauxp_level); 273 tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2); 274 275 for (i = 0; i < soc->num_pads; i++) { 276 u32 clk = 0, data = 0; 277 278 if (mipidev->pads & BIT(i)) { 279 data = MIPI_CAL_CONFIG_SELECT | 280 MIPI_CAL_CONFIG_HSPDOS(soc->hspdos) | 281 MIPI_CAL_CONFIG_HSPUOS(soc->hspuos) | 282 MIPI_CAL_CONFIG_TERMOS(soc->termos); 283 clk = MIPI_CAL_CONFIG_SELECT | 284 MIPI_CAL_CONFIG_HSCLKPDOSD(soc->hsclkpdos) | 285 MIPI_CAL_CONFIG_HSCLKPUOSD(soc->hsclkpuos); 286 } 287 288 tegra_mipi_writel(mipi, data, soc->pads[i].data); 289 290 if (soc->has_clk_lane && soc->pads[i].clk != 0) 291 tegra_mipi_writel(mipi, clk, soc->pads[i].clk); 292 } 293 294 value = tegra_mipi_readl(mipi, MIPI_CAL_CTRL); 295 value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf); 296 value &= ~MIPI_CAL_CTRL_PRESCALE(0x3); 297 value |= MIPI_CAL_CTRL_NOISE_FILTER(0xa); 298 value |= MIPI_CAL_CTRL_PRESCALE(0x2); 299 300 if (!soc->clock_enable_override) 301 value &= ~MIPI_CAL_CTRL_CLKEN_OVR; 302 else 303 value |= MIPI_CAL_CTRL_CLKEN_OVR; 304 305 tegra_mipi_writel(mipi, value, MIPI_CAL_CTRL); 306 307 /* clear any pending status bits */ 308 value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS); 309 tegra_mipi_writel(mipi, value, MIPI_CAL_STATUS); 310 311 value = tegra_mipi_readl(mipi, MIPI_CAL_CTRL); 312 value |= MIPI_CAL_CTRL_START; 313 tegra_mipi_writel(mipi, value, MIPI_CAL_CTRL); 314 315 /* 316 * Wait for min 72uS to let calibration logic finish calibration 317 * sequence codes before waiting for pads idle state to apply the 318 * results. 319 */ 320 usleep_range(75, 80); 321 322 return 0; 323 } 324 325 static const struct tegra_mipi_ops tegra114_mipi_ops = { 326 .enable = tegra114_mipi_enable, 327 .disable = tegra114_mipi_disable, 328 .start_calibration = tegra114_mipi_start_calibration, 329 .finish_calibration = tegra114_mipi_finish_calibration, 330 }; 331 332 static const struct tegra_mipi_pad tegra114_mipi_pads[] = { 333 { .data = MIPI_CAL_CONFIG_CSIA }, 334 { .data = MIPI_CAL_CONFIG_CSIB }, 335 { .data = MIPI_CAL_CONFIG_CSIC }, 336 { .data = MIPI_CAL_CONFIG_CSID }, 337 { .data = MIPI_CAL_CONFIG_CSIE }, 338 { .data = MIPI_CAL_CONFIG_DSIA }, 339 { .data = MIPI_CAL_CONFIG_DSIB }, 340 { .data = MIPI_CAL_CONFIG_DSIC }, 341 { .data = MIPI_CAL_CONFIG_DSID }, 342 }; 343 344 static const struct tegra_mipi_soc tegra114_mipi_soc = { 345 .has_clk_lane = false, 346 .pads = tegra114_mipi_pads, 347 .num_pads = ARRAY_SIZE(tegra114_mipi_pads), 348 .clock_enable_override = true, 349 .needs_vclamp_ref = true, 350 .pad_drive_down_ref = 0x2, 351 .pad_drive_up_ref = 0x0, 352 .pad_vclamp_level = 0x0, 353 .pad_vauxp_level = 0x0, 354 .hspdos = 0x0, 355 .hspuos = 0x4, 356 .termos = 0x5, 357 .hsclkpdos = 0x0, 358 .hsclkpuos = 0x4, 359 }; 360 361 static const struct tegra_mipi_pad tegra124_mipi_pads[] = { 362 { .data = MIPI_CAL_CONFIG_CSIA, .clk = MIPI_CAL_CONFIG_CSIAB_CLK }, 363 { .data = MIPI_CAL_CONFIG_CSIB, .clk = MIPI_CAL_CONFIG_CSIAB_CLK }, 364 { .data = MIPI_CAL_CONFIG_CSIC, .clk = MIPI_CAL_CONFIG_CSICD_CLK }, 365 { .data = MIPI_CAL_CONFIG_CSID, .clk = MIPI_CAL_CONFIG_CSICD_CLK }, 366 { .data = MIPI_CAL_CONFIG_CSIE, .clk = MIPI_CAL_CONFIG_CSIE_CLK }, 367 { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK }, 368 { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK }, 369 }; 370 371 static const struct tegra_mipi_soc tegra124_mipi_soc = { 372 .has_clk_lane = true, 373 .pads = tegra124_mipi_pads, 374 .num_pads = ARRAY_SIZE(tegra124_mipi_pads), 375 .clock_enable_override = true, 376 .needs_vclamp_ref = true, 377 .pad_drive_down_ref = 0x2, 378 .pad_drive_up_ref = 0x0, 379 .pad_vclamp_level = 0x0, 380 .pad_vauxp_level = 0x0, 381 .hspdos = 0x0, 382 .hspuos = 0x0, 383 .termos = 0x0, 384 .hsclkpdos = 0x1, 385 .hsclkpuos = 0x2, 386 }; 387 388 static const struct tegra_mipi_soc tegra132_mipi_soc = { 389 .has_clk_lane = true, 390 .pads = tegra124_mipi_pads, 391 .num_pads = ARRAY_SIZE(tegra124_mipi_pads), 392 .clock_enable_override = false, 393 .needs_vclamp_ref = false, 394 .pad_drive_down_ref = 0x0, 395 .pad_drive_up_ref = 0x3, 396 .pad_vclamp_level = 0x0, 397 .pad_vauxp_level = 0x0, 398 .hspdos = 0x0, 399 .hspuos = 0x0, 400 .termos = 0x0, 401 .hsclkpdos = 0x3, 402 .hsclkpuos = 0x2, 403 }; 404 405 static const struct tegra_mipi_pad tegra210_mipi_pads[] = { 406 { .data = MIPI_CAL_CONFIG_CSIA, .clk = 0 }, 407 { .data = MIPI_CAL_CONFIG_CSIB, .clk = 0 }, 408 { .data = MIPI_CAL_CONFIG_CSIC, .clk = 0 }, 409 { .data = MIPI_CAL_CONFIG_CSID, .clk = 0 }, 410 { .data = MIPI_CAL_CONFIG_CSIE, .clk = 0 }, 411 { .data = MIPI_CAL_CONFIG_CSIF, .clk = 0 }, 412 { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK }, 413 { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK }, 414 { .data = MIPI_CAL_CONFIG_DSIC, .clk = MIPI_CAL_CONFIG_DSIC_CLK }, 415 { .data = MIPI_CAL_CONFIG_DSID, .clk = MIPI_CAL_CONFIG_DSID_CLK }, 416 }; 417 418 static const struct tegra_mipi_soc tegra210_mipi_soc = { 419 .has_clk_lane = true, 420 .pads = tegra210_mipi_pads, 421 .num_pads = ARRAY_SIZE(tegra210_mipi_pads), 422 .clock_enable_override = true, 423 .needs_vclamp_ref = false, 424 .pad_drive_down_ref = 0x0, 425 .pad_drive_up_ref = 0x3, 426 .pad_vclamp_level = 0x1, 427 .pad_vauxp_level = 0x1, 428 .hspdos = 0x0, 429 .hspuos = 0x2, 430 .termos = 0x0, 431 .hsclkpdos = 0x0, 432 .hsclkpuos = 0x2, 433 }; 434 435 static const struct of_device_id tegra_mipi_of_match[] = { 436 { .compatible = "nvidia,tegra114-mipi", .data = &tegra114_mipi_soc }, 437 { .compatible = "nvidia,tegra124-mipi", .data = &tegra124_mipi_soc }, 438 { .compatible = "nvidia,tegra132-mipi", .data = &tegra132_mipi_soc }, 439 { .compatible = "nvidia,tegra210-mipi", .data = &tegra210_mipi_soc }, 440 { }, 441 }; 442 443 static int tegra_mipi_probe(struct platform_device *pdev) 444 { 445 const struct of_device_id *match; 446 struct tegra_mipi *mipi; 447 448 match = of_match_node(tegra_mipi_of_match, pdev->dev.of_node); 449 if (!match) 450 return -ENODEV; 451 452 mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL); 453 if (!mipi) 454 return -ENOMEM; 455 456 mipi->soc = match->data; 457 mipi->dev = &pdev->dev; 458 459 mipi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 460 if (IS_ERR(mipi->regs)) 461 return PTR_ERR(mipi->regs); 462 463 mutex_init(&mipi->lock); 464 465 mipi->clk = devm_clk_get_prepared(&pdev->dev, NULL); 466 if (IS_ERR(mipi->clk)) { 467 dev_err(&pdev->dev, "failed to get clock\n"); 468 return PTR_ERR(mipi->clk); 469 } 470 471 platform_set_drvdata(pdev, mipi); 472 473 return devm_tegra_mipi_add_provider(&pdev->dev, pdev->dev.of_node, 474 &tegra114_mipi_ops); 475 } 476 477 struct platform_driver tegra_mipi_driver = { 478 .driver = { 479 .name = "tegra-mipi", 480 .of_match_table = tegra_mipi_of_match, 481 }, 482 .probe = tegra_mipi_probe, 483 }; 484