linux/sound/soc/intel/haswell/sst-haswell-dsp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Intel Haswell SST DSP driver
   4 *
   5 * Copyright (C) 2013, Intel Corporation. All rights reserved.
   6 */
   7
   8#include <linux/delay.h>
   9#include <linux/fs.h>
  10#include <linux/slab.h>
  11#include <linux/device.h>
  12#include <linux/sched.h>
  13#include <linux/export.h>
  14#include <linux/interrupt.h>
  15#include <linux/module.h>
  16#include <linux/dma-mapping.h>
  17#include <linux/platform_device.h>
  18#include <linux/pci.h>
  19#include <linux/firmware.h>
  20#include <linux/pm_runtime.h>
  21
  22#include "../common/sst-dsp.h"
  23#include "../common/sst-dsp-priv.h"
  24#include "../haswell/sst-haswell-ipc.h"
  25
  26#include <trace/events/hswadsp.h>
  27
  28#define SST_HSW_FW_SIGNATURE_SIZE       4
  29#define SST_HSW_FW_SIGN                 "$SST"
  30#define SST_HSW_FW_LIB_SIGN             "$LIB"
  31
  32#define SST_WPT_SHIM_OFFSET     0xFB000
  33#define SST_LP_SHIM_OFFSET      0xE7000
  34#define SST_WPT_IRAM_OFFSET     0xA0000
  35#define SST_LP_IRAM_OFFSET      0x80000
  36#define SST_WPT_DSP_DRAM_OFFSET 0x400000
  37#define SST_WPT_DSP_IRAM_OFFSET 0x00000
  38#define SST_LPT_DSP_DRAM_OFFSET 0x400000
  39#define SST_LPT_DSP_IRAM_OFFSET 0x00000
  40
  41#define SST_SHIM_PM_REG         0x84
  42
  43#define SST_HSW_IRAM    1
  44#define SST_HSW_DRAM    2
  45#define SST_HSW_REGS    3
  46
  47struct dma_block_info {
  48        __le32 type;            /* IRAM/DRAM */
  49        __le32 size;            /* Bytes */
  50        __le32 ram_offset;      /* Offset in I/DRAM */
  51        __le32 rsvd;            /* Reserved field */
  52} __attribute__((packed));
  53
  54struct fw_module_info {
  55        __le32 persistent_size;
  56        __le32 scratch_size;
  57} __attribute__((packed));
  58
  59struct fw_header {
  60        unsigned char signature[SST_HSW_FW_SIGNATURE_SIZE]; /* FW signature */
  61        __le32 file_size;               /* size of fw minus this header */
  62        __le32 modules;         /*  # of modules */
  63        __le32 file_format;     /* version of header format */
  64        __le32 reserved[4];
  65} __attribute__((packed));
  66
  67struct fw_module_header {
  68        unsigned char signature[SST_HSW_FW_SIGNATURE_SIZE]; /* module signature */
  69        __le32 mod_size;        /* size of module */
  70        __le32 blocks;  /* # of blocks */
  71        __le16 padding;
  72        __le16 type;    /* codec type, pp lib */
  73        __le32 entry_point;
  74        struct fw_module_info info;
  75} __attribute__((packed));
  76
  77static void hsw_free(struct sst_dsp *sst);
  78
  79static int hsw_parse_module(struct sst_dsp *dsp, struct sst_fw *fw,
  80        struct fw_module_header *module)
  81{
  82        struct dma_block_info *block;
  83        struct sst_module *mod;
  84        struct sst_module_template template;
  85        int count, ret;
  86        void __iomem *ram;
  87        int type = le16_to_cpu(module->type);
  88        int entry_point = le32_to_cpu(module->entry_point);
  89
  90        /* TODO: allowed module types need to be configurable */
  91        if (type != SST_HSW_MODULE_BASE_FW &&
  92            type != SST_HSW_MODULE_PCM_SYSTEM &&
  93            type != SST_HSW_MODULE_PCM &&
  94            type != SST_HSW_MODULE_PCM_REFERENCE &&
  95            type != SST_HSW_MODULE_PCM_CAPTURE &&
  96            type != SST_HSW_MODULE_WAVES &&
  97            type != SST_HSW_MODULE_LPAL)
  98                return 0;
  99
 100        dev_dbg(dsp->dev, "new module sign 0x%s size 0x%x blocks 0x%x type 0x%x\n",
 101                module->signature, module->mod_size,
 102                module->blocks, type);
 103        dev_dbg(dsp->dev, " entrypoint 0x%x\n", entry_point);
 104        dev_dbg(dsp->dev, " persistent 0x%x scratch 0x%x\n",
 105                module->info.persistent_size, module->info.scratch_size);
 106
 107        memset(&template, 0, sizeof(template));
 108        template.id = type;
 109        template.entry = entry_point - 4;
 110        template.persistent_size = le32_to_cpu(module->info.persistent_size);
 111        template.scratch_size = le32_to_cpu(module->info.scratch_size);
 112
 113        mod = sst_module_new(fw, &template, NULL);
 114        if (mod == NULL)
 115                return -ENOMEM;
 116
 117        block = (void *)module + sizeof(*module);
 118
 119        for (count = 0; count < le32_to_cpu(module->blocks); count++) {
 120
 121                if (le32_to_cpu(block->size) <= 0) {
 122                        dev_err(dsp->dev,
 123                                "error: block %d size invalid\n", count);
 124                        sst_module_free(mod);
 125                        return -EINVAL;
 126                }
 127
 128                switch (le32_to_cpu(block->type)) {
 129                case SST_HSW_IRAM:
 130                        ram = dsp->addr.lpe;
 131                        mod->offset = le32_to_cpu(block->ram_offset) +
 132                                dsp->addr.iram_offset;
 133                        mod->type = SST_MEM_IRAM;
 134                        break;
 135                case SST_HSW_DRAM:
 136                case SST_HSW_REGS:
 137                        ram = dsp->addr.lpe;
 138                        mod->offset = le32_to_cpu(block->ram_offset);
 139                        mod->type = SST_MEM_DRAM;
 140                        break;
 141                default:
 142                        dev_err(dsp->dev, "error: bad type 0x%x for block 0x%x\n",
 143                                block->type, count);
 144                        sst_module_free(mod);
 145                        return -EINVAL;
 146                }
 147
 148                mod->size = le32_to_cpu(block->size);
 149                mod->data = (void *)block + sizeof(*block);
 150                mod->data_offset = mod->data - fw->dma_buf;
 151
 152                dev_dbg(dsp->dev, "module block %d type 0x%x "
 153                        "size 0x%x ==> ram %p offset 0x%x\n",
 154                        count, mod->type, block->size, ram,
 155                        block->ram_offset);
 156
 157                ret = sst_module_alloc_blocks(mod);
 158                if (ret < 0) {
 159                        dev_err(dsp->dev, "error: could not allocate blocks for module %d\n",
 160                                count);
 161                        sst_module_free(mod);
 162                        return ret;
 163                }
 164
 165                block = (void *)block + sizeof(*block) +
 166                        le32_to_cpu(block->size);
 167        }
 168        mod->state = SST_MODULE_STATE_LOADED;
 169
 170        return 0;
 171}
 172
 173static int hsw_parse_fw_image(struct sst_fw *sst_fw)
 174{
 175        struct fw_header *header;
 176        struct fw_module_header *module;
 177        struct sst_dsp *dsp = sst_fw->dsp;
 178        int ret, count;
 179
 180        /* Read the header information from the data pointer */
 181        header = (struct fw_header *)sst_fw->dma_buf;
 182
 183        /* verify FW */
 184        if ((strncmp(header->signature, SST_HSW_FW_SIGN, 4) != 0) ||
 185            (sst_fw->size !=
 186             le32_to_cpu(header->file_size) + sizeof(*header))) {
 187                dev_err(dsp->dev, "error: invalid fw sign/filesize mismatch\n");
 188                return -EINVAL;
 189        }
 190
 191        dev_dbg(dsp->dev, "header size=0x%x modules=0x%x fmt=0x%x size=%zu\n",
 192                header->file_size, header->modules,
 193                header->file_format, sizeof(*header));
 194
 195        /* parse each module */
 196        module = (void *)sst_fw->dma_buf + sizeof(*header);
 197        for (count = 0; count < le32_to_cpu(header->modules); count++) {
 198
 199                /* module */
 200                ret = hsw_parse_module(dsp, sst_fw, module);
 201                if (ret < 0) {
 202                        dev_err(dsp->dev, "error: invalid module %d\n", count);
 203                        return ret;
 204                }
 205                module = (void *)module + sizeof(*module) +
 206                        le32_to_cpu(module->mod_size);
 207        }
 208
 209        return 0;
 210}
 211
 212static irqreturn_t hsw_irq(int irq, void *context)
 213{
 214        struct sst_dsp *sst = (struct sst_dsp *) context;
 215        u32 isr;
 216        int ret = IRQ_NONE;
 217
 218        spin_lock(&sst->spinlock);
 219
 220        /* Interrupt arrived, check src */
 221        isr = sst_dsp_shim_read_unlocked(sst, SST_ISRX);
 222        if (isr & SST_ISRX_DONE) {
 223                trace_sst_irq_done(isr,
 224                        sst_dsp_shim_read_unlocked(sst, SST_IMRX));
 225
 226                /* Mask Done interrupt before return */
 227                sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX,
 228                        SST_IMRX_DONE, SST_IMRX_DONE);
 229                ret = IRQ_WAKE_THREAD;
 230        }
 231
 232        if (isr & SST_ISRX_BUSY) {
 233                trace_sst_irq_busy(isr,
 234                        sst_dsp_shim_read_unlocked(sst, SST_IMRX));
 235
 236                /* Mask Busy interrupt before return */
 237                sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX,
 238                        SST_IMRX_BUSY, SST_IMRX_BUSY);
 239                ret = IRQ_WAKE_THREAD;
 240        }
 241
 242        spin_unlock(&sst->spinlock);
 243        return ret;
 244}
 245
 246static void hsw_set_dsp_D3(struct sst_dsp *sst)
 247{
 248        u32 val;
 249        u32 reg;
 250
 251        /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
 252        reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
 253        reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
 254        writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 255
 256        /* enable power gating and switch off DRAM & IRAM blocks */
 257        val = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
 258        val |= SST_VDRTCL0_DSRAMPGE_MASK |
 259                SST_VDRTCL0_ISRAMPGE_MASK;
 260        val &= ~(SST_VDRTCL0_D3PGD | SST_VDRTCL0_D3SRAMPGD);
 261        writel(val, sst->addr.pci_cfg + SST_VDRTCTL0);
 262
 263        /* switch off audio PLL */
 264        val = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
 265        val |= SST_VDRTCL2_APLLSE_MASK;
 266        writel(val, sst->addr.pci_cfg + SST_VDRTCTL2);
 267
 268        /* disable MCLK(clkctl.smos = 0) */
 269        sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
 270                SST_CLKCTL_MASK, 0);
 271
 272        /* Set D3 state, delay 50 us */
 273        val = readl(sst->addr.pci_cfg + SST_PMCS);
 274        val |= SST_PMCS_PS_MASK;
 275        writel(val, sst->addr.pci_cfg + SST_PMCS);
 276        udelay(50);
 277
 278        /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
 279        reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
 280        reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
 281        writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 282
 283        udelay(50);
 284
 285}
 286
 287static void hsw_reset(struct sst_dsp *sst)
 288{
 289        /* put DSP into reset and stall */
 290        sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
 291                SST_CSR_RST | SST_CSR_STALL,
 292                SST_CSR_RST | SST_CSR_STALL);
 293
 294        /* keep in reset for 10ms */
 295        mdelay(10);
 296
 297        /* take DSP out of reset and keep stalled for FW loading */
 298        sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
 299                SST_CSR_RST | SST_CSR_STALL, SST_CSR_STALL);
 300}
 301
 302static int hsw_set_dsp_D0(struct sst_dsp *sst)
 303{
 304        int tries = 10;
 305        u32 reg, fw_dump_bit;
 306
 307        /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
 308        reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
 309        reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
 310        writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 311
 312        /* Disable D3PG (VDRTCTL0.D3PGD = 1) */
 313        reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
 314        reg |= SST_VDRTCL0_D3PGD;
 315        writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
 316
 317        /* Set D0 state */
 318        reg = readl(sst->addr.pci_cfg + SST_PMCS);
 319        reg &= ~SST_PMCS_PS_MASK;
 320        writel(reg, sst->addr.pci_cfg + SST_PMCS);
 321
 322        /* check that ADSP shim is enabled */
 323        while (tries--) {
 324                reg = readl(sst->addr.pci_cfg + SST_PMCS) & SST_PMCS_PS_MASK;
 325                if (reg == 0)
 326                        goto finish;
 327
 328                msleep(1);
 329        }
 330
 331        return -ENODEV;
 332
 333finish:
 334        /* select SSP1 19.2MHz base clock, SSP clock 0, turn off Low Power Clock */
 335        sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
 336                SST_CSR_S1IOCS | SST_CSR_SBCS1 | SST_CSR_LPCS, 0x0);
 337
 338        /* stall DSP core, set clk to 192/96Mhz */
 339        sst_dsp_shim_update_bits_unlocked(sst,
 340                SST_CSR, SST_CSR_STALL | SST_CSR_DCS_MASK,
 341                SST_CSR_STALL | SST_CSR_DCS(4));
 342
 343        /* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */
 344        sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
 345                SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0,
 346                SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0);
 347
 348        /* Stall and reset core, set CSR */
 349        hsw_reset(sst);
 350
 351        /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
 352        reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
 353        reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
 354        writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 355
 356        udelay(50);
 357
 358        /* switch on audio PLL */
 359        reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
 360        reg &= ~SST_VDRTCL2_APLLSE_MASK;
 361        writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 362
 363        /* set default power gating control, enable power gating control for all blocks. that is,
 364        can't be accessed, please enable each block before accessing. */
 365        reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
 366        reg |= SST_VDRTCL0_DSRAMPGE_MASK | SST_VDRTCL0_ISRAMPGE_MASK;
 367        /* for D0, always enable the block(DSRAM[0]) used for FW dump */
 368        fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT;
 369        writel(reg & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0);
 370
 371
 372        /* disable DMA finish function for SSP0 & SSP1 */
 373        sst_dsp_shim_update_bits_unlocked(sst, SST_CSR2, SST_CSR2_SDFD_SSP1,
 374                SST_CSR2_SDFD_SSP1);
 375
 376        /* set on-demond mode on engine 0,1 for all channels */
 377        sst_dsp_shim_update_bits(sst, SST_HMDC,
 378                        SST_HMDC_HDDA_E0_ALLCH | SST_HMDC_HDDA_E1_ALLCH,
 379                        SST_HMDC_HDDA_E0_ALLCH | SST_HMDC_HDDA_E1_ALLCH);
 380
 381        /* Enable Interrupt from both sides */
 382        sst_dsp_shim_update_bits(sst, SST_IMRX, (SST_IMRX_BUSY | SST_IMRX_DONE),
 383                                 0x0);
 384        sst_dsp_shim_update_bits(sst, SST_IMRD, (SST_IMRD_DONE | SST_IMRD_BUSY |
 385                                SST_IMRD_SSP0 | SST_IMRD_DMAC), 0x0);
 386
 387        /* clear IPC registers */
 388        sst_dsp_shim_write(sst, SST_IPCX, 0x0);
 389        sst_dsp_shim_write(sst, SST_IPCD, 0x0);
 390        sst_dsp_shim_write(sst, 0x80, 0x6);
 391        sst_dsp_shim_write(sst, 0xe0, 0x300a);
 392
 393        return 0;
 394}
 395
 396static void hsw_boot(struct sst_dsp *sst)
 397{
 398        /* set oportunistic mode on engine 0,1 for all channels */
 399        sst_dsp_shim_update_bits(sst, SST_HMDC,
 400                        SST_HMDC_HDDA_E0_ALLCH | SST_HMDC_HDDA_E1_ALLCH, 0);
 401
 402        /* set DSP to RUN */
 403        sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, SST_CSR_STALL, 0x0);
 404}
 405
 406static void hsw_stall(struct sst_dsp *sst)
 407{
 408        /* stall DSP */
 409        sst_dsp_shim_update_bits(sst, SST_CSR,
 410                SST_CSR_24MHZ_LPCS | SST_CSR_STALL,
 411                SST_CSR_STALL | SST_CSR_24MHZ_LPCS);
 412}
 413
 414static void hsw_sleep(struct sst_dsp *sst)
 415{
 416        dev_dbg(sst->dev, "HSW_PM dsp runtime suspend\n");
 417
 418        /* put DSP into reset and stall */
 419        sst_dsp_shim_update_bits(sst, SST_CSR,
 420                SST_CSR_24MHZ_LPCS | SST_CSR_RST | SST_CSR_STALL,
 421                SST_CSR_RST | SST_CSR_STALL | SST_CSR_24MHZ_LPCS);
 422
 423        hsw_set_dsp_D3(sst);
 424        dev_dbg(sst->dev, "HSW_PM dsp runtime suspend exit\n");
 425}
 426
 427static int hsw_wake(struct sst_dsp *sst)
 428{
 429        int ret;
 430
 431        dev_dbg(sst->dev, "HSW_PM dsp runtime resume\n");
 432
 433        ret = hsw_set_dsp_D0(sst);
 434        if (ret < 0)
 435                return ret;
 436
 437        dev_dbg(sst->dev, "HSW_PM dsp runtime resume exit\n");
 438
 439        return 0;
 440}
 441
 442struct sst_adsp_memregion {
 443        u32 start;
 444        u32 end;
 445        int blocks;
 446        enum sst_mem_type type;
 447};
 448
 449/* lynx point ADSP mem regions */
 450static const struct sst_adsp_memregion lp_region[] = {
 451        {0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */
 452        {0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */
 453        {0x80000, 0xE0000, 12, SST_MEM_IRAM}, /* I-SRAM - 12 * 32kB */
 454};
 455
 456/* wild cat point ADSP mem regions */
 457static const struct sst_adsp_memregion wpt_region[] = {
 458        {0x00000, 0xA0000, 20, SST_MEM_DRAM}, /* D-SRAM0,D-SRAM1,D-SRAM2 - 20 * 32kB */
 459        {0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */
 460};
 461
 462static int hsw_acpi_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata)
 463{
 464        /* ADSP DRAM & IRAM */
 465        sst->addr.lpe_base = pdata->lpe_base;
 466        sst->addr.lpe = ioremap(pdata->lpe_base, pdata->lpe_size);
 467        if (!sst->addr.lpe)
 468                return -ENODEV;
 469
 470        /* ADSP PCI MMIO config space */
 471        sst->addr.pci_cfg = ioremap(pdata->pcicfg_base, pdata->pcicfg_size);
 472        if (!sst->addr.pci_cfg) {
 473                iounmap(sst->addr.lpe);
 474                return -ENODEV;
 475        }
 476
 477        /* SST Shim */
 478        sst->addr.shim = sst->addr.lpe + sst->addr.shim_offset;
 479        return 0;
 480}
 481
 482struct sst_sram_shift {
 483        u32 dev_id;     /* SST Device IDs  */
 484        u32 iram_shift;
 485        u32 dram_shift;
 486};
 487
 488static const struct sst_sram_shift sram_shift[] = {
 489        {SST_DEV_ID_LYNX_POINT, 6, 16}, /* lp */
 490        {SST_DEV_ID_WILDCAT_POINT, 2, 12}, /* wpt */
 491};
 492
 493static u32 hsw_block_get_bit(struct sst_mem_block *block)
 494{
 495        u32 bit = 0, shift = 0, index;
 496        struct sst_dsp *sst = block->dsp;
 497
 498        for (index = 0; index < ARRAY_SIZE(sram_shift); index++) {
 499                if (sram_shift[index].dev_id == sst->id)
 500                        break;
 501        }
 502
 503        if (index < ARRAY_SIZE(sram_shift)) {
 504                switch (block->type) {
 505                case SST_MEM_DRAM:
 506                        shift = sram_shift[index].dram_shift;
 507                        break;
 508                case SST_MEM_IRAM:
 509                        shift = sram_shift[index].iram_shift;
 510                        break;
 511                default:
 512                        shift = 0;
 513                }
 514        } else
 515                shift = 0;
 516
 517        bit = 1 << (block->index + shift);
 518
 519        return bit;
 520}
 521
 522/*dummy read a SRAM block.*/
 523static void sst_mem_block_dummy_read(struct sst_mem_block *block)
 524{
 525        u32 size;
 526        u8 tmp_buf[4];
 527        struct sst_dsp *sst = block->dsp;
 528
 529        size = block->size > 4 ? 4 : block->size;
 530        memcpy_fromio(tmp_buf, sst->addr.lpe + block->offset, size);
 531}
 532
 533/* enable 32kB memory block - locks held by caller */
 534static int hsw_block_enable(struct sst_mem_block *block)
 535{
 536        struct sst_dsp *sst = block->dsp;
 537        u32 bit, val;
 538
 539        if (block->users++ > 0)
 540                return 0;
 541
 542        dev_dbg(block->dsp->dev, " enabled block %d:%d at offset 0x%x\n",
 543                block->type, block->index, block->offset);
 544
 545        /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
 546        val = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
 547        val &= ~SST_VDRTCL2_DCLCGE;
 548        writel(val, sst->addr.pci_cfg + SST_VDRTCTL2);
 549
 550        val = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
 551        bit = hsw_block_get_bit(block);
 552        writel(val & ~bit, sst->addr.pci_cfg + SST_VDRTCTL0);
 553
 554        /* wait 18 DSP clock ticks */
 555        udelay(10);
 556
 557        /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
 558        val = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
 559        val |= SST_VDRTCL2_DCLCGE;
 560        writel(val, sst->addr.pci_cfg + SST_VDRTCTL2);
 561
 562        udelay(50);
 563
 564        /*add a dummy read before the SRAM block is written, otherwise the writing may miss bytes sometimes.*/
 565        sst_mem_block_dummy_read(block);
 566        return 0;
 567}
 568
 569/* disable 32kB memory block - locks held by caller */
 570static int hsw_block_disable(struct sst_mem_block *block)
 571{
 572        struct sst_dsp *sst = block->dsp;
 573        u32 bit, val;
 574
 575        if (--block->users > 0)
 576                return 0;
 577
 578        dev_dbg(block->dsp->dev, " disabled block %d:%d at offset 0x%x\n",
 579                block->type, block->index, block->offset);
 580
 581        /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
 582        val = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
 583        val &= ~SST_VDRTCL2_DCLCGE;
 584        writel(val, sst->addr.pci_cfg + SST_VDRTCTL2);
 585
 586
 587        val = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
 588        bit = hsw_block_get_bit(block);
 589        /* don't disable DSRAM[0], keep it always enable for FW dump*/
 590        if (bit != (1 << SST_VDRTCL0_DSRAMPGE_SHIFT))
 591                writel(val | bit, sst->addr.pci_cfg + SST_VDRTCTL0);
 592
 593        /* wait 18 DSP clock ticks */
 594        udelay(10);
 595
 596        /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
 597        val = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
 598        val |= SST_VDRTCL2_DCLCGE;
 599        writel(val, sst->addr.pci_cfg + SST_VDRTCTL2);
 600
 601        udelay(50);
 602
 603        return 0;
 604}
 605
 606static const struct sst_block_ops sst_hsw_ops = {
 607        .enable = hsw_block_enable,
 608        .disable = hsw_block_disable,
 609};
 610
 611static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata)
 612{
 613        const struct sst_adsp_memregion *region;
 614        struct device *dev;
 615        int ret = -ENODEV, i, j, region_count;
 616        u32 offset, size, fw_dump_bit;
 617
 618        dev = sst->dma_dev;
 619
 620        switch (sst->id) {
 621        case SST_DEV_ID_LYNX_POINT:
 622                region = lp_region;
 623                region_count = ARRAY_SIZE(lp_region);
 624                sst->addr.iram_offset = SST_LP_IRAM_OFFSET;
 625                sst->addr.dsp_iram_offset = SST_LPT_DSP_IRAM_OFFSET;
 626                sst->addr.dsp_dram_offset = SST_LPT_DSP_DRAM_OFFSET;
 627                sst->addr.shim_offset = SST_LP_SHIM_OFFSET;
 628                break;
 629        case SST_DEV_ID_WILDCAT_POINT:
 630                region = wpt_region;
 631                region_count = ARRAY_SIZE(wpt_region);
 632                sst->addr.iram_offset = SST_WPT_IRAM_OFFSET;
 633                sst->addr.dsp_iram_offset = SST_WPT_DSP_IRAM_OFFSET;
 634                sst->addr.dsp_dram_offset = SST_WPT_DSP_DRAM_OFFSET;
 635                sst->addr.shim_offset = SST_WPT_SHIM_OFFSET;
 636                break;
 637        default:
 638                dev_err(dev, "error: failed to get mem resources\n");
 639                return ret;
 640        }
 641
 642        ret = hsw_acpi_resource_map(sst, pdata);
 643        if (ret < 0) {
 644                dev_err(dev, "error: failed to map resources\n");
 645                return ret;
 646        }
 647
 648        /* enable the DSP SHIM */
 649        ret = hsw_set_dsp_D0(sst);
 650        if (ret < 0) {
 651                dev_err(dev, "error: failed to set DSP D0 and reset SHIM\n");
 652                return ret;
 653        }
 654
 655        ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(31));
 656        if (ret)
 657                return ret;
 658
 659
 660        /* register DSP memory blocks - ideally we should get this from ACPI */
 661        for (i = 0; i < region_count; i++) {
 662                offset = region[i].start;
 663                size = (region[i].end - region[i].start) / region[i].blocks;
 664
 665                /* register individual memory blocks */
 666                for (j = 0; j < region[i].blocks; j++) {
 667                        sst_mem_block_register(sst, offset, size,
 668                                region[i].type, &sst_hsw_ops, j, sst);
 669                        offset += size;
 670                }
 671        }
 672
 673        /* always enable the block(DSRAM[0]) used for FW dump */
 674        fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT;
 675        /* set default power gating control, enable power gating control for all blocks. that is,
 676        can't be accessed, please enable each block before accessing. */
 677        writel(0xffffffff & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0);
 678
 679        return 0;
 680}
 681
 682static void hsw_free(struct sst_dsp *sst)
 683{
 684        sst_mem_block_unregister_all(sst);
 685        iounmap(sst->addr.lpe);
 686        iounmap(sst->addr.pci_cfg);
 687}
 688
 689struct sst_ops haswell_ops = {
 690        .reset = hsw_reset,
 691        .boot = hsw_boot,
 692        .stall = hsw_stall,
 693        .wake = hsw_wake,
 694        .sleep = hsw_sleep,
 695        .write = sst_shim32_write,
 696        .read = sst_shim32_read,
 697        .write64 = sst_shim32_write64,
 698        .read64 = sst_shim32_read64,
 699        .ram_read = sst_memcpy_fromio_32,
 700        .ram_write = sst_memcpy_toio_32,
 701        .irq_handler = hsw_irq,
 702        .init = hsw_init,
 703        .free = hsw_free,
 704        .parse_fw = hsw_parse_fw_image,
 705};
 706