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