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