]> Pileus Git - ~andy/linux/blob - drivers/misc/mic/host/mic_boot.c
60c54d5c43c25e57da8d27eb0145d665e3a32e68
[~andy/linux] / drivers / misc / mic / host / mic_boot.c
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  * Intel MIC Host driver.
19  *
20  */
21 #include <linux/delay.h>
22 #include <linux/firmware.h>
23
24 #include <linux/mic_common.h>
25 #include "../common/mic_dev.h"
26 #include "mic_device.h"
27 #include "mic_smpt.h"
28 #include "mic_virtio.h"
29
30 /**
31  * mic_reset - Reset the MIC device.
32  * @mdev: pointer to mic_device instance
33  */
34 static void mic_reset(struct mic_device *mdev)
35 {
36         int i;
37
38 #define MIC_RESET_TO (45)
39
40         mdev->ops->reset_fw_ready(mdev);
41         mdev->ops->reset(mdev);
42
43         for (i = 0; i < MIC_RESET_TO; i++) {
44                 if (mdev->ops->is_fw_ready(mdev))
45                         return;
46                 /*
47                  * Resets typically take 10s of seconds to complete.
48                  * Since an MMIO read is required to check if the
49                  * firmware is ready or not, a 1 second delay works nicely.
50                  */
51                 msleep(1000);
52         }
53         mic_set_state(mdev, MIC_RESET_FAILED);
54 }
55
56 /* Initialize the MIC bootparams */
57 void mic_bootparam_init(struct mic_device *mdev)
58 {
59         struct mic_bootparam *bootparam = mdev->dp;
60
61         bootparam->magic = MIC_MAGIC;
62         bootparam->c2h_shutdown_db = mdev->shutdown_db;
63         bootparam->h2c_shutdown_db = -1;
64         bootparam->h2c_config_db = -1;
65         bootparam->shutdown_status = 0;
66         bootparam->shutdown_card = 0;
67 }
68
69 /**
70  * mic_start - Start the MIC.
71  * @mdev: pointer to mic_device instance
72  * @buf: buffer containing boot string including firmware/ramdisk path.
73  *
74  * This function prepares an MIC for boot and initiates boot.
75  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
76  */
77 int mic_start(struct mic_device *mdev, const char *buf)
78 {
79         int rc;
80         mutex_lock(&mdev->mic_mutex);
81 retry:
82         if (MIC_OFFLINE != mdev->state) {
83                 rc = -EINVAL;
84                 goto unlock_ret;
85         }
86         if (!mdev->ops->is_fw_ready(mdev)) {
87                 mic_reset(mdev);
88                 /*
89                  * The state will either be MIC_OFFLINE if the reset succeeded
90                  * or MIC_RESET_FAILED if the firmware reset failed.
91                  */
92                 goto retry;
93         }
94         rc = mdev->ops->load_mic_fw(mdev, buf);
95         if (rc)
96                 goto unlock_ret;
97         mic_smpt_restore(mdev);
98         mic_intr_restore(mdev);
99         mdev->intr_ops->enable_interrupts(mdev);
100         mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
101         mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
102         mdev->ops->send_firmware_intr(mdev);
103         mic_set_state(mdev, MIC_ONLINE);
104 unlock_ret:
105         mutex_unlock(&mdev->mic_mutex);
106         return rc;
107 }
108
109 /**
110  * mic_stop - Prepare the MIC for reset and trigger reset.
111  * @mdev: pointer to mic_device instance
112  * @force: force a MIC to reset even if it is already offline.
113  *
114  * RETURNS: None.
115  */
116 void mic_stop(struct mic_device *mdev, bool force)
117 {
118         mutex_lock(&mdev->mic_mutex);
119         if (MIC_OFFLINE != mdev->state || force) {
120                 mic_virtio_reset_devices(mdev);
121                 mic_bootparam_init(mdev);
122                 mic_reset(mdev);
123                 if (MIC_RESET_FAILED == mdev->state)
124                         goto unlock;
125                 mic_set_shutdown_status(mdev, MIC_NOP);
126                 mic_set_state(mdev, MIC_OFFLINE);
127         }
128 unlock:
129         mutex_unlock(&mdev->mic_mutex);
130 }
131
132 /**
133  * mic_shutdown - Initiate MIC shutdown.
134  * @mdev: pointer to mic_device instance
135  *
136  * RETURNS: None.
137  */
138 void mic_shutdown(struct mic_device *mdev)
139 {
140         struct mic_bootparam *bootparam = mdev->dp;
141         s8 db = bootparam->h2c_shutdown_db;
142
143         mutex_lock(&mdev->mic_mutex);
144         if (MIC_ONLINE == mdev->state && db != -1) {
145                 bootparam->shutdown_card = 1;
146                 mdev->ops->send_intr(mdev, db);
147                 mic_set_state(mdev, MIC_SHUTTING_DOWN);
148         }
149         mutex_unlock(&mdev->mic_mutex);
150 }
151
152 /**
153  * mic_shutdown_work - Handle shutdown interrupt from MIC.
154  * @work: The work structure.
155  *
156  * This work is scheduled whenever the host has received a shutdown
157  * interrupt from the MIC.
158  */
159 void mic_shutdown_work(struct work_struct *work)
160 {
161         struct mic_device *mdev = container_of(work, struct mic_device,
162                         shutdown_work);
163         struct mic_bootparam *bootparam = mdev->dp;
164
165         mutex_lock(&mdev->mic_mutex);
166         mic_set_shutdown_status(mdev, bootparam->shutdown_status);
167         bootparam->shutdown_status = 0;
168         if (MIC_SHUTTING_DOWN != mdev->state)
169                 mic_set_state(mdev, MIC_SHUTTING_DOWN);
170         mutex_unlock(&mdev->mic_mutex);
171 }
172
173 /**
174  * mic_reset_trigger_work - Trigger MIC reset.
175  * @work: The work structure.
176  *
177  * This work is scheduled whenever the host wants to reset the MIC.
178  */
179 void mic_reset_trigger_work(struct work_struct *work)
180 {
181         struct mic_device *mdev = container_of(work, struct mic_device,
182                         reset_trigger_work);
183
184         mic_stop(mdev, false);
185 }