root/sound/soc/sof/intel/byt.c

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

DEFINITIONS

This source file includes following definitions.
  1. byt_get_registers
  2. byt_dump
  3. byt_irq_handler
  4. byt_irq_thread
  5. byt_send_msg
  6. byt_get_reply
  7. byt_get_mailbox_offset
  8. byt_get_window_offset
  9. byt_host_done
  10. byt_dsp_done
  11. byt_run
  12. byt_reset
  13. tangier_pci_probe
  14. byt_acpi_probe

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

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