1 /* 2 * tegra30_ahub.c - Tegra30 AHUB driver 3 * 4 * Copyright (c) 2011,2012, NVIDIA CORPORATION. All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <linux/clk.h> 20 #include <linux/device.h> 21 #include <linux/io.h> 22 #include <linux/module.h> 23 #include <linux/of_platform.h> 24 #include <linux/platform_device.h> 25 #include <linux/pm_runtime.h> 26 #include <linux/regmap.h> 27 #include <linux/slab.h> 28 #include <linux/clk/tegra.h> 29 #include <sound/soc.h> 30 #include "tegra30_ahub.h" 31 32 #define DRV_NAME "tegra30-ahub" 33 34 static struct tegra30_ahub *ahub; 35 36 static inline void tegra30_apbif_write(u32 reg, u32 val) 37 { 38 regmap_write(ahub->regmap_apbif, reg, val); 39 } 40 41 static inline u32 tegra30_apbif_read(u32 reg) 42 { 43 u32 val; 44 regmap_read(ahub->regmap_apbif, reg, &val); 45 return val; 46 } 47 48 static inline void tegra30_audio_write(u32 reg, u32 val) 49 { 50 regmap_write(ahub->regmap_ahub, reg, val); 51 } 52 53 static int tegra30_ahub_runtime_suspend(struct device *dev) 54 { 55 regcache_cache_only(ahub->regmap_apbif, true); 56 regcache_cache_only(ahub->regmap_ahub, true); 57 58 clk_disable_unprepare(ahub->clk_apbif); 59 clk_disable_unprepare(ahub->clk_d_audio); 60 61 return 0; 62 } 63 64 /* 65 * clk_apbif isn't required for an I2S<->I2S configuration where no PCM data 66 * is read from or sent to memory. However, that's not something the rest of 67 * the driver supports right now, so we'll just treat the two clocks as one 68 * for now. 69 * 70 * These functions should not be a plain ref-count. Instead, each active stream 71 * contributes some requirement to the minimum clock rate, so starting or 72 * stopping streams should dynamically adjust the clock as required. However, 73 * this is not yet implemented. 74 */ 75 static int tegra30_ahub_runtime_resume(struct device *dev) 76 { 77 int ret; 78 79 ret = clk_prepare_enable(ahub->clk_d_audio); 80 if (ret) { 81 dev_err(dev, "clk_enable d_audio failed: %d\n", ret); 82 return ret; 83 } 84 ret = clk_prepare_enable(ahub->clk_apbif); 85 if (ret) { 86 dev_err(dev, "clk_enable apbif failed: %d\n", ret); 87 clk_disable(ahub->clk_d_audio); 88 return ret; 89 } 90 91 regcache_cache_only(ahub->regmap_apbif, false); 92 regcache_cache_only(ahub->regmap_ahub, false); 93 94 return 0; 95 } 96 97 int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, 98 unsigned long *fiforeg, 99 unsigned long *reqsel) 100 { 101 int channel; 102 u32 reg, val; 103 104 channel = find_first_zero_bit(ahub->rx_usage, 105 TEGRA30_AHUB_CHANNEL_CTRL_COUNT); 106 if (channel >= TEGRA30_AHUB_CHANNEL_CTRL_COUNT) 107 return -EBUSY; 108 109 __set_bit(channel, ahub->rx_usage); 110 111 *rxcif = TEGRA30_AHUB_RXCIF_APBIF_RX0 + channel; 112 *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_RXFIFO + 113 (channel * TEGRA30_AHUB_CHANNEL_RXFIFO_STRIDE); 114 *reqsel = ahub->dma_sel + channel; 115 116 reg = TEGRA30_AHUB_CHANNEL_CTRL + 117 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); 118 val = tegra30_apbif_read(reg); 119 val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK | 120 TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK); 121 val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_SHIFT) | 122 TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_EN | 123 TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16; 124 tegra30_apbif_write(reg, val); 125 126 reg = TEGRA30_AHUB_CIF_RX_CTRL + 127 (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE); 128 val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | 129 (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | 130 (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | 131 TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 | 132 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 | 133 TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX; 134 tegra30_apbif_write(reg, val); 135 136 return 0; 137 } 138 EXPORT_SYMBOL_GPL(tegra30_ahub_allocate_rx_fifo); 139 140 int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif) 141 { 142 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; 143 int reg, val; 144 145 reg = TEGRA30_AHUB_CHANNEL_CTRL + 146 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); 147 val = tegra30_apbif_read(reg); 148 val |= TEGRA30_AHUB_CHANNEL_CTRL_RX_EN; 149 tegra30_apbif_write(reg, val); 150 151 return 0; 152 } 153 EXPORT_SYMBOL_GPL(tegra30_ahub_enable_rx_fifo); 154 155 int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif) 156 { 157 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; 158 int reg, val; 159 160 reg = TEGRA30_AHUB_CHANNEL_CTRL + 161 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); 162 val = tegra30_apbif_read(reg); 163 val &= ~TEGRA30_AHUB_CHANNEL_CTRL_RX_EN; 164 tegra30_apbif_write(reg, val); 165 166 return 0; 167 } 168 EXPORT_SYMBOL_GPL(tegra30_ahub_disable_rx_fifo); 169 170 int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif) 171 { 172 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; 173 174 __clear_bit(channel, ahub->rx_usage); 175 176 return 0; 177 } 178 EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo); 179 180 int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, 181 unsigned long *fiforeg, 182 unsigned long *reqsel) 183 { 184 int channel; 185 u32 reg, val; 186 187 channel = find_first_zero_bit(ahub->tx_usage, 188 TEGRA30_AHUB_CHANNEL_CTRL_COUNT); 189 if (channel >= TEGRA30_AHUB_CHANNEL_CTRL_COUNT) 190 return -EBUSY; 191 192 __set_bit(channel, ahub->tx_usage); 193 194 *txcif = TEGRA30_AHUB_TXCIF_APBIF_TX0 + channel; 195 *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_TXFIFO + 196 (channel * TEGRA30_AHUB_CHANNEL_TXFIFO_STRIDE); 197 *reqsel = ahub->dma_sel + channel; 198 199 reg = TEGRA30_AHUB_CHANNEL_CTRL + 200 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); 201 val = tegra30_apbif_read(reg); 202 val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK | 203 TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK); 204 val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_SHIFT) | 205 TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_EN | 206 TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16; 207 tegra30_apbif_write(reg, val); 208 209 reg = TEGRA30_AHUB_CIF_TX_CTRL + 210 (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE); 211 val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | 212 (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | 213 (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | 214 TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 | 215 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 | 216 TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; 217 tegra30_apbif_write(reg, val); 218 219 return 0; 220 } 221 EXPORT_SYMBOL_GPL(tegra30_ahub_allocate_tx_fifo); 222 223 int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif) 224 { 225 int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0; 226 int reg, val; 227 228 reg = TEGRA30_AHUB_CHANNEL_CTRL + 229 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); 230 val = tegra30_apbif_read(reg); 231 val |= TEGRA30_AHUB_CHANNEL_CTRL_TX_EN; 232 tegra30_apbif_write(reg, val); 233 234 return 0; 235 } 236 EXPORT_SYMBOL_GPL(tegra30_ahub_enable_tx_fifo); 237 238 int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif) 239 { 240 int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0; 241 int reg, val; 242 243 reg = TEGRA30_AHUB_CHANNEL_CTRL + 244 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); 245 val = tegra30_apbif_read(reg); 246 val &= ~TEGRA30_AHUB_CHANNEL_CTRL_TX_EN; 247 tegra30_apbif_write(reg, val); 248 249 return 0; 250 } 251 EXPORT_SYMBOL_GPL(tegra30_ahub_disable_tx_fifo); 252 253 int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif) 254 { 255 int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0; 256 257 __clear_bit(channel, ahub->tx_usage); 258 259 return 0; 260 } 261 EXPORT_SYMBOL_GPL(tegra30_ahub_free_tx_fifo); 262 263 int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif, 264 enum tegra30_ahub_txcif txcif) 265 { 266 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; 267 int reg; 268 269 reg = TEGRA30_AHUB_AUDIO_RX + 270 (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE); 271 tegra30_audio_write(reg, 1 << txcif); 272 273 return 0; 274 } 275 EXPORT_SYMBOL_GPL(tegra30_ahub_set_rx_cif_source); 276 277 int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif) 278 { 279 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; 280 int reg; 281 282 reg = TEGRA30_AHUB_AUDIO_RX + 283 (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE); 284 tegra30_audio_write(reg, 0); 285 286 return 0; 287 } 288 EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source); 289 290 static const char * const configlink_clocks[] = { 291 "i2s0", 292 "i2s1", 293 "i2s2", 294 "i2s3", 295 "i2s4", 296 "dam0", 297 "dam1", 298 "dam2", 299 "spdif_in", 300 }; 301 302 #define LAST_REG(name) \ 303 (TEGRA30_AHUB_##name + \ 304 (TEGRA30_AHUB_##name##_STRIDE * TEGRA30_AHUB_##name##_COUNT) - 4) 305 306 #define REG_IN_ARRAY(reg, name) \ 307 ((reg >= TEGRA30_AHUB_##name) && \ 308 (reg <= LAST_REG(name) && \ 309 (!((reg - TEGRA30_AHUB_##name) % TEGRA30_AHUB_##name##_STRIDE)))) 310 311 static bool tegra30_ahub_apbif_wr_rd_reg(struct device *dev, unsigned int reg) 312 { 313 switch (reg) { 314 case TEGRA30_AHUB_CONFIG_LINK_CTRL: 315 case TEGRA30_AHUB_MISC_CTRL: 316 case TEGRA30_AHUB_APBDMA_LIVE_STATUS: 317 case TEGRA30_AHUB_I2S_LIVE_STATUS: 318 case TEGRA30_AHUB_SPDIF_LIVE_STATUS: 319 case TEGRA30_AHUB_I2S_INT_MASK: 320 case TEGRA30_AHUB_DAM_INT_MASK: 321 case TEGRA30_AHUB_SPDIF_INT_MASK: 322 case TEGRA30_AHUB_APBIF_INT_MASK: 323 case TEGRA30_AHUB_I2S_INT_STATUS: 324 case TEGRA30_AHUB_DAM_INT_STATUS: 325 case TEGRA30_AHUB_SPDIF_INT_STATUS: 326 case TEGRA30_AHUB_APBIF_INT_STATUS: 327 case TEGRA30_AHUB_I2S_INT_SOURCE: 328 case TEGRA30_AHUB_DAM_INT_SOURCE: 329 case TEGRA30_AHUB_SPDIF_INT_SOURCE: 330 case TEGRA30_AHUB_APBIF_INT_SOURCE: 331 case TEGRA30_AHUB_I2S_INT_SET: 332 case TEGRA30_AHUB_DAM_INT_SET: 333 case TEGRA30_AHUB_SPDIF_INT_SET: 334 case TEGRA30_AHUB_APBIF_INT_SET: 335 return true; 336 default: 337 break; 338 }; 339 340 if (REG_IN_ARRAY(reg, CHANNEL_CTRL) || 341 REG_IN_ARRAY(reg, CHANNEL_CLEAR) || 342 REG_IN_ARRAY(reg, CHANNEL_STATUS) || 343 REG_IN_ARRAY(reg, CHANNEL_TXFIFO) || 344 REG_IN_ARRAY(reg, CHANNEL_RXFIFO) || 345 REG_IN_ARRAY(reg, CIF_TX_CTRL) || 346 REG_IN_ARRAY(reg, CIF_RX_CTRL) || 347 REG_IN_ARRAY(reg, DAM_LIVE_STATUS)) 348 return true; 349 350 return false; 351 } 352 353 static bool tegra30_ahub_apbif_volatile_reg(struct device *dev, 354 unsigned int reg) 355 { 356 switch (reg) { 357 case TEGRA30_AHUB_CONFIG_LINK_CTRL: 358 case TEGRA30_AHUB_MISC_CTRL: 359 case TEGRA30_AHUB_APBDMA_LIVE_STATUS: 360 case TEGRA30_AHUB_I2S_LIVE_STATUS: 361 case TEGRA30_AHUB_SPDIF_LIVE_STATUS: 362 case TEGRA30_AHUB_I2S_INT_STATUS: 363 case TEGRA30_AHUB_DAM_INT_STATUS: 364 case TEGRA30_AHUB_SPDIF_INT_STATUS: 365 case TEGRA30_AHUB_APBIF_INT_STATUS: 366 case TEGRA30_AHUB_I2S_INT_SET: 367 case TEGRA30_AHUB_DAM_INT_SET: 368 case TEGRA30_AHUB_SPDIF_INT_SET: 369 case TEGRA30_AHUB_APBIF_INT_SET: 370 return true; 371 default: 372 break; 373 }; 374 375 if (REG_IN_ARRAY(reg, CHANNEL_CLEAR) || 376 REG_IN_ARRAY(reg, CHANNEL_STATUS) || 377 REG_IN_ARRAY(reg, CHANNEL_TXFIFO) || 378 REG_IN_ARRAY(reg, CHANNEL_RXFIFO) || 379 REG_IN_ARRAY(reg, DAM_LIVE_STATUS)) 380 return true; 381 382 return false; 383 } 384 385 static bool tegra30_ahub_apbif_precious_reg(struct device *dev, 386 unsigned int reg) 387 { 388 if (REG_IN_ARRAY(reg, CHANNEL_TXFIFO) || 389 REG_IN_ARRAY(reg, CHANNEL_RXFIFO)) 390 return true; 391 392 return false; 393 } 394 395 static const struct regmap_config tegra30_ahub_apbif_regmap_config = { 396 .name = "apbif", 397 .reg_bits = 32, 398 .val_bits = 32, 399 .reg_stride = 4, 400 .max_register = TEGRA30_AHUB_APBIF_INT_SET, 401 .writeable_reg = tegra30_ahub_apbif_wr_rd_reg, 402 .readable_reg = tegra30_ahub_apbif_wr_rd_reg, 403 .volatile_reg = tegra30_ahub_apbif_volatile_reg, 404 .precious_reg = tegra30_ahub_apbif_precious_reg, 405 .cache_type = REGCACHE_RBTREE, 406 }; 407 408 static bool tegra30_ahub_ahub_wr_rd_reg(struct device *dev, unsigned int reg) 409 { 410 if (REG_IN_ARRAY(reg, AUDIO_RX)) 411 return true; 412 413 return false; 414 } 415 416 static const struct regmap_config tegra30_ahub_ahub_regmap_config = { 417 .name = "ahub", 418 .reg_bits = 32, 419 .val_bits = 32, 420 .reg_stride = 4, 421 .max_register = LAST_REG(AUDIO_RX), 422 .writeable_reg = tegra30_ahub_ahub_wr_rd_reg, 423 .readable_reg = tegra30_ahub_ahub_wr_rd_reg, 424 .cache_type = REGCACHE_RBTREE, 425 }; 426 427 static int tegra30_ahub_probe(struct platform_device *pdev) 428 { 429 struct clk *clk; 430 int i; 431 struct resource *res0, *res1, *region; 432 u32 of_dma[2]; 433 void __iomem *regs_apbif, *regs_ahub; 434 int ret = 0; 435 436 if (ahub) 437 return -ENODEV; 438 439 /* 440 * The AHUB hosts a register bus: the "configlink". For this to 441 * operate correctly, all devices on this bus must be out of reset. 442 * Ensure that here. 443 */ 444 for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) { 445 clk = clk_get(&pdev->dev, configlink_clocks[i]); 446 if (IS_ERR(clk)) { 447 dev_err(&pdev->dev, "Can't get clock %s\n", 448 configlink_clocks[i]); 449 ret = PTR_ERR(clk); 450 goto err; 451 } 452 tegra_periph_reset_deassert(clk); 453 clk_put(clk); 454 } 455 456 ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub), 457 GFP_KERNEL); 458 if (!ahub) { 459 dev_err(&pdev->dev, "Can't allocate tegra30_ahub\n"); 460 ret = -ENOMEM; 461 goto err; 462 } 463 dev_set_drvdata(&pdev->dev, ahub); 464 465 ahub->dev = &pdev->dev; 466 467 ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio"); 468 if (IS_ERR(ahub->clk_d_audio)) { 469 dev_err(&pdev->dev, "Can't retrieve ahub d_audio clock\n"); 470 ret = PTR_ERR(ahub->clk_d_audio); 471 goto err; 472 } 473 474 ahub->clk_apbif = clk_get(&pdev->dev, "apbif"); 475 if (IS_ERR(ahub->clk_apbif)) { 476 dev_err(&pdev->dev, "Can't retrieve ahub apbif clock\n"); 477 ret = PTR_ERR(ahub->clk_apbif); 478 goto err_clk_put_d_audio; 479 } 480 481 if (of_property_read_u32_array(pdev->dev.of_node, 482 "nvidia,dma-request-selector", 483 of_dma, 2) < 0) { 484 dev_err(&pdev->dev, 485 "Missing property nvidia,dma-request-selector\n"); 486 ret = -ENODEV; 487 goto err_clk_put_d_audio; 488 } 489 ahub->dma_sel = of_dma[1]; 490 491 res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); 492 if (!res0) { 493 dev_err(&pdev->dev, "No apbif memory resource\n"); 494 ret = -ENODEV; 495 goto err_clk_put_apbif; 496 } 497 498 region = devm_request_mem_region(&pdev->dev, res0->start, 499 resource_size(res0), DRV_NAME); 500 if (!region) { 501 dev_err(&pdev->dev, "request region apbif failed\n"); 502 ret = -EBUSY; 503 goto err_clk_put_apbif; 504 } 505 ahub->apbif_addr = res0->start; 506 507 regs_apbif = devm_ioremap(&pdev->dev, res0->start, 508 resource_size(res0)); 509 if (!regs_apbif) { 510 dev_err(&pdev->dev, "ioremap apbif failed\n"); 511 ret = -ENOMEM; 512 goto err_clk_put_apbif; 513 } 514 515 ahub->regmap_apbif = devm_regmap_init_mmio(&pdev->dev, regs_apbif, 516 &tegra30_ahub_apbif_regmap_config); 517 if (IS_ERR(ahub->regmap_apbif)) { 518 dev_err(&pdev->dev, "apbif regmap init failed\n"); 519 ret = PTR_ERR(ahub->regmap_apbif); 520 goto err_clk_put_apbif; 521 } 522 regcache_cache_only(ahub->regmap_apbif, true); 523 524 res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); 525 if (!res1) { 526 dev_err(&pdev->dev, "No ahub memory resource\n"); 527 ret = -ENODEV; 528 goto err_clk_put_apbif; 529 } 530 531 region = devm_request_mem_region(&pdev->dev, res1->start, 532 resource_size(res1), DRV_NAME); 533 if (!region) { 534 dev_err(&pdev->dev, "request region ahub failed\n"); 535 ret = -EBUSY; 536 goto err_clk_put_apbif; 537 } 538 539 regs_ahub = devm_ioremap(&pdev->dev, res1->start, 540 resource_size(res1)); 541 if (!regs_ahub) { 542 dev_err(&pdev->dev, "ioremap ahub failed\n"); 543 ret = -ENOMEM; 544 goto err_clk_put_apbif; 545 } 546 547 ahub->regmap_ahub = devm_regmap_init_mmio(&pdev->dev, regs_ahub, 548 &tegra30_ahub_ahub_regmap_config); 549 if (IS_ERR(ahub->regmap_ahub)) { 550 dev_err(&pdev->dev, "ahub regmap init failed\n"); 551 ret = PTR_ERR(ahub->regmap_ahub); 552 goto err_clk_put_apbif; 553 } 554 regcache_cache_only(ahub->regmap_ahub, true); 555 556 pm_runtime_enable(&pdev->dev); 557 if (!pm_runtime_enabled(&pdev->dev)) { 558 ret = tegra30_ahub_runtime_resume(&pdev->dev); 559 if (ret) 560 goto err_pm_disable; 561 } 562 563 of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); 564 565 return 0; 566 567 err_pm_disable: 568 pm_runtime_disable(&pdev->dev); 569 err_clk_put_apbif: 570 clk_put(ahub->clk_apbif); 571 err_clk_put_d_audio: 572 clk_put(ahub->clk_d_audio); 573 ahub = NULL; 574 err: 575 return ret; 576 } 577 578 static int tegra30_ahub_remove(struct platform_device *pdev) 579 { 580 if (!ahub) 581 return -ENODEV; 582 583 pm_runtime_disable(&pdev->dev); 584 if (!pm_runtime_status_suspended(&pdev->dev)) 585 tegra30_ahub_runtime_suspend(&pdev->dev); 586 587 clk_put(ahub->clk_apbif); 588 clk_put(ahub->clk_d_audio); 589 590 ahub = NULL; 591 592 return 0; 593 } 594 595 static const struct of_device_id tegra30_ahub_of_match[] = { 596 { .compatible = "nvidia,tegra30-ahub", }, 597 {}, 598 }; 599 600 static const struct dev_pm_ops tegra30_ahub_pm_ops = { 601 SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend, 602 tegra30_ahub_runtime_resume, NULL) 603 }; 604 605 static struct platform_driver tegra30_ahub_driver = { 606 .probe = tegra30_ahub_probe, 607 .remove = tegra30_ahub_remove, 608 .driver = { 609 .name = DRV_NAME, 610 .owner = THIS_MODULE, 611 .of_match_table = tegra30_ahub_of_match, 612 .pm = &tegra30_ahub_pm_ops, 613 }, 614 }; 615 module_platform_driver(tegra30_ahub_driver); 616 617 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); 618 MODULE_DESCRIPTION("Tegra30 AHUB driver"); 619 MODULE_LICENSE("GPL v2"); 620 MODULE_ALIAS("platform:" DRV_NAME); 621 MODULE_DEVICE_TABLE(of, tegra30_ahub_of_match); 622