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 33 static 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); 108 do_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 */ 120 static 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 159 do_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 */ 173 static 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 */ 184 static const struct pci_device_id intel_sst_ids[] = { 185 { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0}, 186 { 0, } 187 }; 188 189 static 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 201 module_pci_driver(sst_driver); 202 203 MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine PCI Driver"); 204 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); 205 MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); 206 MODULE_AUTHOR("Dharageswari R <dharageswari.r@intel.com>"); 207 MODULE_AUTHOR("KP Jeeja <jeeja.kp@intel.com>"); 208 MODULE_LICENSE("GPL v2"); 209 MODULE_ALIAS("sst"); 210