| 1 | |
| 2 | |
| 3 | * Driver for Audio DMA Controller (ADMAC) on t8103 (M1) and other Apple chips
|
| 4 | *
|
| 5 | * Copyright (C) The Asahi Linux Contributors
|
| 6 |
|
| 7 |
|
| 8 | #include <linux/bits.h>
|
| 9 | #include <linux/bitfield.h>
|
| 10 | #include <linux/device.h>
|
| 11 | #include <linux/init.h>
|
| 12 | #include <linux/module.h>
|
| 13 | #include <linux/of.h>
|
| 14 | #include <linux/of_dma.h>
|
| 15 | #include <linux/platform_device.h>
|
| 16 | #include <linux/reset.h>
|
| 17 | #include <linux/spinlock.h>
|
| 18 | #include <linux/interrupt.h>
|
| 19 |
|
| 20 | #include "dmaengine.h"
|
| 21 |
|
| 22 | #define NCHANNELS_MAX 64
|
| 23 | #define IRQ_NOUTPUTS 4
|
| 24 |
|
| 25 | |
| 26 | * For allocation purposes we split the cache
|
| 27 | * memory into blocks of fixed size (given in bytes).
|
| 28 |
|
| 29 | #define SRAM_BLOCK 2048
|
| 30 |
|
| 31 | #define RING_WRITE_SLOT GENMASK(1, 0)
|
| 32 | #define RING_READ_SLOT GENMASK(5, 4)
|
| 33 | #define RING_FULL BIT(9)
|
| 34 | #define RING_EMPTY BIT(8)
|
| 35 | #define RING_ERR BIT(10)
|
| 36 |
|
| 37 | #define STATUS_DESC_DONE BIT(0)
|
| 38 | #define STATUS_ERR BIT(6)
|
| 39 |
|
| 40 | #define FLAG_DESC_NOTIFY BIT(16)
|
| 41 |
|
| 42 | #define REG_TX_START 0x0000
|
| 43 | #define REG_TX_STOP 0x0004
|
| 44 | #define REG_RX_START 0x0008
|
| 45 | #define REG_RX_STOP 0x000c
|
| 46 | #define REG_IMPRINT 0x0090
|
| 47 | #define REG_TX_SRAM_SIZE 0x0094
|
| 48 | #define REG_RX_SRAM_SIZE 0x0098
|
| 49 |
|
| 50 | #define REG_CHAN_CTL(ch) (0x8000 + (ch) * 0x200)
|
| 51 | #define REG_CHAN_CTL_RST_RINGS BIT(0)
|
| 52 |
|
| 53 | #define REG_DESC_RING(ch) (0x8070 + (ch) * 0x200)
|
| 54 | #define REG_REPORT_RING(ch) (0x8074 + (ch) * 0x200)
|
| 55 |
|
| 56 | #define REG_RESIDUE(ch) (0x8064 + (ch) * 0x200)
|
| 57 |
|
| 58 | #define REG_BUS_WIDTH(ch) (0x8040 + (ch) * 0x200)
|
| 59 |
|
| 60 | #define BUS_WIDTH_WORD_SIZE GENMASK(3, 0)
|
| 61 | #define BUS_WIDTH_FRAME_SIZE GENMASK(7, 4)
|
| 62 | #define BUS_WIDTH_8BIT 0x00
|
| 63 | #define BUS_WIDTH_16BIT 0x01
|
| 64 | #define BUS_WIDTH_32BIT 0x02
|
| 65 | #define BUS_WIDTH_FRAME_2_WORDS 0x10
|
| 66 | #define BUS_WIDTH_FRAME_4_WORDS 0x20
|
| 67 |
|
| 68 | #define REG_CHAN_SRAM_CARVEOUT(ch) (0x8050 + (ch) * 0x200)
|
| 69 | #define CHAN_SRAM_CARVEOUT_SIZE GENMASK(31, 16)
|
| 70 | #define CHAN_SRAM_CARVEOUT_BASE GENMASK(15, 0)
|
| 71 |
|
| 72 | #define REG_CHAN_FIFOCTL(ch) (0x8054 + (ch) * 0x200)
|
| 73 | #define CHAN_FIFOCTL_LIMIT GENMASK(31, 16)
|
| 74 | #define CHAN_FIFOCTL_THRESHOLD GENMASK(15, 0)
|
| 75 |
|
| 76 | #define REG_DESC_WRITE(ch) (0x10000 + ((ch) / 2) * 0x4 + ((ch) & 1) * 0x4000)
|
| 77 | #define REG_REPORT_READ(ch) (0x10100 + ((ch) / 2) * 0x4 + ((ch) & 1) * 0x4000)
|
| 78 |
|
| 79 | #define REG_TX_INTSTATE(idx) (0x0030 + (idx) * 4)
|
| 80 | #define REG_RX_INTSTATE(idx) (0x0040 + (idx) * 4)
|
| 81 | #define REG_GLOBAL_INTSTATE(idx) (0x0050 + (idx) * 4)
|
| 82 | #define REG_CHAN_INTSTATUS(ch, idx) (0x8010 + (ch) * 0x200 + (idx) * 4)
|
| 83 | #define REG_CHAN_INTMASK(ch, idx) (0x8020 + (ch) * 0x200 + (idx) * 4)
|
| 84 |
|
| 85 | struct admac_data;
|
| 86 | struct admac_tx;
|
| 87 |
|
| 88 | struct admac_chan {
|
| 89 | unsigned int no;
|
| 90 | struct admac_data *host;
|
| 91 | struct dma_chan chan;
|
| 92 | struct tasklet_struct tasklet;
|
| 93 |
|
| 94 | u32 carveout;
|
| 95 |
|
| 96 | spinlock_t lock;
|
| 97 | struct admac_tx *current_tx;
|
| 98 | int nperiod_acks;
|
| 99 |
|
| 100 | |
| 101 | * We maintain a 'submitted' and 'issued' list mainly for interface
|
| 102 | * correctness. Typical use of the driver (per channel) will be
|
| 103 | * prepping, submitting and issuing a single cyclic transaction which
|
| 104 | * will stay current until terminate_all is called.
|
| 105 |
|
| 106 | struct list_head submitted;
|
| 107 | struct list_head issued;
|
| 108 |
|
| 109 | struct list_head to_free;
|
| 110 | };
|
| 111 |
|
| 112 | struct admac_sram {
|
| 113 | u32 size;
|
| 114 | |
| 115 | * SRAM_CARVEOUT has 16-bit fields, so the SRAM cannot be larger than
|
| 116 | * 64K and a 32-bit bitfield over 2K blocks covers it.
|
| 117 |
|
| 118 | u32 allocated;
|
| 119 | };
|
| 120 |
|
| 121 | struct admac_data {
|
| 122 | struct dma_device dma;
|
| 123 | struct device *dev;
|
| 124 | __iomem void *base;
|
| 125 | struct reset_control *rstc;
|
| 126 |
|
| 127 | struct mutex cache_alloc_lock;
|
| 128 | struct admac_sram txcache, rxcache;
|
| 129 |
|
| 130 | int irq;
|
| 131 | int irq_index;
|
| 132 | int nchannels;
|
| 133 | struct admac_chan channels[] __counted_by(nchannels);
|
| 134 | };
|
| 135 |
|
| 136 | struct admac_tx {
|
| 137 | struct dma_async_tx_descriptor tx;
|
| 138 | bool cyclic;
|
| 139 | dma_addr_t buf_addr;
|
| 140 | dma_addr_t buf_end;
|
| 141 | size_t buf_len;
|
| 142 | size_t period_len;
|
| 143 |
|
| 144 | size_t submitted_pos;
|
| 145 | size_t reclaimed_pos;
|
| 146 |
|
| 147 | struct list_head node;
|
| 148 | };
|
| 149 |
|
| 150 | static int admac_alloc_sram_carveout(struct admac_data *ad,
|
| 151 | enum dma_transfer_direction dir,
|
| 152 | u32 *out)
|
| 153 | {
|
| 154 | struct admac_sram *sram;
|
| 155 | int i, ret = 0, nblocks;
|
| 156 | ad->txcache.size = readl_relaxed(ad->base + REG_TX_SRAM_SIZE);
|
| 157 | ad->rxcache.size = readl_relaxed(ad->base + REG_RX_SRAM_SIZE);
|
| 158 |
|
| 159 | if (dir == DMA_MEM_TO_DEV)
|
| 160 | sram = &ad->txcache;
|
| 161 | else
|
| 162 | sram = &ad->rxcache;
|
| 163 |
|
| 164 | mutex_lock(&ad->cache_alloc_lock);
|
| 165 |
|
| 166 | nblocks = sram->size / SRAM_BLOCK;
|
| 167 | for (i = 0; i < nblocks; i++)
|
| 168 | if (!(sram->allocated & BIT(i)))
|
| 169 | break;
|
| 170 |
|
| 171 | if (i < nblocks) {
|
| 172 | *out = FIELD_PREP(CHAN_SRAM_CARVEOUT_BASE, i * SRAM_BLOCK) |
|
| 173 | FIELD_PREP(CHAN_SRAM_CARVEOUT_SIZE, SRAM_BLOCK);
|
| 174 | sram->allocated |= BIT(i);
|
| 175 | } else {
|
| 176 | ret = -EBUSY;
|
| 177 | }
|
| 178 |
|
| 179 | mutex_unlock(&ad->cache_alloc_lock);
|
| 180 |
|
| 181 | return ret;
|
| 182 | }
|
| 183 |
|
| 184 | static void admac_free_sram_carveout(struct admac_data *ad,
|
| 185 | enum dma_transfer_direction dir,
|
| 186 | u32 carveout)
|
| 187 | {
|
| 188 | struct admac_sram *sram;
|
| 189 | u32 base = FIELD_GET(CHAN_SRAM_CARVEOUT_BASE, carveout);
|
| 190 | int i;
|
| 191 |
|
| 192 | if (dir == DMA_MEM_TO_DEV)
|
| 193 | sram = &ad->txcache;
|
| 194 | else
|
| 195 | sram = &ad->rxcache;
|
| 196 |
|
| 197 | if (WARN_ON(base >= sram->size))
|
| 198 | return;
|
| 199 |
|
| 200 | mutex_lock(&ad->cache_alloc_lock);
|
| 201 | i = base / SRAM_BLOCK;
|
| 202 | sram->allocated &= ~BIT(i);
|
| 203 | mutex_unlock(&ad->cache_alloc_lock);
|
| 204 | }
|
| 205 |
|
| 206 | static void admac_modify(struct admac_data *ad, int reg, u32 mask, u32 val)
|
| 207 | {
|
| 208 | void __iomem *addr = ad->base + reg;
|
| 209 | u32 curr = readl_relaxed(addr);
|
| 210 |
|
| 211 | writel_relaxed((curr & ~mask) | (val & mask), addr);
|
| 212 | }
|
| 213 |
|
| 214 | static struct admac_chan *to_admac_chan(struct dma_chan *chan)
|
| 215 | {
|
| 216 | return container_of(chan, struct admac_chan, chan);
|
| 217 | }
|
| 218 |
|
| 219 | static struct admac_tx *to_admac_tx(struct dma_async_tx_descriptor *tx)
|
| 220 | {
|
| 221 | return container_of(tx, struct admac_tx, tx);
|
| 222 | }
|
| 223 |
|
| 224 | static enum dma_transfer_direction admac_chan_direction(int channo)
|
| 225 | {
|
| 226 |
|
| 227 | return (channo & 1) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
|
| 228 | }
|
| 229 |
|
| 230 | static dma_cookie_t admac_tx_submit(struct dma_async_tx_descriptor *tx)
|
| 231 | {
|
| 232 | struct admac_tx *adtx = to_admac_tx(tx);
|
| 233 | struct admac_chan *adchan = to_admac_chan(tx->chan);
|
| 234 | unsigned long flags;
|
| 235 | dma_cookie_t cookie;
|
| 236 |
|
| 237 | spin_lock_irqsave(&adchan->lock, flags);
|
| 238 | cookie = dma_cookie_assign(tx);
|
| 239 | list_add_tail(&adtx->node, &adchan->submitted);
|
| 240 | spin_unlock_irqrestore(&adchan->lock, flags);
|
| 241 |
|
| 242 | return cookie;
|
| 243 | }
|
| 244 |
|
| 245 | static int admac_desc_free(struct dma_async_tx_descriptor *tx)
|
| 246 | {
|
| 247 | kfree(to_admac_tx(tx));
|
| 248 |
|
| 249 | return 0;
|
| 250 | }
|
| 251 |
|
| 252 | static struct dma_async_tx_descriptor *admac_prep_dma_cyclic(
|
| 253 | struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
|
| 254 | size_t period_len, enum dma_transfer_direction direction,
|
| 255 | unsigned long flags)
|
| 256 | {
|
| 257 | struct admac_chan *adchan = container_of(chan, struct admac_chan, chan);
|
| 258 | struct admac_tx *adtx;
|
| 259 |
|
| 260 | if (direction != admac_chan_direction(adchan->no))
|
| 261 | return NULL;
|
| 262 |
|
| 263 | adtx = kzalloc_obj(*adtx, GFP_NOWAIT);
|
| 264 | if (!adtx)
|
| 265 | return NULL;
|
| 266 |
|
| 267 | adtx->cyclic = true;
|
| 268 |
|
| 269 | adtx->buf_addr = buf_addr;
|
| 270 | adtx->buf_len = buf_len;
|
| 271 | adtx->buf_end = buf_addr + buf_len;
|
| 272 | adtx->period_len = period_len;
|
| 273 |
|
| 274 | adtx->submitted_pos = 0;
|
| 275 | adtx->reclaimed_pos = 0;
|
| 276 |
|
| 277 | dma_async_tx_descriptor_init(&adtx->tx, chan);
|
| 278 | adtx->tx.tx_submit = admac_tx_submit;
|
| 279 | adtx->tx.desc_free = admac_desc_free;
|
| 280 |
|
| 281 | return &adtx->tx;
|
| 282 | }
|
| 283 |
|
| 284 | |
| 285 | * Write one hardware descriptor for a dmaengine cyclic transaction.
|
| 286 |
|
| 287 | static void admac_cyclic_write_one_desc(struct admac_data *ad, int channo,
|
| 288 | struct admac_tx *tx)
|
| 289 | {
|
| 290 | dma_addr_t addr;
|
| 291 |
|
| 292 | addr = tx->buf_addr + (tx->submitted_pos % tx->buf_len);
|
| 293 |
|
| 294 |
|
| 295 | WARN_ON_ONCE(addr + tx->period_len > tx->buf_end);
|
| 296 |
|
| 297 | dev_dbg(ad->dev, "ch%d descriptor: addr=0x%pad len=0x%zx flags=0x%lx\n",
|
| 298 | channo, &addr, tx->period_len, FLAG_DESC_NOTIFY);
|
| 299 |
|
| 300 | writel_relaxed(lower_32_bits(addr), ad->base + REG_DESC_WRITE(channo));
|
| 301 | writel_relaxed(upper_32_bits(addr), ad->base + REG_DESC_WRITE(channo));
|
| 302 | writel_relaxed(tx->period_len, ad->base + REG_DESC_WRITE(channo));
|
| 303 | writel_relaxed(FLAG_DESC_NOTIFY, ad->base + REG_DESC_WRITE(channo));
|
| 304 |
|
| 305 | tx->submitted_pos += tx->period_len;
|
| 306 | tx->submitted_pos %= 2 * tx->buf_len;
|
| 307 | }
|
| 308 |
|
| 309 | |
| 310 | * Write all the hardware descriptors for a dmaengine cyclic
|
| 311 | * transaction there is space for.
|
| 312 |
|
| 313 | static void admac_cyclic_write_desc(struct admac_data *ad, int channo,
|
| 314 | struct admac_tx *tx)
|
| 315 | {
|
| 316 | int i;
|
| 317 |
|
| 318 | for (i = 0; i < 4; i++) {
|
| 319 | if (readl_relaxed(ad->base + REG_DESC_RING(channo)) & RING_FULL)
|
| 320 | break;
|
| 321 | admac_cyclic_write_one_desc(ad, channo, tx);
|
| 322 | }
|
| 323 | }
|
| 324 |
|
| 325 | static int admac_ring_noccupied_slots(int ringval)
|
| 326 | {
|
| 327 | int wrslot = FIELD_GET(RING_WRITE_SLOT, ringval);
|
| 328 | int rdslot = FIELD_GET(RING_READ_SLOT, ringval);
|
| 329 |
|
| 330 | if (wrslot != rdslot) {
|
| 331 | return (wrslot + 4 - rdslot) % 4;
|
| 332 | } else {
|
| 333 | WARN_ON((ringval & (RING_FULL | RING_EMPTY)) == 0);
|
| 334 |
|
| 335 | if (ringval & RING_FULL)
|
| 336 | return 4;
|
| 337 | else
|
| 338 | return 0;
|
| 339 | }
|
| 340 | }
|
| 341 |
|
| 342 | |
| 343 | * Read from hardware the residue of a cyclic dmaengine transaction.
|
| 344 |
|
| 345 | static u32 admac_cyclic_read_residue(struct admac_data *ad, int channo,
|
| 346 | struct admac_tx *adtx)
|
| 347 | {
|
| 348 | u32 ring1, ring2;
|
| 349 | u32 residue1, residue2;
|
| 350 | int nreports;
|
| 351 | size_t pos;
|
| 352 |
|
| 353 | ring1 = readl_relaxed(ad->base + REG_REPORT_RING(channo));
|
| 354 | residue1 = readl_relaxed(ad->base + REG_RESIDUE(channo));
|
| 355 | ring2 = readl_relaxed(ad->base + REG_REPORT_RING(channo));
|
| 356 | residue2 = readl_relaxed(ad->base + REG_RESIDUE(channo));
|
| 357 |
|
| 358 | if (residue2 > residue1) {
|
| 359 | |
| 360 | * Controller must have loaded next descriptor between
|
| 361 | * the two residue reads
|
| 362 |
|
| 363 | nreports = admac_ring_noccupied_slots(ring1) + 1;
|
| 364 | } else {
|
| 365 |
|
| 366 | nreports = admac_ring_noccupied_slots(ring2);
|
| 367 | }
|
| 368 |
|
| 369 | pos = adtx->reclaimed_pos + adtx->period_len * (nreports + 1) - residue2;
|
| 370 |
|
| 371 | return adtx->buf_len - pos % adtx->buf_len;
|
| 372 | }
|
| 373 |
|
| 374 | static enum dma_status admac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
|
| 375 | struct dma_tx_state *txstate)
|
| 376 | {
|
| 377 | struct admac_chan *adchan = to_admac_chan(chan);
|
| 378 | struct admac_data *ad = adchan->host;
|
| 379 | struct admac_tx *adtx;
|
| 380 |
|
| 381 | enum dma_status ret;
|
| 382 | size_t residue;
|
| 383 | unsigned long flags;
|
| 384 |
|
| 385 | ret = dma_cookie_status(chan, cookie, txstate);
|
| 386 | if (ret == DMA_COMPLETE || !txstate)
|
| 387 | return ret;
|
| 388 |
|
| 389 | spin_lock_irqsave(&adchan->lock, flags);
|
| 390 | adtx = adchan->current_tx;
|
| 391 |
|
| 392 | if (adtx && adtx->tx.cookie == cookie) {
|
| 393 | ret = DMA_IN_PROGRESS;
|
| 394 | residue = admac_cyclic_read_residue(ad, adchan->no, adtx);
|
| 395 | } else {
|
| 396 | ret = DMA_IN_PROGRESS;
|
| 397 | residue = 0;
|
| 398 | list_for_each_entry(adtx, &adchan->issued, node) {
|
| 399 | if (adtx->tx.cookie == cookie) {
|
| 400 | residue = adtx->buf_len;
|
| 401 | break;
|
| 402 | }
|
| 403 | }
|
| 404 | }
|
| 405 | spin_unlock_irqrestore(&adchan->lock, flags);
|
| 406 |
|
| 407 | dma_set_residue(txstate, residue);
|
| 408 | return ret;
|
| 409 | }
|
| 410 |
|
| 411 | static void admac_start_chan(struct admac_chan *adchan)
|
| 412 | {
|
| 413 | struct admac_data *ad = adchan->host;
|
| 414 | u32 startbit = 1 << (adchan->no / 2);
|
| 415 |
|
| 416 | writel_relaxed(STATUS_DESC_DONE | STATUS_ERR,
|
| 417 | ad->base + REG_CHAN_INTSTATUS(adchan->no, ad->irq_index));
|
| 418 | writel_relaxed(STATUS_DESC_DONE | STATUS_ERR,
|
| 419 | ad->base + REG_CHAN_INTMASK(adchan->no, ad->irq_index));
|
| 420 |
|
| 421 | switch (admac_chan_direction(adchan->no)) {
|
| 422 | case DMA_MEM_TO_DEV:
|
| 423 | writel_relaxed(startbit, ad->base + REG_TX_START);
|
| 424 | break;
|
| 425 | case DMA_DEV_TO_MEM:
|
| 426 | writel_relaxed(startbit, ad->base + REG_RX_START);
|
| 427 | break;
|
| 428 | default:
|
| 429 | break;
|
| 430 | }
|
| 431 | dev_dbg(adchan->host->dev, "ch%d start\n", adchan->no);
|
| 432 | }
|
| 433 |
|
| 434 | static void admac_stop_chan(struct admac_chan *adchan)
|
| 435 | {
|
| 436 | struct admac_data *ad = adchan->host;
|
| 437 | u32 stopbit = 1 << (adchan->no / 2);
|
| 438 |
|
| 439 | switch (admac_chan_direction(adchan->no)) {
|
| 440 | case DMA_MEM_TO_DEV:
|
| 441 | writel_relaxed(stopbit, ad->base + REG_TX_STOP);
|
| 442 | break;
|
| 443 | case DMA_DEV_TO_MEM:
|
| 444 | writel_relaxed(stopbit, ad->base + REG_RX_STOP);
|
| 445 | break;
|
| 446 | default:
|
| 447 | break;
|
| 448 | }
|
| 449 | dev_dbg(adchan->host->dev, "ch%d stop\n", adchan->no);
|
| 450 | }
|
| 451 |
|
| 452 | static void admac_reset_rings(struct admac_chan *adchan)
|
| 453 | {
|
| 454 | struct admac_data *ad = adchan->host;
|
| 455 |
|
| 456 | writel_relaxed(REG_CHAN_CTL_RST_RINGS,
|
| 457 | ad->base + REG_CHAN_CTL(adchan->no));
|
| 458 | writel_relaxed(0, ad->base + REG_CHAN_CTL(adchan->no));
|
| 459 | }
|
| 460 |
|
| 461 | static void admac_start_current_tx(struct admac_chan *adchan)
|
| 462 | {
|
| 463 | struct admac_data *ad = adchan->host;
|
| 464 | int ch = adchan->no;
|
| 465 |
|
| 466 | admac_reset_rings(adchan);
|
| 467 | writel_relaxed(0, ad->base + REG_CHAN_CTL(ch));
|
| 468 |
|
| 469 | admac_cyclic_write_one_desc(ad, ch, adchan->current_tx);
|
| 470 | admac_start_chan(adchan);
|
| 471 | admac_cyclic_write_desc(ad, ch, adchan->current_tx);
|
| 472 | }
|
| 473 |
|
| 474 | static void admac_issue_pending(struct dma_chan *chan)
|
| 475 | {
|
| 476 | struct admac_chan *adchan = to_admac_chan(chan);
|
| 477 | struct admac_tx *tx;
|
| 478 | unsigned long flags;
|
| 479 |
|
| 480 | spin_lock_irqsave(&adchan->lock, flags);
|
| 481 | list_splice_tail_init(&adchan->submitted, &adchan->issued);
|
| 482 | if (!list_empty(&adchan->issued) && !adchan->current_tx) {
|
| 483 | tx = list_first_entry(&adchan->issued, struct admac_tx, node);
|
| 484 | list_del(&tx->node);
|
| 485 |
|
| 486 | adchan->current_tx = tx;
|
| 487 | adchan->nperiod_acks = 0;
|
| 488 | admac_start_current_tx(adchan);
|
| 489 | }
|
| 490 | spin_unlock_irqrestore(&adchan->lock, flags);
|
| 491 | }
|
| 492 |
|
| 493 | static int admac_pause(struct dma_chan *chan)
|
| 494 | {
|
| 495 | struct admac_chan *adchan = to_admac_chan(chan);
|
| 496 |
|
| 497 | admac_stop_chan(adchan);
|
| 498 |
|
| 499 | return 0;
|
| 500 | }
|
| 501 |
|
| 502 | static int admac_resume(struct dma_chan *chan)
|
| 503 | {
|
| 504 | struct admac_chan *adchan = to_admac_chan(chan);
|
| 505 |
|
| 506 | admac_start_chan(adchan);
|
| 507 |
|
| 508 | return 0;
|
| 509 | }
|
| 510 |
|
| 511 | static int admac_terminate_all(struct dma_chan *chan)
|
| 512 | {
|
| 513 | struct admac_chan *adchan = to_admac_chan(chan);
|
| 514 | unsigned long flags;
|
| 515 |
|
| 516 | spin_lock_irqsave(&adchan->lock, flags);
|
| 517 | admac_stop_chan(adchan);
|
| 518 | admac_reset_rings(adchan);
|
| 519 |
|
| 520 | if (adchan->current_tx) {
|
| 521 | list_add_tail(&adchan->current_tx->node, &adchan->to_free);
|
| 522 | adchan->current_tx = NULL;
|
| 523 | }
|
| 524 | |
| 525 | * Descriptors can only be freed after the tasklet
|
| 526 | * has been killed (in admac_synchronize).
|
| 527 |
|
| 528 | list_splice_tail_init(&adchan->submitted, &adchan->to_free);
|
| 529 | list_splice_tail_init(&adchan->issued, &adchan->to_free);
|
| 530 | spin_unlock_irqrestore(&adchan->lock, flags);
|
| 531 |
|
| 532 | return 0;
|
| 533 | }
|
| 534 |
|
| 535 | static void admac_synchronize(struct dma_chan *chan)
|
| 536 | {
|
| 537 | struct admac_chan *adchan = to_admac_chan(chan);
|
| 538 | struct admac_tx *adtx, *_adtx;
|
| 539 | unsigned long flags;
|
| 540 | LIST_HEAD(head);
|
| 541 |
|
| 542 | spin_lock_irqsave(&adchan->lock, flags);
|
| 543 | list_splice_tail_init(&adchan->to_free, &head);
|
| 544 | spin_unlock_irqrestore(&adchan->lock, flags);
|
| 545 |
|
| 546 | tasklet_kill(&adchan->tasklet);
|
| 547 |
|
| 548 | list_for_each_entry_safe(adtx, _adtx, &head, node) {
|
| 549 | list_del(&adtx->node);
|
| 550 | admac_desc_free(&adtx->tx);
|
| 551 | }
|
| 552 | }
|
| 553 |
|
| 554 | static int admac_alloc_chan_resources(struct dma_chan *chan)
|
| 555 | {
|
| 556 | struct admac_chan *adchan = to_admac_chan(chan);
|
| 557 | struct admac_data *ad = adchan->host;
|
| 558 | int ret;
|
| 559 |
|
| 560 | dma_cookie_init(&adchan->chan);
|
| 561 | ret = admac_alloc_sram_carveout(ad, admac_chan_direction(adchan->no),
|
| 562 | &adchan->carveout);
|
| 563 | if (ret < 0)
|
| 564 | return ret;
|
| 565 |
|
| 566 | writel_relaxed(adchan->carveout,
|
| 567 | ad->base + REG_CHAN_SRAM_CARVEOUT(adchan->no));
|
| 568 | return 0;
|
| 569 | }
|
| 570 |
|
| 571 | static void admac_free_chan_resources(struct dma_chan *chan)
|
| 572 | {
|
| 573 | struct admac_chan *adchan = to_admac_chan(chan);
|
| 574 |
|
| 575 | admac_terminate_all(chan);
|
| 576 | admac_synchronize(chan);
|
| 577 | admac_free_sram_carveout(adchan->host, admac_chan_direction(adchan->no),
|
| 578 | adchan->carveout);
|
| 579 | }
|
| 580 |
|
| 581 | static struct dma_chan *admac_dma_of_xlate(struct of_phandle_args *dma_spec,
|
| 582 | struct of_dma *ofdma)
|
| 583 | {
|
| 584 | struct admac_data *ad = (struct admac_data *) ofdma->of_dma_data;
|
| 585 | unsigned int index;
|
| 586 |
|
| 587 | if (dma_spec->args_count != 1)
|
| 588 | return NULL;
|
| 589 |
|
| 590 | index = dma_spec->args[0];
|
| 591 |
|
| 592 | if (index >= ad->nchannels) {
|
| 593 | dev_err(ad->dev, "channel index %u out of bounds\n", index);
|
| 594 | return NULL;
|
| 595 | }
|
| 596 |
|
| 597 | return dma_get_slave_channel(&ad->channels[index].chan);
|
| 598 | }
|
| 599 |
|
| 600 | static int admac_drain_reports(struct admac_data *ad, int channo)
|
| 601 | {
|
| 602 | int count;
|
| 603 |
|
| 604 | for (count = 0; count < 4; count++) {
|
| 605 | u32 countval_hi, countval_lo, unk1, flags;
|
| 606 |
|
| 607 | if (readl_relaxed(ad->base + REG_REPORT_RING(channo)) & RING_EMPTY)
|
| 608 | break;
|
| 609 |
|
| 610 | countval_lo = readl_relaxed(ad->base + REG_REPORT_READ(channo));
|
| 611 | countval_hi = readl_relaxed(ad->base + REG_REPORT_READ(channo));
|
| 612 | unk1 = readl_relaxed(ad->base + REG_REPORT_READ(channo));
|
| 613 | flags = readl_relaxed(ad->base + REG_REPORT_READ(channo));
|
| 614 |
|
| 615 | dev_dbg(ad->dev, "ch%d report: countval=0x%llx unk1=0x%x flags=0x%x\n",
|
| 616 | channo, ((u64) countval_hi) << 32 | countval_lo, unk1, flags);
|
| 617 | }
|
| 618 |
|
| 619 | return count;
|
| 620 | }
|
| 621 |
|
| 622 | static void admac_handle_status_err(struct admac_data *ad, int channo)
|
| 623 | {
|
| 624 | bool handled = false;
|
| 625 |
|
| 626 | if (readl_relaxed(ad->base + REG_DESC_RING(channo)) & RING_ERR) {
|
| 627 | writel_relaxed(RING_ERR, ad->base + REG_DESC_RING(channo));
|
| 628 | dev_err_ratelimited(ad->dev, "ch%d descriptor ring error\n", channo);
|
| 629 | handled = true;
|
| 630 | }
|
| 631 |
|
| 632 | if (readl_relaxed(ad->base + REG_REPORT_RING(channo)) & RING_ERR) {
|
| 633 | writel_relaxed(RING_ERR, ad->base + REG_REPORT_RING(channo));
|
| 634 | dev_err_ratelimited(ad->dev, "ch%d report ring error\n", channo);
|
| 635 | handled = true;
|
| 636 | }
|
| 637 |
|
| 638 | if (unlikely(!handled)) {
|
| 639 | dev_err(ad->dev, "ch%d unknown error, masking errors as cause of IRQs\n", channo);
|
| 640 | admac_modify(ad, REG_CHAN_INTMASK(channo, ad->irq_index),
|
| 641 | STATUS_ERR, 0);
|
| 642 | }
|
| 643 | }
|
| 644 |
|
| 645 | static void admac_handle_status_desc_done(struct admac_data *ad, int channo)
|
| 646 | {
|
| 647 | struct admac_chan *adchan = &ad->channels[channo];
|
| 648 | unsigned long flags;
|
| 649 | int nreports;
|
| 650 |
|
| 651 | writel_relaxed(STATUS_DESC_DONE,
|
| 652 | ad->base + REG_CHAN_INTSTATUS(channo, ad->irq_index));
|
| 653 |
|
| 654 | spin_lock_irqsave(&adchan->lock, flags);
|
| 655 | nreports = admac_drain_reports(ad, channo);
|
| 656 |
|
| 657 | if (adchan->current_tx) {
|
| 658 | struct admac_tx *tx = adchan->current_tx;
|
| 659 |
|
| 660 | adchan->nperiod_acks += nreports;
|
| 661 | tx->reclaimed_pos += nreports * tx->period_len;
|
| 662 | tx->reclaimed_pos %= 2 * tx->buf_len;
|
| 663 |
|
| 664 | admac_cyclic_write_desc(ad, channo, tx);
|
| 665 | tasklet_schedule(&adchan->tasklet);
|
| 666 | }
|
| 667 | spin_unlock_irqrestore(&adchan->lock, flags);
|
| 668 | }
|
| 669 |
|
| 670 | static void admac_handle_chan_int(struct admac_data *ad, int no)
|
| 671 | {
|
| 672 | u32 cause = readl_relaxed(ad->base + REG_CHAN_INTSTATUS(no, ad->irq_index));
|
| 673 |
|
| 674 | if (cause & STATUS_ERR)
|
| 675 | admac_handle_status_err(ad, no);
|
| 676 |
|
| 677 | if (cause & STATUS_DESC_DONE)
|
| 678 | admac_handle_status_desc_done(ad, no);
|
| 679 | }
|
| 680 |
|
| 681 | static irqreturn_t admac_interrupt(int irq, void *devid)
|
| 682 | {
|
| 683 | struct admac_data *ad = devid;
|
| 684 | u32 rx_intstate, tx_intstate, global_intstate;
|
| 685 | int i;
|
| 686 |
|
| 687 | rx_intstate = readl_relaxed(ad->base + REG_RX_INTSTATE(ad->irq_index));
|
| 688 | tx_intstate = readl_relaxed(ad->base + REG_TX_INTSTATE(ad->irq_index));
|
| 689 | global_intstate = readl_relaxed(ad->base + REG_GLOBAL_INTSTATE(ad->irq_index));
|
| 690 |
|
| 691 | if (!tx_intstate && !rx_intstate && !global_intstate)
|
| 692 | return IRQ_NONE;
|
| 693 |
|
| 694 | for (i = 0; i < ad->nchannels; i += 2) {
|
| 695 | if (tx_intstate & 1)
|
| 696 | admac_handle_chan_int(ad, i);
|
| 697 | tx_intstate >>= 1;
|
| 698 | }
|
| 699 |
|
| 700 | for (i = 1; i < ad->nchannels; i += 2) {
|
| 701 | if (rx_intstate & 1)
|
| 702 | admac_handle_chan_int(ad, i);
|
| 703 | rx_intstate >>= 1;
|
| 704 | }
|
| 705 |
|
| 706 | if (global_intstate) {
|
| 707 | dev_warn(ad->dev, "clearing unknown global interrupt flag: %x\n",
|
| 708 | global_intstate);
|
| 709 | writel_relaxed(~(u32) 0, ad->base + REG_GLOBAL_INTSTATE(ad->irq_index));
|
| 710 | }
|
| 711 |
|
| 712 | return IRQ_HANDLED;
|
| 713 | }
|
| 714 |
|
| 715 | static void admac_chan_tasklet(struct tasklet_struct *t)
|
| 716 | {
|
| 717 | struct admac_chan *adchan = from_tasklet(adchan, t, tasklet);
|
| 718 | struct admac_tx *adtx;
|
| 719 | struct dmaengine_desc_callback cb;
|
| 720 | struct dmaengine_result tx_result;
|
| 721 | int nacks;
|
| 722 |
|
| 723 | spin_lock_irq(&adchan->lock);
|
| 724 | adtx = adchan->current_tx;
|
| 725 | nacks = adchan->nperiod_acks;
|
| 726 | adchan->nperiod_acks = 0;
|
| 727 | spin_unlock_irq(&adchan->lock);
|
| 728 |
|
| 729 | if (!adtx || !nacks)
|
| 730 | return;
|
| 731 |
|
| 732 | tx_result.result = DMA_TRANS_NOERROR;
|
| 733 | tx_result.residue = 0;
|
| 734 |
|
| 735 | dmaengine_desc_get_callback(&adtx->tx, &cb);
|
| 736 | while (nacks--)
|
| 737 | dmaengine_desc_callback_invoke(&cb, &tx_result);
|
| 738 | }
|
| 739 |
|
| 740 | static int admac_device_config(struct dma_chan *chan,
|
| 741 | struct dma_slave_config *config)
|
| 742 | {
|
| 743 | struct admac_chan *adchan = to_admac_chan(chan);
|
| 744 | struct admac_data *ad = adchan->host;
|
| 745 | bool is_tx = admac_chan_direction(adchan->no) == DMA_MEM_TO_DEV;
|
| 746 | int wordsize = 0;
|
| 747 | u32 bus_width = readl_relaxed(ad->base + REG_BUS_WIDTH(adchan->no)) &
|
| 748 | ~(BUS_WIDTH_WORD_SIZE | BUS_WIDTH_FRAME_SIZE);
|
| 749 |
|
| 750 | switch (is_tx ? config->dst_addr_width : config->src_addr_width) {
|
| 751 | case DMA_SLAVE_BUSWIDTH_1_BYTE:
|
| 752 | wordsize = 1;
|
| 753 | bus_width |= BUS_WIDTH_8BIT;
|
| 754 | break;
|
| 755 | case DMA_SLAVE_BUSWIDTH_2_BYTES:
|
| 756 | wordsize = 2;
|
| 757 | bus_width |= BUS_WIDTH_16BIT;
|
| 758 | break;
|
| 759 | case DMA_SLAVE_BUSWIDTH_4_BYTES:
|
| 760 | wordsize = 4;
|
| 761 | bus_width |= BUS_WIDTH_32BIT;
|
| 762 | break;
|
| 763 | default:
|
| 764 | return -EINVAL;
|
| 765 | }
|
| 766 |
|
| 767 | |
| 768 | * We take port_window_size to be the number of words in a frame.
|
| 769 | *
|
| 770 | * The controller has some means of out-of-band signalling, to the peripheral,
|
| 771 | * of words position in a frame. That's where the importance of this control
|
| 772 | * comes from.
|
| 773 |
|
| 774 | switch (is_tx ? config->dst_port_window_size : config->src_port_window_size) {
|
| 775 | case 0 ... 1:
|
| 776 | break;
|
| 777 | case 2:
|
| 778 | bus_width |= BUS_WIDTH_FRAME_2_WORDS;
|
| 779 | break;
|
| 780 | case 4:
|
| 781 | bus_width |= BUS_WIDTH_FRAME_4_WORDS;
|
| 782 | break;
|
| 783 | default:
|
| 784 | return -EINVAL;
|
| 785 | }
|
| 786 |
|
| 787 | writel_relaxed(bus_width, ad->base + REG_BUS_WIDTH(adchan->no));
|
| 788 |
|
| 789 | |
| 790 | * By FIFOCTL_LIMIT we seem to set the maximal number of bytes allowed to be
|
| 791 | * held in controller's per-channel FIFO. Transfers seem to be triggered
|
| 792 | * around the time FIFO occupancy touches FIFOCTL_THRESHOLD.
|
| 793 | *
|
| 794 | * The numbers we set are more or less arbitrary.
|
| 795 |
|
| 796 | writel_relaxed(FIELD_PREP(CHAN_FIFOCTL_LIMIT, 0x30 * wordsize)
|
| 797 | | FIELD_PREP(CHAN_FIFOCTL_THRESHOLD, 0x18 * wordsize),
|
| 798 | ad->base + REG_CHAN_FIFOCTL(adchan->no));
|
| 799 |
|
| 800 | return 0;
|
| 801 | }
|
| 802 |
|
| 803 | static int admac_probe(struct platform_device *pdev)
|
| 804 | {
|
| 805 | struct device_node *np = pdev->dev.of_node;
|
| 806 | struct admac_data *ad;
|
| 807 | struct dma_device *dma;
|
| 808 | int nchannels;
|
| 809 | int err, irq, i;
|
| 810 |
|
| 811 | err = of_property_read_u32(np, "dma-channels", &nchannels);
|
| 812 | if (err || nchannels > NCHANNELS_MAX) {
|
| 813 | dev_err(&pdev->dev, "missing or invalid dma-channels property\n");
|
| 814 | return -EINVAL;
|
| 815 | }
|
| 816 |
|
| 817 | ad = devm_kzalloc(&pdev->dev, struct_size(ad, channels, nchannels), GFP_KERNEL);
|
| 818 | if (!ad)
|
| 819 | return -ENOMEM;
|
| 820 |
|
| 821 | platform_set_drvdata(pdev, ad);
|
| 822 | ad->dev = &pdev->dev;
|
| 823 | ad->nchannels = nchannels;
|
| 824 | mutex_init(&ad->cache_alloc_lock);
|
| 825 |
|
| 826 | |
| 827 | * The controller has 4 IRQ outputs. Try them all until
|
| 828 | * we find one we can use.
|
| 829 |
|
| 830 | for (i = 0; i < IRQ_NOUTPUTS; i++) {
|
| 831 | irq = platform_get_irq_optional(pdev, i);
|
| 832 | if (irq >= 0) {
|
| 833 | ad->irq_index = i;
|
| 834 | break;
|
| 835 | }
|
| 836 | }
|
| 837 |
|
| 838 | if (irq < 0)
|
| 839 | return dev_err_probe(&pdev->dev, irq, "no usable interrupt\n");
|
| 840 | ad->irq = irq;
|
| 841 |
|
| 842 | ad->base = devm_platform_ioremap_resource(pdev, 0);
|
| 843 | if (IS_ERR(ad->base))
|
| 844 | return dev_err_probe(&pdev->dev, PTR_ERR(ad->base),
|
| 845 | "unable to obtain MMIO resource\n");
|
| 846 |
|
| 847 | ad->rstc = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
|
| 848 | if (IS_ERR(ad->rstc))
|
| 849 | return PTR_ERR(ad->rstc);
|
| 850 |
|
| 851 | dma = &ad->dma;
|
| 852 |
|
| 853 | dma_cap_set(DMA_PRIVATE, dma->cap_mask);
|
| 854 | dma_cap_set(DMA_CYCLIC, dma->cap_mask);
|
| 855 |
|
| 856 | dma->dev = &pdev->dev;
|
| 857 | dma->device_alloc_chan_resources = admac_alloc_chan_resources;
|
| 858 | dma->device_free_chan_resources = admac_free_chan_resources;
|
| 859 | dma->device_tx_status = admac_tx_status;
|
| 860 | dma->device_issue_pending = admac_issue_pending;
|
| 861 | dma->device_terminate_all = admac_terminate_all;
|
| 862 | dma->device_synchronize = admac_synchronize;
|
| 863 | dma->device_prep_dma_cyclic = admac_prep_dma_cyclic;
|
| 864 | dma->device_config = admac_device_config;
|
| 865 | dma->device_pause = admac_pause;
|
| 866 | dma->device_resume = admac_resume;
|
| 867 |
|
| 868 | dma->directions = BIT(DMA_MEM_TO_DEV) | BIT(DMA_DEV_TO_MEM);
|
| 869 | dma->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
|
| 870 | dma->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
|
| 871 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
|
| 872 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
|
| 873 | dma->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
|
| 874 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
|
| 875 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
|
| 876 |
|
| 877 | INIT_LIST_HEAD(&dma->channels);
|
| 878 | for (i = 0; i < nchannels; i++) {
|
| 879 | struct admac_chan *adchan = &ad->channels[i];
|
| 880 |
|
| 881 | adchan->host = ad;
|
| 882 | adchan->no = i;
|
| 883 | adchan->chan.device = &ad->dma;
|
| 884 | spin_lock_init(&adchan->lock);
|
| 885 | INIT_LIST_HEAD(&adchan->submitted);
|
| 886 | INIT_LIST_HEAD(&adchan->issued);
|
| 887 | INIT_LIST_HEAD(&adchan->to_free);
|
| 888 | list_add_tail(&adchan->chan.device_node, &dma->channels);
|
| 889 | tasklet_setup(&adchan->tasklet, admac_chan_tasklet);
|
| 890 | }
|
| 891 |
|
| 892 | err = reset_control_reset(ad->rstc);
|
| 893 | if (err)
|
| 894 | return dev_err_probe(&pdev->dev, err,
|
| 895 | "unable to trigger reset\n");
|
| 896 |
|
| 897 | err = request_irq(irq, admac_interrupt, 0, dev_name(&pdev->dev), ad);
|
| 898 | if (err) {
|
| 899 | dev_err_probe(&pdev->dev, err,
|
| 900 | "unable to register interrupt\n");
|
| 901 | goto free_reset;
|
| 902 | }
|
| 903 |
|
| 904 | err = dma_async_device_register(&ad->dma);
|
| 905 | if (err) {
|
| 906 | dev_err_probe(&pdev->dev, err, "failed to register DMA device\n");
|
| 907 | goto free_irq;
|
| 908 | }
|
| 909 |
|
| 910 | err = of_dma_controller_register(pdev->dev.of_node, admac_dma_of_xlate, ad);
|
| 911 | if (err) {
|
| 912 | dma_async_device_unregister(&ad->dma);
|
| 913 | dev_err_probe(&pdev->dev, err, "failed to register with OF\n");
|
| 914 | goto free_irq;
|
| 915 | }
|
| 916 |
|
| 917 | dev_info(&pdev->dev, "Audio DMA Controller\n");
|
| 918 |
|
| 919 | return 0;
|
| 920 |
|
| 921 | free_irq:
|
| 922 | free_irq(ad->irq, ad);
|
| 923 | free_reset:
|
| 924 | reset_control_rearm(ad->rstc);
|
| 925 | return err;
|
| 926 | }
|
| 927 |
|
| 928 | static void admac_remove(struct platform_device *pdev)
|
| 929 | {
|
| 930 | struct admac_data *ad = platform_get_drvdata(pdev);
|
| 931 |
|
| 932 | of_dma_controller_free(pdev->dev.of_node);
|
| 933 | dma_async_device_unregister(&ad->dma);
|
| 934 | free_irq(ad->irq, ad);
|
| 935 | reset_control_rearm(ad->rstc);
|
| 936 | }
|
| 937 |
|
| 938 | static const struct of_device_id admac_of_match[] = {
|
| 939 | { .compatible = "apple,t8103-admac", },
|
| 940 | { .compatible = "apple,admac", },
|
| 941 | { }
|
| 942 | };
|
| 943 | MODULE_DEVICE_TABLE(of, admac_of_match);
|
| 944 |
|
| 945 | static struct platform_driver apple_admac_driver = {
|
| 946 | .driver = {
|
| 947 | .name = "apple-admac",
|
| 948 | .of_match_table = admac_of_match,
|
| 949 | },
|
| 950 | .probe = admac_probe,
|
| 951 | .remove = admac_remove,
|
| 952 | };
|
| 953 | module_platform_driver(apple_admac_driver);
|
| 954 |
|
| 955 | MODULE_AUTHOR("Martin Povišer <[email protected]>");
|
| 956 | MODULE_DESCRIPTION("Driver for Audio DMA Controller (ADMAC) on Apple SoCs");
|
| 957 | MODULE_LICENSE("GPL");
|