diff options
| author | Linus Walleij <linus.walleij@linaro.org> | 2014-04-03 11:45:15 -0400 |
|---|---|---|
| committer | Lee Jones <lee.jones@linaro.org> | 2014-06-03 03:11:42 -0400 |
| commit | dcc21cc09e3c22d0ede4e105afa8884eba293b58 (patch) | |
| tree | e4494fc0509fa542e1ca87f3add2cc85709b3ee4 /include/linux/mfd | |
| parent | 3d2379909374ef2de6bc57ed8966c7ca8c9dfb82 (diff) | |
mfd: Add driver for Atmel Microcontroller on iPaq h3xxx
This adds a driver for the Atmel Microcontroller found on the
iPAQ h3xxx series. This device handles some keys, the
touchscreen, and the battery monitoring.
This is a port of a driver from handhelds.org 2.6.21 kernel,
written by Alessandro Gardich based on Andrew Christians
original HAL-driver. It has been heavily cleaned and
converted to mfd-core by Dmitry Artamonow and rewritten
again for the v3.x series kernels by Linus Walleij,
bringing back some of the functionality lost from Andrew's
original driver.
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Alessandro Gardich <gremlin@gremlin.it>
Signed-off-by: Dmitry Artamonow <mad_soft@inbox.ru>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'include/linux/mfd')
| -rw-r--r-- | include/linux/mfd/ipaq-micro.h | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/include/linux/mfd/ipaq-micro.h b/include/linux/mfd/ipaq-micro.h new file mode 100644 index 000000000000..5c4d29f6674f --- /dev/null +++ b/include/linux/mfd/ipaq-micro.h | |||
| @@ -0,0 +1,148 @@ | |||
| 1 | /* | ||
| 2 | * Header file for the compaq Micro MFD | ||
| 3 | */ | ||
| 4 | |||
| 5 | #ifndef _MFD_IPAQ_MICRO_H_ | ||
| 6 | #define _MFD_IPAQ_MICRO_H_ | ||
| 7 | |||
| 8 | #include <linux/spinlock.h> | ||
| 9 | #include <linux/completion.h> | ||
| 10 | #include <linux/list.h> | ||
| 11 | |||
| 12 | #define TX_BUF_SIZE 32 | ||
| 13 | #define RX_BUF_SIZE 16 | ||
| 14 | #define CHAR_SOF 0x02 | ||
| 15 | |||
| 16 | /* | ||
| 17 | * These are the different messages that can be sent to the microcontroller | ||
| 18 | * to control various aspects. | ||
| 19 | */ | ||
| 20 | #define MSG_VERSION 0x0 | ||
| 21 | #define MSG_KEYBOARD 0x2 | ||
| 22 | #define MSG_TOUCHSCREEN 0x3 | ||
| 23 | #define MSG_EEPROM_READ 0x4 | ||
| 24 | #define MSG_EEPROM_WRITE 0x5 | ||
| 25 | #define MSG_THERMAL_SENSOR 0x6 | ||
| 26 | #define MSG_NOTIFY_LED 0x8 | ||
| 27 | #define MSG_BATTERY 0x9 | ||
| 28 | #define MSG_SPI_READ 0xb | ||
| 29 | #define MSG_SPI_WRITE 0xc | ||
| 30 | #define MSG_BACKLIGHT 0xd /* H3600 only */ | ||
| 31 | #define MSG_CODEC_CTRL 0xe /* H3100 only */ | ||
| 32 | #define MSG_DISPLAY_CTRL 0xf /* H3100 only */ | ||
| 33 | |||
| 34 | /* state of receiver parser */ | ||
| 35 | enum rx_state { | ||
| 36 | STATE_SOF = 0, /* Next byte should be start of frame */ | ||
| 37 | STATE_ID, /* Next byte is ID & message length */ | ||
| 38 | STATE_DATA, /* Next byte is a data byte */ | ||
| 39 | STATE_CHKSUM /* Next byte should be checksum */ | ||
| 40 | }; | ||
| 41 | |||
| 42 | /** | ||
| 43 | * struct ipaq_micro_txdev - TX state | ||
| 44 | * @len: length of message in TX buffer | ||
| 45 | * @index: current index into TX buffer | ||
| 46 | * @buf: TX buffer | ||
| 47 | */ | ||
| 48 | struct ipaq_micro_txdev { | ||
| 49 | u8 len; | ||
| 50 | u8 index; | ||
| 51 | u8 buf[TX_BUF_SIZE]; | ||
| 52 | }; | ||
| 53 | |||
| 54 | /** | ||
| 55 | * struct ipaq_micro_rxdev - RX state | ||
| 56 | * @state: context of RX state machine | ||
| 57 | * @chksum: calculated checksum | ||
| 58 | * @id: message ID from packet | ||
| 59 | * @len: RX buffer length | ||
| 60 | * @index: RX buffer index | ||
| 61 | * @buf: RX buffer | ||
| 62 | */ | ||
| 63 | struct ipaq_micro_rxdev { | ||
| 64 | enum rx_state state; | ||
| 65 | unsigned char chksum; | ||
| 66 | u8 id; | ||
| 67 | unsigned int len; | ||
| 68 | unsigned int index; | ||
| 69 | u8 buf[RX_BUF_SIZE]; | ||
| 70 | }; | ||
| 71 | |||
| 72 | /** | ||
| 73 | * struct ipaq_micro_msg - message to the iPAQ microcontroller | ||
| 74 | * @id: 4-bit ID of the message | ||
| 75 | * @tx_len: length of TX data | ||
| 76 | * @tx_data: TX data to send | ||
| 77 | * @rx_len: length of receieved RX data | ||
| 78 | * @rx_data: RX data to recieve | ||
| 79 | * @ack: a completion that will be completed when RX is complete | ||
| 80 | * @node: list node if message gets queued | ||
| 81 | */ | ||
| 82 | struct ipaq_micro_msg { | ||
| 83 | u8 id; | ||
| 84 | u8 tx_len; | ||
| 85 | u8 tx_data[TX_BUF_SIZE]; | ||
| 86 | u8 rx_len; | ||
| 87 | u8 rx_data[RX_BUF_SIZE]; | ||
| 88 | struct completion ack; | ||
| 89 | struct list_head node; | ||
| 90 | }; | ||
| 91 | |||
| 92 | /** | ||
| 93 | * struct ipaq_micro - iPAQ microcontroller state | ||
| 94 | * @dev: corresponding platform device | ||
| 95 | * @base: virtual memory base for underlying serial device | ||
| 96 | * @sdlc: virtual memory base for Synchronous Data Link Controller | ||
| 97 | * @version: version string | ||
| 98 | * @tx: TX state | ||
| 99 | * @rx: RX state | ||
| 100 | * @lock: lock for this state container | ||
| 101 | * @msg: current message | ||
| 102 | * @queue: message queue | ||
| 103 | * @key: callback for asynchronous key events | ||
| 104 | * @key_data: data to pass along with key events | ||
| 105 | * @ts: callback for asynchronous touchscreen events | ||
| 106 | * @ts_data: data to pass along with key events | ||
| 107 | */ | ||
| 108 | struct ipaq_micro { | ||
| 109 | struct device *dev; | ||
| 110 | void __iomem *base; | ||
| 111 | void __iomem *sdlc; | ||
| 112 | char version[5]; | ||
| 113 | struct ipaq_micro_txdev tx; /* transmit ISR state */ | ||
| 114 | struct ipaq_micro_rxdev rx; /* receive ISR state */ | ||
| 115 | spinlock_t lock; | ||
| 116 | struct ipaq_micro_msg *msg; | ||
| 117 | struct list_head queue; | ||
| 118 | void (*key) (void *data, int len, unsigned char *rxdata); | ||
| 119 | void *key_data; | ||
| 120 | void (*ts) (void *data, int len, unsigned char *rxdata); | ||
| 121 | void *ts_data; | ||
| 122 | }; | ||
| 123 | |||
| 124 | extern int | ||
| 125 | ipaq_micro_tx_msg(struct ipaq_micro *micro, struct ipaq_micro_msg *msg); | ||
| 126 | |||
| 127 | static inline int | ||
| 128 | ipaq_micro_tx_msg_sync(struct ipaq_micro *micro, | ||
| 129 | struct ipaq_micro_msg *msg) | ||
| 130 | { | ||
| 131 | int ret; | ||
| 132 | |||
| 133 | init_completion(&msg->ack); | ||
| 134 | ret = ipaq_micro_tx_msg(micro, msg); | ||
| 135 | wait_for_completion(&msg->ack); | ||
| 136 | |||
| 137 | return ret; | ||
| 138 | } | ||
| 139 | |||
| 140 | static inline int | ||
| 141 | ipaq_micro_tx_msg_async(struct ipaq_micro *micro, | ||
| 142 | struct ipaq_micro_msg *msg) | ||
| 143 | { | ||
| 144 | init_completion(&msg->ack); | ||
| 145 | return ipaq_micro_tx_msg(micro, msg); | ||
| 146 | } | ||
| 147 | |||
| 148 | #endif /* _MFD_IPAQ_MICRO_H_ */ | ||
