mei: reenable mei_hcsr_set abstraction
[linux-2.6-block.git] / drivers / misc / mei / hw-me.c
CommitLineData
3ce72726
OW
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
733ba91c 4 * Copyright (c) 2003-2012, Intel Corporation.
3ce72726
OW
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 */
16
17#include <linux/pci.h>
4f3afe1d 18#include <linux/mei.h>
47a73801
TW
19
20#include "mei_dev.h"
9dc64d6a 21#include "hw-me.h"
3ce72726 22
3a65dd4e
TW
23/**
24 * mei_reg_read - Reads 32bit data from the mei device
25 *
26 * @dev: the device structure
27 * @offset: offset from which to read the data
28 *
29 * returns register value (u32)
30 */
31static inline u32 mei_reg_read(const struct mei_device *dev,
32 unsigned long offset)
33{
34 return ioread32(dev->mem_addr + offset);
35}
36
37
38/**
39 * mei_reg_write - Writes 32bit data to the mei device
40 *
41 * @dev: the device structure
42 * @offset: offset from which to write the data
43 * @value: register value to write (u32)
44 */
45static inline void mei_reg_write(const struct mei_device *dev,
46 unsigned long offset, u32 value)
47{
48 iowrite32(value, dev->mem_addr + offset);
49}
3ce72726 50
3a65dd4e 51/**
d025284d
TW
52 * mei_mecbrw_read - Reads 32bit data from ME circular buffer
53 * read window register
3a65dd4e
TW
54 *
55 * @dev: the device structure
56 *
d025284d 57 * returns ME_CB_RW register value (u32)
3a65dd4e 58 */
3a65dd4e
TW
59u32 mei_mecbrw_read(const struct mei_device *dev)
60{
61 return mei_reg_read(dev, ME_CB_RW);
62}
63/**
64 * mei_mecsr_read - Reads 32bit data from the ME CSR
65 *
66 * @dev: the device structure
67 *
68 * returns ME_CSR_HA register value (u32)
69 */
70u32 mei_mecsr_read(const struct mei_device *dev)
71{
72 return mei_reg_read(dev, ME_CSR_HA);
73}
3ce72726
OW
74
75/**
d025284d
TW
76 * mei_hcsr_read - Reads 32bit data from the host CSR
77 *
78 * @dev: the device structure
79 *
80 * returns H_CSR register value (u32)
81 */
82u32 mei_hcsr_read(const struct mei_device *dev)
83{
84 return mei_reg_read(dev, H_CSR);
85}
86
87/**
88 * mei_hcsr_set - writes H_CSR register to the mei device,
3ce72726
OW
89 * and ignores the H_IS bit for it is write-one-to-zero.
90 *
91 * @dev: the device structure
92 */
88eb99f2 93static inline void mei_hcsr_set(struct mei_device *dev, u32 hcsr)
3ce72726 94{
88eb99f2
TW
95 hcsr &= ~H_IS;
96 mei_reg_write(dev, H_CSR, hcsr);
3ce72726
OW
97}
98
99/**
d025284d 100 * mei_clear_interrupts - clear and stop interrupts
3a65dd4e
TW
101 *
102 * @dev: the device structure
103 */
104void mei_clear_interrupts(struct mei_device *dev)
105{
9ea73ddd
TW
106 u32 hcsr = mei_hcsr_read(dev);
107 if ((hcsr & H_IS) == H_IS)
108 mei_reg_write(dev, H_CSR, hcsr);
3a65dd4e
TW
109}
110
111/**
112 * mei_enable_interrupts - enables mei device interrupts
3ce72726
OW
113 *
114 * @dev: the device structure
115 */
116void mei_enable_interrupts(struct mei_device *dev)
117{
9ea73ddd
TW
118 u32 hcsr = mei_hcsr_read(dev);
119 hcsr |= H_IE;
88eb99f2 120 mei_hcsr_set(dev, hcsr);
3ce72726
OW
121}
122
123/**
3a65dd4e 124 * mei_disable_interrupts - disables mei device interrupts
3ce72726
OW
125 *
126 * @dev: the device structure
127 */
128void mei_disable_interrupts(struct mei_device *dev)
129{
9ea73ddd
TW
130 u32 hcsr = mei_hcsr_read(dev);
131 hcsr &= ~H_IE;
88eb99f2 132 mei_hcsr_set(dev, hcsr);
3ce72726
OW
133}
134
adfba322
TW
135/**
136 * mei_hw_reset - resets fw via mei csr register.
137 *
138 * @dev: the device structure
139 * @interrupts_enabled: if interrupt should be enabled after reset.
140 */
141void mei_hw_reset(struct mei_device *dev, bool intr_enable)
142{
143 u32 hcsr = mei_hcsr_read(dev);
144
145 dev_dbg(&dev->pdev->dev, "before reset HCSR = 0x%08x.\n", hcsr);
146
147 hcsr |= (H_RST | H_IG);
148
149 if (intr_enable)
150 hcsr |= H_IE;
151 else
152 hcsr &= ~H_IE;
153
88eb99f2 154 mei_hcsr_set(dev, hcsr);
adfba322 155
88eb99f2 156 hcsr = mei_hcsr_read(dev) | H_IG;
adfba322 157 hcsr &= ~H_RST;
adfba322 158
88eb99f2 159 mei_hcsr_set(dev, hcsr);
adfba322
TW
160
161 hcsr = mei_hcsr_read(dev);
162
163 dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", hcsr);
164}
165
115ba28c
TW
166/**
167 * mei_host_set_ready - enable device
168 *
169 * @dev - mei device
170 * returns bool
171 */
172
173void mei_host_set_ready(struct mei_device *dev)
174{
175 dev->host_hw_state |= H_IE | H_IG | H_RDY;
88eb99f2 176 mei_hcsr_set(dev, dev->host_hw_state);
115ba28c
TW
177}
178/**
179 * mei_host_is_ready - check whether the host has turned ready
180 *
181 * @dev - mei device
182 * returns bool
183 */
184bool mei_host_is_ready(struct mei_device *dev)
185{
186 return (dev->host_hw_state & H_RDY) == H_RDY;
187}
188
189/**
190 * mei_me_is_ready - check whether the me has turned ready
191 *
192 * @dev - mei device
193 * returns bool
194 */
195bool mei_me_is_ready(struct mei_device *dev)
196{
197 return (dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA;
198}
3a65dd4e
TW
199
200/**
201 * mei_interrupt_quick_handler - The ISR of the MEI device
202 *
203 * @irq: The irq number
204 * @dev_id: pointer to the device structure
205 *
206 * returns irqreturn_t
207 */
208irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
209{
210 struct mei_device *dev = (struct mei_device *) dev_id;
211 u32 csr_reg = mei_hcsr_read(dev);
212
213 if ((csr_reg & H_IS) != H_IS)
214 return IRQ_NONE;
215
216 /* clear H_IS bit in H_CSR */
217 mei_reg_write(dev, H_CSR, csr_reg);
218
219 return IRQ_WAKE_THREAD;
220}
221
3ce72726 222/**
726917f0 223 * mei_hbuf_filled_slots - gets number of device filled buffer slots
3ce72726
OW
224 *
225 * @device: the device structure
226 *
227 * returns number of filled slots
228 */
726917f0 229static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
3ce72726
OW
230{
231 char read_ptr, write_ptr;
232
726917f0
TW
233 dev->host_hw_state = mei_hcsr_read(dev);
234
3ce72726
OW
235 read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8);
236 write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16);
237
238 return (unsigned char) (write_ptr - read_ptr);
239}
240
241/**
726917f0 242 * mei_hbuf_is_empty - checks if host buffer is empty.
3ce72726
OW
243 *
244 * @dev: the device structure
245 *
726917f0 246 * returns true if empty, false - otherwise.
3ce72726 247 */
726917f0 248bool mei_hbuf_is_empty(struct mei_device *dev)
3ce72726 249{
726917f0 250 return mei_hbuf_filled_slots(dev) == 0;
3ce72726
OW
251}
252
253/**
726917f0 254 * mei_hbuf_empty_slots - counts write empty slots.
3ce72726
OW
255 *
256 * @dev: the device structure
257 *
258 * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count
259 */
726917f0 260int mei_hbuf_empty_slots(struct mei_device *dev)
3ce72726 261{
24aadc80 262 unsigned char filled_slots, empty_slots;
3ce72726 263
726917f0 264 filled_slots = mei_hbuf_filled_slots(dev);
24aadc80 265 empty_slots = dev->hbuf_depth - filled_slots;
3ce72726
OW
266
267 /* check for overflow */
24aadc80 268 if (filled_slots > dev->hbuf_depth)
3ce72726
OW
269 return -EOVERFLOW;
270
271 return empty_slots;
272}
273
274/**
275 * mei_write_message - writes a message to mei device.
276 *
277 * @dev: the device structure
438763f3
TW
278 * @hader: mei HECI header of message
279 * @buf: message payload will be written
3ce72726 280 *
1ccb7b62 281 * This function returns -EIO if write has failed
3ce72726 282 */
169d1338 283int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header,
438763f3 284 unsigned char *buf)
3ce72726 285{
169d1338 286 unsigned long rem, dw_cnt;
438763f3 287 unsigned long length = header->length;
169d1338 288 u32 *reg_buf = (u32 *)buf;
88eb99f2 289 u32 hcsr;
169d1338
TW
290 int i;
291 int empty_slots;
3ce72726 292
15d4acc5 293 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header));
3ce72726 294
726917f0 295 empty_slots = mei_hbuf_empty_slots(dev);
169d1338 296 dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots);
3ce72726 297
7bdf72d3 298 dw_cnt = mei_data2slots(length);
169d1338 299 if (empty_slots < 0 || dw_cnt > empty_slots)
1ccb7b62 300 return -EIO;
3ce72726
OW
301
302 mei_reg_write(dev, H_CB_WW, *((u32 *) header));
303
169d1338
TW
304 for (i = 0; i < length / 4; i++)
305 mei_reg_write(dev, H_CB_WW, reg_buf[i]);
3ce72726 306
169d1338
TW
307 rem = length & 0x3;
308 if (rem > 0) {
309 u32 reg = 0;
310 memcpy(&reg, &buf[length - rem], rem);
311 mei_reg_write(dev, H_CB_WW, reg);
3ce72726
OW
312 }
313
88eb99f2
TW
314 hcsr = mei_hcsr_read(dev) | H_IG;
315 mei_hcsr_set(dev, hcsr);
3ce72726 316 dev->me_hw_state = mei_mecsr_read(dev);
115ba28c 317 if (!mei_me_is_ready(dev))
1ccb7b62 318 return -EIO;
3ce72726 319
1ccb7b62 320 return 0;
3ce72726
OW
321}
322
323/**
324 * mei_count_full_read_slots - counts read full slots.
325 *
326 * @dev: the device structure
327 *
328 * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count
329 */
330int mei_count_full_read_slots(struct mei_device *dev)
331{
332 char read_ptr, write_ptr;
333 unsigned char buffer_depth, filled_slots;
334
335 dev->me_hw_state = mei_mecsr_read(dev);
336 buffer_depth = (unsigned char)((dev->me_hw_state & ME_CBD_HRA) >> 24);
337 read_ptr = (char) ((dev->me_hw_state & ME_CBRP_HRA) >> 8);
338 write_ptr = (char) ((dev->me_hw_state & ME_CBWP_HRA) >> 16);
339 filled_slots = (unsigned char) (write_ptr - read_ptr);
340
341 /* check for overflow */
342 if (filled_slots > buffer_depth)
343 return -EOVERFLOW;
344
345 dev_dbg(&dev->pdev->dev, "filled_slots =%08x\n", filled_slots);
346 return (int)filled_slots;
347}
348
349/**
350 * mei_read_slots - reads a message from mei device.
351 *
352 * @dev: the device structure
353 * @buffer: message buffer will be written
354 * @buffer_length: message size will be read
355 */
edf1eed4
TW
356void mei_read_slots(struct mei_device *dev, unsigned char *buffer,
357 unsigned long buffer_length)
3ce72726 358{
edf1eed4 359 u32 *reg_buf = (u32 *)buffer;
88eb99f2 360 u32 hcsr;
3ce72726 361
edf1eed4
TW
362 for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32))
363 *reg_buf++ = mei_mecbrw_read(dev);
3ce72726
OW
364
365 if (buffer_length > 0) {
edf1eed4
TW
366 u32 reg = mei_mecbrw_read(dev);
367 memcpy(reg_buf, &reg, buffer_length);
3ce72726
OW
368 }
369
88eb99f2
TW
370 hcsr = mei_hcsr_read(dev) | H_IG;
371 mei_hcsr_set(dev, hcsr);
3ce72726
OW
372}
373