linux/sound/soc/intel/atom/sst/sst_pci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  sst_pci.c - SST (LPE) driver init file for pci enumeration.
   4 *
   5 *  Copyright (C) 2008-14       Intel Corp
   6 *  Authors:    Vinod Koul <vinod.koul@intel.com>
   7 *              Harsha Priya <priya.harsha@intel.com>
   8 *              Dharageswari R <dharageswari.r@intel.com>
   9 *              KP Jeeja <jeeja.kp@intel.com>
  10 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  11 *
  12 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  13 */
  14#include <linux/module.h>
  15#include <linux/pci.h>
  16#include <linux/fs.h>
  17#include <linux/firmware.h>
  18#include <linux/pm_runtime.h>
  19#include <sound/core.h>
  20#include <sound/soc.h>
  21#include <asm/platform_sst_audio.h>
  22#include "../sst-mfld-platform.h"
  23#include "sst.h"
  24
  25static int sst_platform_get_resources(struct intel_sst_drv *ctx)
  26{
  27        int ddr_base, ret = 0;
  28        struct pci_dev *pci = ctx->pci;
  29
  30        ret = pci_request_regions(pci, SST_DRV_NAME);
  31        if (ret)
  32                return ret;
  33
  34        /* map registers */
  35        /* DDR base */
  36        if (ctx->dev_id == SST_MRFLD_PCI_ID) {
  37                ctx->ddr_base = pci_resource_start(pci, 0);
  38                /* check that the relocated IMR base matches with FW Binary */
  39                ddr_base = relocate_imr_addr_mrfld(ctx->ddr_base);
  40                if (!ctx->pdata->lib_info) {
  41                        dev_err(ctx->dev, "lib_info pointer NULL\n");
  42                        ret = -EINVAL;
  43                        goto do_release_regions;
  44                }
  45                if (ddr_base != ctx->pdata->lib_info->mod_base) {
  46                        dev_err(ctx->dev,
  47                                        "FW LSP DDR BASE does not match with IFWI\n");
  48                        ret = -EINVAL;
  49                        goto do_release_regions;
  50                }
  51                ctx->ddr_end = pci_resource_end(pci, 0);
  52
  53                ctx->ddr = pcim_iomap(pci, 0,
  54                                        pci_resource_len(pci, 0));
  55                if (!ctx->ddr) {
  56                        ret = -EINVAL;
  57                        goto do_release_regions;
  58                }
  59                dev_dbg(ctx->dev, "sst: DDR Ptr %p\n", ctx->ddr);
  60        } else {
  61                ctx->ddr = NULL;
  62        }
  63        /* SHIM */
  64        ctx->shim_phy_add = pci_resource_start(pci, 1);
  65        ctx->shim = pcim_iomap(pci, 1, pci_resource_len(pci, 1));
  66        if (!ctx->shim) {
  67                ret = -EINVAL;
  68                goto do_release_regions;
  69        }
  70        dev_dbg(ctx->dev, "SST Shim Ptr %p\n", ctx->shim);
  71
  72        /* Shared SRAM */
  73        ctx->mailbox_add = pci_resource_start(pci, 2);
  74        ctx->mailbox = pcim_iomap(pci, 2, pci_resource_len(pci, 2));
  75        if (!ctx->mailbox) {
  76                ret = -EINVAL;
  77                goto do_release_regions;
  78        }
  79        dev_dbg(ctx->dev, "SRAM Ptr %p\n", ctx->mailbox);
  80
  81        /* IRAM */
  82        ctx->iram_end = pci_resource_end(pci, 3);
  83        ctx->iram_base = pci_resource_start(pci, 3);
  84        ctx->iram = pcim_iomap(pci, 3, pci_resource_len(pci, 3));
  85        if (!ctx->iram) {
  86                ret = -EINVAL;
  87                goto do_release_regions;
  88        }
  89        dev_dbg(ctx->dev, "IRAM Ptr %p\n", ctx->iram);
  90
  91        /* DRAM */
  92        ctx->dram_end = pci_resource_end(pci, 4);
  93        ctx->dram_base = pci_resource_start(pci, 4);
  94        ctx->dram = pcim_iomap(pci, 4, pci_resource_len(pci, 4));
  95        if (!ctx->dram) {
  96                ret = -EINVAL;
  97                goto do_release_regions;
  98        }
  99        dev_dbg(ctx->dev, "DRAM Ptr %p\n", ctx->dram);
 100do_release_regions:
 101        pci_release_regions(pci);
 102        return 0;
 103}
 104
 105/*
 106 * intel_sst_probe - PCI probe function
 107 *
 108 * @pci:        PCI device structure
 109 * @pci_id: PCI device ID structure
 110 *
 111 */
 112static int intel_sst_probe(struct pci_dev *pci,
 113                        const struct pci_device_id *pci_id)
 114{
 115        int ret = 0;
 116        struct intel_sst_drv *sst_drv_ctx;
 117        struct sst_platform_info *sst_pdata = pci->dev.platform_data;
 118
 119        dev_dbg(&pci->dev, "Probe for DID %x\n", pci->device);
 120        ret = sst_alloc_drv_context(&sst_drv_ctx, &pci->dev, pci->device);
 121        if (ret < 0)
 122                return ret;
 123
 124        sst_drv_ctx->pdata = sst_pdata;
 125        sst_drv_ctx->irq_num = pci->irq;
 126        snprintf(sst_drv_ctx->firmware_name, sizeof(sst_drv_ctx->firmware_name),
 127                        "%s%04x%s", "fw_sst_",
 128                        sst_drv_ctx->dev_id, ".bin");
 129
 130        ret = sst_context_init(sst_drv_ctx);
 131        if (ret < 0)
 132                return ret;
 133
 134        /* Init the device */
 135        ret = pcim_enable_device(pci);
 136        if (ret) {
 137                dev_err(sst_drv_ctx->dev,
 138                        "device can't be enabled. Returned err: %d\n", ret);
 139                goto do_free_drv_ctx;
 140        }
 141        sst_drv_ctx->pci = pci_dev_get(pci);
 142        ret = sst_platform_get_resources(sst_drv_ctx);
 143        if (ret < 0)
 144                goto do_free_drv_ctx;
 145
 146        pci_set_drvdata(pci, sst_drv_ctx);
 147        sst_configure_runtime_pm(sst_drv_ctx);
 148
 149        return ret;
 150
 151do_free_drv_ctx:
 152        sst_context_cleanup(sst_drv_ctx);
 153        dev_err(sst_drv_ctx->dev, "Probe failed with %d\n", ret);
 154        return ret;
 155}
 156
 157/**
 158 * intel_sst_remove - PCI remove function
 159 *
 160 * @pci:        PCI device structure
 161 *
 162 * This function is called by OS when a device is unloaded
 163 * This frees the interrupt etc
 164 */
 165static void intel_sst_remove(struct pci_dev *pci)
 166{
 167        struct intel_sst_drv *sst_drv_ctx = pci_get_drvdata(pci);
 168
 169        sst_context_cleanup(sst_drv_ctx);
 170        pci_dev_put(sst_drv_ctx->pci);
 171        pci_release_regions(pci);
 172        pci_set_drvdata(pci, NULL);
 173}
 174
 175/* PCI Routines */
 176static const struct pci_device_id intel_sst_ids[] = {
 177        { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0},
 178        { 0, }
 179};
 180
 181static struct pci_driver sst_driver = {
 182        .name = SST_DRV_NAME,
 183        .id_table = intel_sst_ids,
 184        .probe = intel_sst_probe,
 185        .remove = intel_sst_remove,
 186#ifdef CONFIG_PM
 187        .driver = {
 188                .pm = &intel_sst_pm,
 189        },
 190#endif
 191};
 192
 193module_pci_driver(sst_driver);
 194
 195MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine PCI Driver");
 196MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
 197MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
 198MODULE_AUTHOR("Dharageswari R <dharageswari.r@intel.com>");
 199MODULE_AUTHOR("KP Jeeja <jeeja.kp@intel.com>");
 200MODULE_LICENSE("GPL v2");
 201MODULE_ALIAS("sst");
 202