Commit | Line | Data |
---|---|---|
f533a035 VK |
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 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"); |