diff options
Diffstat (limited to 'Documentation/misc-devices')
| -rw-r--r-- | Documentation/misc-devices/eeprom | 2 | ||||
| -rw-r--r-- | Documentation/misc-devices/ics932s401 | 2 | ||||
| -rw-r--r-- | Documentation/misc-devices/lis3lv02d | 93 | ||||
| -rw-r--r-- | Documentation/misc-devices/mei/.gitignore | 1 | ||||
| -rw-r--r-- | Documentation/misc-devices/mei/Makefile | 8 | ||||
| -rw-r--r-- | Documentation/misc-devices/mei/TODO | 2 | ||||
| -rw-r--r-- | Documentation/misc-devices/mei/mei-amt-version.c | 479 | ||||
| -rw-r--r-- | Documentation/misc-devices/mei/mei-client-bus.txt | 138 | ||||
| -rw-r--r-- | Documentation/misc-devices/mei/mei.txt | 215 | ||||
| -rw-r--r-- | Documentation/misc-devices/spear-pcie-gadget.txt | 130 | 
10 files changed, 1068 insertions, 2 deletions
diff --git a/Documentation/misc-devices/eeprom b/Documentation/misc-devices/eeprom index f7e8104b576..ba692011f22 100644 --- a/Documentation/misc-devices/eeprom +++ b/Documentation/misc-devices/eeprom @@ -38,7 +38,7 @@ Supported chips:  Authors:          Frodo Looijaard <frodol@dds.nl>,          Philip Edelbrock <phil@netroedge.com>, -        Jean Delvare <khali@linux-fr.org>, +        Jean Delvare <jdelvare@suse.de>,          Greg Kroah-Hartman <greg@kroah.com>,          IBM Corp. diff --git a/Documentation/misc-devices/ics932s401 b/Documentation/misc-devices/ics932s401 index 07a739f406d..bdac67ff6e3 100644 --- a/Documentation/misc-devices/ics932s401 +++ b/Documentation/misc-devices/ics932s401 @@ -5,7 +5,7 @@ Supported chips:    * IDT ICS932S401      Prefix: 'ics932s401'      Addresses scanned: I2C 0x69 -    Datasheet: Publically available at the IDT website +    Datasheet: Publicly available at the IDT website  Author: Darrick J. Wong diff --git a/Documentation/misc-devices/lis3lv02d b/Documentation/misc-devices/lis3lv02d new file mode 100644 index 00000000000..af815b9ba41 --- /dev/null +++ b/Documentation/misc-devices/lis3lv02d @@ -0,0 +1,93 @@ +Kernel driver lis3lv02d +======================= + +Supported chips: + +  * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision) +  * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits) and +    LIS331DLH (16 bits) + +Authors: +        Yan Burman <burman.yan@gmail.com> +	Eric Piel <eric.piel@tremplin-utc.net> + + +Description +----------- + +This driver provides support for the accelerometer found in various HP laptops +sporting the feature officially called "HP Mobile Data Protection System 3D" or +"HP 3D DriveGuard". It detects automatically laptops with this sensor. Known +models (full list can be found in drivers/platform/x86/hp_accel.c) will have +their axis automatically oriented on standard way (eg: you can directly play +neverball). The accelerometer data is readable via +/sys/devices/platform/lis3lv02d. Reported values are scaled +to mg values (1/1000th of earth gravity). + +Sysfs attributes under /sys/devices/platform/lis3lv02d/: +position - 3D position that the accelerometer reports. Format: "(x,y,z)" +rate - read reports the sampling rate of the accelerometer device in HZ. +	write changes sampling rate of the accelerometer device. +	Only values which are supported by HW are accepted. +selftest - performs selftest for the chip as specified by chip manufacturer. + +This driver also provides an absolute input class device, allowing +the laptop to act as a pinball machine-esque joystick. Joystick device can be +calibrated. Joystick device can be in two different modes. +By default output values are scaled between -32768 .. 32767. In joystick raw +mode, joystick and sysfs position entry have the same scale. There can be +small difference due to input system fuzziness feature. +Events are also available as input event device. + +Selftest is meant only for hardware diagnostic purposes. It is not meant to be +used during normal operations. Position data is not corrupted during selftest +but interrupt behaviour is not guaranteed to work reliably. In test mode, the +sensing element is internally moved little bit. Selftest measures difference +between normal mode and test mode. Chip specifications tell the acceptance +limit for each type of the chip. Limits are provided via platform data +to allow adjustment of the limits without a change to the actual driver. +Seltest returns either "OK x y z" or "FAIL x y z" where x, y and z are +measured difference between modes. Axes are not remapped in selftest mode. +Measurement values are provided to help HW diagnostic applications to make +final decision. + +On HP laptops, if the led infrastructure is activated, support for a led +indicating disk protection will be provided as /sys/class/leds/hp::hddprotect. + +Another feature of the driver is misc device called "freefall" that +acts similar to /dev/rtc and reacts on free-fall interrupts received +from the device. It supports blocking operations, poll/select and +fasync operation modes. You must read 1 bytes from the device.  The +result is number of free-fall interrupts since the last successful +read (or 255 if number of interrupts would not fit). See the hpfall.c +file for an example on using the device. + + +Axes orientation +---------------- + +For better compatibility between the various laptops. The values reported by +the accelerometer are converted into a "standard" organisation of the axes +(aka "can play neverball out of the box"): + * When the laptop is horizontal the position reported is about 0 for X and Y +	and a positive value for Z + * If the left side is elevated, X increases (becomes positive) + * If the front side (where the touchpad is) is elevated, Y decreases +	(becomes negative) + * If the laptop is put upside-down, Z becomes negative + +If your laptop model is not recognized (cf "dmesg"), you can send an +email to the maintainer to add it to the database.  When reporting a new +laptop, please include the output of "dmidecode" plus the value of +/sys/devices/platform/lis3lv02d/position in these four cases. + +Q&A +--- + +Q: How do I safely simulate freefall? I have an HP "portable +workstation" which has about 3.5kg and a plastic case, so letting it +fall to the ground is out of question... + +A: The sensor is pretty sensitive, so your hands can do it. Lift it +into free space, follow the fall with your hands for like 10 +centimeters. That should be enough to trigger the detection. diff --git a/Documentation/misc-devices/mei/.gitignore b/Documentation/misc-devices/mei/.gitignore new file mode 100644 index 00000000000..f356b81ca1e --- /dev/null +++ b/Documentation/misc-devices/mei/.gitignore @@ -0,0 +1 @@ +mei-amt-version diff --git a/Documentation/misc-devices/mei/Makefile b/Documentation/misc-devices/mei/Makefile new file mode 100644 index 00000000000..00e8c3e836f --- /dev/null +++ b/Documentation/misc-devices/mei/Makefile @@ -0,0 +1,8 @@ +# kbuild trick to avoid linker error. Can be omitted if a module is built. +obj- := dummy.o + +# List of programs to build +hostprogs-y := mei-amt-version +HOSTCFLAGS_mei-amt-version.o += -I$(objtree)/usr/include +# Tell kbuild to always build the programs +always := $(hostprogs-y) diff --git a/Documentation/misc-devices/mei/TODO b/Documentation/misc-devices/mei/TODO new file mode 100644 index 00000000000..6b3625d3058 --- /dev/null +++ b/Documentation/misc-devices/mei/TODO @@ -0,0 +1,2 @@ +TODO: +	- Cleanup and split the timer function diff --git a/Documentation/misc-devices/mei/mei-amt-version.c b/Documentation/misc-devices/mei/mei-amt-version.c new file mode 100644 index 00000000000..57d0d871dcf --- /dev/null +++ b/Documentation/misc-devices/mei/mei-amt-version.c @@ -0,0 +1,479 @@ +/****************************************************************************** + * Intel Management Engine Interface (Intel MEI) Linux driver + * Intel MEI Interface Header + * + * This file is provided under a dual BSD/GPLv2 license.  When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2012 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + *	Intel Corporation. + *	linux-mei@linux.intel.com + *	http://www.intel.com + * + * BSD LICENSE + * + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + *  * Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + *  * Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in + *    the documentation and/or other materials provided with the + *    distribution. + *  * Neither the name Intel Corporation nor the names of its + *    contributors may be used to endorse or promote products derived + *    from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <errno.h> +#include <stdint.h> +#include <stdbool.h> +#include <bits/wordsize.h> +#include <linux/mei.h> + +/***************************************************************************** + * Intel Management Engine Interface + *****************************************************************************/ + +#define mei_msg(_me, fmt, ARGS...) do {         \ +	if (_me->verbose)                       \ +		fprintf(stderr, fmt, ##ARGS);	\ +} while (0) + +#define mei_err(_me, fmt, ARGS...) do {         \ +	fprintf(stderr, "Error: " fmt, ##ARGS); \ +} while (0) + +struct mei { +	uuid_le guid; +	bool initialized; +	bool verbose; +	unsigned int buf_size; +	unsigned char prot_ver; +	int fd; +}; + +static void mei_deinit(struct mei *cl) +{ +	if (cl->fd != -1) +		close(cl->fd); +	cl->fd = -1; +	cl->buf_size = 0; +	cl->prot_ver = 0; +	cl->initialized = false; +} + +static bool mei_init(struct mei *me, const uuid_le *guid, +		unsigned char req_protocol_version, bool verbose) +{ +	int result; +	struct mei_client *cl; +	struct mei_connect_client_data data; + +	me->verbose = verbose; + +	me->fd = open("/dev/mei", O_RDWR); +	if (me->fd == -1) { +		mei_err(me, "Cannot establish a handle to the Intel MEI driver\n"); +		goto err; +	} +	memcpy(&me->guid, guid, sizeof(*guid)); +	memset(&data, 0, sizeof(data)); +	me->initialized = true; + +	memcpy(&data.in_client_uuid, &me->guid, sizeof(me->guid)); +	result = ioctl(me->fd, IOCTL_MEI_CONNECT_CLIENT, &data); +	if (result) { +		mei_err(me, "IOCTL_MEI_CONNECT_CLIENT receive message. err=%d\n", result); +		goto err; +	} +	cl = &data.out_client_properties; +	mei_msg(me, "max_message_length %d\n", cl->max_msg_length); +	mei_msg(me, "protocol_version %d\n", cl->protocol_version); + +	if ((req_protocol_version > 0) && +	     (cl->protocol_version != req_protocol_version)) { +		mei_err(me, "Intel MEI protocol version not supported\n"); +		goto err; +	} + +	me->buf_size = cl->max_msg_length; +	me->prot_ver = cl->protocol_version; + +	return true; +err: +	mei_deinit(me); +	return false; +} + +static ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer, +			ssize_t len, unsigned long timeout) +{ +	ssize_t rc; + +	mei_msg(me, "call read length = %zd\n", len); + +	rc = read(me->fd, buffer, len); +	if (rc < 0) { +		mei_err(me, "read failed with status %zd %s\n", +				rc, strerror(errno)); +		mei_deinit(me); +	} else { +		mei_msg(me, "read succeeded with result %zd\n", rc); +	} +	return rc; +} + +static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer, +			ssize_t len, unsigned long timeout) +{ +	struct timeval tv; +	ssize_t written; +	ssize_t rc; +	fd_set set; + +	tv.tv_sec = timeout / 1000; +	tv.tv_usec = (timeout % 1000) * 1000000; + +	mei_msg(me, "call write length = %zd\n", len); + +	written = write(me->fd, buffer, len); +	if (written < 0) { +		rc = -errno; +		mei_err(me, "write failed with status %zd %s\n", +			written, strerror(errno)); +		goto out; +	} + +	FD_ZERO(&set); +	FD_SET(me->fd, &set); +	rc = select(me->fd + 1 , &set, NULL, NULL, &tv); +	if (rc > 0 && FD_ISSET(me->fd, &set)) { +		mei_msg(me, "write success\n"); +	} else if (rc == 0) { +		mei_err(me, "write failed on timeout with status\n"); +		goto out; +	} else { /* rc < 0 */ +		mei_err(me, "write failed on select with status %zd\n", rc); +		goto out; +	} + +	rc = written; +out: +	if (rc < 0) +		mei_deinit(me); + +	return rc; +} + +/*************************************************************************** + * Intel Advanced Management Technology ME Client + ***************************************************************************/ + +#define AMT_MAJOR_VERSION 1 +#define AMT_MINOR_VERSION 1 + +#define AMT_STATUS_SUCCESS                0x0 +#define AMT_STATUS_INTERNAL_ERROR         0x1 +#define AMT_STATUS_NOT_READY              0x2 +#define AMT_STATUS_INVALID_AMT_MODE       0x3 +#define AMT_STATUS_INVALID_MESSAGE_LENGTH 0x4 + +#define AMT_STATUS_HOST_IF_EMPTY_RESPONSE  0x4000 +#define AMT_STATUS_SDK_RESOURCES      0x1004 + + +#define AMT_BIOS_VERSION_LEN   65 +#define AMT_VERSIONS_NUMBER    50 +#define AMT_UNICODE_STRING_LEN 20 + +struct amt_unicode_string { +	uint16_t length; +	char string[AMT_UNICODE_STRING_LEN]; +} __attribute__((packed)); + +struct amt_version_type { +	struct amt_unicode_string description; +	struct amt_unicode_string version; +} __attribute__((packed)); + +struct amt_version { +	uint8_t major; +	uint8_t minor; +} __attribute__((packed)); + +struct amt_code_versions { +	uint8_t bios[AMT_BIOS_VERSION_LEN]; +	uint32_t count; +	struct amt_version_type versions[AMT_VERSIONS_NUMBER]; +} __attribute__((packed)); + +/*************************************************************************** + * Intel Advanced Management Technology Host Interface + ***************************************************************************/ + +struct amt_host_if_msg_header { +	struct amt_version version; +	uint16_t _reserved; +	uint32_t command; +	uint32_t length; +} __attribute__((packed)); + +struct amt_host_if_resp_header { +	struct amt_host_if_msg_header header; +	uint32_t status; +	unsigned char data[0]; +} __attribute__((packed)); + +const uuid_le MEI_IAMTHIF = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d,  \ +				0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c); + +#define AMT_HOST_IF_CODE_VERSIONS_REQUEST  0x0400001A +#define AMT_HOST_IF_CODE_VERSIONS_RESPONSE 0x0480001A + +const struct amt_host_if_msg_header CODE_VERSION_REQ = { +	.version = {AMT_MAJOR_VERSION, AMT_MINOR_VERSION}, +	._reserved = 0, +	.command = AMT_HOST_IF_CODE_VERSIONS_REQUEST, +	.length = 0 +}; + + +struct amt_host_if { +	struct mei mei_cl; +	unsigned long send_timeout; +	bool initialized; +}; + + +static bool amt_host_if_init(struct amt_host_if *acmd, +		      unsigned long send_timeout, bool verbose) +{ +	acmd->send_timeout = (send_timeout) ? send_timeout : 20000; +	acmd->initialized = mei_init(&acmd->mei_cl, &MEI_IAMTHIF, 0, verbose); +	return acmd->initialized; +} + +static void amt_host_if_deinit(struct amt_host_if *acmd) +{ +	mei_deinit(&acmd->mei_cl); +	acmd->initialized = false; +} + +static uint32_t amt_verify_code_versions(const struct amt_host_if_resp_header *resp) +{ +	uint32_t status = AMT_STATUS_SUCCESS; +	struct amt_code_versions *code_ver; +	size_t code_ver_len; +	uint32_t ver_type_cnt; +	uint32_t len; +	uint32_t i; + +	code_ver = (struct amt_code_versions *)resp->data; +	/* length - sizeof(status) */ +	code_ver_len = resp->header.length - sizeof(uint32_t); +	ver_type_cnt = code_ver_len - +			sizeof(code_ver->bios) - +			sizeof(code_ver->count); +	if (code_ver->count != ver_type_cnt / sizeof(struct amt_version_type)) { +		status = AMT_STATUS_INTERNAL_ERROR; +		goto out; +	} + +	for (i = 0; i < code_ver->count; i++) { +		len = code_ver->versions[i].description.length; + +		if (len > AMT_UNICODE_STRING_LEN) { +			status = AMT_STATUS_INTERNAL_ERROR; +			goto out; +		} + +		len = code_ver->versions[i].version.length; +		if (code_ver->versions[i].version.string[len] != '\0' || +		    len != strlen(code_ver->versions[i].version.string)) { +			status = AMT_STATUS_INTERNAL_ERROR; +			goto out; +		} +	} +out: +	return status; +} + +static uint32_t amt_verify_response_header(uint32_t command, +				const struct amt_host_if_msg_header *resp_hdr, +				uint32_t response_size) +{ +	if (response_size < sizeof(struct amt_host_if_resp_header)) { +		return AMT_STATUS_INTERNAL_ERROR; +	} else if (response_size != (resp_hdr->length + +				sizeof(struct amt_host_if_msg_header))) { +		return AMT_STATUS_INTERNAL_ERROR; +	} else if (resp_hdr->command != command) { +		return AMT_STATUS_INTERNAL_ERROR; +	} else if (resp_hdr->_reserved != 0) { +		return AMT_STATUS_INTERNAL_ERROR; +	} else if (resp_hdr->version.major != AMT_MAJOR_VERSION || +		   resp_hdr->version.minor < AMT_MINOR_VERSION) { +		return AMT_STATUS_INTERNAL_ERROR; +	} +	return AMT_STATUS_SUCCESS; +} + +static uint32_t amt_host_if_call(struct amt_host_if *acmd, +			const unsigned char *command, ssize_t command_sz, +			uint8_t **read_buf, uint32_t rcmd, +			unsigned int expected_sz) +{ +	uint32_t in_buf_sz; +	uint32_t out_buf_sz; +	ssize_t written; +	uint32_t status; +	struct amt_host_if_resp_header *msg_hdr; + +	in_buf_sz = acmd->mei_cl.buf_size; +	*read_buf = (uint8_t *)malloc(sizeof(uint8_t) * in_buf_sz); +	if (*read_buf == NULL) +		return AMT_STATUS_SDK_RESOURCES; +	memset(*read_buf, 0, in_buf_sz); +	msg_hdr = (struct amt_host_if_resp_header *)*read_buf; + +	written = mei_send_msg(&acmd->mei_cl, +				command, command_sz, acmd->send_timeout); +	if (written != command_sz) +		return AMT_STATUS_INTERNAL_ERROR; + +	out_buf_sz = mei_recv_msg(&acmd->mei_cl, *read_buf, in_buf_sz, 2000); +	if (out_buf_sz <= 0) +		return AMT_STATUS_HOST_IF_EMPTY_RESPONSE; + +	status = msg_hdr->status; +	if (status != AMT_STATUS_SUCCESS) +		return status; + +	status = amt_verify_response_header(rcmd, +				&msg_hdr->header, out_buf_sz); +	if (status != AMT_STATUS_SUCCESS) +		return status; + +	if (expected_sz && expected_sz != out_buf_sz) +		return AMT_STATUS_INTERNAL_ERROR; + +	return AMT_STATUS_SUCCESS; +} + + +static uint32_t amt_get_code_versions(struct amt_host_if *cmd, +			       struct amt_code_versions *versions) +{ +	struct amt_host_if_resp_header *response = NULL; +	uint32_t status; + +	status = amt_host_if_call(cmd, +			(const unsigned char *)&CODE_VERSION_REQ, +			sizeof(CODE_VERSION_REQ), +			(uint8_t **)&response, +			AMT_HOST_IF_CODE_VERSIONS_RESPONSE, 0); + +	if (status != AMT_STATUS_SUCCESS) +		goto out; + +	status = amt_verify_code_versions(response); +	if (status != AMT_STATUS_SUCCESS) +		goto out; + +	memcpy(versions, response->data, sizeof(struct amt_code_versions)); +out: +	if (response != NULL) +		free(response); + +	return status; +} + +/************************** end of amt_host_if_command ***********************/ +int main(int argc, char **argv) +{ +	struct amt_code_versions ver; +	struct amt_host_if acmd; +	unsigned int i; +	uint32_t status; +	int ret; +	bool verbose; + +	verbose = (argc > 1 && strcmp(argv[1], "-v") == 0); + +	if (!amt_host_if_init(&acmd, 5000, verbose)) { +		ret = 1; +		goto out; +	} + +	status = amt_get_code_versions(&acmd, &ver); + +	amt_host_if_deinit(&acmd); + +	switch (status) { +	case AMT_STATUS_HOST_IF_EMPTY_RESPONSE: +		printf("Intel AMT: DISABLED\n"); +		ret = 0; +		break; +	case AMT_STATUS_SUCCESS: +		printf("Intel AMT: ENABLED\n"); +		for (i = 0; i < ver.count; i++) { +			printf("%s:\t%s\n", ver.versions[i].description.string, +				ver.versions[i].version.string); +		} +		ret = 0; +		break; +	default: +		printf("An error has occurred\n"); +		ret = 1; +		break; +	} + +out: +	return ret; +} diff --git a/Documentation/misc-devices/mei/mei-client-bus.txt b/Documentation/misc-devices/mei/mei-client-bus.txt new file mode 100644 index 00000000000..f83910a8ce7 --- /dev/null +++ b/Documentation/misc-devices/mei/mei-client-bus.txt @@ -0,0 +1,138 @@ +Intel(R) Management Engine (ME) Client bus API +=============================================== + + +Rationale +========= +MEI misc character device is useful for dedicated applications to send and receive +data to the many FW appliance found in Intel's ME from the user space. +However for some of the ME functionalities it make sense to leverage existing software +stack and expose them through existing kernel subsystems. + +In order to plug seamlessly into the kernel device driver model we add kernel virtual +bus abstraction on top of the MEI driver. This allows implementing linux kernel drivers +for the various MEI features as a stand alone entities found in their respective subsystem. +Existing device drivers can even potentially be re-used by adding an MEI CL bus layer to +the existing code. + + +MEI CL bus API +=========== +A driver implementation for an MEI Client is very similar to existing bus +based device drivers. The driver registers itself as an MEI CL bus driver through +the mei_cl_driver structure: + +struct mei_cl_driver { +	struct device_driver driver; +	const char *name; + +	const struct mei_cl_device_id *id_table; + +	int (*probe)(struct mei_cl_device *dev, const struct mei_cl_id *id); +	int (*remove)(struct mei_cl_device *dev); +}; + +struct mei_cl_id { +	char name[MEI_NAME_SIZE]; +	kernel_ulong_t driver_info; +}; + +The mei_cl_id structure allows the driver to bind itself against a device name. + +To actually register a driver on the ME Client bus one must call the mei_cl_add_driver() +API. This is typically called at module init time. + +Once registered on the ME Client bus, a driver will typically try to do some I/O on +this bus and this should be done through the mei_cl_send() and mei_cl_recv() +routines. The latter is synchronous (blocks and sleeps until data shows up). +In order for drivers to be notified of pending events waiting for them (e.g. +an Rx event) they can register an event handler through the +mei_cl_register_event_cb() routine. Currently only the MEI_EVENT_RX event +will trigger an event handler call and the driver implementation is supposed +to call mei_recv() from the event handler in order to fetch the pending +received buffers. + + +Example +======= +As a theoretical example let's pretend the ME comes with a "contact" NFC IP. +The driver init and exit routines for this device would look like: + +#define CONTACT_DRIVER_NAME "contact" + +static struct mei_cl_device_id contact_mei_cl_tbl[] = { +	{ CONTACT_DRIVER_NAME, }, + +	/* required last entry */ +	{ } +}; +MODULE_DEVICE_TABLE(mei_cl, contact_mei_cl_tbl); + +static struct mei_cl_driver contact_driver = { +       .id_table = contact_mei_tbl, +       .name = CONTACT_DRIVER_NAME, + +       .probe = contact_probe, +       .remove = contact_remove, +}; + +static int contact_init(void) +{ +	int r; + +	r = mei_cl_driver_register(&contact_driver); +	if (r) { +		pr_err(CONTACT_DRIVER_NAME ": driver registration failed\n"); +		return r; +	} + +	return 0; +} + +static void __exit contact_exit(void) +{ +	mei_cl_driver_unregister(&contact_driver); +} + +module_init(contact_init); +module_exit(contact_exit); + +And the driver's simplified probe routine would look like that: + +int contact_probe(struct mei_cl_device *dev, struct mei_cl_device_id *id) +{ +	struct contact_driver *contact; + +	[...] +	mei_cl_enable_device(dev); + +	mei_cl_register_event_cb(dev, contact_event_cb, contact); + +	return 0; + } + +In the probe routine the driver first enable the MEI device and then registers +an ME bus event handler which is as close as it can get to registering a +threaded IRQ handler. +The handler implementation will typically call some I/O routine depending on +the pending events: + +#define MAX_NFC_PAYLOAD 128 + +static void contact_event_cb(struct mei_cl_device *dev, u32 events, +			     void *context) +{ +	struct contact_driver *contact = context; + +	if (events & BIT(MEI_EVENT_RX)) { +		u8 payload[MAX_NFC_PAYLOAD]; +		int payload_size; + +		payload_size = mei_recv(dev, payload, MAX_NFC_PAYLOAD); +		if (payload_size <= 0) +			return; + +		/* Hook to the NFC subsystem */ +		nfc_hci_recv_frame(contact->hdev, payload, payload_size); +	} +} diff --git a/Documentation/misc-devices/mei/mei.txt b/Documentation/misc-devices/mei/mei.txt new file mode 100644 index 00000000000..15bba1aeba9 --- /dev/null +++ b/Documentation/misc-devices/mei/mei.txt @@ -0,0 +1,215 @@ +Intel(R) Management Engine Interface (Intel(R) MEI) +======================= + +Introduction +======================= + +The Intel Management Engine (Intel ME) is an isolated and protected computing +resource (Co-processor) residing inside certain Intel chipsets. The Intel ME +provides support for computer/IT management features. The feature set +depends on the Intel chipset SKU. + +The Intel Management Engine Interface (Intel MEI, previously known as HECI) +is the interface between the Host and Intel ME. This interface is exposed +to the host as a PCI device. The Intel MEI Driver is in charge of the +communication channel between a host application and the Intel ME feature. + +Each Intel ME feature (Intel ME Client) is addressed by a GUID/UUID and +each client has its own protocol. The protocol is message-based with a +header and payload up to 512 bytes. + +Prominent usage of the Intel ME Interface is to communicate with Intel(R) +Active Management Technology (Intel AMT)implemented in firmware running on +the Intel ME. + +Intel AMT provides the ability to manage a host remotely out-of-band (OOB) +even when the operating system running on the host processor has crashed or +is in a sleep state. + +Some examples of Intel AMT usage are: +   - Monitoring hardware state and platform components +   - Remote power off/on (useful for green computing or overnight IT +     maintenance) +   - OS updates +   - Storage of useful platform information such as software assets +   - Built-in hardware KVM +   - Selective network isolation of Ethernet and IP protocol flows based +     on policies set by a remote management console +   - IDE device redirection from remote management console + +Intel AMT (OOB) communication is based on SOAP (deprecated +starting with Release 6.0) over HTTP/S or WS-Management protocol over +HTTP/S that are received from a remote management console application. + +For more information about Intel AMT: +http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide + +Intel MEI Driver +======================= + +The driver exposes a misc device called /dev/mei. + +An application maintains communication with an Intel ME feature while +/dev/mei is open. The binding to a specific feature is performed by calling +MEI_CONNECT_CLIENT_IOCTL, which passes the desired UUID. +The number of instances of an Intel ME feature that can be opened +at the same time depends on the Intel ME feature, but most of the +features allow only a single instance. + +The Intel AMT Host Interface (Intel AMTHI) feature supports multiple +simultaneous user connected applications. The Intel MEI driver +handles this internally by maintaining request queues for the applications. + +The driver is transparent to data that are passed between firmware feature +and host application. + +Because some of the Intel ME features can change the system +configuration, the driver by default allows only a privileged +user to access it. + +A code snippet for an application communicating with Intel AMTHI client: + +	struct mei_connect_client_data data; +	fd = open(MEI_DEVICE); + +	data.d.in_client_uuid = AMTHI_UUID; + +	ioctl(fd, IOCTL_MEI_CONNECT_CLIENT, &data); + +	printf("Ver=%d, MaxLen=%ld\n", +			data.d.in_client_uuid.protocol_version, +			data.d.in_client_uuid.max_msg_length); + +	[...] + +	write(fd, amthi_req_data, amthi_req_data_len); + +	[...] + +	read(fd, &amthi_res_data, amthi_res_data_len); + +	[...] +	close(fd); + +IOCTL: +====== +The Intel MEI Driver supports the following IOCTL command: +	IOCTL_MEI_CONNECT_CLIENT	Connect to firmware Feature (client). + +	usage: +		struct mei_connect_client_data clientData; +		ioctl(fd, IOCTL_MEI_CONNECT_CLIENT, &clientData); + +	inputs: +		mei_connect_client_data struct contain the following +		input field: + +		in_client_uuid -	UUID of the FW Feature that needs +					to connect to. +	outputs: +		out_client_properties - Client Properties: MTU and Protocol Version. + +	error returns: +		EINVAL	Wrong IOCTL Number +		ENODEV	Device or Connection is not initialized or ready. +			(e.g. Wrong UUID) +		ENOMEM	Unable to allocate memory to client internal data. +		EFAULT	Fatal Error (e.g. Unable to access user input data) +		EBUSY	Connection Already Open + +	Notes: +        max_msg_length (MTU) in client properties describes the maximum +        data that can be sent or received. (e.g. if MTU=2K, can send +        requests up to bytes 2k and received responses up to 2k bytes). + +Intel ME Applications: +============== + +1) Intel Local Management Service (Intel LMS) + +	Applications running locally on the platform communicate with Intel AMT Release +	2.0 and later releases in the same way that network applications do via SOAP +	over HTTP (deprecated starting with Release 6.0) or with WS-Management over +	SOAP over HTTP. This means that some Intel AMT features can be accessed from a +	local application using the same network interface as a remote application +	communicating with Intel AMT over the network. + +	When a local application sends a message addressed to the local Intel AMT host +	name, the Intel LMS, which listens for traffic directed to the host name, +	intercepts the message and routes it to the Intel MEI. +	For more information: +	http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide +	Under "About Intel AMT" => "Local Access" + +	For downloading Intel LMS: +	http://software.intel.com/en-us/articles/download-the-latest-intel-amt-open-source-drivers/ + +	The Intel LMS opens a connection using the Intel MEI driver to the Intel LMS +	firmware feature using a defined UUID and then communicates with the feature +	using a protocol called Intel AMT Port Forwarding Protocol(Intel APF protocol). +	The protocol is used to maintain multiple sessions with Intel AMT from a +	single application. + +	See the protocol specification in the Intel AMT Software Development Kit(SDK) +	http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide +	Under "SDK Resources" => "Intel(R) vPro(TM) Gateway(MPS)" +	=> "Information for Intel(R) vPro(TM) Gateway Developers" +	=> "Description of the Intel AMT Port Forwarding (APF)Protocol" + +  2) Intel AMT Remote configuration using a Local Agent +	A Local Agent enables IT personnel to configure Intel AMT out-of-the-box +	without requiring installing additional data to enable setup. The remote +	configuration process may involve an ISV-developed remote configuration +	agent that runs on the host. +	For more information: +	http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide +	Under "Setup and Configuration of Intel AMT" => +	"SDK Tools Supporting Setup and Configuration" => +	"Using the Local Agent Sample" + +	An open source Intel AMT configuration utility,	implementing a local agent +	that accesses the Intel MEI driver, can be found here: +	http://software.intel.com/en-us/articles/download-the-latest-intel-amt-open-source-drivers/ + + +Intel AMT OS Health Watchdog: +============================= +The Intel AMT Watchdog is an OS Health (Hang/Crash) watchdog. +Whenever the OS hangs or crashes, Intel AMT will send an event +to any subscriber to this event. This mechanism means that +IT knows when a platform crashes even when there is a hard failure on the host. + +The Intel AMT Watchdog is composed of two parts: +	1) Firmware feature - receives the heartbeats +	   and sends an event when the heartbeats stop. +	2) Intel MEI driver - connects to the watchdog feature, configures the +	   watchdog and sends the heartbeats. + +The Intel MEI driver uses the kernel watchdog API to configure the Intel AMT +Watchdog and to send heartbeats to it. The default timeout of the +watchdog is 120 seconds. + +If the Intel AMT Watchdog feature does not exist (i.e. the connection failed), +the Intel MEI driver will disable the sending of heartbeats. + +Supported Chipsets: +================== +7 Series Chipset Family +6 Series Chipset Family +5 Series Chipset Family +4 Series Chipset Family +Mobile 4 Series Chipset Family +ICH9 +82946GZ/GL +82G35 Express +82Q963/Q965 +82P965/G965 +Mobile PM965/GM965 +Mobile GME965/GLE960 +82Q35 Express +82G33/G31/P35/P31 Express +82Q33 Express +82X38/X48 Express + +--- +linux-mei@linux.intel.com diff --git a/Documentation/misc-devices/spear-pcie-gadget.txt b/Documentation/misc-devices/spear-pcie-gadget.txt new file mode 100644 index 00000000000..02c13ef5e90 --- /dev/null +++ b/Documentation/misc-devices/spear-pcie-gadget.txt @@ -0,0 +1,130 @@ +Spear PCIe Gadget Driver: + +Author +============= +Pratyush Anand (pratyush.anand@st.com) + +Location +============ +driver/misc/spear13xx_pcie_gadget.c + +Supported Chip: +=================== +SPEAr1300 +SPEAr1310 + +Menuconfig option: +========================== +Device Drivers +	Misc devices +		PCIe gadget support for SPEAr13XX platform +purpose +=========== +This driver has several nodes which can be read/written by configfs interface. +Its main purpose is to configure selected dual mode PCIe controller as device +and then program its various registers to configure it as a particular device +type. This driver can be used to show spear's PCIe device capability. + +Description of different nodes: +================================= + +read behavior of nodes: +------------------------------ +link 		:gives ltssm status. +int_type 	:type of supported interrupt +no_of_msi 	:zero if MSI is not enabled by host. A positive value is the +		number of MSI vector granted. +vendor_id	:returns programmed vendor id (hex) +device_id	:returns programmed device id(hex) +bar0_size:	:returns size of bar0 in hex. +bar0_address	:returns address of bar0 mapped area in hex. +bar0_rw_offset	:returns offset of bar0 for which bar0_data will return value. +bar0_data	:returns data at bar0_rw_offset. + +write behavior of nodes: +------------------------------ +link 		:write UP to enable ltsmm DOWN to disable +int_type	:write interrupt type to be configured and (int_type could be +		INTA, MSI or NO_INT). Select MSI only when you have programmed +		no_of_msi node. +no_of_msi	:number of MSI vector needed. +inta		:write 1 to assert INTA and 0 to de-assert. +send_msi	:write MSI vector to be sent. +vendor_id	:write vendor id(hex) to be programmed. +device_id	:write device id(hex) to be programmed. +bar0_size	:write size of bar0 in hex. default bar0 size is 1000 (hex) +		bytes. +bar0_address	:write	address of bar0 mapped area in hex. (default mapping of +		bar0 is SYSRAM1(E0800000). Always program bar size before bar +		address. Kernel might modify bar size and address for alignment, so +		read back bar size and address after writing to cross check. +bar0_rw_offset	:write offset of bar0 for which	bar0_data will write value. +bar0_data	:write data to be written at bar0_rw_offset. + +Node programming example +=========================== +Program all PCIe registers in such a way that when this device is connected +to the PCIe host, then host sees this device as 1MB RAM. +#mount -t configfs none /Config +For nth PCIe Device Controller +# cd /config/pcie_gadget.n/ +Now you have all the nodes in this directory. +program vendor id as 0x104a +# echo 104A >> vendor_id + +program device id as 0xCD80 +# echo CD80 >> device_id + +program BAR0 size as 1MB +# echo 100000 >> bar0_size + +check for programmed bar0 size +# cat bar0_size + +Program BAR0 Address as DDR (0x2100000). This is the physical address of +memory, which is to be made visible to PCIe host. Similarly any other peripheral +can also be made visible to PCIe host. E.g., if you program base address of UART +as BAR0 address then when this device will be connected to a host, it will be +visible as UART. +# echo 2100000 >> bar0_address + +program interrupt type : INTA +# echo INTA >> int_type + +go for link up now. +# echo UP >> link + +It will have to be insured that, once link up is done on gadget, then only host +is initialized and start to search PCIe devices on its port. + +/*wait till link is up*/ +# cat link +wait till it returns UP. + +To assert INTA +# echo 1 >> inta + +To de-assert INTA +# echo 0 >> inta + +if MSI is to be used as interrupt, program no of msi vector needed (say4) +# echo 4 >> no_of_msi + +select MSI as interrupt type +# echo MSI >> int_type + +go for link up now +# echo UP >> link + +wait till link is up +# cat link +An application can repetitively read this node till link is found UP. It can +sleep between two read. + +wait till msi is enabled +# cat no_of_msi +Should return 4 (number of requested MSI vector) + +to send msi vector 2 +# echo 2 >> send_msi +#cd -  | 
