1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * tegra30_ahub.c - Tegra30 AHUB driver 4 * 5 * Copyright (c) 2011,2012, NVIDIA CORPORATION. All rights reserved. 6 */ 7 8 #include <linux/clk.h> 9 #include <linux/device.h> 10 #include <linux/io.h> 11 #include <linux/module.h> 12 #include <linux/of_platform.h> 13 #include <linux/platform_device.h> 14 #include <linux/pm_runtime.h> 15 #include <linux/regmap.h> 16 #include <linux/reset.h> 17 #include <linux/slab.h> 18 #include <sound/soc.h> 19 #include "tegra30_ahub.h" 20 21 #define DRV_NAME "tegra30-ahub" 22 23 static struct tegra30_ahub *ahub; 24 25 static inline void tegra30_apbif_write(u32 reg, u32 val) 26 { 27 regmap_write(ahub->regmap_apbif, reg, val); 28 } 29 30 static inline u32 tegra30_apbif_read(u32 reg) 31 { 32 u32 val; 33 34 regmap_read(ahub->regmap_apbif, reg, &val); 35 return val; 36 } 37 38 static inline void tegra30_audio_write(u32 reg, u32 val) 39 { 40 regmap_write(ahub->regmap_ahub, reg, val); 41 } 42 43 static int tegra30_ahub_runtime_suspend(struct device *dev) 44 { 45 regcache_cache_only(ahub->regmap_apbif, true); 46 regcache_cache_only(ahub->regmap_ahub, true); 47 48 clk_bulk_disable_unprepare(ahub->nclocks, ahub->clocks); 49 50 return 0; 51 } 52 53 /* 54 * clk_apbif isn't required for an I2S<->I2S configuration where no PCM data 55 * is read from or sent to memory. However, that's not something the rest of 56 * the driver supports right now, so we'll just treat the two clocks as one 57 * for now. 58 * 59 * These functions should not be a plain ref-count. Instead, each active stream 60 * contributes some requirement to the minimum clock rate, so starting or 61 * stopping streams should dynamically adjust the clock as required. However, 62 * this is not yet implemented. 63 */ 64 static int tegra30_ahub_runtime_resume(struct device *dev) 65 { 66 int ret; 67 68 ret = reset_control_assert(ahub->reset); 69 if (ret) 70 return ret; 71 72 ret = clk_bulk_prepare_enable(ahub->nclocks, ahub->clocks); 73 if (ret) 74 return ret; 75 76 usleep_range(10, 100); 77 78 ret = reset_control_deassert(ahub->reset); 79 if (ret) 80 goto disable_clocks; 81 82 regcache_cache_only(ahub->regmap_apbif, false); 83 regcache_cache_only(ahub->regmap_ahub, false); 84 regcache_mark_dirty(ahub->regmap_apbif); 85 regcache_mark_dirty(ahub->regmap_ahub); 86 87 ret = regcache_sync(ahub->regmap_apbif); 88 if (ret) 89 goto disable_clocks; 90 91 ret = regcache_sync(ahub->regmap_ahub); 92 if (ret) 93 goto disable_clocks; 94 95 return 0; 96 97 disable_clocks: 98 clk_bulk_disable_unprepare(ahub->nclocks, ahub->clocks); 99 100 return ret; 101 } 102 103 int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, 104 char *dmachan, int dmachan_len, 105 dma_addr_t *fiforeg) 106 { 107 int channel; 108 u32 reg, val; 109 struct tegra30_ahub_cif_conf cif_conf; 110 111 channel = find_first_zero_bit(ahub->rx_usage, 112 TEGRA30_AHUB_CHANNEL_CTRL_COUNT); 113 if (channel >= TEGRA30_AHUB_CHANNEL_CTRL_COUNT) 114 return -EBUSY; 115 116 __set_bit(channel, ahub->rx_usage); 117 118 *rxcif = TEGRA30_AHUB_RXCIF_APBIF_RX0 + channel; 119 snprintf(dmachan, dmachan_len, "rx%d", channel); 120 *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_RXFIFO + 121 (channel * TEGRA30_AHUB_CHANNEL_RXFIFO_STRIDE); 122 123 pm_runtime_get_sync(ahub->dev); 124 125 reg = TEGRA30_AHUB_CHANNEL_CTRL + 126 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); 127 val = tegra30_apbif_read(reg); 128 val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK | 129 TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK); 130 val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_SHIFT) | 131 TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_EN | 132 TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16; 133 tegra30_apbif_write(reg, val); 134 135 cif_conf.threshold = 0; 136 cif_conf.audio_channels = 2; 137 cif_conf.client_channels = 2; 138 cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16; 139 cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16; 140 cif_conf.expand = 0; 141 cif_conf.stereo_conv = 0; 142 cif_conf.replicate = 0; 143 cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX; 144 cif_conf.truncate = 0; 145 cif_conf.mono_conv = 0; 146 147 reg = TEGRA30_AHUB_CIF_RX_CTRL + 148 (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE); 149 ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf); 150 151 pm_runtime_put(ahub->dev); 152 153 return 0; 154 } 155 EXPORT_SYMBOL_GPL(tegra30_ahub_allocate_rx_fifo); 156 157 int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif) 158 { 159 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; 160 int reg, val; 161 162 pm_runtime_get_sync(ahub->dev); 163 164 reg = TEGRA30_AHUB_CHANNEL_CTRL + 165 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); 166 val = tegra30_apbif_read(reg); 167 val |= TEGRA30_AHUB_CHANNEL_CTRL_RX_EN; 168 tegra30_apbif_write(reg, val); 169 170 pm_runtime_put(ahub->dev); 171 172 return 0; 173 } 174 EXPORT_SYMBOL_GPL(tegra30_ahub_enable_rx_fifo); 175 176 int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif) 177 { 178 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; 179 int reg, val; 180 181 pm_runtime_get_sync(ahub->dev); 182 183 reg = TEGRA30_AHUB_CHANNEL_CTRL + 184 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); 185 val = tegra30_apbif_read(reg); 186 val &= ~TEGRA30_AHUB_CHANNEL_CTRL_RX_EN; 187 tegra30_apbif_write(reg, val); 188 189 pm_runtime_put(ahub->dev); 190 191 return 0; 192 } 193 EXPORT_SYMBOL_GPL(tegra30_ahub_disable_rx_fifo); 194 195 int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif) 196 { 197 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; 198 199 __clear_bit(channel, ahub->rx_usage); 200 201 return 0; 202 } 203 EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo); 204 205 int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, 206 char *dmachan, int dmachan_len, 207 dma_addr_t *fiforeg) 208 { 209 int channel; 210 u32 reg, val; 211 struct tegra30_ahub_cif_conf cif_conf; 212 213 channel = find_first_zero_bit(ahub->tx_usage, 214 TEGRA30_AHUB_CHANNEL_CTRL_COUNT); 215 if (channel >= TEGRA30_AHUB_CHANNEL_CTRL_COUNT) 216 return -EBUSY; 217 218 __set_bit(channel, ahub->tx_usage); 219 220 *txcif = TEGRA30_AHUB_TXCIF_APBIF_TX0 + channel; 221 snprintf(dmachan, dmachan_len, "tx%d", channel); 222 *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_TXFIFO + 223 (channel * TEGRA30_AHUB_CHANNEL_TXFIFO_STRIDE); 224 225 pm_runtime_get_sync(ahub->dev); 226 227 reg = TEGRA30_AHUB_CHANNEL_CTRL + 228 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); 229 val = tegra30_apbif_read(reg); 230 val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK | 231 TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK); 232 val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_SHIFT) | 233 TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_EN | 234 TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16; 235 tegra30_apbif_write(reg, val); 236 237 cif_conf.threshold = 0; 238 cif_conf.audio_channels = 2; 239 cif_conf.client_channels = 2; 240 cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16; 241 cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16; 242 cif_conf.expand = 0; 243 cif_conf.stereo_conv = 0; 244 cif_conf.replicate = 0; 245 cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX; 246 cif_conf.truncate = 0; 247 cif_conf.mono_conv = 0; 248 249 reg = TEGRA30_AHUB_CIF_TX_CTRL + 250 (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE); 251 ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf); 252 253 pm_runtime_put(ahub->dev); 254 255 return 0; 256 } 257 EXPORT_SYMBOL_GPL(tegra30_ahub_allocate_tx_fifo); 258 259 int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif) 260 { 261 int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0; 262 int reg, val; 263 264 pm_runtime_get_sync(ahub->dev); 265 266 reg = TEGRA30_AHUB_CHANNEL_CTRL + 267 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); 268 val = tegra30_apbif_read(reg); 269 val |= TEGRA30_AHUB_CHANNEL_CTRL_TX_EN; 270 tegra30_apbif_write(reg, val); 271 272 pm_runtime_put(ahub->dev); 273 274 return 0; 275 } 276 EXPORT_SYMBOL_GPL(tegra30_ahub_enable_tx_fifo); 277 278 int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif) 279 { 280 int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0; 281 int reg, val; 282 283 pm_runtime_get_sync(ahub->dev); 284 285 reg = TEGRA30_AHUB_CHANNEL_CTRL + 286 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); 287 val = tegra30_apbif_read(reg); 288 val &= ~TEGRA30_AHUB_CHANNEL_CTRL_TX_EN; 289 tegra30_apbif_write(reg, val); 290 291 pm_runtime_put(ahub->dev); 292 293 return 0; 294 } 295 EXPORT_SYMBOL_GPL(tegra30_ahub_disable_tx_fifo); 296 297 int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif) 298 { 299 int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0; 300 301 __clear_bit(channel, ahub->tx_usage); 302 303 return 0; 304 } 305 EXPORT_SYMBOL_GPL(tegra30_ahub_free_tx_fifo); 306 307 int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif, 308 enum tegra30_ahub_txcif txcif) 309 { 310 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; 311 int reg; 312 313 pm_runtime_get_sync(ahub->dev); 314 315 reg = TEGRA30_AHUB_AUDIO_RX + 316 (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE); 317 tegra30_audio_write(reg, 1 << txcif); 318 319 pm_runtime_put(ahub->dev); 320 321 return 0; 322 } 323 EXPORT_SYMBOL_GPL(tegra30_ahub_set_rx_cif_source); 324 325 int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif) 326 { 327 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; 328 int reg; 329 330 pm_runtime_get_sync(ahub->dev); 331 332 reg = TEGRA30_AHUB_AUDIO_RX + 333 (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE); 334 tegra30_audio_write(reg, 0); 335 336 pm_runtime_put(ahub->dev); 337 338 return 0; 339 } 340 EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source); 341 342 #define MOD_LIST_MASK_TEGRA30 BIT(0) 343 #define MOD_LIST_MASK_TEGRA114 BIT(1) 344 #define MOD_LIST_MASK_TEGRA124 BIT(2) 345 346 #define MOD_LIST_MASK_TEGRA30_OR_LATER \ 347 (MOD_LIST_MASK_TEGRA30 | MOD_LIST_MASK_TEGRA114 | \ 348 MOD_LIST_MASK_TEGRA124) 349 #define MOD_LIST_MASK_TEGRA114_OR_LATER \ 350 (MOD_LIST_MASK_TEGRA114 | MOD_LIST_MASK_TEGRA124) 351 352 static const struct { 353 const char *rst_name; 354 u32 mod_list_mask; 355 } configlink_mods[] = { 356 { "d_audio", MOD_LIST_MASK_TEGRA30_OR_LATER }, 357 { "apbif", MOD_LIST_MASK_TEGRA30_OR_LATER }, 358 { "i2s0", MOD_LIST_MASK_TEGRA30_OR_LATER }, 359 { "i2s1", MOD_LIST_MASK_TEGRA30_OR_LATER }, 360 { "i2s2", MOD_LIST_MASK_TEGRA30_OR_LATER }, 361 { "i2s3", MOD_LIST_MASK_TEGRA30_OR_LATER }, 362 { "i2s4", MOD_LIST_MASK_TEGRA30_OR_LATER }, 363 { "dam0", MOD_LIST_MASK_TEGRA30_OR_LATER }, 364 { "dam1", MOD_LIST_MASK_TEGRA30_OR_LATER }, 365 { "dam2", MOD_LIST_MASK_TEGRA30_OR_LATER }, 366 { "spdif", MOD_LIST_MASK_TEGRA30_OR_LATER }, 367 { "amx", MOD_LIST_MASK_TEGRA114_OR_LATER }, 368 { "adx", MOD_LIST_MASK_TEGRA114_OR_LATER }, 369 { "amx1", MOD_LIST_MASK_TEGRA124 }, 370 { "adx1", MOD_LIST_MASK_TEGRA124 }, 371 { "afc0", MOD_LIST_MASK_TEGRA124 }, 372 { "afc1", MOD_LIST_MASK_TEGRA124 }, 373 { "afc2", MOD_LIST_MASK_TEGRA124 }, 374 { "afc3", MOD_LIST_MASK_TEGRA124 }, 375 { "afc4", MOD_LIST_MASK_TEGRA124 }, 376 { "afc5", MOD_LIST_MASK_TEGRA124 }, 377 }; 378 379 #define LAST_REG(name) \ 380 (TEGRA30_AHUB_##name + \ 381 (TEGRA30_AHUB_##name##_STRIDE * TEGRA30_AHUB_##name##_COUNT) - 4) 382 383 #define REG_IN_ARRAY(reg, name) \ 384 ((reg >= TEGRA30_AHUB_##name) && \ 385 (reg <= LAST_REG(name) && \ 386 (!((reg - TEGRA30_AHUB_##name) % TEGRA30_AHUB_##name##_STRIDE)))) 387 388 static bool tegra30_ahub_apbif_wr_rd_reg(struct device *dev, unsigned int reg) 389 { 390 switch (reg) { 391 case TEGRA30_AHUB_CONFIG_LINK_CTRL: 392 case TEGRA30_AHUB_MISC_CTRL: 393 case TEGRA30_AHUB_APBDMA_LIVE_STATUS: 394 case TEGRA30_AHUB_I2S_LIVE_STATUS: 395 case TEGRA30_AHUB_SPDIF_LIVE_STATUS: 396 case TEGRA30_AHUB_I2S_INT_MASK: 397 case TEGRA30_AHUB_DAM_INT_MASK: 398 case TEGRA30_AHUB_SPDIF_INT_MASK: 399 case TEGRA30_AHUB_APBIF_INT_MASK: 400 case TEGRA30_AHUB_I2S_INT_STATUS: 401 case TEGRA30_AHUB_DAM_INT_STATUS: 402 case TEGRA30_AHUB_SPDIF_INT_STATUS: 403 case TEGRA30_AHUB_APBIF_INT_STATUS: 404 case TEGRA30_AHUB_I2S_INT_SOURCE: 405 case TEGRA30_AHUB_DAM_INT_SOURCE: 406 case TEGRA30_AHUB_SPDIF_INT_SOURCE: 407 case TEGRA30_AHUB_APBIF_INT_SOURCE: 408 case TEGRA30_AHUB_I2S_INT_SET: 409 case TEGRA30_AHUB_DAM_INT_SET: 410 case TEGRA30_AHUB_SPDIF_INT_SET: 411 case TEGRA30_AHUB_APBIF_INT_SET: 412 return true; 413 default: 414 break; 415 } 416 417 if (REG_IN_ARRAY(reg, CHANNEL_CTRL) || 418 REG_IN_ARRAY(reg, CHANNEL_CLEAR) || 419 REG_IN_ARRAY(reg, CHANNEL_STATUS) || 420 REG_IN_ARRAY(reg, CHANNEL_TXFIFO) || 421 REG_IN_ARRAY(reg, CHANNEL_RXFIFO) || 422 REG_IN_ARRAY(reg, CIF_TX_CTRL) || 423 REG_IN_ARRAY(reg, CIF_RX_CTRL) || 424 REG_IN_ARRAY(reg, DAM_LIVE_STATUS)) 425 return true; 426 427 return false; 428 } 429 430 static bool tegra30_ahub_apbif_volatile_reg(struct device *dev, 431 unsigned int reg) 432 { 433 switch (reg) { 434 case TEGRA30_AHUB_CONFIG_LINK_CTRL: 435 case TEGRA30_AHUB_MISC_CTRL: 436 case TEGRA30_AHUB_APBDMA_LIVE_STATUS: 437 case TEGRA30_AHUB_I2S_LIVE_STATUS: 438 case TEGRA30_AHUB_SPDIF_LIVE_STATUS: 439 case TEGRA30_AHUB_I2S_INT_STATUS: 440 case TEGRA30_AHUB_DAM_INT_STATUS: 441 case TEGRA30_AHUB_SPDIF_INT_STATUS: 442 case TEGRA30_AHUB_APBIF_INT_STATUS: 443 case TEGRA30_AHUB_I2S_INT_SET: 444 case TEGRA30_AHUB_DAM_INT_SET: 445 case TEGRA30_AHUB_SPDIF_INT_SET: 446 case TEGRA30_AHUB_APBIF_INT_SET: 447 return true; 448 default: 449 break; 450 } 451 452 if (REG_IN_ARRAY(reg, CHANNEL_CLEAR) || 453 REG_IN_ARRAY(reg, CHANNEL_STATUS) || 454 REG_IN_ARRAY(reg, CHANNEL_TXFIFO) || 455 REG_IN_ARRAY(reg, CHANNEL_RXFIFO) || 456 REG_IN_ARRAY(reg, DAM_LIVE_STATUS)) 457 return true; 458 459 return false; 460 } 461 462 static bool tegra30_ahub_apbif_precious_reg(struct device *dev, 463 unsigned int reg) 464 { 465 if (REG_IN_ARRAY(reg, CHANNEL_TXFIFO) || 466 REG_IN_ARRAY(reg, CHANNEL_RXFIFO)) 467 return true; 468 469 return false; 470 } 471 472 static const struct regmap_config tegra30_ahub_apbif_regmap_config = { 473 .name = "apbif", 474 .reg_bits = 32, 475 .val_bits = 32, 476 .reg_stride = 4, 477 .max_register = TEGRA30_AHUB_APBIF_INT_SET, 478 .writeable_reg = tegra30_ahub_apbif_wr_rd_reg, 479 .readable_reg = tegra30_ahub_apbif_wr_rd_reg, 480 .volatile_reg = tegra30_ahub_apbif_volatile_reg, 481 .precious_reg = tegra30_ahub_apbif_precious_reg, 482 .cache_type = REGCACHE_FLAT, 483 }; 484 485 static bool tegra30_ahub_ahub_wr_rd_reg(struct device *dev, unsigned int reg) 486 { 487 if (REG_IN_ARRAY(reg, AUDIO_RX)) 488 return true; 489 490 return false; 491 } 492 493 static const struct regmap_config tegra30_ahub_ahub_regmap_config = { 494 .name = "ahub", 495 .reg_bits = 32, 496 .val_bits = 32, 497 .reg_stride = 4, 498 .max_register = LAST_REG(AUDIO_RX), 499 .writeable_reg = tegra30_ahub_ahub_wr_rd_reg, 500 .readable_reg = tegra30_ahub_ahub_wr_rd_reg, 501 .cache_type = REGCACHE_FLAT, 502 }; 503 504 static struct tegra30_ahub_soc_data soc_data_tegra30 = { 505 .mod_list_mask = MOD_LIST_MASK_TEGRA30, 506 .set_audio_cif = tegra30_ahub_set_cif, 507 }; 508 509 static struct tegra30_ahub_soc_data soc_data_tegra114 = { 510 .mod_list_mask = MOD_LIST_MASK_TEGRA114, 511 .set_audio_cif = tegra30_ahub_set_cif, 512 }; 513 514 static struct tegra30_ahub_soc_data soc_data_tegra124 = { 515 .mod_list_mask = MOD_LIST_MASK_TEGRA124, 516 .set_audio_cif = tegra124_ahub_set_cif, 517 }; 518 519 static const struct of_device_id tegra30_ahub_of_match[] = { 520 { .compatible = "nvidia,tegra124-ahub", .data = &soc_data_tegra124 }, 521 { .compatible = "nvidia,tegra114-ahub", .data = &soc_data_tegra114 }, 522 { .compatible = "nvidia,tegra30-ahub", .data = &soc_data_tegra30 }, 523 {}, 524 }; 525 526 static int tegra30_ahub_probe(struct platform_device *pdev) 527 { 528 const struct of_device_id *match; 529 const struct tegra30_ahub_soc_data *soc_data; 530 struct reset_control *rst; 531 int i; 532 struct resource *res0; 533 void __iomem *regs_apbif, *regs_ahub; 534 int ret = 0; 535 536 if (ahub) 537 return -ENODEV; 538 539 match = of_match_device(tegra30_ahub_of_match, &pdev->dev); 540 if (!match) 541 return -EINVAL; 542 soc_data = match->data; 543 544 /* 545 * The AHUB hosts a register bus: the "configlink". For this to 546 * operate correctly, all devices on this bus must be out of reset. 547 */ 548 for (i = 0; i < ARRAY_SIZE(configlink_mods); i++) { 549 if (!(configlink_mods[i].mod_list_mask & 550 soc_data->mod_list_mask)) 551 continue; 552 553 rst = reset_control_get_exclusive(&pdev->dev, 554 configlink_mods[i].rst_name); 555 if (IS_ERR(rst)) { 556 dev_err(&pdev->dev, "Can't get reset %s\n", 557 configlink_mods[i].rst_name); 558 ret = PTR_ERR(rst); 559 return ret; 560 } 561 562 /* just check presence of the reset control in DT */ 563 reset_control_put(rst); 564 } 565 566 ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub), 567 GFP_KERNEL); 568 if (!ahub) 569 return -ENOMEM; 570 dev_set_drvdata(&pdev->dev, ahub); 571 572 ahub->soc_data = soc_data; 573 ahub->dev = &pdev->dev; 574 575 ahub->clocks[ahub->nclocks++].id = "apbif"; 576 ahub->clocks[ahub->nclocks++].id = "d_audio"; 577 578 ret = devm_clk_bulk_get(&pdev->dev, ahub->nclocks, ahub->clocks); 579 if (ret) 580 return ret; 581 582 ahub->reset = devm_reset_control_array_get_exclusive(&pdev->dev); 583 if (IS_ERR(ahub->reset)) { 584 dev_err(&pdev->dev, "Can't get resets: %pe\n", ahub->reset); 585 return PTR_ERR(ahub->reset); 586 } 587 588 res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); 589 regs_apbif = devm_ioremap_resource(&pdev->dev, res0); 590 if (IS_ERR(regs_apbif)) 591 return PTR_ERR(regs_apbif); 592 593 ahub->apbif_addr = res0->start; 594 595 ahub->regmap_apbif = devm_regmap_init_mmio(&pdev->dev, regs_apbif, 596 &tegra30_ahub_apbif_regmap_config); 597 if (IS_ERR(ahub->regmap_apbif)) { 598 dev_err(&pdev->dev, "apbif regmap init failed\n"); 599 ret = PTR_ERR(ahub->regmap_apbif); 600 return ret; 601 } 602 regcache_cache_only(ahub->regmap_apbif, true); 603 604 regs_ahub = devm_platform_ioremap_resource(pdev, 1); 605 if (IS_ERR(regs_ahub)) 606 return PTR_ERR(regs_ahub); 607 608 ahub->regmap_ahub = devm_regmap_init_mmio(&pdev->dev, regs_ahub, 609 &tegra30_ahub_ahub_regmap_config); 610 if (IS_ERR(ahub->regmap_ahub)) { 611 dev_err(&pdev->dev, "ahub regmap init failed\n"); 612 ret = PTR_ERR(ahub->regmap_ahub); 613 return ret; 614 } 615 regcache_cache_only(ahub->regmap_ahub, true); 616 617 pm_runtime_enable(&pdev->dev); 618 if (!pm_runtime_enabled(&pdev->dev)) { 619 ret = tegra30_ahub_runtime_resume(&pdev->dev); 620 if (ret) 621 goto err_pm_disable; 622 } 623 624 of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); 625 626 return 0; 627 628 err_pm_disable: 629 pm_runtime_disable(&pdev->dev); 630 631 return ret; 632 } 633 634 static int tegra30_ahub_remove(struct platform_device *pdev) 635 { 636 if (!ahub) 637 return -ENODEV; 638 639 pm_runtime_disable(&pdev->dev); 640 if (!pm_runtime_status_suspended(&pdev->dev)) 641 tegra30_ahub_runtime_suspend(&pdev->dev); 642 643 return 0; 644 } 645 646 #ifdef CONFIG_PM_SLEEP 647 static int tegra30_ahub_suspend(struct device *dev) 648 { 649 regcache_mark_dirty(ahub->regmap_ahub); 650 regcache_mark_dirty(ahub->regmap_apbif); 651 652 return 0; 653 } 654 655 static int tegra30_ahub_resume(struct device *dev) 656 { 657 int ret; 658 659 ret = pm_runtime_get_sync(dev); 660 if (ret < 0) { 661 pm_runtime_put(dev); 662 return ret; 663 } 664 ret = regcache_sync(ahub->regmap_ahub); 665 ret |= regcache_sync(ahub->regmap_apbif); 666 pm_runtime_put(dev); 667 668 return ret; 669 } 670 #endif 671 672 static const struct dev_pm_ops tegra30_ahub_pm_ops = { 673 SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend, 674 tegra30_ahub_runtime_resume, NULL) 675 SET_SYSTEM_SLEEP_PM_OPS(tegra30_ahub_suspend, tegra30_ahub_resume) 676 }; 677 678 static struct platform_driver tegra30_ahub_driver = { 679 .probe = tegra30_ahub_probe, 680 .remove = tegra30_ahub_remove, 681 .driver = { 682 .name = DRV_NAME, 683 .of_match_table = tegra30_ahub_of_match, 684 .pm = &tegra30_ahub_pm_ops, 685 }, 686 }; 687 module_platform_driver(tegra30_ahub_driver); 688 689 void tegra30_ahub_set_cif(struct regmap *regmap, unsigned int reg, 690 struct tegra30_ahub_cif_conf *conf) 691 { 692 unsigned int value; 693 694 value = (conf->threshold << 695 TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | 696 ((conf->audio_channels - 1) << 697 TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | 698 ((conf->client_channels - 1) << 699 TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | 700 (conf->audio_bits << 701 TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) | 702 (conf->client_bits << 703 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) | 704 (conf->expand << 705 TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) | 706 (conf->stereo_conv << 707 TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) | 708 (conf->replicate << 709 TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) | 710 (conf->direction << 711 TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) | 712 (conf->truncate << 713 TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) | 714 (conf->mono_conv << 715 TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT); 716 717 regmap_write(regmap, reg, value); 718 } 719 EXPORT_SYMBOL_GPL(tegra30_ahub_set_cif); 720 721 void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg, 722 struct tegra30_ahub_cif_conf *conf) 723 { 724 unsigned int value; 725 726 value = (conf->threshold << 727 TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | 728 ((conf->audio_channels - 1) << 729 TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | 730 ((conf->client_channels - 1) << 731 TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | 732 (conf->audio_bits << 733 TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) | 734 (conf->client_bits << 735 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) | 736 (conf->expand << 737 TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) | 738 (conf->stereo_conv << 739 TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) | 740 (conf->replicate << 741 TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) | 742 (conf->direction << 743 TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) | 744 (conf->truncate << 745 TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) | 746 (conf->mono_conv << 747 TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT); 748 749 regmap_write(regmap, reg, value); 750 } 751 EXPORT_SYMBOL_GPL(tegra124_ahub_set_cif); 752 753 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); 754 MODULE_DESCRIPTION("Tegra30 AHUB driver"); 755 MODULE_LICENSE("GPL v2"); 756 MODULE_ALIAS("platform:" DRV_NAME); 757 MODULE_DEVICE_TABLE(of, tegra30_ahub_of_match); 758