root/sound/soc/tegra/tegra30_ahub.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tegra30_apbif_write
  2. tegra30_apbif_read
  3. tegra30_audio_write
  4. tegra30_ahub_runtime_suspend
  5. tegra30_ahub_runtime_resume
  6. tegra30_ahub_allocate_rx_fifo
  7. tegra30_ahub_enable_rx_fifo
  8. tegra30_ahub_disable_rx_fifo
  9. tegra30_ahub_free_rx_fifo
  10. tegra30_ahub_allocate_tx_fifo
  11. tegra30_ahub_enable_tx_fifo
  12. tegra30_ahub_disable_tx_fifo
  13. tegra30_ahub_free_tx_fifo
  14. tegra30_ahub_set_rx_cif_source
  15. tegra30_ahub_unset_rx_cif_source
  16. tegra30_ahub_apbif_wr_rd_reg
  17. tegra30_ahub_apbif_volatile_reg
  18. tegra30_ahub_apbif_precious_reg
  19. tegra30_ahub_ahub_wr_rd_reg
  20. tegra30_ahub_probe
  21. tegra30_ahub_remove
  22. tegra30_ahub_suspend
  23. tegra30_ahub_resume
  24. tegra30_ahub_set_cif
  25. tegra124_ahub_set_cif

   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);

/* [<][>][^][v][top][bottom][index][help] */