Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Intel MIC Platform Software Stack (MPSS)
  4 *
  5 * Copyright(c) 2013 Intel Corporation.
  6 *
  7 * Intel MIC Host driver.
  8 */
  9#include <linux/fs.h>
 10#include <linux/module.h>
 11#include <linux/pci.h>
 12#include <linux/poll.h>
 13
 14#include <linux/mic_common.h>
 15#include "../common/mic_dev.h"
 16#include "mic_device.h"
 17#include "mic_x100.h"
 18#include "mic_smpt.h"
 19
 20static const char mic_driver_name[] = "mic";
 21
 22static const struct pci_device_id mic_pci_tbl[] = {
 23	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2250)},
 24	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2251)},
 25	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2252)},
 26	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2253)},
 27	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2254)},
 28	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2255)},
 29	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2256)},
 30	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2257)},
 31	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2258)},
 32	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2259)},
 33	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225a)},
 34	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225b)},
 35	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225c)},
 36	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225d)},
 37	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225e)},
 38
 39	/* required last entry */
 40	{ 0, }
 41};
 42
 43MODULE_DEVICE_TABLE(pci, mic_pci_tbl);
 44
 45/* ID allocator for MIC devices */
 46static struct ida g_mic_ida;
 47
 48/* Initialize the device page */
 49static int mic_dp_init(struct mic_device *mdev)
 50{
 51	mdev->dp = kzalloc(MIC_DP_SIZE, GFP_KERNEL);
 52	if (!mdev->dp)
 53		return -ENOMEM;
 54
 55	mdev->dp_dma_addr = mic_map_single(mdev,
 56		mdev->dp, MIC_DP_SIZE);
 57	if (mic_map_error(mdev->dp_dma_addr)) {
 58		kfree(mdev->dp);
 59		dev_err(&mdev->pdev->dev, "%s %d err %d\n",
 60			__func__, __LINE__, -ENOMEM);
 61		return -ENOMEM;
 62	}
 63	mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
 64	mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
 65	return 0;
 66}
 67
 68/* Uninitialize the device page */
 69static void mic_dp_uninit(struct mic_device *mdev)
 70{
 71	mic_unmap_single(mdev, mdev->dp_dma_addr, MIC_DP_SIZE);
 72	kfree(mdev->dp);
 73}
 74
 75/**
 76 * mic_ops_init: Initialize HW specific operation tables.
 77 *
 78 * @mdev: pointer to mic_device instance
 79 *
 80 * returns none.
 81 */
 82static void mic_ops_init(struct mic_device *mdev)
 83{
 84	switch (mdev->family) {
 85	case MIC_FAMILY_X100:
 86		mdev->ops = &mic_x100_ops;
 87		mdev->intr_ops = &mic_x100_intr_ops;
 88		mdev->smpt_ops = &mic_x100_smpt_ops;
 89		break;
 90	default:
 91		break;
 92	}
 93}
 94
 95/**
 96 * mic_get_family - Determine hardware family to which this MIC belongs.
 97 *
 98 * @pdev: The pci device structure
 99 *
100 * returns family.
101 */
102static enum mic_hw_family mic_get_family(struct pci_dev *pdev)
103{
104	enum mic_hw_family family;
105
106	switch (pdev->device) {
107	case MIC_X100_PCI_DEVICE_2250:
108	case MIC_X100_PCI_DEVICE_2251:
109	case MIC_X100_PCI_DEVICE_2252:
110	case MIC_X100_PCI_DEVICE_2253:
111	case MIC_X100_PCI_DEVICE_2254:
112	case MIC_X100_PCI_DEVICE_2255:
113	case MIC_X100_PCI_DEVICE_2256:
114	case MIC_X100_PCI_DEVICE_2257:
115	case MIC_X100_PCI_DEVICE_2258:
116	case MIC_X100_PCI_DEVICE_2259:
117	case MIC_X100_PCI_DEVICE_225a:
118	case MIC_X100_PCI_DEVICE_225b:
119	case MIC_X100_PCI_DEVICE_225c:
120	case MIC_X100_PCI_DEVICE_225d:
121	case MIC_X100_PCI_DEVICE_225e:
122		family = MIC_FAMILY_X100;
123		break;
124	default:
125		family = MIC_FAMILY_UNKNOWN;
126		break;
127	}
128	return family;
129}
130
131/**
132 * mic_device_init - Allocates and initializes the MIC device structure
133 *
134 * @mdev: pointer to mic_device instance
135 * @pdev: The pci device structure
136 *
137 * returns none.
138 */
139static void
140mic_device_init(struct mic_device *mdev, struct pci_dev *pdev)
141{
142	mdev->pdev = pdev;
143	mdev->family = mic_get_family(pdev);
144	mdev->stepping = pdev->revision;
145	mic_ops_init(mdev);
146	mutex_init(&mdev->mic_mutex);
147	mdev->irq_info.next_avail_src = 0;
148}
149
150/**
151 * mic_probe - Device Initialization Routine
152 *
153 * @pdev: PCI device structure
154 * @ent: entry in mic_pci_tbl
155 *
156 * returns 0 on success, < 0 on failure.
157 */
158static int mic_probe(struct pci_dev *pdev,
159		     const struct pci_device_id *ent)
160{
161	int rc;
162	struct mic_device *mdev;
163
164	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
165	if (!mdev) {
166		rc = -ENOMEM;
167		dev_err(&pdev->dev, "mdev kmalloc failed rc %d\n", rc);
168		goto mdev_alloc_fail;
169	}
170	mdev->id = ida_simple_get(&g_mic_ida, 0, MIC_MAX_NUM_DEVS, GFP_KERNEL);
171	if (mdev->id < 0) {
172		rc = mdev->id;
173		dev_err(&pdev->dev, "ida_simple_get failed rc %d\n", rc);
174		goto ida_fail;
175	}
176
177	mic_device_init(mdev, pdev);
178
179	rc = pci_enable_device(pdev);
180	if (rc) {
181		dev_err(&pdev->dev, "failed to enable pci device.\n");
182		goto ida_remove;
183	}
184
185	pci_set_master(pdev);
186
187	rc = pci_request_regions(pdev, mic_driver_name);
188	if (rc) {
189		dev_err(&pdev->dev, "failed to get pci regions.\n");
190		goto disable_device;
191	}
192
193	rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
194	if (rc) {
195		dev_err(&pdev->dev, "Cannot set DMA mask\n");
196		goto release_regions;
197	}
198
199	mdev->mmio.pa = pci_resource_start(pdev, mdev->ops->mmio_bar);
200	mdev->mmio.len = pci_resource_len(pdev, mdev->ops->mmio_bar);
201	mdev->mmio.va = pci_ioremap_bar(pdev, mdev->ops->mmio_bar);
202	if (!mdev->mmio.va) {
203		dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
204		rc = -EIO;
205		goto release_regions;
206	}
207
208	mdev->aper.pa = pci_resource_start(pdev, mdev->ops->aper_bar);
209	mdev->aper.len = pci_resource_len(pdev, mdev->ops->aper_bar);
210	mdev->aper.va = ioremap_wc(mdev->aper.pa, mdev->aper.len);
211	if (!mdev->aper.va) {
212		dev_err(&pdev->dev, "Cannot remap Aperture BAR\n");
213		rc = -EIO;
214		goto unmap_mmio;
215	}
216
217	mdev->intr_ops->intr_init(mdev);
218	rc = mic_setup_interrupts(mdev, pdev);
219	if (rc) {
220		dev_err(&pdev->dev, "mic_setup_interrupts failed %d\n", rc);
221		goto unmap_aper;
222	}
223	rc = mic_smpt_init(mdev);
224	if (rc) {
225		dev_err(&pdev->dev, "smpt_init failed %d\n", rc);
226		goto free_interrupts;
227	}
228
229	pci_set_drvdata(pdev, mdev);
230
231	rc = mic_dp_init(mdev);
232	if (rc) {
233		dev_err(&pdev->dev, "mic_dp_init failed rc %d\n", rc);
234		goto smpt_uninit;
235	}
236	mic_bootparam_init(mdev);
237	mic_create_debug_dir(mdev);
238
239	mdev->cosm_dev = cosm_register_device(&mdev->pdev->dev, &cosm_hw_ops);
240	if (IS_ERR(mdev->cosm_dev)) {
241		rc = PTR_ERR(mdev->cosm_dev);
242		dev_err(&pdev->dev, "cosm_add_device failed rc %d\n", rc);
243		goto cleanup_debug_dir;
244	}
245	return 0;
246cleanup_debug_dir:
247	mic_delete_debug_dir(mdev);
248	mic_dp_uninit(mdev);
249smpt_uninit:
250	mic_smpt_uninit(mdev);
251free_interrupts:
252	mic_free_interrupts(mdev, pdev);
253unmap_aper:
254	iounmap(mdev->aper.va);
255unmap_mmio:
256	iounmap(mdev->mmio.va);
257release_regions:
258	pci_release_regions(pdev);
259disable_device:
260	pci_disable_device(pdev);
261ida_remove:
262	ida_simple_remove(&g_mic_ida, mdev->id);
263ida_fail:
264	kfree(mdev);
265mdev_alloc_fail:
266	dev_err(&pdev->dev, "Probe failed rc %d\n", rc);
267	return rc;
268}
269
270/**
271 * mic_remove - Device Removal Routine
272 * mic_remove is called by the PCI subsystem to alert the driver
273 * that it should release a PCI device.
274 *
275 * @pdev: PCI device structure
276 */
277static void mic_remove(struct pci_dev *pdev)
278{
279	struct mic_device *mdev;
280
281	mdev = pci_get_drvdata(pdev);
282	if (!mdev)
283		return;
284
285	cosm_unregister_device(mdev->cosm_dev);
286	mic_delete_debug_dir(mdev);
287	mic_dp_uninit(mdev);
288	mic_smpt_uninit(mdev);
289	mic_free_interrupts(mdev, pdev);
290	iounmap(mdev->aper.va);
291	iounmap(mdev->mmio.va);
292	pci_release_regions(pdev);
293	pci_disable_device(pdev);
294	ida_simple_remove(&g_mic_ida, mdev->id);
295	kfree(mdev);
296}
297
298static struct pci_driver mic_driver = {
299	.name = mic_driver_name,
300	.id_table = mic_pci_tbl,
301	.probe = mic_probe,
302	.remove = mic_remove
303};
304
305static int __init mic_init(void)
306{
307	int ret;
308
309	request_module("mic_x100_dma");
310	mic_init_debugfs();
311	ida_init(&g_mic_ida);
312	ret = pci_register_driver(&mic_driver);
313	if (ret) {
314		pr_err("pci_register_driver failed ret %d\n", ret);
315		goto cleanup_debugfs;
316	}
317	return 0;
318cleanup_debugfs:
319	ida_destroy(&g_mic_ida);
320	mic_exit_debugfs();
321	return ret;
322}
323
324static void __exit mic_exit(void)
325{
326	pci_unregister_driver(&mic_driver);
327	ida_destroy(&g_mic_ida);
328	mic_exit_debugfs();
329}
330
331module_init(mic_init);
332module_exit(mic_exit);
333
334MODULE_AUTHOR("Intel Corporation");
335MODULE_DESCRIPTION("Intel(R) MIC X100 Host driver");
336MODULE_LICENSE("GPL v2");