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 dma_addr_t *fiforeg, 99 unsigned int *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 dma_addr_t *fiforeg, 182 unsigned int *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 #define CLK_LIST_MASK_TEGRA30 BIT(0) 291 #define CLK_LIST_MASK_TEGRA114 BIT(1) 292 293 #define CLK_LIST_MASK_TEGRA30_OR_LATER \ 294 (CLK_LIST_MASK_TEGRA30 | CLK_LIST_MASK_TEGRA114) 295 296 static const struct { 297 const char *clk_name; 298 u32 clk_list_mask; 299 } configlink_clocks[] = { 300 { "i2s0", CLK_LIST_MASK_TEGRA30_OR_LATER }, 301 { "i2s1", CLK_LIST_MASK_TEGRA30_OR_LATER }, 302 { "i2s2", CLK_LIST_MASK_TEGRA30_OR_LATER }, 303 { "i2s3", CLK_LIST_MASK_TEGRA30_OR_LATER }, 304 { "i2s4", CLK_LIST_MASK_TEGRA30_OR_LATER }, 305 { "dam0", CLK_LIST_MASK_TEGRA30_OR_LATER }, 306 { "dam1", CLK_LIST_MASK_TEGRA30_OR_LATER }, 307 { "dam2", CLK_LIST_MASK_TEGRA30_OR_LATER }, 308 { "spdif_in", CLK_LIST_MASK_TEGRA30_OR_LATER }, 309 { "amx", CLK_LIST_MASK_TEGRA114 }, 310 { "adx", CLK_LIST_MASK_TEGRA114 }, 311 }; 312 313 #define LAST_REG(name) \ 314 (TEGRA30_AHUB_##name + \ 315 (TEGRA30_AHUB_##name##_STRIDE * TEGRA30_AHUB_##name##_COUNT) - 4) 316 317 #define REG_IN_ARRAY(reg, name) \ 318 ((reg >= TEGRA30_AHUB_##name) && \ 319 (reg <= LAST_REG(name) && \ 320 (!((reg - TEGRA30_AHUB_##name) % TEGRA30_AHUB_##name##_STRIDE)))) 321 322 static bool tegra30_ahub_apbif_wr_rd_reg(struct device *dev, unsigned int reg) 323 { 324 switch (reg) { 325 case TEGRA30_AHUB_CONFIG_LINK_CTRL: 326 case TEGRA30_AHUB_MISC_CTRL: 327 case TEGRA30_AHUB_APBDMA_LIVE_STATUS: 328 case TEGRA30_AHUB_I2S_LIVE_STATUS: 329 case TEGRA30_AHUB_SPDIF_LIVE_STATUS: 330 case TEGRA30_AHUB_I2S_INT_MASK: 331 case TEGRA30_AHUB_DAM_INT_MASK: 332 case TEGRA30_AHUB_SPDIF_INT_MASK: 333 case TEGRA30_AHUB_APBIF_INT_MASK: 334 case TEGRA30_AHUB_I2S_INT_STATUS: 335 case TEGRA30_AHUB_DAM_INT_STATUS: 336 case TEGRA30_AHUB_SPDIF_INT_STATUS: 337 case TEGRA30_AHUB_APBIF_INT_STATUS: 338 case TEGRA30_AHUB_I2S_INT_SOURCE: 339 case TEGRA30_AHUB_DAM_INT_SOURCE: 340 case TEGRA30_AHUB_SPDIF_INT_SOURCE: 341 case TEGRA30_AHUB_APBIF_INT_SOURCE: 342 case TEGRA30_AHUB_I2S_INT_SET: 343 case TEGRA30_AHUB_DAM_INT_SET: 344 case TEGRA30_AHUB_SPDIF_INT_SET: 345 case TEGRA30_AHUB_APBIF_INT_SET: 346 return true; 347 default: 348 break; 349 }; 350 351 if (REG_IN_ARRAY(reg, CHANNEL_CTRL) || 352 REG_IN_ARRAY(reg, CHANNEL_CLEAR) || 353 REG_IN_ARRAY(reg, CHANNEL_STATUS) || 354 REG_IN_ARRAY(reg, CHANNEL_TXFIFO) || 355 REG_IN_ARRAY(reg, CHANNEL_RXFIFO) || 356 REG_IN_ARRAY(reg, CIF_TX_CTRL) || 357 REG_IN_ARRAY(reg, CIF_RX_CTRL) || 358 REG_IN_ARRAY(reg, DAM_LIVE_STATUS)) 359 return true; 360 361 return false; 362 } 363 364 static bool tegra30_ahub_apbif_volatile_reg(struct device *dev, 365 unsigned int reg) 366 { 367 switch (reg) { 368 case TEGRA30_AHUB_CONFIG_LINK_CTRL: 369 case TEGRA30_AHUB_MISC_CTRL: 370 case TEGRA30_AHUB_APBDMA_LIVE_STATUS: 371 case TEGRA30_AHUB_I2S_LIVE_STATUS: 372 case TEGRA30_AHUB_SPDIF_LIVE_STATUS: 373 case TEGRA30_AHUB_I2S_INT_STATUS: 374 case TEGRA30_AHUB_DAM_INT_STATUS: 375 case TEGRA30_AHUB_SPDIF_INT_STATUS: 376 case TEGRA30_AHUB_APBIF_INT_STATUS: 377 case TEGRA30_AHUB_I2S_INT_SET: 378 case TEGRA30_AHUB_DAM_INT_SET: 379 case TEGRA30_AHUB_SPDIF_INT_SET: 380 case TEGRA30_AHUB_APBIF_INT_SET: 381 return true; 382 default: 383 break; 384 }; 385 386 if (REG_IN_ARRAY(reg, CHANNEL_CLEAR) || 387 REG_IN_ARRAY(reg, CHANNEL_STATUS) || 388 REG_IN_ARRAY(reg, CHANNEL_TXFIFO) || 389 REG_IN_ARRAY(reg, CHANNEL_RXFIFO) || 390 REG_IN_ARRAY(reg, DAM_LIVE_STATUS)) 391 return true; 392 393 return false; 394 } 395 396 static bool tegra30_ahub_apbif_precious_reg(struct device *dev, 397 unsigned int reg) 398 { 399 if (REG_IN_ARRAY(reg, CHANNEL_TXFIFO) || 400 REG_IN_ARRAY(reg, CHANNEL_RXFIFO)) 401 return true; 402 403 return false; 404 } 405 406 static const struct regmap_config tegra30_ahub_apbif_regmap_config = { 407 .name = "apbif", 408 .reg_bits = 32, 409 .val_bits = 32, 410 .reg_stride = 4, 411 .max_register = TEGRA30_AHUB_APBIF_INT_SET, 412 .writeable_reg = tegra30_ahub_apbif_wr_rd_reg, 413 .readable_reg = tegra30_ahub_apbif_wr_rd_reg, 414 .volatile_reg = tegra30_ahub_apbif_volatile_reg, 415 .precious_reg = tegra30_ahub_apbif_precious_reg, 416 .cache_type = REGCACHE_RBTREE, 417 }; 418 419 static bool tegra30_ahub_ahub_wr_rd_reg(struct device *dev, unsigned int reg) 420 { 421 if (REG_IN_ARRAY(reg, AUDIO_RX)) 422 return true; 423 424 return false; 425 } 426 427 static const struct regmap_config tegra30_ahub_ahub_regmap_config = { 428 .name = "ahub", 429 .reg_bits = 32, 430 .val_bits = 32, 431 .reg_stride = 4, 432 .max_register = LAST_REG(AUDIO_RX), 433 .writeable_reg = tegra30_ahub_ahub_wr_rd_reg, 434 .readable_reg = tegra30_ahub_ahub_wr_rd_reg, 435 .cache_type = REGCACHE_RBTREE, 436 }; 437 438 static struct tegra30_ahub_soc_data soc_data_tegra30 = { 439 .clk_list_mask = CLK_LIST_MASK_TEGRA30, 440 }; 441 442 static struct tegra30_ahub_soc_data soc_data_tegra114 = { 443 .clk_list_mask = CLK_LIST_MASK_TEGRA114, 444 }; 445 446 static const struct of_device_id tegra30_ahub_of_match[] = { 447 { .compatible = "nvidia,tegra114-ahub", .data = &soc_data_tegra114 }, 448 { .compatible = "nvidia,tegra30-ahub", .data = &soc_data_tegra30 }, 449 {}, 450 }; 451 452 static int tegra30_ahub_probe(struct platform_device *pdev) 453 { 454 const struct of_device_id *match; 455 const struct tegra30_ahub_soc_data *soc_data; 456 struct clk *clk; 457 int i; 458 struct resource *res0, *res1, *region; 459 u32 of_dma[2]; 460 void __iomem *regs_apbif, *regs_ahub; 461 int ret = 0; 462 463 if (ahub) 464 return -ENODEV; 465 466 match = of_match_device(tegra30_ahub_of_match, &pdev->dev); 467 if (!match) 468 return -EINVAL; 469 soc_data = match->data; 470 471 /* 472 * The AHUB hosts a register bus: the "configlink". For this to 473 * operate correctly, all devices on this bus must be out of reset. 474 * Ensure that here. 475 */ 476 for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) { 477 if (!(configlink_clocks[i].clk_list_mask & 478 soc_data->clk_list_mask)) 479 continue; 480 clk = clk_get(&pdev->dev, configlink_clocks[i].clk_name); 481 if (IS_ERR(clk)) { 482 dev_err(&pdev->dev, "Can't get clock %s\n", 483 configlink_clocks[i].clk_name); 484 ret = PTR_ERR(clk); 485 goto err; 486 } 487 tegra_periph_reset_deassert(clk); 488 clk_put(clk); 489 } 490 491 ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub), 492 GFP_KERNEL); 493 if (!ahub) { 494 dev_err(&pdev->dev, "Can't allocate tegra30_ahub\n"); 495 ret = -ENOMEM; 496 goto err; 497 } 498 dev_set_drvdata(&pdev->dev, ahub); 499 500 ahub->dev = &pdev->dev; 501 502 ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio"); 503 if (IS_ERR(ahub->clk_d_audio)) { 504 dev_err(&pdev->dev, "Can't retrieve ahub d_audio clock\n"); 505 ret = PTR_ERR(ahub->clk_d_audio); 506 goto err; 507 } 508 509 ahub->clk_apbif = clk_get(&pdev->dev, "apbif"); 510 if (IS_ERR(ahub->clk_apbif)) { 511 dev_err(&pdev->dev, "Can't retrieve ahub apbif clock\n"); 512 ret = PTR_ERR(ahub->clk_apbif); 513 goto err_clk_put_d_audio; 514 } 515 516 if (of_property_read_u32_array(pdev->dev.of_node, 517 "nvidia,dma-request-selector", 518 of_dma, 2) < 0) { 519 dev_err(&pdev->dev, 520 "Missing property nvidia,dma-request-selector\n"); 521 ret = -ENODEV; 522 goto err_clk_put_d_audio; 523 } 524 ahub->dma_sel = of_dma[1]; 525 526 res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); 527 if (!res0) { 528 dev_err(&pdev->dev, "No apbif memory resource\n"); 529 ret = -ENODEV; 530 goto err_clk_put_apbif; 531 } 532 533 region = devm_request_mem_region(&pdev->dev, res0->start, 534 resource_size(res0), DRV_NAME); 535 if (!region) { 536 dev_err(&pdev->dev, "request region apbif failed\n"); 537 ret = -EBUSY; 538 goto err_clk_put_apbif; 539 } 540 ahub->apbif_addr = res0->start; 541 542 regs_apbif = devm_ioremap(&pdev->dev, res0->start, 543 resource_size(res0)); 544 if (!regs_apbif) { 545 dev_err(&pdev->dev, "ioremap apbif failed\n"); 546 ret = -ENOMEM; 547 goto err_clk_put_apbif; 548 } 549 550 ahub->regmap_apbif = devm_regmap_init_mmio(&pdev->dev, regs_apbif, 551 &tegra30_ahub_apbif_regmap_config); 552 if (IS_ERR(ahub->regmap_apbif)) { 553 dev_err(&pdev->dev, "apbif regmap init failed\n"); 554 ret = PTR_ERR(ahub->regmap_apbif); 555 goto err_clk_put_apbif; 556 } 557 regcache_cache_only(ahub->regmap_apbif, true); 558 559 res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); 560 if (!res1) { 561 dev_err(&pdev->dev, "No ahub memory resource\n"); 562 ret = -ENODEV; 563 goto err_clk_put_apbif; 564 } 565 566 region = devm_request_mem_region(&pdev->dev, res1->start, 567 resource_size(res1), DRV_NAME); 568 if (!region) { 569 dev_err(&pdev->dev, "request region ahub failed\n"); 570 ret = -EBUSY; 571 goto err_clk_put_apbif; 572 } 573 574 regs_ahub = devm_ioremap(&pdev->dev, res1->start, 575 resource_size(res1)); 576 if (!regs_ahub) { 577 dev_err(&pdev->dev, "ioremap ahub failed\n"); 578 ret = -ENOMEM; 579 goto err_clk_put_apbif; 580 } 581 582 ahub->regmap_ahub = devm_regmap_init_mmio(&pdev->dev, regs_ahub, 583 &tegra30_ahub_ahub_regmap_config); 584 if (IS_ERR(ahub->regmap_ahub)) { 585 dev_err(&pdev->dev, "ahub regmap init failed\n"); 586 ret = PTR_ERR(ahub->regmap_ahub); 587 goto err_clk_put_apbif; 588 } 589 regcache_cache_only(ahub->regmap_ahub, true); 590 591 pm_runtime_enable(&pdev->dev); 592 if (!pm_runtime_enabled(&pdev->dev)) { 593 ret = tegra30_ahub_runtime_resume(&pdev->dev); 594 if (ret) 595 goto err_pm_disable; 596 } 597 598 of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); 599 600 return 0; 601 602 err_pm_disable: 603 pm_runtime_disable(&pdev->dev); 604 err_clk_put_apbif: 605 clk_put(ahub->clk_apbif); 606 err_clk_put_d_audio: 607 clk_put(ahub->clk_d_audio); 608 ahub = NULL; 609 err: 610 return ret; 611 } 612 613 static int tegra30_ahub_remove(struct platform_device *pdev) 614 { 615 if (!ahub) 616 return -ENODEV; 617 618 pm_runtime_disable(&pdev->dev); 619 if (!pm_runtime_status_suspended(&pdev->dev)) 620 tegra30_ahub_runtime_suspend(&pdev->dev); 621 622 clk_put(ahub->clk_apbif); 623 clk_put(ahub->clk_d_audio); 624 625 ahub = NULL; 626 627 return 0; 628 } 629 630 static const struct dev_pm_ops tegra30_ahub_pm_ops = { 631 SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend, 632 tegra30_ahub_runtime_resume, NULL) 633 }; 634 635 static struct platform_driver tegra30_ahub_driver = { 636 .probe = tegra30_ahub_probe, 637 .remove = tegra30_ahub_remove, 638 .driver = { 639 .name = DRV_NAME, 640 .owner = THIS_MODULE, 641 .of_match_table = tegra30_ahub_of_match, 642 .pm = &tegra30_ahub_pm_ops, 643 }, 644 }; 645 module_platform_driver(tegra30_ahub_driver); 646 647 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); 648 MODULE_DESCRIPTION("Tegra30 AHUB driver"); 649 MODULE_LICENSE("GPL v2"); 650 MODULE_ALIAS("platform:" DRV_NAME); 651 MODULE_DEVICE_TABLE(of, tegra30_ahub_of_match); 652