Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  sst_pci.c - SST (LPE) driver init file for pci enumeration.
0004  *
0005  *  Copyright (C) 2008-14   Intel Corp
0006  *  Authors:    Vinod Koul <vinod.koul@intel.com>
0007  *      Harsha Priya <priya.harsha@intel.com>
0008  *      Dharageswari R <dharageswari.r@intel.com>
0009  *      KP Jeeja <jeeja.kp@intel.com>
0010  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0011  *
0012  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0013  */
0014 #include <linux/module.h>
0015 #include <linux/pci.h>
0016 #include <linux/fs.h>
0017 #include <linux/firmware.h>
0018 #include <linux/pm_runtime.h>
0019 #include <sound/core.h>
0020 #include <sound/soc.h>
0021 #include <asm/platform_sst_audio.h>
0022 #include "../sst-mfld-platform.h"
0023 #include "sst.h"
0024 
0025 static int sst_platform_get_resources(struct intel_sst_drv *ctx)
0026 {
0027     int ddr_base, ret = 0;
0028     struct pci_dev *pci = ctx->pci;
0029 
0030     ret = pci_request_regions(pci, SST_DRV_NAME);
0031     if (ret)
0032         return ret;
0033 
0034     /* map registers */
0035     /* DDR base */
0036     if (ctx->dev_id == SST_MRFLD_PCI_ID) {
0037         ctx->ddr_base = pci_resource_start(pci, 0);
0038         /* check that the relocated IMR base matches with FW Binary */
0039         ddr_base = relocate_imr_addr_mrfld(ctx->ddr_base);
0040         if (!ctx->pdata->lib_info) {
0041             dev_err(ctx->dev, "lib_info pointer NULL\n");
0042             ret = -EINVAL;
0043             goto do_release_regions;
0044         }
0045         if (ddr_base != ctx->pdata->lib_info->mod_base) {
0046             dev_err(ctx->dev,
0047                     "FW LSP DDR BASE does not match with IFWI\n");
0048             ret = -EINVAL;
0049             goto do_release_regions;
0050         }
0051         ctx->ddr_end = pci_resource_end(pci, 0);
0052 
0053         ctx->ddr = pcim_iomap(pci, 0,
0054                     pci_resource_len(pci, 0));
0055         if (!ctx->ddr) {
0056             ret = -EINVAL;
0057             goto do_release_regions;
0058         }
0059         dev_dbg(ctx->dev, "sst: DDR Ptr %p\n", ctx->ddr);
0060     } else {
0061         ctx->ddr = NULL;
0062     }
0063     /* SHIM */
0064     ctx->shim_phy_add = pci_resource_start(pci, 1);
0065     ctx->shim = pcim_iomap(pci, 1, pci_resource_len(pci, 1));
0066     if (!ctx->shim) {
0067         ret = -EINVAL;
0068         goto do_release_regions;
0069     }
0070     dev_dbg(ctx->dev, "SST Shim Ptr %p\n", ctx->shim);
0071 
0072     /* Shared SRAM */
0073     ctx->mailbox_add = pci_resource_start(pci, 2);
0074     ctx->mailbox = pcim_iomap(pci, 2, pci_resource_len(pci, 2));
0075     if (!ctx->mailbox) {
0076         ret = -EINVAL;
0077         goto do_release_regions;
0078     }
0079     dev_dbg(ctx->dev, "SRAM Ptr %p\n", ctx->mailbox);
0080 
0081     /* IRAM */
0082     ctx->iram_end = pci_resource_end(pci, 3);
0083     ctx->iram_base = pci_resource_start(pci, 3);
0084     ctx->iram = pcim_iomap(pci, 3, pci_resource_len(pci, 3));
0085     if (!ctx->iram) {
0086         ret = -EINVAL;
0087         goto do_release_regions;
0088     }
0089     dev_dbg(ctx->dev, "IRAM Ptr %p\n", ctx->iram);
0090 
0091     /* DRAM */
0092     ctx->dram_end = pci_resource_end(pci, 4);
0093     ctx->dram_base = pci_resource_start(pci, 4);
0094     ctx->dram = pcim_iomap(pci, 4, pci_resource_len(pci, 4));
0095     if (!ctx->dram) {
0096         ret = -EINVAL;
0097         goto do_release_regions;
0098     }
0099     dev_dbg(ctx->dev, "DRAM Ptr %p\n", ctx->dram);
0100 do_release_regions:
0101     pci_release_regions(pci);
0102     return ret;
0103 }
0104 
0105 /*
0106  * intel_sst_probe - PCI probe function
0107  *
0108  * @pci:    PCI device structure
0109  * @pci_id: PCI device ID structure
0110  *
0111  */
0112 static int intel_sst_probe(struct pci_dev *pci,
0113             const struct pci_device_id *pci_id)
0114 {
0115     int ret = 0;
0116     struct intel_sst_drv *sst_drv_ctx;
0117     struct sst_platform_info *sst_pdata = pci->dev.platform_data;
0118 
0119     dev_dbg(&pci->dev, "Probe for DID %x\n", pci->device);
0120     ret = sst_alloc_drv_context(&sst_drv_ctx, &pci->dev, pci->device);
0121     if (ret < 0)
0122         return ret;
0123 
0124     sst_drv_ctx->pdata = sst_pdata;
0125     sst_drv_ctx->irq_num = pci->irq;
0126     snprintf(sst_drv_ctx->firmware_name, sizeof(sst_drv_ctx->firmware_name),
0127             "%s%04x%s", "fw_sst_",
0128             sst_drv_ctx->dev_id, ".bin");
0129 
0130     ret = sst_context_init(sst_drv_ctx);
0131     if (ret < 0)
0132         return ret;
0133 
0134     /* Init the device */
0135     ret = pcim_enable_device(pci);
0136     if (ret) {
0137         dev_err(sst_drv_ctx->dev,
0138             "device can't be enabled. Returned err: %d\n", ret);
0139         goto do_free_drv_ctx;
0140     }
0141     sst_drv_ctx->pci = pci_dev_get(pci);
0142     ret = sst_platform_get_resources(sst_drv_ctx);
0143     if (ret < 0)
0144         goto do_free_drv_ctx;
0145 
0146     pci_set_drvdata(pci, sst_drv_ctx);
0147     sst_configure_runtime_pm(sst_drv_ctx);
0148 
0149     return ret;
0150 
0151 do_free_drv_ctx:
0152     sst_context_cleanup(sst_drv_ctx);
0153     dev_err(sst_drv_ctx->dev, "Probe failed with %d\n", ret);
0154     return ret;
0155 }
0156 
0157 /**
0158  * intel_sst_remove - PCI remove function
0159  *
0160  * @pci:    PCI device structure
0161  *
0162  * This function is called by OS when a device is unloaded
0163  * This frees the interrupt etc
0164  */
0165 static void intel_sst_remove(struct pci_dev *pci)
0166 {
0167     struct intel_sst_drv *sst_drv_ctx = pci_get_drvdata(pci);
0168 
0169     sst_context_cleanup(sst_drv_ctx);
0170     pci_dev_put(sst_drv_ctx->pci);
0171     pci_release_regions(pci);
0172     pci_set_drvdata(pci, NULL);
0173 }
0174 
0175 /* PCI Routines */
0176 static const struct pci_device_id intel_sst_ids[] = {
0177     { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0},
0178     { 0, }
0179 };
0180 
0181 static struct pci_driver sst_driver = {
0182     .name = SST_DRV_NAME,
0183     .id_table = intel_sst_ids,
0184     .probe = intel_sst_probe,
0185     .remove = intel_sst_remove,
0186 #ifdef CONFIG_PM
0187     .driver = {
0188         .pm = &intel_sst_pm,
0189     },
0190 #endif
0191 };
0192 
0193 module_pci_driver(sst_driver);
0194 
0195 MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine PCI Driver");
0196 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
0197 MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
0198 MODULE_AUTHOR("Dharageswari R <dharageswari.r@intel.com>");
0199 MODULE_AUTHOR("KP Jeeja <jeeja.kp@intel.com>");
0200 MODULE_LICENSE("GPL v2");
0201 MODULE_ALIAS("sst");