hw-me.c 6.9 KB
Newer Older
O
Oren Weil 已提交
1 2 3
/*
 *
 * Intel Management Engine Interface (Intel MEI) Linux driver
4
 * Copyright (c) 2003-2012, Intel Corporation.
O
Oren Weil 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 */

#include <linux/pci.h>
18
#include <linux/mei.h>
19 20

#include "mei_dev.h"
T
Tomas Winkler 已提交
21
#include "hw-me.h"
O
Oren Weil 已提交
22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
/**
 * mei_reg_read - Reads 32bit data from the mei device
 *
 * @dev: the device structure
 * @offset: offset from which to read the data
 *
 * returns register value (u32)
 */
static inline u32 mei_reg_read(const struct mei_device *dev,
			       unsigned long offset)
{
	return ioread32(dev->mem_addr + offset);
}


/**
 * mei_reg_write - Writes 32bit data to the mei device
 *
 * @dev: the device structure
 * @offset: offset from which to write the data
 * @value: register value to write (u32)
 */
static inline void mei_reg_write(const struct mei_device *dev,
				 unsigned long offset, u32 value)
{
	iowrite32(value, dev->mem_addr + offset);
}
O
Oren Weil 已提交
50

51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
/**
 * mei_hcsr_read - Reads 32bit data from the host CSR
 *
 * @dev: the device structure
 *
 * returns the byte read.
 */
u32 mei_hcsr_read(const struct mei_device *dev)
{
	return mei_reg_read(dev, H_CSR);
}

u32 mei_mecbrw_read(const struct mei_device *dev)
{
	return mei_reg_read(dev, ME_CB_RW);
}
/**
 * mei_mecsr_read - Reads 32bit data from the ME CSR
 *
 * @dev: the device structure
 *
 * returns ME_CSR_HA register value (u32)
 */
u32 mei_mecsr_read(const struct mei_device *dev)
{
	return mei_reg_read(dev, ME_CSR_HA);
}
O
Oren Weil 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93

/**
 * mei_set_csr_register - writes H_CSR register to the mei device,
 * and ignores the H_IS bit for it is write-one-to-zero.
 *
 * @dev: the device structure
 */
void mei_hcsr_set(struct mei_device *dev)
{
	if ((dev->host_hw_state & H_IS) == H_IS)
		dev->host_hw_state &= ~H_IS;
	mei_reg_write(dev, H_CSR, dev->host_hw_state);
	dev->host_hw_state = mei_hcsr_read(dev);
}

/**
94 95 96 97 98 99 100 101 102 103 104 105
 * mei_enable_interrupts - clear and stop interrupts
 *
 * @dev: the device structure
 */
void mei_clear_interrupts(struct mei_device *dev)
{
	if ((dev->host_hw_state & H_IS) == H_IS)
		mei_reg_write(dev, H_CSR, dev->host_hw_state);
}

/**
 * mei_enable_interrupts - enables mei device interrupts
O
Oren Weil 已提交
106 107 108 109 110 111 112 113 114 115
 *
 * @dev: the device structure
 */
void mei_enable_interrupts(struct mei_device *dev)
{
	dev->host_hw_state |= H_IE;
	mei_hcsr_set(dev);
}

/**
116
 * mei_disable_interrupts - disables mei device interrupts
O
Oren Weil 已提交
117 118 119 120 121 122 123 124 125
 *
 * @dev: the device structure
 */
void mei_disable_interrupts(struct mei_device *dev)
{
	dev->host_hw_state &= ~H_IE;
	mei_hcsr_set(dev);
}

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148

/**
 * mei_interrupt_quick_handler - The ISR of the MEI device
 *
 * @irq: The irq number
 * @dev_id: pointer to the device structure
 *
 * returns irqreturn_t
 */
irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
{
	struct mei_device *dev = (struct mei_device *) dev_id;
	u32 csr_reg = mei_hcsr_read(dev);

	if ((csr_reg & H_IS) != H_IS)
		return IRQ_NONE;

	/* clear H_IS bit in H_CSR */
	mei_reg_write(dev, H_CSR, csr_reg);

	return IRQ_WAKE_THREAD;
}

O
Oren Weil 已提交
149
/**
150
 * mei_hbuf_filled_slots - gets number of device filled buffer slots
O
Oren Weil 已提交
151 152 153 154 155
 *
 * @device: the device structure
 *
 * returns number of filled slots
 */
156
static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
O
Oren Weil 已提交
157 158 159
{
	char read_ptr, write_ptr;

160 161
	dev->host_hw_state = mei_hcsr_read(dev);

O
Oren Weil 已提交
162 163 164 165 166 167 168
	read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8);
	write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16);

	return (unsigned char) (write_ptr - read_ptr);
}

/**
169
 * mei_hbuf_is_empty - checks if host buffer is empty.
O
Oren Weil 已提交
170 171 172
 *
 * @dev: the device structure
 *
173
 * returns true if empty, false - otherwise.
O
Oren Weil 已提交
174
 */
175
bool mei_hbuf_is_empty(struct mei_device *dev)
O
Oren Weil 已提交
176
{
177
	return mei_hbuf_filled_slots(dev) == 0;
O
Oren Weil 已提交
178 179 180
}

/**
181
 * mei_hbuf_empty_slots - counts write empty slots.
O
Oren Weil 已提交
182 183 184 185 186
 *
 * @dev: the device structure
 *
 * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count
 */
187
int mei_hbuf_empty_slots(struct mei_device *dev)
O
Oren Weil 已提交
188
{
189
	unsigned char filled_slots, empty_slots;
O
Oren Weil 已提交
190

191
	filled_slots = mei_hbuf_filled_slots(dev);
192
	empty_slots = dev->hbuf_depth - filled_slots;
O
Oren Weil 已提交
193 194

	/* check for overflow */
195
	if (filled_slots > dev->hbuf_depth)
O
Oren Weil 已提交
196 197 198 199 200 201 202 203 204
		return -EOVERFLOW;

	return empty_slots;
}

/**
 * mei_write_message - writes a message to mei device.
 *
 * @dev: the device structure
205 206
 * @hader: mei HECI header of message
 * @buf: message payload will be written
O
Oren Weil 已提交
207
 *
208
 * This function returns -EIO if write has failed
O
Oren Weil 已提交
209
 */
210
int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header,
211
		      unsigned char *buf)
O
Oren Weil 已提交
212
{
213
	unsigned long rem, dw_cnt;
214
	unsigned long length = header->length;
215 216 217
	u32 *reg_buf = (u32 *)buf;
	int i;
	int empty_slots;
O
Oren Weil 已提交
218

219
	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header));
O
Oren Weil 已提交
220

221
	empty_slots = mei_hbuf_empty_slots(dev);
222
	dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots);
O
Oren Weil 已提交
223

224
	dw_cnt = mei_data2slots(length);
225
	if (empty_slots < 0 || dw_cnt > empty_slots)
226
		return -EIO;
O
Oren Weil 已提交
227 228 229

	mei_reg_write(dev, H_CB_WW, *((u32 *) header));

230 231
	for (i = 0; i < length / 4; i++)
		mei_reg_write(dev, H_CB_WW, reg_buf[i]);
O
Oren Weil 已提交
232

233 234 235 236 237
	rem = length & 0x3;
	if (rem > 0) {
		u32 reg = 0;
		memcpy(&reg, &buf[length - rem], rem);
		mei_reg_write(dev, H_CB_WW, reg);
O
Oren Weil 已提交
238 239
	}

240
	dev->host_hw_state = mei_hcsr_read(dev);
O
Oren Weil 已提交
241 242 243 244
	dev->host_hw_state |= H_IG;
	mei_hcsr_set(dev);
	dev->me_hw_state = mei_mecsr_read(dev);
	if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
245
		return -EIO;
O
Oren Weil 已提交
246

247
	return 0;
O
Oren Weil 已提交
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
}

/**
 * mei_count_full_read_slots - counts read full slots.
 *
 * @dev: the device structure
 *
 * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count
 */
int mei_count_full_read_slots(struct mei_device *dev)
{
	char read_ptr, write_ptr;
	unsigned char buffer_depth, filled_slots;

	dev->me_hw_state = mei_mecsr_read(dev);
	buffer_depth = (unsigned char)((dev->me_hw_state & ME_CBD_HRA) >> 24);
	read_ptr = (char) ((dev->me_hw_state & ME_CBRP_HRA) >> 8);
	write_ptr = (char) ((dev->me_hw_state & ME_CBWP_HRA) >> 16);
	filled_slots = (unsigned char) (write_ptr - read_ptr);

	/* check for overflow */
	if (filled_slots > buffer_depth)
		return -EOVERFLOW;

	dev_dbg(&dev->pdev->dev, "filled_slots =%08x\n", filled_slots);
	return (int)filled_slots;
}

/**
 * mei_read_slots - reads a message from mei device.
 *
 * @dev: the device structure
 * @buffer: message buffer will be written
 * @buffer_length: message size will be read
 */
283 284
void mei_read_slots(struct mei_device *dev, unsigned char *buffer,
		    unsigned long buffer_length)
O
Oren Weil 已提交
285
{
286
	u32 *reg_buf = (u32 *)buffer;
O
Oren Weil 已提交
287

288 289
	for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32))
		*reg_buf++ = mei_mecbrw_read(dev);
O
Oren Weil 已提交
290 291

	if (buffer_length > 0) {
292 293
		u32 reg = mei_mecbrw_read(dev);
		memcpy(reg_buf, &reg, buffer_length);
O
Oren Weil 已提交
294 295 296 297 298 299
	}

	dev->host_hw_state |= H_IG;
	mei_hcsr_set(dev);
}