summaryrefslogtreecommitdiffstats
path: root/drivers/staging/nvec/nvec.h
blob: aa7c70ef94f5f7d51017c0b63491f5c8ac88f794 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
 * NVEC: NVIDIA compliant embedded controller interface
 *
 * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.launchpad.net>
 *
 * Authors:  Pierre-Hugues Husson <phhusson@free.fr>
 *           Ilya Petrov <ilya.muromec@gmail.com>
 *           Marc Dietrich <marvin24@gmx.de>
 *           Julian Andres Klode <jak@jak-linux.org>
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 */

#ifndef __LINUX_MFD_NVEC
#define __LINUX_MFD_NVEC

#include <linux/atomic.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/notifier.h>
#include <linux/reset.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>

/* NVEC_POOL_SIZE - Size of the pool in &struct nvec_msg */
#define NVEC_POOL_SIZE	64

/*
 * NVEC_MSG_SIZE - Maximum size of the data field of &struct nvec_msg.
 *
 * A message must store up to a SMBus block operation which consists of
 * one command byte, one count byte, and up to 32 payload bytes = 34
 * byte.
 */
#define NVEC_MSG_SIZE	34

/**
 * enum nvec_event_size - The size of an event message
 * @NVEC_2BYTES: The message has one command byte and one data byte
 * @NVEC_3BYTES: The message has one command byte and two data bytes
 * @NVEC_VAR_SIZE: The message has one command byte, one count byte, and has
 *                 up to as many bytes as the number in the count byte. The
 *                 maximum is 32
 *
 * Events can be fixed or variable sized. This is useless on other message
 * types, which are always variable sized.
 */
enum nvec_event_size {
	NVEC_2BYTES,
	NVEC_3BYTES,
	NVEC_VAR_SIZE,
};

/**
 * enum nvec_msg_type - The type of a message
 * @NVEC_SYS: A system request/response
 * @NVEC_BAT: A battery request/response
 * @NVEC_KBD: A keyboard request/response
 * @NVEC_PS2: A mouse request/response
 * @NVEC_CNTL: A EC control request/response
 * @NVEC_KB_EVT: An event from the keyboard
 * @NVEC_PS2_EVT: An event from the mouse
 *
 * Events can be fixed or variable sized. This is useless on other message
 * types, which are always variable sized.
 */
enum nvec_msg_type {
	NVEC_SYS = 1,
	NVEC_BAT,
	NVEC_GPIO,
	NVEC_SLEEP,
	NVEC_KBD,
	NVEC_PS2,
	NVEC_CNTL,
	NVEC_OEM0 = 0x0d,
	NVEC_KB_EVT = 0x80,
	NVEC_PS2_EVT,
};

/**
 * struct nvec_msg - A buffer for a single message
 * @node: Messages are part of various lists in a &struct nvec_chip
 * @data: The data of the message
 * @size: For TX messages, the number of bytes used in @data
 * @pos:  For RX messages, the current position to write to. For TX messages,
 *        the position to read from.
 * @used: Used for the message pool to mark a message as free/allocated.
 *
 * This structure is used to hold outgoing and incoming messages. Outgoing
 * messages have a different format than incoming messages, and that is not
 * documented yet.
 */
struct nvec_msg {
	struct list_head node;
	unsigned char data[NVEC_MSG_SIZE];
	unsigned short size;
	unsigned short pos;
	atomic_t used;
};

/**
 * struct nvec_chip - A single connection to an NVIDIA Embedded controller
 * @dev: The device
 * @gpio: The same as for &struct nvec_platform_data
 * @irq: The IRQ of the I2C device
 * @i2c_addr: The address of the I2C slave
 * @base: The base of the memory mapped region of the I2C device
 * @i2c_clk: The clock of the I2C device
 * @rst: The reset of the I2C device
 * @notifier_list: Notifiers to be called on received messages, see
 *                 nvec_register_notifier()
 * @rx_data: Received messages that have to be processed
 * @tx_data: Messages waiting to be sent to the controller
 * @nvec_status_notifier: Internal notifier (see nvec_status_notifier())
 * @rx_work: A work structure for the RX worker nvec_dispatch()
 * @tx_work: A work structure for the TX worker nvec_request_master()
 * @wq: The work queue in which @rx_work and @tx_work are executed
 * @rx: The message currently being retrieved or %NULL
 * @msg_pool: A pool of messages for allocation
 * @tx: The message currently being transferred
 * @tx_scratch: Used for building pseudo messages
 * @ec_transfer: A completion that will be completed once a message has been
 *               received (see nvec_rx_completed())
 * @tx_lock: Spinlock for modifications on @tx_data
 * @rx_lock: Spinlock for modifications on @rx_data
 * @sync_write_mutex: A mutex for nvec_write_sync()
 * @sync_write: A completion to signal that a synchronous message is complete
 * @sync_write_pending: The first two bytes of the request (type and subtype)
 * @last_sync_msg: The last synchronous message.
 * @state: State of our finite state machine used in nvec_interrupt()
 */
struct nvec_chip {
	struct device *dev;
	int gpio;
	int irq;
	u32 i2c_addr;
	void __iomem *base;
	struct clk *i2c_clk;
	struct reset_control *rst;
	struct atomic_notifier_head notifier_list;
	struct list_head rx_data, tx_data;
	struct notifier_block nvec_status_notifier;
	struct work_struct rx_work, tx_work;
	struct workqueue_struct *wq;
	struct nvec_msg msg_pool[NVEC_POOL_SIZE];
	struct nvec_msg *rx;

	struct nvec_msg *tx;
	struct nvec_msg tx_scratch;
	struct completion ec_transfer;

	spinlock_t tx_lock, rx_lock;

	/* sync write stuff */
	struct mutex sync_write_mutex;
	struct completion sync_write;
	u16 sync_write_pending;
	struct nvec_msg *last_sync_msg;

	int state;
};

int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
		     short size);

int nvec_write_sync(struct nvec_chip *nvec,
		    const unsigned char *data, short size,
		    struct nvec_msg **msg);

int nvec_register_notifier(struct nvec_chip *nvec,
			   struct notifier_block *nb,
			   unsigned int events);

int nvec_unregister_notifier(struct nvec_chip *dev, struct notifier_block *nb);

void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg);

#endif