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