xref: /openbmc/linux/sound/soc/intel/atom/sst/sst_pci.c (revision e3d786a3)
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