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 25 static 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); 100 do_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 */ 112 static 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 151 do_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 */ 165 static 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 */ 176 static const struct pci_device_id intel_sst_ids[] = { 177 { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0}, 178 { 0, } 179 }; 180 181 static 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 193 module_pci_driver(sst_driver); 194 195 MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine PCI Driver"); 196 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); 197 MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); 198 MODULE_AUTHOR("Dharageswari R <dharageswari.r@intel.com>"); 199 MODULE_AUTHOR("KP Jeeja <jeeja.kp@intel.com>"); 200 MODULE_LICENSE("GPL v2"); 201 MODULE_ALIAS("sst"); 202