aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSudeep Dutt <sudeep.dutt@intel.com>2013-09-05 19:42:06 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-09-26 16:50:56 -0400
commitaa27badd8972adb731f05d49ab74ec63e0826935 (patch)
treeb83e73982675e15a3f94260ffbade97d2fa1e4ee
parent3a6a9201897c6482573ad07ee880574147761006 (diff)
Intel MIC Card Driver for X100 family.
This patch does the following: a) Initializes the Intel MIC X100 platform device and driver. b) Sets up support to handle shutdown requests from the host. c) Maps the device page after obtaining the device page address from the scratchpad registers updated by the host. d) Informs the host upon a card crash by registering a panic notifier. e) Informs the host upon a poweroff/halt event. Co-author: Dasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com> Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com> Signed-off-by: Caz Yokoyama <Caz.Yokoyama@intel.com> Signed-off-by: Dasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com> Signed-off-by: Nikhil Rao <nikhil.rao@intel.com> Signed-off-by: Harshavardhan R Kharche <harshavardhan.r.kharche@intel.com> Signed-off-by: Sudeep Dutt <sudeep.dutt@intel.com> Acked-by: Yaozu (Eddie) Dong <eddie.dong@intel.com> Reviewed-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/misc/mic/Kconfig18
-rw-r--r--drivers/misc/mic/Makefile1
-rw-r--r--drivers/misc/mic/card/Makefile10
-rw-r--r--drivers/misc/mic/card/mic_debugfs.c130
-rw-r--r--drivers/misc/mic/card/mic_device.c299
-rw-r--r--drivers/misc/mic/card/mic_device.h133
-rw-r--r--drivers/misc/mic/card/mic_x100.c256
-rw-r--r--drivers/misc/mic/card/mic_x100.h48
8 files changed, 895 insertions, 0 deletions
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig
index aaefd0cf82a7..279a2e649059 100644
--- a/drivers/misc/mic/Kconfig
+++ b/drivers/misc/mic/Kconfig
@@ -17,3 +17,21 @@ config INTEL_MIC_HOST
17 More information about the Intel MIC family as well as the Linux 17 More information about the Intel MIC family as well as the Linux
18 OS and tools for MIC to use with this driver are available from 18 OS and tools for MIC to use with this driver are available from
19 <http://software.intel.com/en-us/mic-developer>. 19 <http://software.intel.com/en-us/mic-developer>.
20
21comment "Intel MIC Card Driver"
22
23config INTEL_MIC_CARD
24 tristate "Intel MIC Card Driver"
25 depends on 64BIT
26 default N
27 help
28 This enables card driver support for the Intel Many Integrated
29 Core (MIC) device family. The card driver communicates shutdown/
30 crash events to the host and allows registration/configuration of
31 virtio devices. Intel MIC X100 devices are currently supported.
32
33 If you are building a card kernel for an Intel MIC device then
34 say M (recommended) or Y, else say N. If unsure say N.
35
36 For more information see
37 <http://software.intel.com/en-us/mic-developer>.
diff --git a/drivers/misc/mic/Makefile b/drivers/misc/mic/Makefile
index 8e724212d94c..05b34d683a58 100644
--- a/drivers/misc/mic/Makefile
+++ b/drivers/misc/mic/Makefile
@@ -3,3 +3,4 @@
3# Copyright(c) 2013, Intel Corporation. 3# Copyright(c) 2013, Intel Corporation.
4# 4#
5obj-$(CONFIG_INTEL_MIC_HOST) += host/ 5obj-$(CONFIG_INTEL_MIC_HOST) += host/
6obj-$(CONFIG_INTEL_MIC_CARD) += card/
diff --git a/drivers/misc/mic/card/Makefile b/drivers/misc/mic/card/Makefile
new file mode 100644
index 000000000000..6e9675e12a09
--- /dev/null
+++ b/drivers/misc/mic/card/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile - Intel MIC Linux driver.
3# Copyright(c) 2013, Intel Corporation.
4#
5ccflags-y += -DINTEL_MIC_CARD
6
7obj-$(CONFIG_INTEL_MIC_CARD) += mic_card.o
8mic_card-y += mic_x100.o
9mic_card-y += mic_device.o
10mic_card-y += mic_debugfs.o
diff --git a/drivers/misc/mic/card/mic_debugfs.c b/drivers/misc/mic/card/mic_debugfs.c
new file mode 100644
index 000000000000..95cf186ff73a
--- /dev/null
+++ b/drivers/misc/mic/card/mic_debugfs.c
@@ -0,0 +1,130 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Disclaimer: The codes contained in these modules may be specific to
19 * the Intel Software Development Platform codenamed: Knights Ferry, and
20 * the Intel product codenamed: Knights Corner, and are not backward
21 * compatible with other Intel products. Additionally, Intel will NOT
22 * support the codes or instruction set in future products.
23 *
24 * Intel MIC Card driver.
25 *
26 */
27#include <linux/debugfs.h>
28#include <linux/delay.h>
29#include <linux/seq_file.h>
30#include <linux/interrupt.h>
31#include <linux/device.h>
32
33#include "../common/mic_device.h"
34#include "mic_device.h"
35
36/* Debugfs parent dir */
37static struct dentry *mic_dbg;
38
39/**
40 * mic_intr_test - Send interrupts to host.
41 */
42static int mic_intr_test(struct seq_file *s, void *unused)
43{
44 struct mic_driver *mdrv = s->private;
45 struct mic_device *mdev = &mdrv->mdev;
46
47 mic_send_intr(mdev, 0);
48 msleep(1000);
49 mic_send_intr(mdev, 1);
50 msleep(1000);
51 mic_send_intr(mdev, 2);
52 msleep(1000);
53 mic_send_intr(mdev, 3);
54 msleep(1000);
55
56 return 0;
57}
58
59static int mic_intr_test_open(struct inode *inode, struct file *file)
60{
61 return single_open(file, mic_intr_test, inode->i_private);
62}
63
64static int mic_intr_test_release(struct inode *inode, struct file *file)
65{
66 return single_release(inode, file);
67}
68
69static const struct file_operations intr_test_ops = {
70 .owner = THIS_MODULE,
71 .open = mic_intr_test_open,
72 .read = seq_read,
73 .llseek = seq_lseek,
74 .release = mic_intr_test_release
75};
76
77/**
78 * mic_create_card_debug_dir - Initialize MIC debugfs entries.
79 */
80void __init mic_create_card_debug_dir(struct mic_driver *mdrv)
81{
82 struct dentry *d;
83
84 if (!mic_dbg)
85 return;
86
87 mdrv->dbg_dir = debugfs_create_dir(mdrv->name, mic_dbg);
88 if (!mdrv->dbg_dir) {
89 dev_err(mdrv->dev, "Cant create dbg_dir %s\n", mdrv->name);
90 return;
91 }
92
93 d = debugfs_create_file("intr_test", 0444, mdrv->dbg_dir,
94 mdrv, &intr_test_ops);
95
96 if (!d) {
97 dev_err(mdrv->dev,
98 "Cant create dbg intr_test %s\n", mdrv->name);
99 return;
100 }
101}
102
103/**
104 * mic_delete_card_debug_dir - Uninitialize MIC debugfs entries.
105 */
106void mic_delete_card_debug_dir(struct mic_driver *mdrv)
107{
108 if (!mdrv->dbg_dir)
109 return;
110
111 debugfs_remove_recursive(mdrv->dbg_dir);
112}
113
114/**
115 * mic_init_card_debugfs - Initialize global debugfs entry.
116 */
117void __init mic_init_card_debugfs(void)
118{
119 mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
120 if (!mic_dbg)
121 pr_err("can't create debugfs dir\n");
122}
123
124/**
125 * mic_exit_card_debugfs - Uninitialize global debugfs entry
126 */
127void mic_exit_card_debugfs(void)
128{
129 debugfs_remove(mic_dbg);
130}
diff --git a/drivers/misc/mic/card/mic_device.c b/drivers/misc/mic/card/mic_device.c
new file mode 100644
index 000000000000..3c5c302dba41
--- /dev/null
+++ b/drivers/misc/mic/card/mic_device.c
@@ -0,0 +1,299 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Disclaimer: The codes contained in these modules may be specific to
19 * the Intel Software Development Platform codenamed: Knights Ferry, and
20 * the Intel product codenamed: Knights Corner, and are not backward
21 * compatible with other Intel products. Additionally, Intel will NOT
22 * support the codes or instruction set in future products.
23 *
24 * Intel MIC Card driver.
25 *
26 */
27#include <linux/module.h>
28#include <linux/pci.h>
29#include <linux/interrupt.h>
30#include <linux/reboot.h>
31
32#include <linux/mic_common.h>
33#include "../common/mic_device.h"
34#include "mic_device.h"
35
36static struct mic_driver *g_drv;
37static struct mic_irq *shutdown_cookie;
38
39static void mic_notify_host(u8 state)
40{
41 struct mic_driver *mdrv = g_drv;
42 struct mic_bootparam __iomem *bootparam = mdrv->dp;
43
44 iowrite8(state, &bootparam->shutdown_status);
45 dev_dbg(mdrv->dev, "%s %d system_state %d\n",
46 __func__, __LINE__, state);
47 mic_send_intr(&mdrv->mdev, ioread8(&bootparam->c2h_shutdown_db));
48}
49
50static int mic_panic_event(struct notifier_block *this, unsigned long event,
51 void *ptr)
52{
53 struct mic_driver *mdrv = g_drv;
54 struct mic_bootparam __iomem *bootparam = mdrv->dp;
55
56 iowrite8(-1, &bootparam->h2c_config_db);
57 iowrite8(-1, &bootparam->h2c_shutdown_db);
58 mic_notify_host(MIC_CRASHED);
59 return NOTIFY_DONE;
60}
61
62static struct notifier_block mic_panic = {
63 .notifier_call = mic_panic_event,
64};
65
66static irqreturn_t mic_shutdown_isr(int irq, void *data)
67{
68 struct mic_driver *mdrv = g_drv;
69 struct mic_bootparam __iomem *bootparam = mdrv->dp;
70
71 mic_ack_interrupt(&g_drv->mdev);
72 if (ioread8(&bootparam->shutdown_card))
73 orderly_poweroff(true);
74 return IRQ_HANDLED;
75}
76
77static int mic_shutdown_init(void)
78{
79 int rc = 0;
80 struct mic_driver *mdrv = g_drv;
81 struct mic_bootparam __iomem *bootparam = mdrv->dp;
82 int shutdown_db;
83
84 shutdown_db = mic_next_card_db();
85 shutdown_cookie = mic_request_card_irq(mic_shutdown_isr,
86 "Shutdown", mdrv, shutdown_db);
87 if (IS_ERR(shutdown_cookie))
88 rc = PTR_ERR(shutdown_cookie);
89 else
90 iowrite8(shutdown_db, &bootparam->h2c_shutdown_db);
91 return rc;
92}
93
94static void mic_shutdown_uninit(void)
95{
96 struct mic_driver *mdrv = g_drv;
97 struct mic_bootparam __iomem *bootparam = mdrv->dp;
98
99 iowrite8(-1, &bootparam->h2c_shutdown_db);
100 mic_free_card_irq(shutdown_cookie, mdrv);
101}
102
103static int __init mic_dp_init(void)
104{
105 struct mic_driver *mdrv = g_drv;
106 struct mic_device *mdev = &mdrv->mdev;
107 struct mic_bootparam __iomem *bootparam;
108 u64 lo, hi, dp_dma_addr;
109 u32 magic;
110
111 lo = mic_read_spad(&mdrv->mdev, MIC_DPLO_SPAD);
112 hi = mic_read_spad(&mdrv->mdev, MIC_DPHI_SPAD);
113
114 dp_dma_addr = lo | (hi << 32);
115 mdrv->dp = mic_card_map(mdev, dp_dma_addr, MIC_DP_SIZE);
116 if (!mdrv->dp) {
117 dev_err(mdrv->dev, "Cannot remap Aperture BAR\n");
118 return -ENOMEM;
119 }
120 bootparam = mdrv->dp;
121 magic = ioread32(&bootparam->magic);
122 if (MIC_MAGIC != magic) {
123 dev_err(mdrv->dev, "bootparam magic mismatch 0x%x\n", magic);
124 return -EIO;
125 }
126 return 0;
127}
128
129/* Uninitialize the device page */
130static void mic_dp_uninit(void)
131{
132 mic_card_unmap(&g_drv->mdev, g_drv->dp);
133}
134
135/**
136 * mic_request_card_irq - request an irq.
137 *
138 * @func: The callback function that handles the interrupt.
139 * @name: The ASCII name of the callee requesting the irq.
140 * @data: private data that is returned back when calling the
141 * function handler.
142 * @index: The doorbell index of the requester.
143 *
144 * returns: The cookie that is transparent to the caller. Passed
145 * back when calling mic_free_irq. An appropriate error code
146 * is returned on failure. Caller needs to use IS_ERR(return_val)
147 * to check for failure and PTR_ERR(return_val) to obtained the
148 * error code.
149 *
150 */
151struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data),
152 const char *name, void *data, int index)
153{
154 int rc = 0;
155 unsigned long cookie;
156 struct mic_driver *mdrv = g_drv;
157
158 rc = request_irq(mic_db_to_irq(mdrv, index), func,
159 0, name, data);
160 if (rc) {
161 dev_err(mdrv->dev, "request_irq failed rc = %d\n", rc);
162 goto err;
163 }
164 mdrv->irq_info.irq_usage_count[index]++;
165 cookie = index;
166 return (struct mic_irq *)cookie;
167err:
168 return ERR_PTR(rc);
169
170}
171
172/**
173 * mic_free_card_irq - free irq.
174 *
175 * @cookie: cookie obtained during a successful call to mic_request_irq
176 * @data: private data specified by the calling function during the
177 * mic_request_irq
178 *
179 * returns: none.
180 */
181void mic_free_card_irq(struct mic_irq *cookie, void *data)
182{
183 int index;
184 struct mic_driver *mdrv = g_drv;
185
186 index = (unsigned long)cookie & 0xFFFFU;
187 free_irq(mic_db_to_irq(mdrv, index), data);
188 mdrv->irq_info.irq_usage_count[index]--;
189}
190
191/**
192 * mic_next_card_db - Get the doorbell with minimum usage count.
193 *
194 * Returns the irq index.
195 */
196int mic_next_card_db(void)
197{
198 int i;
199 int index = 0;
200 struct mic_driver *mdrv = g_drv;
201
202 for (i = 0; i < mdrv->intr_info.num_intr; i++) {
203 if (mdrv->irq_info.irq_usage_count[i] <
204 mdrv->irq_info.irq_usage_count[index])
205 index = i;
206 }
207
208 return index;
209}
210
211/**
212 * mic_init_irq - Initialize irq information.
213 *
214 * Returns 0 in success. Appropriate error code on failure.
215 */
216static int mic_init_irq(void)
217{
218 struct mic_driver *mdrv = g_drv;
219
220 mdrv->irq_info.irq_usage_count = kzalloc((sizeof(u32) *
221 mdrv->intr_info.num_intr),
222 GFP_KERNEL);
223 if (!mdrv->irq_info.irq_usage_count)
224 return -ENOMEM;
225 return 0;
226}
227
228/**
229 * mic_uninit_irq - Uninitialize irq information.
230 *
231 * None.
232 */
233static void mic_uninit_irq(void)
234{
235 struct mic_driver *mdrv = g_drv;
236
237 kfree(mdrv->irq_info.irq_usage_count);
238}
239
240/*
241 * mic_driver_init - MIC driver initialization tasks.
242 *
243 * Returns 0 in success. Appropriate error code on failure.
244 */
245int __init mic_driver_init(struct mic_driver *mdrv)
246{
247 int rc;
248
249 g_drv = mdrv;
250 /*
251 * Unloading the card module is not supported. The MIC card module
252 * handles fundamental operations like host/card initiated shutdowns
253 * and informing the host about card crashes and cannot be unloaded.
254 */
255 if (!try_module_get(mdrv->dev->driver->owner)) {
256 rc = -ENODEV;
257 goto done;
258 }
259 rc = mic_dp_init();
260 if (rc)
261 goto put;
262 rc = mic_init_irq();
263 if (rc)
264 goto dp_uninit;
265 rc = mic_shutdown_init();
266 if (rc)
267 goto irq_uninit;
268 mic_create_card_debug_dir(mdrv);
269 atomic_notifier_chain_register(&panic_notifier_list, &mic_panic);
270done:
271 return rc;
272irq_uninit:
273 mic_uninit_irq();
274dp_uninit:
275 mic_dp_uninit();
276put:
277 module_put(mdrv->dev->driver->owner);
278 return rc;
279}
280
281/*
282 * mic_driver_uninit - MIC driver uninitialization tasks.
283 *
284 * Returns None
285 */
286void mic_driver_uninit(struct mic_driver *mdrv)
287{
288 mic_delete_card_debug_dir(mdrv);
289 /*
290 * Inform the host about the shutdown status i.e. poweroff/restart etc.
291 * The module cannot be unloaded so the only code path to call
292 * mic_devices_uninit(..) is the shutdown callback.
293 */
294 mic_notify_host(system_state);
295 mic_shutdown_uninit();
296 mic_uninit_irq();
297 mic_dp_uninit();
298 module_put(mdrv->dev->driver->owner);
299}
diff --git a/drivers/misc/mic/card/mic_device.h b/drivers/misc/mic/card/mic_device.h
new file mode 100644
index 000000000000..347b9b3b7916
--- /dev/null
+++ b/drivers/misc/mic/card/mic_device.h
@@ -0,0 +1,133 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Disclaimer: The codes contained in these modules may be specific to
19 * the Intel Software Development Platform codenamed: Knights Ferry, and
20 * the Intel product codenamed: Knights Corner, and are not backward
21 * compatible with other Intel products. Additionally, Intel will NOT
22 * support the codes or instruction set in future products.
23 *
24 * Intel MIC Card driver.
25 *
26 */
27#ifndef _MIC_CARD_DEVICE_H_
28#define _MIC_CARD_DEVICE_H_
29
30#include <linux/workqueue.h>
31#include <linux/io.h>
32
33/**
34 * struct mic_intr_info - Contains h/w specific interrupt sources info
35 *
36 * @num_intr: The number of irqs available
37 */
38struct mic_intr_info {
39 u32 num_intr;
40};
41
42/**
43 * struct mic_irq_info - OS specific irq information
44 *
45 * @irq_usage_count: usage count array tracking the number of sources
46 * assigned for each irq.
47 */
48struct mic_irq_info {
49 int *irq_usage_count;
50};
51
52/**
53 * struct mic_device - MIC device information.
54 *
55 * @mmio: MMIO bar information.
56 */
57struct mic_device {
58 struct mic_mw mmio;
59};
60
61/**
62 * struct mic_driver - MIC card driver information.
63 *
64 * @name: Name for MIC driver.
65 * @dbg_dir: debugfs directory of this MIC device.
66 * @dev: The device backing this MIC.
67 * @dp: The pointer to the virtio device page.
68 * @mdev: MIC device information for the host.
69 * @hotplug_work: Hot plug work for adding/removing virtio devices.
70 * @irq_info: The OS specific irq information
71 * @intr_info: H/W specific interrupt information.
72 */
73struct mic_driver {
74 char name[20];
75 struct dentry *dbg_dir;
76 struct device *dev;
77 void __iomem *dp;
78 struct mic_device mdev;
79 struct work_struct hotplug_work;
80 struct mic_irq_info irq_info;
81 struct mic_intr_info intr_info;
82};
83
84/**
85 * struct mic_irq - opaque pointer used as cookie
86 */
87struct mic_irq;
88
89/**
90 * mic_mmio_read - read from an MMIO register.
91 * @mw: MMIO register base virtual address.
92 * @offset: register offset.
93 *
94 * RETURNS: register value.
95 */
96static inline u32 mic_mmio_read(struct mic_mw *mw, u32 offset)
97{
98 return ioread32(mw->va + offset);
99}
100
101/**
102 * mic_mmio_write - write to an MMIO register.
103 * @mw: MMIO register base virtual address.
104 * @val: the data value to put into the register
105 * @offset: register offset.
106 *
107 * RETURNS: none.
108 */
109static inline void
110mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
111{
112 iowrite32(val, mw->va + offset);
113}
114
115int mic_driver_init(struct mic_driver *mdrv);
116void mic_driver_uninit(struct mic_driver *mdrv);
117int mic_next_card_db(void);
118struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data),
119 const char *name, void *data, int intr_src);
120void mic_free_card_irq(struct mic_irq *cookie, void *data);
121u32 mic_read_spad(struct mic_device *mdev, unsigned int idx);
122void mic_send_intr(struct mic_device *mdev, int doorbell);
123int mic_db_to_irq(struct mic_driver *mdrv, int db);
124u32 mic_ack_interrupt(struct mic_device *mdev);
125void mic_hw_intr_init(struct mic_driver *mdrv);
126void __iomem *
127mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size);
128void mic_card_unmap(struct mic_device *mdev, void __iomem *addr);
129void __init mic_create_card_debug_dir(struct mic_driver *mdrv);
130void mic_delete_card_debug_dir(struct mic_driver *mdrv);
131void __init mic_init_card_debugfs(void);
132void mic_exit_card_debugfs(void);
133#endif
diff --git a/drivers/misc/mic/card/mic_x100.c b/drivers/misc/mic/card/mic_x100.c
new file mode 100644
index 000000000000..7cb3469cf684
--- /dev/null
+++ b/drivers/misc/mic/card/mic_x100.c
@@ -0,0 +1,256 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Disclaimer: The codes contained in these modules may be specific to
19 * the Intel Software Development Platform codenamed: Knights Ferry, and
20 * the Intel product codenamed: Knights Corner, and are not backward
21 * compatible with other Intel products. Additionally, Intel will NOT
22 * support the codes or instruction set in future products.
23 *
24 * Intel MIC Card driver.
25 *
26 */
27#include <linux/module.h>
28#include <linux/pci.h>
29#include <linux/platform_device.h>
30
31#include "../common/mic_device.h"
32#include "mic_device.h"
33#include "mic_x100.h"
34
35static const char mic_driver_name[] = "mic";
36
37static struct mic_driver g_drv;
38
39/**
40 * mic_read_spad - read from the scratchpad register
41 * @mdev: pointer to mic_device instance
42 * @idx: index to scratchpad register, 0 based
43 *
44 * This function allows reading of the 32bit scratchpad register.
45 *
46 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
47 */
48u32 mic_read_spad(struct mic_device *mdev, unsigned int idx)
49{
50 return mic_mmio_read(&mdev->mmio,
51 MIC_X100_SBOX_BASE_ADDRESS +
52 MIC_X100_SBOX_SPAD0 + idx * 4);
53}
54
55/**
56 * __mic_send_intr - Send interrupt to Host.
57 * @mdev: pointer to mic_device instance
58 * @doorbell: Doorbell number.
59 */
60void mic_send_intr(struct mic_device *mdev, int doorbell)
61{
62 struct mic_mw *mw = &mdev->mmio;
63
64 if (doorbell > MIC_X100_MAX_DOORBELL_IDX)
65 return;
66 /* Ensure that the interrupt is ordered w.r.t previous stores. */
67 wmb();
68 mic_mmio_write(mw, MIC_X100_SBOX_SDBIC0_DBREQ_BIT,
69 MIC_X100_SBOX_BASE_ADDRESS +
70 (MIC_X100_SBOX_SDBIC0 + (4 * doorbell)));
71}
72
73/**
74 * mic_ack_interrupt - Device specific interrupt handling.
75 * @mdev: pointer to mic_device instance
76 *
77 * Returns: bitmask of doorbell events triggered.
78 */
79u32 mic_ack_interrupt(struct mic_device *mdev)
80{
81 return 0;
82}
83
84static inline int mic_get_sbox_irq(int db)
85{
86 return MIC_X100_IRQ_BASE + db;
87}
88
89static inline int mic_get_rdmasr_irq(int index)
90{
91 return MIC_X100_RDMASR_IRQ_BASE + index;
92}
93
94/**
95 * mic_hw_intr_init - Initialize h/w specific interrupt
96 * information.
97 * @mdrv: pointer to mic_driver
98 */
99void mic_hw_intr_init(struct mic_driver *mdrv)
100{
101 mdrv->intr_info.num_intr = MIC_X100_NUM_SBOX_IRQ +
102 MIC_X100_NUM_RDMASR_IRQ;
103}
104
105/**
106 * mic_db_to_irq - Retrieve irq number corresponding to a doorbell.
107 * @mdrv: pointer to mic_driver
108 * @db: The doorbell obtained for which the irq is needed. Doorbell
109 * may correspond to an sbox doorbell or an rdmasr index.
110 *
111 * Returns the irq corresponding to the doorbell.
112 */
113int mic_db_to_irq(struct mic_driver *mdrv, int db)
114{
115 int rdmasr_index;
116 if (db < MIC_X100_NUM_SBOX_IRQ) {
117 return mic_get_sbox_irq(db);
118 } else {
119 rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ +
120 MIC_X100_RDMASR_IRQ_BASE;
121 return mic_get_rdmasr_irq(rdmasr_index);
122 }
123}
124
125/*
126 * mic_card_map - Allocate virtual address for a remote memory region.
127 * @mdev: pointer to mic_device instance.
128 * @addr: Remote DMA address.
129 * @size: Size of the region.
130 *
131 * Returns: Virtual address backing the remote memory region.
132 */
133void __iomem *
134mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size)
135{
136 return ioremap(addr, size);
137}
138
139/*
140 * mic_card_unmap - Unmap the virtual address for a remote memory region.
141 * @mdev: pointer to mic_device instance.
142 * @addr: Virtual address for remote memory region.
143 *
144 * Returns: None.
145 */
146void mic_card_unmap(struct mic_device *mdev, void __iomem *addr)
147{
148 iounmap(addr);
149}
150
151static int __init mic_probe(struct platform_device *pdev)
152{
153 struct mic_driver *mdrv = &g_drv;
154 struct mic_device *mdev = &mdrv->mdev;
155 int rc = 0;
156
157 mdrv->dev = &pdev->dev;
158 snprintf(mdrv->name, sizeof(mic_driver_name), mic_driver_name);
159
160 mdev->mmio.pa = MIC_X100_MMIO_BASE;
161 mdev->mmio.len = MIC_X100_MMIO_LEN;
162 mdev->mmio.va = ioremap(MIC_X100_MMIO_BASE, MIC_X100_MMIO_LEN);
163 if (!mdev->mmio.va) {
164 dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
165 rc = -EIO;
166 goto done;
167 }
168 mic_hw_intr_init(mdrv);
169 rc = mic_driver_init(mdrv);
170 if (rc) {
171 dev_err(&pdev->dev, "mic_driver_init failed rc %d\n", rc);
172 goto iounmap;
173 }
174done:
175 return rc;
176iounmap:
177 iounmap(mdev->mmio.va);
178 return rc;
179}
180
181static int mic_remove(struct platform_device *pdev)
182{
183 struct mic_driver *mdrv = &g_drv;
184 struct mic_device *mdev = &mdrv->mdev;
185
186 mic_driver_uninit(mdrv);
187 iounmap(mdev->mmio.va);
188 return 0;
189}
190
191static void mic_platform_shutdown(struct platform_device *pdev)
192{
193 mic_remove(pdev);
194}
195
196static struct platform_device mic_platform_dev = {
197 .name = mic_driver_name,
198 .id = 0,
199 .num_resources = 0,
200};
201
202static struct platform_driver __refdata mic_platform_driver = {
203 .probe = mic_probe,
204 .remove = mic_remove,
205 .shutdown = mic_platform_shutdown,
206 .driver = {
207 .name = mic_driver_name,
208 .owner = THIS_MODULE,
209 },
210};
211
212static int __init mic_init(void)
213{
214 int ret;
215 struct cpuinfo_x86 *c = &cpu_data(0);
216
217 if (!(c->x86 == 11 && c->x86_model == 1)) {
218 ret = -ENODEV;
219 pr_err("%s not running on X100 ret %d\n", __func__, ret);
220 goto done;
221 }
222
223 mic_init_card_debugfs();
224 ret = platform_device_register(&mic_platform_dev);
225 if (ret) {
226 pr_err("platform_device_register ret %d\n", ret);
227 goto cleanup_debugfs;
228 }
229 ret = platform_driver_register(&mic_platform_driver);
230 if (ret) {
231 pr_err("platform_driver_register ret %d\n", ret);
232 goto device_unregister;
233 }
234 return ret;
235
236device_unregister:
237 platform_device_unregister(&mic_platform_dev);
238cleanup_debugfs:
239 mic_exit_card_debugfs();
240done:
241 return ret;
242}
243
244static void __exit mic_exit(void)
245{
246 platform_driver_unregister(&mic_platform_driver);
247 platform_device_unregister(&mic_platform_dev);
248 mic_exit_card_debugfs();
249}
250
251module_init(mic_init);
252module_exit(mic_exit);
253
254MODULE_AUTHOR("Intel Corporation");
255MODULE_DESCRIPTION("Intel(R) MIC X100 Card driver");
256MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/card/mic_x100.h b/drivers/misc/mic/card/mic_x100.h
new file mode 100644
index 000000000000..d66ea55639c3
--- /dev/null
+++ b/drivers/misc/mic/card/mic_x100.h
@@ -0,0 +1,48 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Disclaimer: The codes contained in these modules may be specific to
19 * the Intel Software Development Platform codenamed: Knights Ferry, and
20 * the Intel product codenamed: Knights Corner, and are not backward
21 * compatible with other Intel products. Additionally, Intel will NOT
22 * support the codes or instruction set in future products.
23 *
24 * Intel MIC Card driver.
25 *
26 */
27#ifndef _MIC_X100_CARD_H_
28#define _MIC_X100_CARD_H_
29
30#define MIC_X100_MMIO_BASE 0x08007C0000ULL
31#define MIC_X100_MMIO_LEN 0x00020000ULL
32#define MIC_X100_SBOX_BASE_ADDRESS 0x00010000ULL
33
34#define MIC_X100_SBOX_SPAD0 0x0000AB20
35#define MIC_X100_SBOX_SDBIC0 0x0000CC90
36#define MIC_X100_SBOX_SDBIC0_DBREQ_BIT 0x80000000
37#define MIC_X100_SBOX_RDMASR0 0x0000B180
38
39#define MIC_X100_MAX_DOORBELL_IDX 8
40
41#define MIC_X100_NUM_SBOX_IRQ 8
42#define MIC_X100_NUM_RDMASR_IRQ 8
43#define MIC_X100_SBOX_IRQ_BASE 0
44#define MIC_X100_RDMASR_IRQ_BASE 17
45
46#define MIC_X100_IRQ_BASE 26
47
48#endif