summaryrefslogtreecommitdiff
path: root/include/linux/mfd/ipaq-micro.h
blob: ee48a4321c57a781a1812f3b54773a79765939e4 (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
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Header file for the compaq Micro MFD
 */

#ifndef _MFD_IPAQ_MICRO_H_
#define _MFD_IPAQ_MICRO_H_

#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/list.h>

#define TX_BUF_SIZE	32
#define RX_BUF_SIZE	16
#define CHAR_SOF	0x02

/*
 * These are the different messages that can be sent to the microcontroller
 * to control various aspects.
 */
#define MSG_VERSION		0x0
#define MSG_KEYBOARD		0x2
#define MSG_TOUCHSCREEN		0x3
#define MSG_EEPROM_READ		0x4
#define MSG_EEPROM_WRITE	0x5
#define MSG_THERMAL_SENSOR	0x6
#define MSG_NOTIFY_LED		0x8
#define MSG_BATTERY		0x9
#define MSG_SPI_READ		0xb
#define MSG_SPI_WRITE		0xc
#define MSG_BACKLIGHT		0xd /* H3600 only */
#define MSG_CODEC_CTRL		0xe /* H3100 only */
#define MSG_DISPLAY_CTRL	0xf /* H3100 only */

/* state of receiver parser */
enum rx_state {
	STATE_SOF = 0,     /* Next byte should be start of frame */
	STATE_ID,          /* Next byte is ID & message length   */
	STATE_DATA,        /* Next byte is a data byte           */
	STATE_CHKSUM       /* Next byte should be checksum       */
};

/**
 * struct ipaq_micro_txdev - TX state
 * @len: length of message in TX buffer
 * @index: current index into TX buffer
 * @buf: TX buffer
 */
struct ipaq_micro_txdev {
	u8 len;
	u8 index;
	u8 buf[TX_BUF_SIZE];
};

/**
 * struct ipaq_micro_rxdev - RX state
 * @state: context of RX state machine
 * @chksum: calculated checksum
 * @id: message ID from packet
 * @len: RX buffer length
 * @index: RX buffer index
 * @buf: RX buffer
 */
struct ipaq_micro_rxdev {
	enum rx_state state;
	unsigned char chksum;
	u8            id;
	unsigned int  len;
	unsigned int  index;
	u8            buf[RX_BUF_SIZE];
};

/**
 * struct ipaq_micro_msg - message to the iPAQ microcontroller
 * @id: 4-bit ID of the message
 * @tx_len: length of TX data
 * @tx_data: TX data to send
 * @rx_len: length of receieved RX data
 * @rx_data: RX data to recieve
 * @ack: a completion that will be completed when RX is complete
 * @node: list node if message gets queued
 */
struct ipaq_micro_msg {
	u8 id;
	u8 tx_len;
	u8 tx_data[TX_BUF_SIZE];
	u8 rx_len;
	u8 rx_data[RX_BUF_SIZE];
	struct completion ack;
	struct list_head node;
};

/**
 * struct ipaq_micro - iPAQ microcontroller state
 * @dev: corresponding platform device
 * @base: virtual memory base for underlying serial device
 * @sdlc: virtual memory base for Synchronous Data Link Controller
 * @version: version string
 * @tx: TX state
 * @rx: RX state
 * @lock: lock for this state container
 * @msg: current message
 * @queue: message queue
 * @key: callback for asynchronous key events
 * @key_data: data to pass along with key events
 * @ts: callback for asynchronous touchscreen events
 * @ts_data: data to pass along with key events
 */
struct ipaq_micro {
	struct device *dev;
	void __iomem *base;
	void __iomem *sdlc;
	char version[5];
	struct ipaq_micro_txdev tx;	/* transmit ISR state */
	struct ipaq_micro_rxdev rx;	/* receive ISR state */
	spinlock_t lock;
	struct ipaq_micro_msg *msg;
	struct list_head queue;
	void (*key) (void *data, int len, unsigned char *rxdata);
	void *key_data;
	void (*ts) (void *data, int len, unsigned char *rxdata);
	void *ts_data;
};

extern int
ipaq_micro_tx_msg(struct ipaq_micro *micro, struct ipaq_micro_msg *msg);

static inline int
ipaq_micro_tx_msg_sync(struct ipaq_micro *micro,
		       struct ipaq_micro_msg *msg)
{
	int ret;

	init_completion(&msg->ack);
	ret = ipaq_micro_tx_msg(micro, msg);
	wait_for_completion(&msg->ack);

	return ret;
}

static inline int
ipaq_micro_tx_msg_async(struct ipaq_micro *micro,
			struct ipaq_micro_msg *msg)
{
	init_completion(&msg->ack);
	return ipaq_micro_tx_msg(micro, msg);
}

#endif /* _MFD_IPAQ_MICRO_H_ */