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