linux/sound/soc/sof/intel/byt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
   2//
   3// This file is provided under a dual BSD/GPLv2 license.  When using or
   4// redistributing this file, you may do so under either license.
   5//
   6// Copyright(c) 2018 Intel Corporation. All rights reserved.
   7//
   8// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
   9//
  10
  11/*
  12 * Hardware interface for audio DSP on Baytrail, Braswell and Cherrytrail.
  13 */
  14
  15#include <linux/module.h>
  16#include <sound/sof.h>
  17#include <sound/sof/xtensa.h>
  18#include "../ops.h"
  19#include "shim.h"
  20
  21/* DSP memories */
  22#define IRAM_OFFSET             0x0C0000
  23#define IRAM_SIZE               (80 * 1024)
  24#define DRAM_OFFSET             0x100000
  25#define DRAM_SIZE               (160 * 1024)
  26#define SHIM_OFFSET             0x140000
  27#define SHIM_SIZE               0x100
  28#define MBOX_OFFSET             0x144000
  29#define MBOX_SIZE               0x1000
  30#define EXCEPT_OFFSET           0x800
  31
  32/* DSP peripherals */
  33#define DMAC0_OFFSET            0x098000
  34#define DMAC1_OFFSET            0x09c000
  35#define DMAC2_OFFSET            0x094000
  36#define DMAC_SIZE               0x420
  37#define SSP0_OFFSET             0x0a0000
  38#define SSP1_OFFSET             0x0a1000
  39#define SSP2_OFFSET             0x0a2000
  40#define SSP3_OFFSET             0x0a4000
  41#define SSP4_OFFSET             0x0a5000
  42#define SSP5_OFFSET             0x0a6000
  43#define SSP_SIZE                0x100
  44
  45#define BYT_STACK_DUMP_SIZE     32
  46
  47#define BYT_PCI_BAR_SIZE        0x200000
  48
  49#define BYT_PANIC_OFFSET(x)     (((x) & GENMASK_ULL(47, 32)) >> 32)
  50
  51/*
  52 * Debug
  53 */
  54
  55#define MBOX_DUMP_SIZE  0x30
  56
  57/* BARs */
  58#define BYT_DSP_BAR             0
  59#define BYT_PCI_BAR             1
  60#define BYT_IMR_BAR             2
  61
  62static const struct snd_sof_debugfs_map byt_debugfs[] = {
  63        {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
  64         SOF_DEBUGFS_ACCESS_ALWAYS},
  65        {"dmac1", BYT_DSP_BAR,  DMAC1_OFFSET, DMAC_SIZE,
  66         SOF_DEBUGFS_ACCESS_ALWAYS},
  67        {"ssp0",  BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE,
  68         SOF_DEBUGFS_ACCESS_ALWAYS},
  69        {"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE,
  70         SOF_DEBUGFS_ACCESS_ALWAYS},
  71        {"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE,
  72         SOF_DEBUGFS_ACCESS_ALWAYS},
  73        {"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE,
  74         SOF_DEBUGFS_ACCESS_D0_ONLY},
  75        {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
  76         SOF_DEBUGFS_ACCESS_D0_ONLY},
  77        {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,
  78         SOF_DEBUGFS_ACCESS_ALWAYS},
  79};
  80
  81static const struct snd_sof_debugfs_map cht_debugfs[] = {
  82        {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
  83         SOF_DEBUGFS_ACCESS_ALWAYS},
  84        {"dmac1", BYT_DSP_BAR,  DMAC1_OFFSET, DMAC_SIZE,
  85         SOF_DEBUGFS_ACCESS_ALWAYS},
  86        {"dmac2", BYT_DSP_BAR,  DMAC2_OFFSET, DMAC_SIZE,
  87         SOF_DEBUGFS_ACCESS_ALWAYS},
  88        {"ssp0",  BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE,
  89         SOF_DEBUGFS_ACCESS_ALWAYS},
  90        {"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE,
  91         SOF_DEBUGFS_ACCESS_ALWAYS},
  92        {"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE,
  93         SOF_DEBUGFS_ACCESS_ALWAYS},
  94        {"ssp3", BYT_DSP_BAR, SSP3_OFFSET, SSP_SIZE,
  95         SOF_DEBUGFS_ACCESS_ALWAYS},
  96        {"ssp4", BYT_DSP_BAR, SSP4_OFFSET, SSP_SIZE,
  97         SOF_DEBUGFS_ACCESS_ALWAYS},
  98        {"ssp5", BYT_DSP_BAR, SSP5_OFFSET, SSP_SIZE,
  99         SOF_DEBUGFS_ACCESS_ALWAYS},
 100        {"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE,
 101         SOF_DEBUGFS_ACCESS_D0_ONLY},
 102        {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
 103         SOF_DEBUGFS_ACCESS_D0_ONLY},
 104        {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,
 105         SOF_DEBUGFS_ACCESS_ALWAYS},
 106};
 107
 108static void byt_host_done(struct snd_sof_dev *sdev);
 109static void byt_dsp_done(struct snd_sof_dev *sdev);
 110static void byt_get_reply(struct snd_sof_dev *sdev);
 111
 112/*
 113 * IPC Firmware ready.
 114 */
 115static void byt_get_windows(struct snd_sof_dev *sdev)
 116{
 117        struct sof_ipc_window_elem *elem;
 118        u32 outbox_offset = 0;
 119        u32 stream_offset = 0;
 120        u32 inbox_offset = 0;
 121        u32 outbox_size = 0;
 122        u32 stream_size = 0;
 123        u32 inbox_size = 0;
 124        int i;
 125
 126        if (!sdev->info_window) {
 127                dev_err(sdev->dev, "error: have no window info\n");
 128                return;
 129        }
 130
 131        for (i = 0; i < sdev->info_window->num_windows; i++) {
 132                elem = &sdev->info_window->window[i];
 133
 134                switch (elem->type) {
 135                case SOF_IPC_REGION_UPBOX:
 136                        inbox_offset = elem->offset + MBOX_OFFSET;
 137                        inbox_size = elem->size;
 138                        snd_sof_debugfs_io_item(sdev,
 139                                                sdev->bar[BYT_DSP_BAR] +
 140                                                inbox_offset,
 141                                                elem->size, "inbox",
 142                                                SOF_DEBUGFS_ACCESS_D0_ONLY);
 143                        break;
 144                case SOF_IPC_REGION_DOWNBOX:
 145                        outbox_offset = elem->offset + MBOX_OFFSET;
 146                        outbox_size = elem->size;
 147                        snd_sof_debugfs_io_item(sdev,
 148                                                sdev->bar[BYT_DSP_BAR] +
 149                                                outbox_offset,
 150                                                elem->size, "outbox",
 151                                                SOF_DEBUGFS_ACCESS_D0_ONLY);
 152                        break;
 153                case SOF_IPC_REGION_TRACE:
 154                        snd_sof_debugfs_io_item(sdev,
 155                                                sdev->bar[BYT_DSP_BAR] +
 156                                                elem->offset +
 157                                                MBOX_OFFSET,
 158                                                elem->size, "etrace",
 159                                                SOF_DEBUGFS_ACCESS_D0_ONLY);
 160                        break;
 161                case SOF_IPC_REGION_DEBUG:
 162                        snd_sof_debugfs_io_item(sdev,
 163                                                sdev->bar[BYT_DSP_BAR] +
 164                                                elem->offset +
 165                                                MBOX_OFFSET,
 166                                                elem->size, "debug",
 167                                                SOF_DEBUGFS_ACCESS_D0_ONLY);
 168                        break;
 169                case SOF_IPC_REGION_STREAM:
 170                        stream_offset = elem->offset + MBOX_OFFSET;
 171                        stream_size = elem->size;
 172                        snd_sof_debugfs_io_item(sdev,
 173                                                sdev->bar[BYT_DSP_BAR] +
 174                                                stream_offset,
 175                                                elem->size, "stream",
 176                                                SOF_DEBUGFS_ACCESS_D0_ONLY);
 177                        break;
 178                case SOF_IPC_REGION_REGS:
 179                        snd_sof_debugfs_io_item(sdev,
 180                                                sdev->bar[BYT_DSP_BAR] +
 181                                                elem->offset +
 182                                                MBOX_OFFSET,
 183                                                elem->size, "regs",
 184                                                SOF_DEBUGFS_ACCESS_D0_ONLY);
 185                        break;
 186                case SOF_IPC_REGION_EXCEPTION:
 187                        sdev->dsp_oops_offset = elem->offset + MBOX_OFFSET;
 188                        snd_sof_debugfs_io_item(sdev,
 189                                                sdev->bar[BYT_DSP_BAR] +
 190                                                elem->offset +
 191                                                MBOX_OFFSET,
 192                                                elem->size, "exception",
 193                                                SOF_DEBUGFS_ACCESS_D0_ONLY);
 194                        break;
 195                default:
 196                        dev_err(sdev->dev, "error: get illegal window info\n");
 197                        return;
 198                }
 199        }
 200
 201        if (outbox_size == 0 || inbox_size == 0) {
 202                dev_err(sdev->dev, "error: get illegal mailbox window\n");
 203                return;
 204        }
 205
 206        snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size,
 207                                 outbox_offset, outbox_size);
 208        sdev->stream_box.offset = stream_offset;
 209        sdev->stream_box.size = stream_size;
 210
 211        dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n",
 212                inbox_offset, inbox_size);
 213        dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n",
 214                outbox_offset, outbox_size);
 215        dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n",
 216                stream_offset, stream_size);
 217}
 218
 219/* check for ABI compatibility and create memory windows on first boot */
 220static int byt_fw_ready(struct snd_sof_dev *sdev, u32 msg_id)
 221{
 222        struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready;
 223        u32 offset;
 224        int ret;
 225
 226        /* mailbox must be on 4k boundary */
 227        offset = MBOX_OFFSET;
 228
 229        dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n",
 230                msg_id, offset);
 231
 232        /* no need to re-check version/ABI for subsequent boots */
 233        if (!sdev->first_boot)
 234                return 0;
 235
 236        /* copy data from the DSP FW ready offset */
 237        sof_block_read(sdev, sdev->mmio_bar, offset, fw_ready,
 238                       sizeof(*fw_ready));
 239
 240        snd_sof_dsp_mailbox_init(sdev, fw_ready->dspbox_offset,
 241                                 fw_ready->dspbox_size,
 242                                 fw_ready->hostbox_offset,
 243                                 fw_ready->hostbox_size);
 244
 245        /* make sure ABI version is compatible */
 246        ret = snd_sof_ipc_valid(sdev);
 247        if (ret < 0)
 248                return ret;
 249
 250        /* now check for extended data */
 251        snd_sof_fw_parse_ext_data(sdev, sdev->mmio_bar, MBOX_OFFSET +
 252                                  sizeof(struct sof_ipc_fw_ready));
 253
 254        byt_get_windows(sdev);
 255
 256        return 0;
 257}
 258
 259/*
 260 * Debug
 261 */
 262
 263static void byt_get_registers(struct snd_sof_dev *sdev,
 264                              struct sof_ipc_dsp_oops_xtensa *xoops,
 265                              struct sof_ipc_panic_info *panic_info,
 266                              u32 *stack, size_t stack_words)
 267{
 268        u32 offset = sdev->dsp_oops_offset;
 269
 270        /* first read regsisters */
 271        sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
 272
 273        /* note: variable AR register array is not read */
 274
 275        /* then get panic info */
 276        offset += xoops->arch_hdr.totalsize;
 277        sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
 278
 279        /* then get the stack */
 280        offset += sizeof(*panic_info);
 281        sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
 282}
 283
 284static void byt_dump(struct snd_sof_dev *sdev, u32 flags)
 285{
 286        struct sof_ipc_dsp_oops_xtensa xoops;
 287        struct sof_ipc_panic_info panic_info;
 288        u32 stack[BYT_STACK_DUMP_SIZE];
 289        u32 status, panic;
 290
 291        /* now try generic SOF status messages */
 292        status = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCD);
 293        panic = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCX);
 294        byt_get_registers(sdev, &xoops, &panic_info, stack,
 295                          BYT_STACK_DUMP_SIZE);
 296        snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
 297                           BYT_STACK_DUMP_SIZE);
 298}
 299
 300/*
 301 * IPC Doorbell IRQ handler and thread.
 302 */
 303
 304static irqreturn_t byt_irq_handler(int irq, void *context)
 305{
 306        struct snd_sof_dev *sdev = context;
 307        u64 isr;
 308        int ret = IRQ_NONE;
 309
 310        /* Interrupt arrived, check src */
 311        isr = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_ISRX);
 312        if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY))
 313                ret = IRQ_WAKE_THREAD;
 314
 315        return ret;
 316}
 317
 318static irqreturn_t byt_irq_thread(int irq, void *context)
 319{
 320        struct snd_sof_dev *sdev = context;
 321        u64 ipcx, ipcd;
 322        u64 imrx;
 323
 324        imrx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRX);
 325        ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX);
 326
 327        /* reply message from DSP */
 328        if (ipcx & SHIM_BYT_IPCX_DONE &&
 329            !(imrx & SHIM_IMRX_DONE)) {
 330                /* Mask Done interrupt before first */
 331                snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR,
 332                                                   SHIM_IMRX,
 333                                                   SHIM_IMRX_DONE,
 334                                                   SHIM_IMRX_DONE);
 335
 336                spin_lock_irq(&sdev->ipc_lock);
 337
 338                /*
 339                 * handle immediate reply from DSP core. If the msg is
 340                 * found, set done bit in cmd_done which is called at the
 341                 * end of message processing function, else set it here
 342                 * because the done bit can't be set in cmd_done function
 343                 * which is triggered by msg
 344                 */
 345                byt_get_reply(sdev);
 346                snd_sof_ipc_reply(sdev, ipcx);
 347
 348                byt_dsp_done(sdev);
 349
 350                spin_unlock_irq(&sdev->ipc_lock);
 351        }
 352
 353        /* new message from DSP */
 354        ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD);
 355        if (ipcd & SHIM_BYT_IPCD_BUSY &&
 356            !(imrx & SHIM_IMRX_BUSY)) {
 357                /* Mask Busy interrupt before return */
 358                snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR,
 359                                                   SHIM_IMRX,
 360                                                   SHIM_IMRX_BUSY,
 361                                                   SHIM_IMRX_BUSY);
 362
 363                /* Handle messages from DSP Core */
 364                if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
 365                        snd_sof_dsp_panic(sdev, BYT_PANIC_OFFSET(ipcd) +
 366                                          MBOX_OFFSET);
 367                } else {
 368                        snd_sof_ipc_msgs_rx(sdev);
 369                }
 370
 371                byt_host_done(sdev);
 372        }
 373
 374        return IRQ_HANDLED;
 375}
 376
 377static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
 378{
 379        /* send the message */
 380        sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
 381                          msg->msg_size);
 382        snd_sof_dsp_write64(sdev, BYT_DSP_BAR, SHIM_IPCX, SHIM_BYT_IPCX_BUSY);
 383
 384        return 0;
 385}
 386
 387static void byt_get_reply(struct snd_sof_dev *sdev)
 388{
 389        struct snd_sof_ipc_msg *msg = sdev->msg;
 390        struct sof_ipc_reply reply;
 391        int ret = 0;
 392
 393        /*
 394         * Sometimes, there is unexpected reply ipc arriving. The reply
 395         * ipc belongs to none of the ipcs sent from driver.
 396         * In this case, the driver must ignore the ipc.
 397         */
 398        if (!msg) {
 399                dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
 400                return;
 401        }
 402
 403        /* get reply */
 404        sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
 405
 406        if (reply.error < 0) {
 407                memcpy(msg->reply_data, &reply, sizeof(reply));
 408                ret = reply.error;
 409        } else {
 410                /* reply correct size ? */
 411                if (reply.hdr.size != msg->reply_size) {
 412                        dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n",
 413                                msg->reply_size, reply.hdr.size);
 414                        ret = -EINVAL;
 415                }
 416
 417                /* read the message */
 418                if (msg->reply_size > 0)
 419                        sof_mailbox_read(sdev, sdev->host_box.offset,
 420                                         msg->reply_data, msg->reply_size);
 421        }
 422
 423        msg->reply_error = ret;
 424}
 425
 426static void byt_host_done(struct snd_sof_dev *sdev)
 427{
 428        /* clear BUSY bit and set DONE bit - accept new messages */
 429        snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCD,
 430                                           SHIM_BYT_IPCD_BUSY |
 431                                           SHIM_BYT_IPCD_DONE,
 432                                           SHIM_BYT_IPCD_DONE);
 433
 434        /* unmask busy interrupt */
 435        snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
 436                                           SHIM_IMRX_BUSY, 0);
 437}
 438
 439static void byt_dsp_done(struct snd_sof_dev *sdev)
 440{
 441        /* clear DONE bit - tell DSP we have completed */
 442        snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX,
 443                                           SHIM_BYT_IPCX_DONE, 0);
 444
 445        /* unmask Done interrupt */
 446        snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
 447                                           SHIM_IMRX_DONE, 0);
 448}
 449
 450/*
 451 * DSP control.
 452 */
 453
 454static int byt_run(struct snd_sof_dev *sdev)
 455{
 456        int tries = 10;
 457
 458        /* release stall and wait to unstall */
 459        snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
 460                                  SHIM_BYT_CSR_STALL, 0x0);
 461        while (tries--) {
 462                if (!(snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_CSR) &
 463                      SHIM_BYT_CSR_PWAITMODE))
 464                        break;
 465                msleep(100);
 466        }
 467        if (tries < 0) {
 468                dev_err(sdev->dev, "error:  unable to run DSP firmware\n");
 469                byt_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX);
 470                return -ENODEV;
 471        }
 472
 473        /* return init core mask */
 474        return 1;
 475}
 476
 477static int byt_reset(struct snd_sof_dev *sdev)
 478{
 479        /* put DSP into reset, set reset vector and stall */
 480        snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
 481                                  SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
 482                                  SHIM_BYT_CSR_STALL,
 483                                  SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
 484                                  SHIM_BYT_CSR_STALL);
 485
 486        usleep_range(10, 15);
 487
 488        /* take DSP out of reset and keep stalled for FW loading */
 489        snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
 490                                  SHIM_BYT_CSR_RST, 0);
 491
 492        return 0;
 493}
 494
 495/* Baytrail DAIs */
 496static struct snd_soc_dai_driver byt_dai[] = {
 497{
 498        .name = "ssp0-port",
 499},
 500{
 501        .name = "ssp1-port",
 502},
 503{
 504        .name = "ssp2-port",
 505},
 506{
 507        .name = "ssp3-port",
 508},
 509{
 510        .name = "ssp4-port",
 511},
 512{
 513        .name = "ssp5-port",
 514},
 515};
 516
 517/*
 518 * Probe and remove.
 519 */
 520
 521#if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
 522
 523static int tangier_pci_probe(struct snd_sof_dev *sdev)
 524{
 525        struct snd_sof_pdata *pdata = sdev->pdata;
 526        const struct sof_dev_desc *desc = pdata->desc;
 527        struct pci_dev *pci = to_pci_dev(sdev->dev);
 528        u32 base, size;
 529        int ret;
 530
 531        /* DSP DMA can only access low 31 bits of host memory */
 532        ret = dma_coerce_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31));
 533        if (ret < 0) {
 534                dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
 535                return ret;
 536        }
 537
 538        /* LPE base */
 539        base = pci_resource_start(pci, desc->resindex_lpe_base) - IRAM_OFFSET;
 540        size = BYT_PCI_BAR_SIZE;
 541
 542        dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
 543        sdev->bar[BYT_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
 544        if (!sdev->bar[BYT_DSP_BAR]) {
 545                dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
 546                        base, size);
 547                return -ENODEV;
 548        }
 549        dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BYT_DSP_BAR]);
 550
 551        /* IMR base - optional */
 552        if (desc->resindex_imr_base == -1)
 553                goto irq;
 554
 555        base = pci_resource_start(pci, desc->resindex_imr_base);
 556        size = pci_resource_len(pci, desc->resindex_imr_base);
 557
 558        /* some BIOSes don't map IMR */
 559        if (base == 0x55aa55aa || base == 0x0) {
 560                dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
 561                goto irq;
 562        }
 563
 564        dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
 565        sdev->bar[BYT_IMR_BAR] = devm_ioremap(sdev->dev, base, size);
 566        if (!sdev->bar[BYT_IMR_BAR]) {
 567                dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
 568                        base, size);
 569                return -ENODEV;
 570        }
 571        dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);
 572
 573irq:
 574        /* register our IRQ */
 575        sdev->ipc_irq = pci->irq;
 576        dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
 577        ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
 578                                        byt_irq_handler, byt_irq_thread,
 579                                        0, "AudioDSP", sdev);
 580        if (ret < 0) {
 581                dev_err(sdev->dev, "error: failed to register IRQ %d\n",
 582                        sdev->ipc_irq);
 583                return ret;
 584        }
 585
 586        /* enable Interrupt from both sides */
 587        snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0);
 588        snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0);
 589
 590        /* set default mailbox offset for FW ready message */
 591        sdev->dsp_box.offset = MBOX_OFFSET;
 592
 593        return ret;
 594}
 595
 596const struct snd_sof_dsp_ops sof_tng_ops = {
 597        /* device init */
 598        .probe          = tangier_pci_probe,
 599
 600        /* DSP core boot / reset */
 601        .run            = byt_run,
 602        .reset          = byt_reset,
 603
 604        /* Register IO */
 605        .write          = sof_io_write,
 606        .read           = sof_io_read,
 607        .write64        = sof_io_write64,
 608        .read64         = sof_io_read64,
 609
 610        /* Block IO */
 611        .block_read     = sof_block_read,
 612        .block_write    = sof_block_write,
 613
 614        /* doorbell */
 615        .irq_handler    = byt_irq_handler,
 616        .irq_thread     = byt_irq_thread,
 617
 618        /* ipc */
 619        .send_msg       = byt_send_msg,
 620        .fw_ready       = byt_fw_ready,
 621
 622        .ipc_msg_data   = intel_ipc_msg_data,
 623        .ipc_pcm_params = intel_ipc_pcm_params,
 624
 625        /* debug */
 626        .debug_map      = byt_debugfs,
 627        .debug_map_count        = ARRAY_SIZE(byt_debugfs),
 628        .dbg_dump       = byt_dump,
 629
 630        /* stream callbacks */
 631        .pcm_open       = intel_pcm_open,
 632        .pcm_close      = intel_pcm_close,
 633
 634        /* module loading */
 635        .load_module    = snd_sof_parse_module_memcpy,
 636
 637        /*Firmware loading */
 638        .load_firmware  = snd_sof_load_firmware_memcpy,
 639
 640        /* DAI drivers */
 641        .drv = byt_dai,
 642        .num_drv = 3, /* we have only 3 SSPs on byt*/
 643};
 644EXPORT_SYMBOL(sof_tng_ops);
 645
 646const struct sof_intel_dsp_desc tng_chip_info = {
 647        .cores_num = 1,
 648        .cores_mask = 1,
 649};
 650EXPORT_SYMBOL(tng_chip_info);
 651
 652#endif /* CONFIG_SND_SOC_SOF_MERRIFIELD */
 653
 654#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
 655
 656static int byt_acpi_probe(struct snd_sof_dev *sdev)
 657{
 658        struct snd_sof_pdata *pdata = sdev->pdata;
 659        const struct sof_dev_desc *desc = pdata->desc;
 660        struct platform_device *pdev =
 661                container_of(sdev->dev, struct platform_device, dev);
 662        struct resource *mmio;
 663        u32 base, size;
 664        int ret;
 665
 666        /* DSP DMA can only access low 31 bits of host memory */
 667        ret = dma_coerce_mask_and_coherent(sdev->dev, DMA_BIT_MASK(31));
 668        if (ret < 0) {
 669                dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
 670                return ret;
 671        }
 672
 673        /* LPE base */
 674        mmio = platform_get_resource(pdev, IORESOURCE_MEM,
 675                                     desc->resindex_lpe_base);
 676        if (mmio) {
 677                base = mmio->start;
 678                size = resource_size(mmio);
 679        } else {
 680                dev_err(sdev->dev, "error: failed to get LPE base at idx %d\n",
 681                        desc->resindex_lpe_base);
 682                return -EINVAL;
 683        }
 684
 685        dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
 686        sdev->bar[BYT_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
 687        if (!sdev->bar[BYT_DSP_BAR]) {
 688                dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
 689                        base, size);
 690                return -ENODEV;
 691        }
 692        dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BYT_DSP_BAR]);
 693
 694        /* TODO: add offsets */
 695        sdev->mmio_bar = BYT_DSP_BAR;
 696        sdev->mailbox_bar = BYT_DSP_BAR;
 697
 698        /* IMR base - optional */
 699        if (desc->resindex_imr_base == -1)
 700                goto irq;
 701
 702        mmio = platform_get_resource(pdev, IORESOURCE_MEM,
 703                                     desc->resindex_imr_base);
 704        if (mmio) {
 705                base = mmio->start;
 706                size = resource_size(mmio);
 707        } else {
 708                dev_err(sdev->dev, "error: failed to get IMR base at idx %d\n",
 709                        desc->resindex_imr_base);
 710                return -ENODEV;
 711        }
 712
 713        /* some BIOSes don't map IMR */
 714        if (base == 0x55aa55aa || base == 0x0) {
 715                dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
 716                goto irq;
 717        }
 718
 719        dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
 720        sdev->bar[BYT_IMR_BAR] = devm_ioremap(sdev->dev, base, size);
 721        if (!sdev->bar[BYT_IMR_BAR]) {
 722                dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
 723                        base, size);
 724                return -ENODEV;
 725        }
 726        dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);
 727
 728irq:
 729        /* register our IRQ */
 730        sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc);
 731        if (sdev->ipc_irq < 0) {
 732                dev_err(sdev->dev, "error: failed to get IRQ at index %d\n",
 733                        desc->irqindex_host_ipc);
 734                return sdev->ipc_irq;
 735        }
 736
 737        dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
 738        ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
 739                                        byt_irq_handler, byt_irq_thread,
 740                                        IRQF_SHARED, "AudioDSP", sdev);
 741        if (ret < 0) {
 742                dev_err(sdev->dev, "error: failed to register IRQ %d\n",
 743                        sdev->ipc_irq);
 744                return ret;
 745        }
 746
 747        /* enable Interrupt from both sides */
 748        snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0);
 749        snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0);
 750
 751        /* set default mailbox offset for FW ready message */
 752        sdev->dsp_box.offset = MBOX_OFFSET;
 753
 754        return ret;
 755}
 756
 757/* baytrail ops */
 758const struct snd_sof_dsp_ops sof_byt_ops = {
 759        /* device init */
 760        .probe          = byt_acpi_probe,
 761
 762        /* DSP core boot / reset */
 763        .run            = byt_run,
 764        .reset          = byt_reset,
 765
 766        /* Register IO */
 767        .write          = sof_io_write,
 768        .read           = sof_io_read,
 769        .write64        = sof_io_write64,
 770        .read64         = sof_io_read64,
 771
 772        /* Block IO */
 773        .block_read     = sof_block_read,
 774        .block_write    = sof_block_write,
 775
 776        /* doorbell */
 777        .irq_handler    = byt_irq_handler,
 778        .irq_thread     = byt_irq_thread,
 779
 780        /* ipc */
 781        .send_msg       = byt_send_msg,
 782        .fw_ready       = byt_fw_ready,
 783
 784        .ipc_msg_data   = intel_ipc_msg_data,
 785        .ipc_pcm_params = intel_ipc_pcm_params,
 786
 787        /* debug */
 788        .debug_map      = byt_debugfs,
 789        .debug_map_count        = ARRAY_SIZE(byt_debugfs),
 790        .dbg_dump       = byt_dump,
 791
 792        /* stream callbacks */
 793        .pcm_open       = intel_pcm_open,
 794        .pcm_close      = intel_pcm_close,
 795
 796        /* module loading */
 797        .load_module    = snd_sof_parse_module_memcpy,
 798
 799        /*Firmware loading */
 800        .load_firmware  = snd_sof_load_firmware_memcpy,
 801
 802        /* DAI drivers */
 803        .drv = byt_dai,
 804        .num_drv = 3, /* we have only 3 SSPs on byt*/
 805};
 806EXPORT_SYMBOL(sof_byt_ops);
 807
 808const struct sof_intel_dsp_desc byt_chip_info = {
 809        .cores_num = 1,
 810        .cores_mask = 1,
 811};
 812EXPORT_SYMBOL(byt_chip_info);
 813
 814/* cherrytrail and braswell ops */
 815const struct snd_sof_dsp_ops sof_cht_ops = {
 816        /* device init */
 817        .probe          = byt_acpi_probe,
 818
 819        /* DSP core boot / reset */
 820        .run            = byt_run,
 821        .reset          = byt_reset,
 822
 823        /* Register IO */
 824        .write          = sof_io_write,
 825        .read           = sof_io_read,
 826        .write64        = sof_io_write64,
 827        .read64         = sof_io_read64,
 828
 829        /* Block IO */
 830        .block_read     = sof_block_read,
 831        .block_write    = sof_block_write,
 832
 833        /* doorbell */
 834        .irq_handler    = byt_irq_handler,
 835        .irq_thread     = byt_irq_thread,
 836
 837        /* ipc */
 838        .send_msg       = byt_send_msg,
 839        .fw_ready       = byt_fw_ready,
 840
 841        .ipc_msg_data   = intel_ipc_msg_data,
 842        .ipc_pcm_params = intel_ipc_pcm_params,
 843
 844        /* debug */
 845        .debug_map      = cht_debugfs,
 846        .debug_map_count        = ARRAY_SIZE(cht_debugfs),
 847        .dbg_dump       = byt_dump,
 848
 849        /* stream callbacks */
 850        .pcm_open       = intel_pcm_open,
 851        .pcm_close      = intel_pcm_close,
 852
 853        /* module loading */
 854        .load_module    = snd_sof_parse_module_memcpy,
 855
 856        /*Firmware loading */
 857        .load_firmware  = snd_sof_load_firmware_memcpy,
 858
 859        /* DAI drivers */
 860        .drv = byt_dai,
 861        /* all 6 SSPs may be available for cherrytrail */
 862        .num_drv = ARRAY_SIZE(byt_dai),
 863};
 864EXPORT_SYMBOL(sof_cht_ops);
 865
 866const struct sof_intel_dsp_desc cht_chip_info = {
 867        .cores_num = 1,
 868        .cores_mask = 1,
 869};
 870EXPORT_SYMBOL(cht_chip_info);
 871
 872#endif /* CONFIG_SND_SOC_SOF_BAYTRAIL */
 873
 874MODULE_LICENSE("Dual BSD/GPL");
 875