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