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