xref: /linux/sound/soc/intel/atom/sst/sst_pci.c (revision a9e6060bb2a6cae6d43a98ec0794844ad01273d3)
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 
sst_platform_get_resources(struct intel_sst_drv * ctx)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  */
intel_sst_probe(struct pci_dev * pci,const struct pci_device_id * pci_id)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  */
intel_sst_remove(struct pci_dev * pci)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