18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * sst_pci.c - SST (LPE) driver init file for pci enumeration. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2008-14 Intel Corp 68c2ecf20Sopenharmony_ci * Authors: Vinod Koul <vinod.koul@intel.com> 78c2ecf20Sopenharmony_ci * Harsha Priya <priya.harsha@intel.com> 88c2ecf20Sopenharmony_ci * Dharageswari R <dharageswari.r@intel.com> 98c2ecf20Sopenharmony_ci * KP Jeeja <jeeja.kp@intel.com> 108c2ecf20Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/pci.h> 168c2ecf20Sopenharmony_ci#include <linux/fs.h> 178c2ecf20Sopenharmony_ci#include <linux/firmware.h> 188c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 198c2ecf20Sopenharmony_ci#include <sound/core.h> 208c2ecf20Sopenharmony_ci#include <sound/soc.h> 218c2ecf20Sopenharmony_ci#include <asm/platform_sst_audio.h> 228c2ecf20Sopenharmony_ci#include "../sst-mfld-platform.h" 238c2ecf20Sopenharmony_ci#include "sst.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic int sst_platform_get_resources(struct intel_sst_drv *ctx) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci int ddr_base, ret = 0; 288c2ecf20Sopenharmony_ci struct pci_dev *pci = ctx->pci; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci ret = pci_request_regions(pci, SST_DRV_NAME); 318c2ecf20Sopenharmony_ci if (ret) 328c2ecf20Sopenharmony_ci return ret; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci /* map registers */ 358c2ecf20Sopenharmony_ci /* DDR base */ 368c2ecf20Sopenharmony_ci if (ctx->dev_id == SST_MRFLD_PCI_ID) { 378c2ecf20Sopenharmony_ci ctx->ddr_base = pci_resource_start(pci, 0); 388c2ecf20Sopenharmony_ci /* check that the relocated IMR base matches with FW Binary */ 398c2ecf20Sopenharmony_ci ddr_base = relocate_imr_addr_mrfld(ctx->ddr_base); 408c2ecf20Sopenharmony_ci if (!ctx->pdata->lib_info) { 418c2ecf20Sopenharmony_ci dev_err(ctx->dev, "lib_info pointer NULL\n"); 428c2ecf20Sopenharmony_ci ret = -EINVAL; 438c2ecf20Sopenharmony_ci goto do_release_regions; 448c2ecf20Sopenharmony_ci } 458c2ecf20Sopenharmony_ci if (ddr_base != ctx->pdata->lib_info->mod_base) { 468c2ecf20Sopenharmony_ci dev_err(ctx->dev, 478c2ecf20Sopenharmony_ci "FW LSP DDR BASE does not match with IFWI\n"); 488c2ecf20Sopenharmony_ci ret = -EINVAL; 498c2ecf20Sopenharmony_ci goto do_release_regions; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci ctx->ddr_end = pci_resource_end(pci, 0); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci ctx->ddr = pcim_iomap(pci, 0, 548c2ecf20Sopenharmony_ci pci_resource_len(pci, 0)); 558c2ecf20Sopenharmony_ci if (!ctx->ddr) { 568c2ecf20Sopenharmony_ci ret = -EINVAL; 578c2ecf20Sopenharmony_ci goto do_release_regions; 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "sst: DDR Ptr %p\n", ctx->ddr); 608c2ecf20Sopenharmony_ci } else { 618c2ecf20Sopenharmony_ci ctx->ddr = NULL; 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci /* SHIM */ 648c2ecf20Sopenharmony_ci ctx->shim_phy_add = pci_resource_start(pci, 1); 658c2ecf20Sopenharmony_ci ctx->shim = pcim_iomap(pci, 1, pci_resource_len(pci, 1)); 668c2ecf20Sopenharmony_ci if (!ctx->shim) { 678c2ecf20Sopenharmony_ci ret = -EINVAL; 688c2ecf20Sopenharmony_ci goto do_release_regions; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "SST Shim Ptr %p\n", ctx->shim); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci /* Shared SRAM */ 738c2ecf20Sopenharmony_ci ctx->mailbox_add = pci_resource_start(pci, 2); 748c2ecf20Sopenharmony_ci ctx->mailbox = pcim_iomap(pci, 2, pci_resource_len(pci, 2)); 758c2ecf20Sopenharmony_ci if (!ctx->mailbox) { 768c2ecf20Sopenharmony_ci ret = -EINVAL; 778c2ecf20Sopenharmony_ci goto do_release_regions; 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "SRAM Ptr %p\n", ctx->mailbox); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* IRAM */ 828c2ecf20Sopenharmony_ci ctx->iram_end = pci_resource_end(pci, 3); 838c2ecf20Sopenharmony_ci ctx->iram_base = pci_resource_start(pci, 3); 848c2ecf20Sopenharmony_ci ctx->iram = pcim_iomap(pci, 3, pci_resource_len(pci, 3)); 858c2ecf20Sopenharmony_ci if (!ctx->iram) { 868c2ecf20Sopenharmony_ci ret = -EINVAL; 878c2ecf20Sopenharmony_ci goto do_release_regions; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "IRAM Ptr %p\n", ctx->iram); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci /* DRAM */ 928c2ecf20Sopenharmony_ci ctx->dram_end = pci_resource_end(pci, 4); 938c2ecf20Sopenharmony_ci ctx->dram_base = pci_resource_start(pci, 4); 948c2ecf20Sopenharmony_ci ctx->dram = pcim_iomap(pci, 4, pci_resource_len(pci, 4)); 958c2ecf20Sopenharmony_ci if (!ctx->dram) { 968c2ecf20Sopenharmony_ci ret = -EINVAL; 978c2ecf20Sopenharmony_ci goto do_release_regions; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "DRAM Ptr %p\n", ctx->dram); 1008c2ecf20Sopenharmony_cido_release_regions: 1018c2ecf20Sopenharmony_ci pci_release_regions(pci); 1028c2ecf20Sopenharmony_ci return ret; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci/* 1068c2ecf20Sopenharmony_ci * intel_sst_probe - PCI probe function 1078c2ecf20Sopenharmony_ci * 1088c2ecf20Sopenharmony_ci * @pci: PCI device structure 1098c2ecf20Sopenharmony_ci * @pci_id: PCI device ID structure 1108c2ecf20Sopenharmony_ci * 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_cistatic int intel_sst_probe(struct pci_dev *pci, 1138c2ecf20Sopenharmony_ci const struct pci_device_id *pci_id) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci int ret = 0; 1168c2ecf20Sopenharmony_ci struct intel_sst_drv *sst_drv_ctx; 1178c2ecf20Sopenharmony_ci struct sst_platform_info *sst_pdata = pci->dev.platform_data; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci dev_dbg(&pci->dev, "Probe for DID %x\n", pci->device); 1208c2ecf20Sopenharmony_ci ret = sst_alloc_drv_context(&sst_drv_ctx, &pci->dev, pci->device); 1218c2ecf20Sopenharmony_ci if (ret < 0) 1228c2ecf20Sopenharmony_ci return ret; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci sst_drv_ctx->pdata = sst_pdata; 1258c2ecf20Sopenharmony_ci sst_drv_ctx->irq_num = pci->irq; 1268c2ecf20Sopenharmony_ci snprintf(sst_drv_ctx->firmware_name, sizeof(sst_drv_ctx->firmware_name), 1278c2ecf20Sopenharmony_ci "%s%04x%s", "fw_sst_", 1288c2ecf20Sopenharmony_ci sst_drv_ctx->dev_id, ".bin"); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci ret = sst_context_init(sst_drv_ctx); 1318c2ecf20Sopenharmony_ci if (ret < 0) 1328c2ecf20Sopenharmony_ci return ret; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci /* Init the device */ 1358c2ecf20Sopenharmony_ci ret = pcim_enable_device(pci); 1368c2ecf20Sopenharmony_ci if (ret) { 1378c2ecf20Sopenharmony_ci dev_err(sst_drv_ctx->dev, 1388c2ecf20Sopenharmony_ci "device can't be enabled. Returned err: %d\n", ret); 1398c2ecf20Sopenharmony_ci goto do_free_drv_ctx; 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci sst_drv_ctx->pci = pci_dev_get(pci); 1428c2ecf20Sopenharmony_ci ret = sst_platform_get_resources(sst_drv_ctx); 1438c2ecf20Sopenharmony_ci if (ret < 0) 1448c2ecf20Sopenharmony_ci goto do_free_drv_ctx; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci pci_set_drvdata(pci, sst_drv_ctx); 1478c2ecf20Sopenharmony_ci sst_configure_runtime_pm(sst_drv_ctx); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci return ret; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cido_free_drv_ctx: 1528c2ecf20Sopenharmony_ci sst_context_cleanup(sst_drv_ctx); 1538c2ecf20Sopenharmony_ci dev_err(sst_drv_ctx->dev, "Probe failed with %d\n", ret); 1548c2ecf20Sopenharmony_ci return ret; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci/** 1588c2ecf20Sopenharmony_ci * intel_sst_remove - PCI remove function 1598c2ecf20Sopenharmony_ci * 1608c2ecf20Sopenharmony_ci * @pci: PCI device structure 1618c2ecf20Sopenharmony_ci * 1628c2ecf20Sopenharmony_ci * This function is called by OS when a device is unloaded 1638c2ecf20Sopenharmony_ci * This frees the interrupt etc 1648c2ecf20Sopenharmony_ci */ 1658c2ecf20Sopenharmony_cistatic void intel_sst_remove(struct pci_dev *pci) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci struct intel_sst_drv *sst_drv_ctx = pci_get_drvdata(pci); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci sst_context_cleanup(sst_drv_ctx); 1708c2ecf20Sopenharmony_ci pci_dev_put(sst_drv_ctx->pci); 1718c2ecf20Sopenharmony_ci pci_release_regions(pci); 1728c2ecf20Sopenharmony_ci pci_set_drvdata(pci, NULL); 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci/* PCI Routines */ 1768c2ecf20Sopenharmony_cistatic const struct pci_device_id intel_sst_ids[] = { 1778c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0}, 1788c2ecf20Sopenharmony_ci { 0, } 1798c2ecf20Sopenharmony_ci}; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic struct pci_driver sst_driver = { 1828c2ecf20Sopenharmony_ci .name = SST_DRV_NAME, 1838c2ecf20Sopenharmony_ci .id_table = intel_sst_ids, 1848c2ecf20Sopenharmony_ci .probe = intel_sst_probe, 1858c2ecf20Sopenharmony_ci .remove = intel_sst_remove, 1868c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 1878c2ecf20Sopenharmony_ci .driver = { 1888c2ecf20Sopenharmony_ci .pm = &intel_sst_pm, 1898c2ecf20Sopenharmony_ci }, 1908c2ecf20Sopenharmony_ci#endif 1918c2ecf20Sopenharmony_ci}; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cimodule_pci_driver(sst_driver); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine PCI Driver"); 1968c2ecf20Sopenharmony_ciMODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); 1978c2ecf20Sopenharmony_ciMODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); 1988c2ecf20Sopenharmony_ciMODULE_AUTHOR("Dharageswari R <dharageswari.r@intel.com>"); 1998c2ecf20Sopenharmony_ciMODULE_AUTHOR("KP Jeeja <jeeja.kp@intel.com>"); 2008c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 2018c2ecf20Sopenharmony_ciMODULE_ALIAS("sst"); 202