Commit 7477fb6fbc339469ea945e007f3f7b3bb13b25f7

Authored by Geert Uytterhoeven
Committed by Linus Torvalds
1 parent 998aaf01c6

HP input: kill warnings due to suseconds_t differences

Kill compiler warnings related to printf() formats in the input drivers for
various HP9000 machines, which are shared between PA-RISC (suseconds_t is int)
and m68k (suseconds_t is long). As both are 32-bit, it's safe to cast to int.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Helge Deller <deller@gmx.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 2 changed files with 6 additions and 6 deletions Inline Diff

drivers/input/misc/hp_sdc_rtc.c
1 /* 1 /*
2 * HP i8042 SDC + MSM-58321 BBRTC driver. 2 * HP i8042 SDC + MSM-58321 BBRTC driver.
3 * 3 *
4 * Copyright (c) 2001 Brian S. Julin 4 * Copyright (c) 2001 Brian S. Julin
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer, 11 * notice, this list of conditions, and the following disclaimer,
12 * without modification. 12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products 13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * Alternatively, this software may be distributed under the terms of the 16 * Alternatively, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL"). 17 * GNU General Public License ("GPL").
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * 28 *
29 * References: 29 * References:
30 * System Device Controller Microprocessor Firmware Theory of Operation 30 * System Device Controller Microprocessor Firmware Theory of Operation
31 * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2 31 * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2
32 * efirtc.c by Stephane Eranian/Hewlett Packard 32 * efirtc.c by Stephane Eranian/Hewlett Packard
33 * 33 *
34 */ 34 */
35 35
36 #include <linux/hp_sdc.h> 36 #include <linux/hp_sdc.h>
37 #include <linux/errno.h> 37 #include <linux/errno.h>
38 #include <linux/smp_lock.h> 38 #include <linux/smp_lock.h>
39 #include <linux/types.h> 39 #include <linux/types.h>
40 #include <linux/init.h> 40 #include <linux/init.h>
41 #include <linux/module.h> 41 #include <linux/module.h>
42 #include <linux/time.h> 42 #include <linux/time.h>
43 #include <linux/miscdevice.h> 43 #include <linux/miscdevice.h>
44 #include <linux/proc_fs.h> 44 #include <linux/proc_fs.h>
45 #include <linux/poll.h> 45 #include <linux/poll.h>
46 #include <linux/rtc.h> 46 #include <linux/rtc.h>
47 #include <linux/semaphore.h> 47 #include <linux/semaphore.h>
48 48
49 MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); 49 MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
50 MODULE_DESCRIPTION("HP i8042 SDC + MSM-58321 RTC Driver"); 50 MODULE_DESCRIPTION("HP i8042 SDC + MSM-58321 RTC Driver");
51 MODULE_LICENSE("Dual BSD/GPL"); 51 MODULE_LICENSE("Dual BSD/GPL");
52 52
53 #define RTC_VERSION "1.10d" 53 #define RTC_VERSION "1.10d"
54 54
55 static unsigned long epoch = 2000; 55 static unsigned long epoch = 2000;
56 56
57 static struct semaphore i8042tregs; 57 static struct semaphore i8042tregs;
58 58
59 static hp_sdc_irqhook hp_sdc_rtc_isr; 59 static hp_sdc_irqhook hp_sdc_rtc_isr;
60 60
61 static struct fasync_struct *hp_sdc_rtc_async_queue; 61 static struct fasync_struct *hp_sdc_rtc_async_queue;
62 62
63 static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait); 63 static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait);
64 64
65 static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf, 65 static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf,
66 size_t count, loff_t *ppos); 66 size_t count, loff_t *ppos);
67 67
68 static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file, 68 static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file,
69 unsigned int cmd, unsigned long arg); 69 unsigned int cmd, unsigned long arg);
70 70
71 static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait); 71 static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait);
72 72
73 static int hp_sdc_rtc_open(struct inode *inode, struct file *file); 73 static int hp_sdc_rtc_open(struct inode *inode, struct file *file);
74 static int hp_sdc_rtc_release(struct inode *inode, struct file *file); 74 static int hp_sdc_rtc_release(struct inode *inode, struct file *file);
75 static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on); 75 static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on);
76 76
77 static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off, 77 static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
78 int count, int *eof, void *data); 78 int count, int *eof, void *data);
79 79
80 static void hp_sdc_rtc_isr (int irq, void *dev_id, 80 static void hp_sdc_rtc_isr (int irq, void *dev_id,
81 uint8_t status, uint8_t data) 81 uint8_t status, uint8_t data)
82 { 82 {
83 return; 83 return;
84 } 84 }
85 85
86 static int hp_sdc_rtc_do_read_bbrtc (struct rtc_time *rtctm) 86 static int hp_sdc_rtc_do_read_bbrtc (struct rtc_time *rtctm)
87 { 87 {
88 struct semaphore tsem; 88 struct semaphore tsem;
89 hp_sdc_transaction t; 89 hp_sdc_transaction t;
90 uint8_t tseq[91]; 90 uint8_t tseq[91];
91 int i; 91 int i;
92 92
93 i = 0; 93 i = 0;
94 while (i < 91) { 94 while (i < 91) {
95 tseq[i++] = HP_SDC_ACT_DATAREG | 95 tseq[i++] = HP_SDC_ACT_DATAREG |
96 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN; 96 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN;
97 tseq[i++] = 0x01; /* write i8042[0x70] */ 97 tseq[i++] = 0x01; /* write i8042[0x70] */
98 tseq[i] = i / 7; /* BBRTC reg address */ 98 tseq[i] = i / 7; /* BBRTC reg address */
99 i++; 99 i++;
100 tseq[i++] = HP_SDC_CMD_DO_RTCR; /* Trigger command */ 100 tseq[i++] = HP_SDC_CMD_DO_RTCR; /* Trigger command */
101 tseq[i++] = 2; /* expect 1 stat/dat pair back. */ 101 tseq[i++] = 2; /* expect 1 stat/dat pair back. */
102 i++; i++; /* buffer for stat/dat pair */ 102 i++; i++; /* buffer for stat/dat pair */
103 } 103 }
104 tseq[84] |= HP_SDC_ACT_SEMAPHORE; 104 tseq[84] |= HP_SDC_ACT_SEMAPHORE;
105 t.endidx = 91; 105 t.endidx = 91;
106 t.seq = tseq; 106 t.seq = tseq;
107 t.act.semaphore = &tsem; 107 t.act.semaphore = &tsem;
108 init_MUTEX_LOCKED(&tsem); 108 init_MUTEX_LOCKED(&tsem);
109 109
110 if (hp_sdc_enqueue_transaction(&t)) return -1; 110 if (hp_sdc_enqueue_transaction(&t)) return -1;
111 111
112 down_interruptible(&tsem); /* Put ourselves to sleep for results. */ 112 down_interruptible(&tsem); /* Put ourselves to sleep for results. */
113 113
114 /* Check for nonpresence of BBRTC */ 114 /* Check for nonpresence of BBRTC */
115 if (!((tseq[83] | tseq[90] | tseq[69] | tseq[76] | 115 if (!((tseq[83] | tseq[90] | tseq[69] | tseq[76] |
116 tseq[55] | tseq[62] | tseq[34] | tseq[41] | 116 tseq[55] | tseq[62] | tseq[34] | tseq[41] |
117 tseq[20] | tseq[27] | tseq[6] | tseq[13]) & 0x0f)) 117 tseq[20] | tseq[27] | tseq[6] | tseq[13]) & 0x0f))
118 return -1; 118 return -1;
119 119
120 memset(rtctm, 0, sizeof(struct rtc_time)); 120 memset(rtctm, 0, sizeof(struct rtc_time));
121 rtctm->tm_year = (tseq[83] & 0x0f) + (tseq[90] & 0x0f) * 10; 121 rtctm->tm_year = (tseq[83] & 0x0f) + (tseq[90] & 0x0f) * 10;
122 rtctm->tm_mon = (tseq[69] & 0x0f) + (tseq[76] & 0x0f) * 10; 122 rtctm->tm_mon = (tseq[69] & 0x0f) + (tseq[76] & 0x0f) * 10;
123 rtctm->tm_mday = (tseq[55] & 0x0f) + (tseq[62] & 0x0f) * 10; 123 rtctm->tm_mday = (tseq[55] & 0x0f) + (tseq[62] & 0x0f) * 10;
124 rtctm->tm_wday = (tseq[48] & 0x0f); 124 rtctm->tm_wday = (tseq[48] & 0x0f);
125 rtctm->tm_hour = (tseq[34] & 0x0f) + (tseq[41] & 0x0f) * 10; 125 rtctm->tm_hour = (tseq[34] & 0x0f) + (tseq[41] & 0x0f) * 10;
126 rtctm->tm_min = (tseq[20] & 0x0f) + (tseq[27] & 0x0f) * 10; 126 rtctm->tm_min = (tseq[20] & 0x0f) + (tseq[27] & 0x0f) * 10;
127 rtctm->tm_sec = (tseq[6] & 0x0f) + (tseq[13] & 0x0f) * 10; 127 rtctm->tm_sec = (tseq[6] & 0x0f) + (tseq[13] & 0x0f) * 10;
128 128
129 return 0; 129 return 0;
130 } 130 }
131 131
132 static int hp_sdc_rtc_read_bbrtc (struct rtc_time *rtctm) 132 static int hp_sdc_rtc_read_bbrtc (struct rtc_time *rtctm)
133 { 133 {
134 struct rtc_time tm, tm_last; 134 struct rtc_time tm, tm_last;
135 int i = 0; 135 int i = 0;
136 136
137 /* MSM-58321 has no read latch, so must read twice and compare. */ 137 /* MSM-58321 has no read latch, so must read twice and compare. */
138 138
139 if (hp_sdc_rtc_do_read_bbrtc(&tm_last)) return -1; 139 if (hp_sdc_rtc_do_read_bbrtc(&tm_last)) return -1;
140 if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1; 140 if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1;
141 141
142 while (memcmp(&tm, &tm_last, sizeof(struct rtc_time))) { 142 while (memcmp(&tm, &tm_last, sizeof(struct rtc_time))) {
143 if (i++ > 4) return -1; 143 if (i++ > 4) return -1;
144 memcpy(&tm_last, &tm, sizeof(struct rtc_time)); 144 memcpy(&tm_last, &tm, sizeof(struct rtc_time));
145 if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1; 145 if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1;
146 } 146 }
147 147
148 memcpy(rtctm, &tm, sizeof(struct rtc_time)); 148 memcpy(rtctm, &tm, sizeof(struct rtc_time));
149 149
150 return 0; 150 return 0;
151 } 151 }
152 152
153 153
154 static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg) 154 static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg)
155 { 155 {
156 hp_sdc_transaction t; 156 hp_sdc_transaction t;
157 uint8_t tseq[26] = { 157 uint8_t tseq[26] = {
158 HP_SDC_ACT_PRECMD | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 158 HP_SDC_ACT_PRECMD | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
159 0, 159 0,
160 HP_SDC_CMD_READ_T1, 2, 0, 0, 160 HP_SDC_CMD_READ_T1, 2, 0, 0,
161 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 161 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
162 HP_SDC_CMD_READ_T2, 2, 0, 0, 162 HP_SDC_CMD_READ_T2, 2, 0, 0,
163 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 163 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
164 HP_SDC_CMD_READ_T3, 2, 0, 0, 164 HP_SDC_CMD_READ_T3, 2, 0, 0,
165 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 165 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
166 HP_SDC_CMD_READ_T4, 2, 0, 0, 166 HP_SDC_CMD_READ_T4, 2, 0, 0,
167 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 167 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
168 HP_SDC_CMD_READ_T5, 2, 0, 0 168 HP_SDC_CMD_READ_T5, 2, 0, 0
169 }; 169 };
170 170
171 t.endidx = numreg * 5; 171 t.endidx = numreg * 5;
172 172
173 tseq[1] = loadcmd; 173 tseq[1] = loadcmd;
174 tseq[t.endidx - 4] |= HP_SDC_ACT_SEMAPHORE; /* numreg assumed > 1 */ 174 tseq[t.endidx - 4] |= HP_SDC_ACT_SEMAPHORE; /* numreg assumed > 1 */
175 175
176 t.seq = tseq; 176 t.seq = tseq;
177 t.act.semaphore = &i8042tregs; 177 t.act.semaphore = &i8042tregs;
178 178
179 down_interruptible(&i8042tregs); /* Sleep if output regs in use. */ 179 down_interruptible(&i8042tregs); /* Sleep if output regs in use. */
180 180
181 if (hp_sdc_enqueue_transaction(&t)) return -1; 181 if (hp_sdc_enqueue_transaction(&t)) return -1;
182 182
183 down_interruptible(&i8042tregs); /* Sleep until results come back. */ 183 down_interruptible(&i8042tregs); /* Sleep until results come back. */
184 up(&i8042tregs); 184 up(&i8042tregs);
185 185
186 return (tseq[5] | 186 return (tseq[5] |
187 ((uint64_t)(tseq[10]) << 8) | ((uint64_t)(tseq[15]) << 16) | 187 ((uint64_t)(tseq[10]) << 8) | ((uint64_t)(tseq[15]) << 16) |
188 ((uint64_t)(tseq[20]) << 24) | ((uint64_t)(tseq[25]) << 32)); 188 ((uint64_t)(tseq[20]) << 24) | ((uint64_t)(tseq[25]) << 32));
189 } 189 }
190 190
191 191
192 /* Read the i8042 real-time clock */ 192 /* Read the i8042 real-time clock */
193 static inline int hp_sdc_rtc_read_rt(struct timeval *res) { 193 static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
194 int64_t raw; 194 int64_t raw;
195 uint32_t tenms; 195 uint32_t tenms;
196 unsigned int days; 196 unsigned int days;
197 197
198 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_RT, 5); 198 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_RT, 5);
199 if (raw < 0) return -1; 199 if (raw < 0) return -1;
200 200
201 tenms = (uint32_t)raw & 0xffffff; 201 tenms = (uint32_t)raw & 0xffffff;
202 days = (unsigned int)(raw >> 24) & 0xffff; 202 days = (unsigned int)(raw >> 24) & 0xffff;
203 203
204 res->tv_usec = (suseconds_t)(tenms % 100) * 10000; 204 res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
205 res->tv_sec = (time_t)(tenms / 100) + days * 86400; 205 res->tv_sec = (time_t)(tenms / 100) + days * 86400;
206 206
207 return 0; 207 return 0;
208 } 208 }
209 209
210 210
211 /* Read the i8042 fast handshake timer */ 211 /* Read the i8042 fast handshake timer */
212 static inline int hp_sdc_rtc_read_fhs(struct timeval *res) { 212 static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
213 uint64_t raw; 213 uint64_t raw;
214 unsigned int tenms; 214 unsigned int tenms;
215 215
216 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_FHS, 2); 216 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_FHS, 2);
217 if (raw < 0) return -1; 217 if (raw < 0) return -1;
218 218
219 tenms = (unsigned int)raw & 0xffff; 219 tenms = (unsigned int)raw & 0xffff;
220 220
221 res->tv_usec = (suseconds_t)(tenms % 100) * 10000; 221 res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
222 res->tv_sec = (time_t)(tenms / 100); 222 res->tv_sec = (time_t)(tenms / 100);
223 223
224 return 0; 224 return 0;
225 } 225 }
226 226
227 227
228 /* Read the i8042 match timer (a.k.a. alarm) */ 228 /* Read the i8042 match timer (a.k.a. alarm) */
229 static inline int hp_sdc_rtc_read_mt(struct timeval *res) { 229 static inline int hp_sdc_rtc_read_mt(struct timeval *res) {
230 int64_t raw; 230 int64_t raw;
231 uint32_t tenms; 231 uint32_t tenms;
232 232
233 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_MT, 3); 233 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_MT, 3);
234 if (raw < 0) return -1; 234 if (raw < 0) return -1;
235 235
236 tenms = (uint32_t)raw & 0xffffff; 236 tenms = (uint32_t)raw & 0xffffff;
237 237
238 res->tv_usec = (suseconds_t)(tenms % 100) * 10000; 238 res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
239 res->tv_sec = (time_t)(tenms / 100); 239 res->tv_sec = (time_t)(tenms / 100);
240 240
241 return 0; 241 return 0;
242 } 242 }
243 243
244 244
245 /* Read the i8042 delay timer */ 245 /* Read the i8042 delay timer */
246 static inline int hp_sdc_rtc_read_dt(struct timeval *res) { 246 static inline int hp_sdc_rtc_read_dt(struct timeval *res) {
247 int64_t raw; 247 int64_t raw;
248 uint32_t tenms; 248 uint32_t tenms;
249 249
250 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_DT, 3); 250 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_DT, 3);
251 if (raw < 0) return -1; 251 if (raw < 0) return -1;
252 252
253 tenms = (uint32_t)raw & 0xffffff; 253 tenms = (uint32_t)raw & 0xffffff;
254 254
255 res->tv_usec = (suseconds_t)(tenms % 100) * 10000; 255 res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
256 res->tv_sec = (time_t)(tenms / 100); 256 res->tv_sec = (time_t)(tenms / 100);
257 257
258 return 0; 258 return 0;
259 } 259 }
260 260
261 261
262 /* Read the i8042 cycle timer (a.k.a. periodic) */ 262 /* Read the i8042 cycle timer (a.k.a. periodic) */
263 static inline int hp_sdc_rtc_read_ct(struct timeval *res) { 263 static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
264 int64_t raw; 264 int64_t raw;
265 uint32_t tenms; 265 uint32_t tenms;
266 266
267 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_CT, 3); 267 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_CT, 3);
268 if (raw < 0) return -1; 268 if (raw < 0) return -1;
269 269
270 tenms = (uint32_t)raw & 0xffffff; 270 tenms = (uint32_t)raw & 0xffffff;
271 271
272 res->tv_usec = (suseconds_t)(tenms % 100) * 10000; 272 res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
273 res->tv_sec = (time_t)(tenms / 100); 273 res->tv_sec = (time_t)(tenms / 100);
274 274
275 return 0; 275 return 0;
276 } 276 }
277 277
278 278
279 /* Set the i8042 real-time clock */ 279 /* Set the i8042 real-time clock */
280 static int hp_sdc_rtc_set_rt (struct timeval *setto) 280 static int hp_sdc_rtc_set_rt (struct timeval *setto)
281 { 281 {
282 uint32_t tenms; 282 uint32_t tenms;
283 unsigned int days; 283 unsigned int days;
284 hp_sdc_transaction t; 284 hp_sdc_transaction t;
285 uint8_t tseq[11] = { 285 uint8_t tseq[11] = {
286 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, 286 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
287 HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0, 287 HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0,
288 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, 288 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
289 HP_SDC_CMD_SET_RTD, 2, 0, 0 289 HP_SDC_CMD_SET_RTD, 2, 0, 0
290 }; 290 };
291 291
292 t.endidx = 10; 292 t.endidx = 10;
293 293
294 if (0xffff < setto->tv_sec / 86400) return -1; 294 if (0xffff < setto->tv_sec / 86400) return -1;
295 days = setto->tv_sec / 86400; 295 days = setto->tv_sec / 86400;
296 if (0xffff < setto->tv_usec / 1000000 / 86400) return -1; 296 if (0xffff < setto->tv_usec / 1000000 / 86400) return -1;
297 days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400; 297 days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400;
298 if (days > 0xffff) return -1; 298 if (days > 0xffff) return -1;
299 299
300 if (0xffffff < setto->tv_sec) return -1; 300 if (0xffffff < setto->tv_sec) return -1;
301 tenms = setto->tv_sec * 100; 301 tenms = setto->tv_sec * 100;
302 if (0xffffff < setto->tv_usec / 10000) return -1; 302 if (0xffffff < setto->tv_usec / 10000) return -1;
303 tenms += setto->tv_usec / 10000; 303 tenms += setto->tv_usec / 10000;
304 if (tenms > 0xffffff) return -1; 304 if (tenms > 0xffffff) return -1;
305 305
306 tseq[3] = (uint8_t)(tenms & 0xff); 306 tseq[3] = (uint8_t)(tenms & 0xff);
307 tseq[4] = (uint8_t)((tenms >> 8) & 0xff); 307 tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
308 tseq[5] = (uint8_t)((tenms >> 16) & 0xff); 308 tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
309 309
310 tseq[9] = (uint8_t)(days & 0xff); 310 tseq[9] = (uint8_t)(days & 0xff);
311 tseq[10] = (uint8_t)((days >> 8) & 0xff); 311 tseq[10] = (uint8_t)((days >> 8) & 0xff);
312 312
313 t.seq = tseq; 313 t.seq = tseq;
314 314
315 if (hp_sdc_enqueue_transaction(&t)) return -1; 315 if (hp_sdc_enqueue_transaction(&t)) return -1;
316 return 0; 316 return 0;
317 } 317 }
318 318
319 /* Set the i8042 fast handshake timer */ 319 /* Set the i8042 fast handshake timer */
320 static int hp_sdc_rtc_set_fhs (struct timeval *setto) 320 static int hp_sdc_rtc_set_fhs (struct timeval *setto)
321 { 321 {
322 uint32_t tenms; 322 uint32_t tenms;
323 hp_sdc_transaction t; 323 hp_sdc_transaction t;
324 uint8_t tseq[5] = { 324 uint8_t tseq[5] = {
325 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, 325 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
326 HP_SDC_CMD_SET_FHS, 2, 0, 0 326 HP_SDC_CMD_SET_FHS, 2, 0, 0
327 }; 327 };
328 328
329 t.endidx = 4; 329 t.endidx = 4;
330 330
331 if (0xffff < setto->tv_sec) return -1; 331 if (0xffff < setto->tv_sec) return -1;
332 tenms = setto->tv_sec * 100; 332 tenms = setto->tv_sec * 100;
333 if (0xffff < setto->tv_usec / 10000) return -1; 333 if (0xffff < setto->tv_usec / 10000) return -1;
334 tenms += setto->tv_usec / 10000; 334 tenms += setto->tv_usec / 10000;
335 if (tenms > 0xffff) return -1; 335 if (tenms > 0xffff) return -1;
336 336
337 tseq[3] = (uint8_t)(tenms & 0xff); 337 tseq[3] = (uint8_t)(tenms & 0xff);
338 tseq[4] = (uint8_t)((tenms >> 8) & 0xff); 338 tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
339 339
340 t.seq = tseq; 340 t.seq = tseq;
341 341
342 if (hp_sdc_enqueue_transaction(&t)) return -1; 342 if (hp_sdc_enqueue_transaction(&t)) return -1;
343 return 0; 343 return 0;
344 } 344 }
345 345
346 346
347 /* Set the i8042 match timer (a.k.a. alarm) */ 347 /* Set the i8042 match timer (a.k.a. alarm) */
348 #define hp_sdc_rtc_set_mt (setto) \ 348 #define hp_sdc_rtc_set_mt (setto) \
349 hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT) 349 hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT)
350 350
351 /* Set the i8042 delay timer */ 351 /* Set the i8042 delay timer */
352 #define hp_sdc_rtc_set_dt (setto) \ 352 #define hp_sdc_rtc_set_dt (setto) \
353 hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT) 353 hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT)
354 354
355 /* Set the i8042 cycle timer (a.k.a. periodic) */ 355 /* Set the i8042 cycle timer (a.k.a. periodic) */
356 #define hp_sdc_rtc_set_ct (setto) \ 356 #define hp_sdc_rtc_set_ct (setto) \
357 hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT) 357 hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT)
358 358
359 /* Set one of the i8042 3-byte wide timers */ 359 /* Set one of the i8042 3-byte wide timers */
360 static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd) 360 static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd)
361 { 361 {
362 uint32_t tenms; 362 uint32_t tenms;
363 hp_sdc_transaction t; 363 hp_sdc_transaction t;
364 uint8_t tseq[6] = { 364 uint8_t tseq[6] = {
365 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, 365 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
366 0, 3, 0, 0, 0 366 0, 3, 0, 0, 0
367 }; 367 };
368 368
369 t.endidx = 6; 369 t.endidx = 6;
370 370
371 if (0xffffff < setto->tv_sec) return -1; 371 if (0xffffff < setto->tv_sec) return -1;
372 tenms = setto->tv_sec * 100; 372 tenms = setto->tv_sec * 100;
373 if (0xffffff < setto->tv_usec / 10000) return -1; 373 if (0xffffff < setto->tv_usec / 10000) return -1;
374 tenms += setto->tv_usec / 10000; 374 tenms += setto->tv_usec / 10000;
375 if (tenms > 0xffffff) return -1; 375 if (tenms > 0xffffff) return -1;
376 376
377 tseq[1] = setcmd; 377 tseq[1] = setcmd;
378 tseq[3] = (uint8_t)(tenms & 0xff); 378 tseq[3] = (uint8_t)(tenms & 0xff);
379 tseq[4] = (uint8_t)((tenms >> 8) & 0xff); 379 tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
380 tseq[5] = (uint8_t)((tenms >> 16) & 0xff); 380 tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
381 381
382 t.seq = tseq; 382 t.seq = tseq;
383 383
384 if (hp_sdc_enqueue_transaction(&t)) { 384 if (hp_sdc_enqueue_transaction(&t)) {
385 return -1; 385 return -1;
386 } 386 }
387 return 0; 387 return 0;
388 } 388 }
389 389
390 static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf, 390 static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf,
391 size_t count, loff_t *ppos) { 391 size_t count, loff_t *ppos) {
392 ssize_t retval; 392 ssize_t retval;
393 393
394 if (count < sizeof(unsigned long)) 394 if (count < sizeof(unsigned long))
395 return -EINVAL; 395 return -EINVAL;
396 396
397 retval = put_user(68, (unsigned long __user *)buf); 397 retval = put_user(68, (unsigned long __user *)buf);
398 return retval; 398 return retval;
399 } 399 }
400 400
401 static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait) 401 static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait)
402 { 402 {
403 unsigned long l; 403 unsigned long l;
404 404
405 l = 0; 405 l = 0;
406 if (l != 0) 406 if (l != 0)
407 return POLLIN | POLLRDNORM; 407 return POLLIN | POLLRDNORM;
408 return 0; 408 return 0;
409 } 409 }
410 410
411 static int hp_sdc_rtc_open(struct inode *inode, struct file *file) 411 static int hp_sdc_rtc_open(struct inode *inode, struct file *file)
412 { 412 {
413 cycle_kernel_lock(); 413 cycle_kernel_lock();
414 return 0; 414 return 0;
415 } 415 }
416 416
417 static int hp_sdc_rtc_release(struct inode *inode, struct file *file) 417 static int hp_sdc_rtc_release(struct inode *inode, struct file *file)
418 { 418 {
419 /* Turn off interrupts? */ 419 /* Turn off interrupts? */
420 420
421 if (file->f_flags & FASYNC) { 421 if (file->f_flags & FASYNC) {
422 hp_sdc_rtc_fasync (-1, file, 0); 422 hp_sdc_rtc_fasync (-1, file, 0);
423 } 423 }
424 424
425 return 0; 425 return 0;
426 } 426 }
427 427
428 static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on) 428 static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on)
429 { 429 {
430 return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue); 430 return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue);
431 } 431 }
432 432
433 static int hp_sdc_rtc_proc_output (char *buf) 433 static int hp_sdc_rtc_proc_output (char *buf)
434 { 434 {
435 #define YN(bit) ("no") 435 #define YN(bit) ("no")
436 #define NY(bit) ("yes") 436 #define NY(bit) ("yes")
437 char *p; 437 char *p;
438 struct rtc_time tm; 438 struct rtc_time tm;
439 struct timeval tv; 439 struct timeval tv;
440 440
441 memset(&tm, 0, sizeof(struct rtc_time)); 441 memset(&tm, 0, sizeof(struct rtc_time));
442 442
443 p = buf; 443 p = buf;
444 444
445 if (hp_sdc_rtc_read_bbrtc(&tm)) { 445 if (hp_sdc_rtc_read_bbrtc(&tm)) {
446 p += sprintf(p, "BBRTC\t\t: READ FAILED!\n"); 446 p += sprintf(p, "BBRTC\t\t: READ FAILED!\n");
447 } else { 447 } else {
448 p += sprintf(p, 448 p += sprintf(p,
449 "rtc_time\t: %02d:%02d:%02d\n" 449 "rtc_time\t: %02d:%02d:%02d\n"
450 "rtc_date\t: %04d-%02d-%02d\n" 450 "rtc_date\t: %04d-%02d-%02d\n"
451 "rtc_epoch\t: %04lu\n", 451 "rtc_epoch\t: %04lu\n",
452 tm.tm_hour, tm.tm_min, tm.tm_sec, 452 tm.tm_hour, tm.tm_min, tm.tm_sec,
453 tm.tm_year + 1900, tm.tm_mon + 1, 453 tm.tm_year + 1900, tm.tm_mon + 1,
454 tm.tm_mday, epoch); 454 tm.tm_mday, epoch);
455 } 455 }
456 456
457 if (hp_sdc_rtc_read_rt(&tv)) { 457 if (hp_sdc_rtc_read_rt(&tv)) {
458 p += sprintf(p, "i8042 rtc\t: READ FAILED!\n"); 458 p += sprintf(p, "i8042 rtc\t: READ FAILED!\n");
459 } else { 459 } else {
460 p += sprintf(p, "i8042 rtc\t: %ld.%02d seconds\n", 460 p += sprintf(p, "i8042 rtc\t: %ld.%02d seconds\n",
461 tv.tv_sec, tv.tv_usec/1000); 461 tv.tv_sec, (int)tv.tv_usec/1000);
462 } 462 }
463 463
464 if (hp_sdc_rtc_read_fhs(&tv)) { 464 if (hp_sdc_rtc_read_fhs(&tv)) {
465 p += sprintf(p, "handshake\t: READ FAILED!\n"); 465 p += sprintf(p, "handshake\t: READ FAILED!\n");
466 } else { 466 } else {
467 p += sprintf(p, "handshake\t: %ld.%02d seconds\n", 467 p += sprintf(p, "handshake\t: %ld.%02d seconds\n",
468 tv.tv_sec, tv.tv_usec/1000); 468 tv.tv_sec, (int)tv.tv_usec/1000);
469 } 469 }
470 470
471 if (hp_sdc_rtc_read_mt(&tv)) { 471 if (hp_sdc_rtc_read_mt(&tv)) {
472 p += sprintf(p, "alarm\t\t: READ FAILED!\n"); 472 p += sprintf(p, "alarm\t\t: READ FAILED!\n");
473 } else { 473 } else {
474 p += sprintf(p, "alarm\t\t: %ld.%02d seconds\n", 474 p += sprintf(p, "alarm\t\t: %ld.%02d seconds\n",
475 tv.tv_sec, tv.tv_usec/1000); 475 tv.tv_sec, (int)tv.tv_usec/1000);
476 } 476 }
477 477
478 if (hp_sdc_rtc_read_dt(&tv)) { 478 if (hp_sdc_rtc_read_dt(&tv)) {
479 p += sprintf(p, "delay\t\t: READ FAILED!\n"); 479 p += sprintf(p, "delay\t\t: READ FAILED!\n");
480 } else { 480 } else {
481 p += sprintf(p, "delay\t\t: %ld.%02d seconds\n", 481 p += sprintf(p, "delay\t\t: %ld.%02d seconds\n",
482 tv.tv_sec, tv.tv_usec/1000); 482 tv.tv_sec, (int)tv.tv_usec/1000);
483 } 483 }
484 484
485 if (hp_sdc_rtc_read_ct(&tv)) { 485 if (hp_sdc_rtc_read_ct(&tv)) {
486 p += sprintf(p, "periodic\t: READ FAILED!\n"); 486 p += sprintf(p, "periodic\t: READ FAILED!\n");
487 } else { 487 } else {
488 p += sprintf(p, "periodic\t: %ld.%02d seconds\n", 488 p += sprintf(p, "periodic\t: %ld.%02d seconds\n",
489 tv.tv_sec, tv.tv_usec/1000); 489 tv.tv_sec, (int)tv.tv_usec/1000);
490 } 490 }
491 491
492 p += sprintf(p, 492 p += sprintf(p,
493 "DST_enable\t: %s\n" 493 "DST_enable\t: %s\n"
494 "BCD\t\t: %s\n" 494 "BCD\t\t: %s\n"
495 "24hr\t\t: %s\n" 495 "24hr\t\t: %s\n"
496 "square_wave\t: %s\n" 496 "square_wave\t: %s\n"
497 "alarm_IRQ\t: %s\n" 497 "alarm_IRQ\t: %s\n"
498 "update_IRQ\t: %s\n" 498 "update_IRQ\t: %s\n"
499 "periodic_IRQ\t: %s\n" 499 "periodic_IRQ\t: %s\n"
500 "periodic_freq\t: %ld\n" 500 "periodic_freq\t: %ld\n"
501 "batt_status\t: %s\n", 501 "batt_status\t: %s\n",
502 YN(RTC_DST_EN), 502 YN(RTC_DST_EN),
503 NY(RTC_DM_BINARY), 503 NY(RTC_DM_BINARY),
504 YN(RTC_24H), 504 YN(RTC_24H),
505 YN(RTC_SQWE), 505 YN(RTC_SQWE),
506 YN(RTC_AIE), 506 YN(RTC_AIE),
507 YN(RTC_UIE), 507 YN(RTC_UIE),
508 YN(RTC_PIE), 508 YN(RTC_PIE),
509 1UL, 509 1UL,
510 1 ? "okay" : "dead"); 510 1 ? "okay" : "dead");
511 511
512 return p - buf; 512 return p - buf;
513 #undef YN 513 #undef YN
514 #undef NY 514 #undef NY
515 } 515 }
516 516
517 static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off, 517 static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
518 int count, int *eof, void *data) 518 int count, int *eof, void *data)
519 { 519 {
520 int len = hp_sdc_rtc_proc_output (page); 520 int len = hp_sdc_rtc_proc_output (page);
521 if (len <= off+count) *eof = 1; 521 if (len <= off+count) *eof = 1;
522 *start = page + off; 522 *start = page + off;
523 len -= off; 523 len -= off;
524 if (len>count) len = count; 524 if (len>count) len = count;
525 if (len<0) len = 0; 525 if (len<0) len = 0;
526 return len; 526 return len;
527 } 527 }
528 528
529 static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file, 529 static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file,
530 unsigned int cmd, unsigned long arg) 530 unsigned int cmd, unsigned long arg)
531 { 531 {
532 #if 1 532 #if 1
533 return -EINVAL; 533 return -EINVAL;
534 #else 534 #else
535 535
536 struct rtc_time wtime; 536 struct rtc_time wtime;
537 struct timeval ttime; 537 struct timeval ttime;
538 int use_wtime = 0; 538 int use_wtime = 0;
539 539
540 /* This needs major work. */ 540 /* This needs major work. */
541 541
542 switch (cmd) { 542 switch (cmd) {
543 543
544 case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ 544 case RTC_AIE_OFF: /* Mask alarm int. enab. bit */
545 case RTC_AIE_ON: /* Allow alarm interrupts. */ 545 case RTC_AIE_ON: /* Allow alarm interrupts. */
546 case RTC_PIE_OFF: /* Mask periodic int. enab. bit */ 546 case RTC_PIE_OFF: /* Mask periodic int. enab. bit */
547 case RTC_PIE_ON: /* Allow periodic ints */ 547 case RTC_PIE_ON: /* Allow periodic ints */
548 case RTC_UIE_ON: /* Allow ints for RTC updates. */ 548 case RTC_UIE_ON: /* Allow ints for RTC updates. */
549 case RTC_UIE_OFF: /* Allow ints for RTC updates. */ 549 case RTC_UIE_OFF: /* Allow ints for RTC updates. */
550 { 550 {
551 /* We cannot mask individual user timers and we 551 /* We cannot mask individual user timers and we
552 cannot tell them apart when they occur, so it 552 cannot tell them apart when they occur, so it
553 would be disingenuous to succeed these IOCTLs */ 553 would be disingenuous to succeed these IOCTLs */
554 return -EINVAL; 554 return -EINVAL;
555 } 555 }
556 case RTC_ALM_READ: /* Read the present alarm time */ 556 case RTC_ALM_READ: /* Read the present alarm time */
557 { 557 {
558 if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT; 558 if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT;
559 if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT; 559 if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
560 560
561 wtime.tm_hour = ttime.tv_sec / 3600; ttime.tv_sec %= 3600; 561 wtime.tm_hour = ttime.tv_sec / 3600; ttime.tv_sec %= 3600;
562 wtime.tm_min = ttime.tv_sec / 60; ttime.tv_sec %= 60; 562 wtime.tm_min = ttime.tv_sec / 60; ttime.tv_sec %= 60;
563 wtime.tm_sec = ttime.tv_sec; 563 wtime.tm_sec = ttime.tv_sec;
564 564
565 break; 565 break;
566 } 566 }
567 case RTC_IRQP_READ: /* Read the periodic IRQ rate. */ 567 case RTC_IRQP_READ: /* Read the periodic IRQ rate. */
568 { 568 {
569 return put_user(hp_sdc_rtc_freq, (unsigned long *)arg); 569 return put_user(hp_sdc_rtc_freq, (unsigned long *)arg);
570 } 570 }
571 case RTC_IRQP_SET: /* Set periodic IRQ rate. */ 571 case RTC_IRQP_SET: /* Set periodic IRQ rate. */
572 { 572 {
573 /* 573 /*
574 * The max we can do is 100Hz. 574 * The max we can do is 100Hz.
575 */ 575 */
576 576
577 if ((arg < 1) || (arg > 100)) return -EINVAL; 577 if ((arg < 1) || (arg > 100)) return -EINVAL;
578 ttime.tv_sec = 0; 578 ttime.tv_sec = 0;
579 ttime.tv_usec = 1000000 / arg; 579 ttime.tv_usec = 1000000 / arg;
580 if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT; 580 if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT;
581 hp_sdc_rtc_freq = arg; 581 hp_sdc_rtc_freq = arg;
582 return 0; 582 return 0;
583 } 583 }
584 case RTC_ALM_SET: /* Store a time into the alarm */ 584 case RTC_ALM_SET: /* Store a time into the alarm */
585 { 585 {
586 /* 586 /*
587 * This expects a struct hp_sdc_rtc_time. Writing 0xff means 587 * This expects a struct hp_sdc_rtc_time. Writing 0xff means
588 * "don't care" or "match all" for PC timers. The HP SDC 588 * "don't care" or "match all" for PC timers. The HP SDC
589 * does not support that perk, but it could be emulated fairly 589 * does not support that perk, but it could be emulated fairly
590 * easily. Only the tm_hour, tm_min and tm_sec are used. 590 * easily. Only the tm_hour, tm_min and tm_sec are used.
591 * We could do it with 10ms accuracy with the HP SDC, if the 591 * We could do it with 10ms accuracy with the HP SDC, if the
592 * rtc interface left us a way to do that. 592 * rtc interface left us a way to do that.
593 */ 593 */
594 struct hp_sdc_rtc_time alm_tm; 594 struct hp_sdc_rtc_time alm_tm;
595 595
596 if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg, 596 if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg,
597 sizeof(struct hp_sdc_rtc_time))) 597 sizeof(struct hp_sdc_rtc_time)))
598 return -EFAULT; 598 return -EFAULT;
599 599
600 if (alm_tm.tm_hour > 23) return -EINVAL; 600 if (alm_tm.tm_hour > 23) return -EINVAL;
601 if (alm_tm.tm_min > 59) return -EINVAL; 601 if (alm_tm.tm_min > 59) return -EINVAL;
602 if (alm_tm.tm_sec > 59) return -EINVAL; 602 if (alm_tm.tm_sec > 59) return -EINVAL;
603 603
604 ttime.sec = alm_tm.tm_hour * 3600 + 604 ttime.sec = alm_tm.tm_hour * 3600 +
605 alm_tm.tm_min * 60 + alm_tm.tm_sec; 605 alm_tm.tm_min * 60 + alm_tm.tm_sec;
606 ttime.usec = 0; 606 ttime.usec = 0;
607 if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT; 607 if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT;
608 return 0; 608 return 0;
609 } 609 }
610 case RTC_RD_TIME: /* Read the time/date from RTC */ 610 case RTC_RD_TIME: /* Read the time/date from RTC */
611 { 611 {
612 if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT; 612 if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
613 break; 613 break;
614 } 614 }
615 case RTC_SET_TIME: /* Set the RTC */ 615 case RTC_SET_TIME: /* Set the RTC */
616 { 616 {
617 struct rtc_time hp_sdc_rtc_tm; 617 struct rtc_time hp_sdc_rtc_tm;
618 unsigned char mon, day, hrs, min, sec, leap_yr; 618 unsigned char mon, day, hrs, min, sec, leap_yr;
619 unsigned int yrs; 619 unsigned int yrs;
620 620
621 if (!capable(CAP_SYS_TIME)) 621 if (!capable(CAP_SYS_TIME))
622 return -EACCES; 622 return -EACCES;
623 if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg, 623 if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg,
624 sizeof(struct rtc_time))) 624 sizeof(struct rtc_time)))
625 return -EFAULT; 625 return -EFAULT;
626 626
627 yrs = hp_sdc_rtc_tm.tm_year + 1900; 627 yrs = hp_sdc_rtc_tm.tm_year + 1900;
628 mon = hp_sdc_rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ 628 mon = hp_sdc_rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
629 day = hp_sdc_rtc_tm.tm_mday; 629 day = hp_sdc_rtc_tm.tm_mday;
630 hrs = hp_sdc_rtc_tm.tm_hour; 630 hrs = hp_sdc_rtc_tm.tm_hour;
631 min = hp_sdc_rtc_tm.tm_min; 631 min = hp_sdc_rtc_tm.tm_min;
632 sec = hp_sdc_rtc_tm.tm_sec; 632 sec = hp_sdc_rtc_tm.tm_sec;
633 633
634 if (yrs < 1970) 634 if (yrs < 1970)
635 return -EINVAL; 635 return -EINVAL;
636 636
637 leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); 637 leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
638 638
639 if ((mon > 12) || (day == 0)) 639 if ((mon > 12) || (day == 0))
640 return -EINVAL; 640 return -EINVAL;
641 if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) 641 if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
642 return -EINVAL; 642 return -EINVAL;
643 if ((hrs >= 24) || (min >= 60) || (sec >= 60)) 643 if ((hrs >= 24) || (min >= 60) || (sec >= 60))
644 return -EINVAL; 644 return -EINVAL;
645 645
646 if ((yrs -= eH) > 255) /* They are unsigned */ 646 if ((yrs -= eH) > 255) /* They are unsigned */
647 return -EINVAL; 647 return -EINVAL;
648 648
649 649
650 return 0; 650 return 0;
651 } 651 }
652 case RTC_EPOCH_READ: /* Read the epoch. */ 652 case RTC_EPOCH_READ: /* Read the epoch. */
653 { 653 {
654 return put_user (epoch, (unsigned long *)arg); 654 return put_user (epoch, (unsigned long *)arg);
655 } 655 }
656 case RTC_EPOCH_SET: /* Set the epoch. */ 656 case RTC_EPOCH_SET: /* Set the epoch. */
657 { 657 {
658 /* 658 /*
659 * There were no RTC clocks before 1900. 659 * There were no RTC clocks before 1900.
660 */ 660 */
661 if (arg < 1900) 661 if (arg < 1900)
662 return -EINVAL; 662 return -EINVAL;
663 if (!capable(CAP_SYS_TIME)) 663 if (!capable(CAP_SYS_TIME))
664 return -EACCES; 664 return -EACCES;
665 665
666 epoch = arg; 666 epoch = arg;
667 return 0; 667 return 0;
668 } 668 }
669 default: 669 default:
670 return -EINVAL; 670 return -EINVAL;
671 } 671 }
672 return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; 672 return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
673 #endif 673 #endif
674 } 674 }
675 675
676 static const struct file_operations hp_sdc_rtc_fops = { 676 static const struct file_operations hp_sdc_rtc_fops = {
677 .owner = THIS_MODULE, 677 .owner = THIS_MODULE,
678 .llseek = no_llseek, 678 .llseek = no_llseek,
679 .read = hp_sdc_rtc_read, 679 .read = hp_sdc_rtc_read,
680 .poll = hp_sdc_rtc_poll, 680 .poll = hp_sdc_rtc_poll,
681 .ioctl = hp_sdc_rtc_ioctl, 681 .ioctl = hp_sdc_rtc_ioctl,
682 .open = hp_sdc_rtc_open, 682 .open = hp_sdc_rtc_open,
683 .release = hp_sdc_rtc_release, 683 .release = hp_sdc_rtc_release,
684 .fasync = hp_sdc_rtc_fasync, 684 .fasync = hp_sdc_rtc_fasync,
685 }; 685 };
686 686
687 static struct miscdevice hp_sdc_rtc_dev = { 687 static struct miscdevice hp_sdc_rtc_dev = {
688 .minor = RTC_MINOR, 688 .minor = RTC_MINOR,
689 .name = "rtc_HIL", 689 .name = "rtc_HIL",
690 .fops = &hp_sdc_rtc_fops 690 .fops = &hp_sdc_rtc_fops
691 }; 691 };
692 692
693 static int __init hp_sdc_rtc_init(void) 693 static int __init hp_sdc_rtc_init(void)
694 { 694 {
695 int ret; 695 int ret;
696 696
697 #ifdef __mc68000__ 697 #ifdef __mc68000__
698 if (!MACH_IS_HP300) 698 if (!MACH_IS_HP300)
699 return -ENODEV; 699 return -ENODEV;
700 #endif 700 #endif
701 701
702 init_MUTEX(&i8042tregs); 702 init_MUTEX(&i8042tregs);
703 703
704 if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr))) 704 if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
705 return ret; 705 return ret;
706 if (misc_register(&hp_sdc_rtc_dev) != 0) 706 if (misc_register(&hp_sdc_rtc_dev) != 0)
707 printk(KERN_INFO "Could not register misc. dev for i8042 rtc\n"); 707 printk(KERN_INFO "Could not register misc. dev for i8042 rtc\n");
708 708
709 create_proc_read_entry ("driver/rtc", 0, NULL, 709 create_proc_read_entry ("driver/rtc", 0, NULL,
710 hp_sdc_rtc_read_proc, NULL); 710 hp_sdc_rtc_read_proc, NULL);
711 711
712 printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support loaded " 712 printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support loaded "
713 "(RTC v " RTC_VERSION ")\n"); 713 "(RTC v " RTC_VERSION ")\n");
714 714
715 return 0; 715 return 0;
716 } 716 }
717 717
718 static void __exit hp_sdc_rtc_exit(void) 718 static void __exit hp_sdc_rtc_exit(void)
719 { 719 {
720 remove_proc_entry ("driver/rtc", NULL); 720 remove_proc_entry ("driver/rtc", NULL);
721 misc_deregister(&hp_sdc_rtc_dev); 721 misc_deregister(&hp_sdc_rtc_dev);
722 hp_sdc_release_timer_irq(hp_sdc_rtc_isr); 722 hp_sdc_release_timer_irq(hp_sdc_rtc_isr);
723 printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n"); 723 printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n");
724 } 724 }
725 725
726 module_init(hp_sdc_rtc_init); 726 module_init(hp_sdc_rtc_init);
727 module_exit(hp_sdc_rtc_exit); 727 module_exit(hp_sdc_rtc_exit);
728 728
drivers/input/serio/hp_sdc.c
1 /* 1 /*
2 * HP i8042-based System Device Controller driver. 2 * HP i8042-based System Device Controller driver.
3 * 3 *
4 * Copyright (c) 2001 Brian S. Julin 4 * Copyright (c) 2001 Brian S. Julin
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer, 11 * notice, this list of conditions, and the following disclaimer,
12 * without modification. 12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products 13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * Alternatively, this software may be distributed under the terms of the 16 * Alternatively, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL"). 17 * GNU General Public License ("GPL").
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * 28 *
29 * References: 29 * References:
30 * System Device Controller Microprocessor Firmware Theory of Operation 30 * System Device Controller Microprocessor Firmware Theory of Operation
31 * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2 31 * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2
32 * Helge Deller's original hilkbd.c port for PA-RISC. 32 * Helge Deller's original hilkbd.c port for PA-RISC.
33 * 33 *
34 * 34 *
35 * Driver theory of operation: 35 * Driver theory of operation:
36 * 36 *
37 * hp_sdc_put does all writing to the SDC. ISR can run on a different 37 * hp_sdc_put does all writing to the SDC. ISR can run on a different
38 * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time 38 * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time
39 * (it cannot really benefit from SMP anyway.) A tasket fit this perfectly. 39 * (it cannot really benefit from SMP anyway.) A tasket fit this perfectly.
40 * 40 *
41 * All data coming back from the SDC is sent via interrupt and can be read 41 * All data coming back from the SDC is sent via interrupt and can be read
42 * fully in the ISR, so there are no latency/throughput problems there. 42 * fully in the ISR, so there are no latency/throughput problems there.
43 * The problem is with output, due to the slow clock speed of the SDC 43 * The problem is with output, due to the slow clock speed of the SDC
44 * compared to the CPU. This should not be too horrible most of the time, 44 * compared to the CPU. This should not be too horrible most of the time,
45 * but if used with HIL devices that support the multibyte transfer command, 45 * but if used with HIL devices that support the multibyte transfer command,
46 * keeping outbound throughput flowing at the 6500KBps that the HIL is 46 * keeping outbound throughput flowing at the 6500KBps that the HIL is
47 * capable of is more than can be done at HZ=100. 47 * capable of is more than can be done at HZ=100.
48 * 48 *
49 * Busy polling for IBF clear wastes CPU cycles and bus cycles. hp_sdc.ibf 49 * Busy polling for IBF clear wastes CPU cycles and bus cycles. hp_sdc.ibf
50 * is set to 0 when the IBF flag in the status register has cleared. ISR 50 * is set to 0 when the IBF flag in the status register has cleared. ISR
51 * may do this, and may also access the parts of queued transactions related 51 * may do this, and may also access the parts of queued transactions related
52 * to reading data back from the SDC, but otherwise will not touch the 52 * to reading data back from the SDC, but otherwise will not touch the
53 * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1. 53 * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1.
54 * 54 *
55 * The i8042 write index and the values in the 4-byte input buffer 55 * The i8042 write index and the values in the 4-byte input buffer
56 * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively, 56 * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively,
57 * to minimize the amount of IO needed to the SDC. However these values 57 * to minimize the amount of IO needed to the SDC. However these values
58 * do not need to be locked since they are only ever accessed by hp_sdc_put. 58 * do not need to be locked since they are only ever accessed by hp_sdc_put.
59 * 59 *
60 * A timer task schedules the tasklet once per second just to make 60 * A timer task schedules the tasklet once per second just to make
61 * sure it doesn't freeze up and to allow for bad reads to time out. 61 * sure it doesn't freeze up and to allow for bad reads to time out.
62 */ 62 */
63 63
64 #include <linux/hp_sdc.h> 64 #include <linux/hp_sdc.h>
65 #include <linux/errno.h> 65 #include <linux/errno.h>
66 #include <linux/init.h> 66 #include <linux/init.h>
67 #include <linux/module.h> 67 #include <linux/module.h>
68 #include <linux/ioport.h> 68 #include <linux/ioport.h>
69 #include <linux/time.h> 69 #include <linux/time.h>
70 #include <linux/semaphore.h> 70 #include <linux/semaphore.h>
71 #include <linux/slab.h> 71 #include <linux/slab.h>
72 #include <linux/hil.h> 72 #include <linux/hil.h>
73 #include <asm/io.h> 73 #include <asm/io.h>
74 #include <asm/system.h> 74 #include <asm/system.h>
75 75
76 /* Machine-specific abstraction */ 76 /* Machine-specific abstraction */
77 77
78 #if defined(__hppa__) 78 #if defined(__hppa__)
79 # include <asm/parisc-device.h> 79 # include <asm/parisc-device.h>
80 # define sdc_readb(p) gsc_readb(p) 80 # define sdc_readb(p) gsc_readb(p)
81 # define sdc_writeb(v,p) gsc_writeb((v),(p)) 81 # define sdc_writeb(v,p) gsc_writeb((v),(p))
82 #elif defined(__mc68000__) 82 #elif defined(__mc68000__)
83 # include <asm/uaccess.h> 83 # include <asm/uaccess.h>
84 # define sdc_readb(p) in_8(p) 84 # define sdc_readb(p) in_8(p)
85 # define sdc_writeb(v,p) out_8((p),(v)) 85 # define sdc_writeb(v,p) out_8((p),(v))
86 #else 86 #else
87 # error "HIL is not supported on this platform" 87 # error "HIL is not supported on this platform"
88 #endif 88 #endif
89 89
90 #define PREFIX "HP SDC: " 90 #define PREFIX "HP SDC: "
91 91
92 MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); 92 MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
93 MODULE_DESCRIPTION("HP i8042-based SDC Driver"); 93 MODULE_DESCRIPTION("HP i8042-based SDC Driver");
94 MODULE_LICENSE("Dual BSD/GPL"); 94 MODULE_LICENSE("Dual BSD/GPL");
95 95
96 EXPORT_SYMBOL(hp_sdc_request_timer_irq); 96 EXPORT_SYMBOL(hp_sdc_request_timer_irq);
97 EXPORT_SYMBOL(hp_sdc_request_hil_irq); 97 EXPORT_SYMBOL(hp_sdc_request_hil_irq);
98 EXPORT_SYMBOL(hp_sdc_request_cooked_irq); 98 EXPORT_SYMBOL(hp_sdc_request_cooked_irq);
99 99
100 EXPORT_SYMBOL(hp_sdc_release_timer_irq); 100 EXPORT_SYMBOL(hp_sdc_release_timer_irq);
101 EXPORT_SYMBOL(hp_sdc_release_hil_irq); 101 EXPORT_SYMBOL(hp_sdc_release_hil_irq);
102 EXPORT_SYMBOL(hp_sdc_release_cooked_irq); 102 EXPORT_SYMBOL(hp_sdc_release_cooked_irq);
103 103
104 EXPORT_SYMBOL(__hp_sdc_enqueue_transaction); 104 EXPORT_SYMBOL(__hp_sdc_enqueue_transaction);
105 EXPORT_SYMBOL(hp_sdc_enqueue_transaction); 105 EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
106 EXPORT_SYMBOL(hp_sdc_dequeue_transaction); 106 EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
107 107
108 static unsigned int hp_sdc_disabled; 108 static unsigned int hp_sdc_disabled;
109 module_param_named(no_hpsdc, hp_sdc_disabled, bool, 0); 109 module_param_named(no_hpsdc, hp_sdc_disabled, bool, 0);
110 MODULE_PARM_DESC(no_hpsdc, "Do not enable HP SDC driver."); 110 MODULE_PARM_DESC(no_hpsdc, "Do not enable HP SDC driver.");
111 111
112 static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */ 112 static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */
113 113
114 /*************** primitives for use in any context *********************/ 114 /*************** primitives for use in any context *********************/
115 static inline uint8_t hp_sdc_status_in8(void) 115 static inline uint8_t hp_sdc_status_in8(void)
116 { 116 {
117 uint8_t status; 117 uint8_t status;
118 unsigned long flags; 118 unsigned long flags;
119 119
120 write_lock_irqsave(&hp_sdc.ibf_lock, flags); 120 write_lock_irqsave(&hp_sdc.ibf_lock, flags);
121 status = sdc_readb(hp_sdc.status_io); 121 status = sdc_readb(hp_sdc.status_io);
122 if (!(status & HP_SDC_STATUS_IBF)) 122 if (!(status & HP_SDC_STATUS_IBF))
123 hp_sdc.ibf = 0; 123 hp_sdc.ibf = 0;
124 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); 124 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
125 125
126 return status; 126 return status;
127 } 127 }
128 128
129 static inline uint8_t hp_sdc_data_in8(void) 129 static inline uint8_t hp_sdc_data_in8(void)
130 { 130 {
131 return sdc_readb(hp_sdc.data_io); 131 return sdc_readb(hp_sdc.data_io);
132 } 132 }
133 133
134 static inline void hp_sdc_status_out8(uint8_t val) 134 static inline void hp_sdc_status_out8(uint8_t val)
135 { 135 {
136 unsigned long flags; 136 unsigned long flags;
137 137
138 write_lock_irqsave(&hp_sdc.ibf_lock, flags); 138 write_lock_irqsave(&hp_sdc.ibf_lock, flags);
139 hp_sdc.ibf = 1; 139 hp_sdc.ibf = 1;
140 if ((val & 0xf0) == 0xe0) 140 if ((val & 0xf0) == 0xe0)
141 hp_sdc.wi = 0xff; 141 hp_sdc.wi = 0xff;
142 sdc_writeb(val, hp_sdc.status_io); 142 sdc_writeb(val, hp_sdc.status_io);
143 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); 143 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
144 } 144 }
145 145
146 static inline void hp_sdc_data_out8(uint8_t val) 146 static inline void hp_sdc_data_out8(uint8_t val)
147 { 147 {
148 unsigned long flags; 148 unsigned long flags;
149 149
150 write_lock_irqsave(&hp_sdc.ibf_lock, flags); 150 write_lock_irqsave(&hp_sdc.ibf_lock, flags);
151 hp_sdc.ibf = 1; 151 hp_sdc.ibf = 1;
152 sdc_writeb(val, hp_sdc.data_io); 152 sdc_writeb(val, hp_sdc.data_io);
153 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); 153 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
154 } 154 }
155 155
156 /* Care must be taken to only invoke hp_sdc_spin_ibf when 156 /* Care must be taken to only invoke hp_sdc_spin_ibf when
157 * absolutely needed, or in rarely invoked subroutines. 157 * absolutely needed, or in rarely invoked subroutines.
158 * Not only does it waste CPU cycles, it also wastes bus cycles. 158 * Not only does it waste CPU cycles, it also wastes bus cycles.
159 */ 159 */
160 static inline void hp_sdc_spin_ibf(void) 160 static inline void hp_sdc_spin_ibf(void)
161 { 161 {
162 unsigned long flags; 162 unsigned long flags;
163 rwlock_t *lock; 163 rwlock_t *lock;
164 164
165 lock = &hp_sdc.ibf_lock; 165 lock = &hp_sdc.ibf_lock;
166 166
167 read_lock_irqsave(lock, flags); 167 read_lock_irqsave(lock, flags);
168 if (!hp_sdc.ibf) { 168 if (!hp_sdc.ibf) {
169 read_unlock_irqrestore(lock, flags); 169 read_unlock_irqrestore(lock, flags);
170 return; 170 return;
171 } 171 }
172 read_unlock(lock); 172 read_unlock(lock);
173 write_lock(lock); 173 write_lock(lock);
174 while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) 174 while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF)
175 { } 175 { }
176 hp_sdc.ibf = 0; 176 hp_sdc.ibf = 0;
177 write_unlock_irqrestore(lock, flags); 177 write_unlock_irqrestore(lock, flags);
178 } 178 }
179 179
180 180
181 /************************ Interrupt context functions ************************/ 181 /************************ Interrupt context functions ************************/
182 static void hp_sdc_take(int irq, void *dev_id, uint8_t status, uint8_t data) 182 static void hp_sdc_take(int irq, void *dev_id, uint8_t status, uint8_t data)
183 { 183 {
184 hp_sdc_transaction *curr; 184 hp_sdc_transaction *curr;
185 185
186 read_lock(&hp_sdc.rtq_lock); 186 read_lock(&hp_sdc.rtq_lock);
187 if (hp_sdc.rcurr < 0) { 187 if (hp_sdc.rcurr < 0) {
188 read_unlock(&hp_sdc.rtq_lock); 188 read_unlock(&hp_sdc.rtq_lock);
189 return; 189 return;
190 } 190 }
191 curr = hp_sdc.tq[hp_sdc.rcurr]; 191 curr = hp_sdc.tq[hp_sdc.rcurr];
192 read_unlock(&hp_sdc.rtq_lock); 192 read_unlock(&hp_sdc.rtq_lock);
193 193
194 curr->seq[curr->idx++] = status; 194 curr->seq[curr->idx++] = status;
195 curr->seq[curr->idx++] = data; 195 curr->seq[curr->idx++] = data;
196 hp_sdc.rqty -= 2; 196 hp_sdc.rqty -= 2;
197 do_gettimeofday(&hp_sdc.rtv); 197 do_gettimeofday(&hp_sdc.rtv);
198 198
199 if (hp_sdc.rqty <= 0) { 199 if (hp_sdc.rqty <= 0) {
200 /* All data has been gathered. */ 200 /* All data has been gathered. */
201 if (curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) 201 if (curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE)
202 if (curr->act.semaphore) 202 if (curr->act.semaphore)
203 up(curr->act.semaphore); 203 up(curr->act.semaphore);
204 204
205 if (curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) 205 if (curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK)
206 if (curr->act.irqhook) 206 if (curr->act.irqhook)
207 curr->act.irqhook(irq, dev_id, status, data); 207 curr->act.irqhook(irq, dev_id, status, data);
208 208
209 curr->actidx = curr->idx; 209 curr->actidx = curr->idx;
210 curr->idx++; 210 curr->idx++;
211 /* Return control of this transaction */ 211 /* Return control of this transaction */
212 write_lock(&hp_sdc.rtq_lock); 212 write_lock(&hp_sdc.rtq_lock);
213 hp_sdc.rcurr = -1; 213 hp_sdc.rcurr = -1;
214 hp_sdc.rqty = 0; 214 hp_sdc.rqty = 0;
215 write_unlock(&hp_sdc.rtq_lock); 215 write_unlock(&hp_sdc.rtq_lock);
216 tasklet_schedule(&hp_sdc.task); 216 tasklet_schedule(&hp_sdc.task);
217 } 217 }
218 } 218 }
219 219
220 static irqreturn_t hp_sdc_isr(int irq, void *dev_id) 220 static irqreturn_t hp_sdc_isr(int irq, void *dev_id)
221 { 221 {
222 uint8_t status, data; 222 uint8_t status, data;
223 223
224 status = hp_sdc_status_in8(); 224 status = hp_sdc_status_in8();
225 /* Read data unconditionally to advance i8042. */ 225 /* Read data unconditionally to advance i8042. */
226 data = hp_sdc_data_in8(); 226 data = hp_sdc_data_in8();
227 227
228 /* For now we are ignoring these until we get the SDC to behave. */ 228 /* For now we are ignoring these until we get the SDC to behave. */
229 if (((status & 0xf1) == 0x51) && data == 0x82) 229 if (((status & 0xf1) == 0x51) && data == 0x82)
230 return IRQ_HANDLED; 230 return IRQ_HANDLED;
231 231
232 switch (status & HP_SDC_STATUS_IRQMASK) { 232 switch (status & HP_SDC_STATUS_IRQMASK) {
233 case 0: /* This case is not documented. */ 233 case 0: /* This case is not documented. */
234 break; 234 break;
235 235
236 case HP_SDC_STATUS_USERTIMER: 236 case HP_SDC_STATUS_USERTIMER:
237 case HP_SDC_STATUS_PERIODIC: 237 case HP_SDC_STATUS_PERIODIC:
238 case HP_SDC_STATUS_TIMER: 238 case HP_SDC_STATUS_TIMER:
239 read_lock(&hp_sdc.hook_lock); 239 read_lock(&hp_sdc.hook_lock);
240 if (hp_sdc.timer != NULL) 240 if (hp_sdc.timer != NULL)
241 hp_sdc.timer(irq, dev_id, status, data); 241 hp_sdc.timer(irq, dev_id, status, data);
242 read_unlock(&hp_sdc.hook_lock); 242 read_unlock(&hp_sdc.hook_lock);
243 break; 243 break;
244 244
245 case HP_SDC_STATUS_REG: 245 case HP_SDC_STATUS_REG:
246 hp_sdc_take(irq, dev_id, status, data); 246 hp_sdc_take(irq, dev_id, status, data);
247 break; 247 break;
248 248
249 case HP_SDC_STATUS_HILCMD: 249 case HP_SDC_STATUS_HILCMD:
250 case HP_SDC_STATUS_HILDATA: 250 case HP_SDC_STATUS_HILDATA:
251 read_lock(&hp_sdc.hook_lock); 251 read_lock(&hp_sdc.hook_lock);
252 if (hp_sdc.hil != NULL) 252 if (hp_sdc.hil != NULL)
253 hp_sdc.hil(irq, dev_id, status, data); 253 hp_sdc.hil(irq, dev_id, status, data);
254 read_unlock(&hp_sdc.hook_lock); 254 read_unlock(&hp_sdc.hook_lock);
255 break; 255 break;
256 256
257 case HP_SDC_STATUS_PUP: 257 case HP_SDC_STATUS_PUP:
258 read_lock(&hp_sdc.hook_lock); 258 read_lock(&hp_sdc.hook_lock);
259 if (hp_sdc.pup != NULL) 259 if (hp_sdc.pup != NULL)
260 hp_sdc.pup(irq, dev_id, status, data); 260 hp_sdc.pup(irq, dev_id, status, data);
261 else 261 else
262 printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n"); 262 printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
263 read_unlock(&hp_sdc.hook_lock); 263 read_unlock(&hp_sdc.hook_lock);
264 break; 264 break;
265 265
266 default: 266 default:
267 read_lock(&hp_sdc.hook_lock); 267 read_lock(&hp_sdc.hook_lock);
268 if (hp_sdc.cooked != NULL) 268 if (hp_sdc.cooked != NULL)
269 hp_sdc.cooked(irq, dev_id, status, data); 269 hp_sdc.cooked(irq, dev_id, status, data);
270 read_unlock(&hp_sdc.hook_lock); 270 read_unlock(&hp_sdc.hook_lock);
271 break; 271 break;
272 } 272 }
273 273
274 return IRQ_HANDLED; 274 return IRQ_HANDLED;
275 } 275 }
276 276
277 277
278 static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) 278 static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id)
279 { 279 {
280 int status; 280 int status;
281 281
282 status = hp_sdc_status_in8(); 282 status = hp_sdc_status_in8();
283 printk(KERN_WARNING PREFIX "NMI !\n"); 283 printk(KERN_WARNING PREFIX "NMI !\n");
284 284
285 #if 0 285 #if 0
286 if (status & HP_SDC_NMISTATUS_FHS) { 286 if (status & HP_SDC_NMISTATUS_FHS) {
287 read_lock(&hp_sdc.hook_lock); 287 read_lock(&hp_sdc.hook_lock);
288 if (hp_sdc.timer != NULL) 288 if (hp_sdc.timer != NULL)
289 hp_sdc.timer(irq, dev_id, status, 0); 289 hp_sdc.timer(irq, dev_id, status, 0);
290 read_unlock(&hp_sdc.hook_lock); 290 read_unlock(&hp_sdc.hook_lock);
291 } else { 291 } else {
292 /* TODO: pass this on to the HIL handler, or do SAK here? */ 292 /* TODO: pass this on to the HIL handler, or do SAK here? */
293 printk(KERN_WARNING PREFIX "HIL NMI\n"); 293 printk(KERN_WARNING PREFIX "HIL NMI\n");
294 } 294 }
295 #endif 295 #endif
296 296
297 return IRQ_HANDLED; 297 return IRQ_HANDLED;
298 } 298 }
299 299
300 300
301 /***************** Kernel (tasklet) context functions ****************/ 301 /***************** Kernel (tasklet) context functions ****************/
302 302
303 unsigned long hp_sdc_put(void); 303 unsigned long hp_sdc_put(void);
304 304
305 static void hp_sdc_tasklet(unsigned long foo) 305 static void hp_sdc_tasklet(unsigned long foo)
306 { 306 {
307 write_lock_irq(&hp_sdc.rtq_lock); 307 write_lock_irq(&hp_sdc.rtq_lock);
308 308
309 if (hp_sdc.rcurr >= 0) { 309 if (hp_sdc.rcurr >= 0) {
310 struct timeval tv; 310 struct timeval tv;
311 311
312 do_gettimeofday(&tv); 312 do_gettimeofday(&tv);
313 if (tv.tv_sec > hp_sdc.rtv.tv_sec) 313 if (tv.tv_sec > hp_sdc.rtv.tv_sec)
314 tv.tv_usec += USEC_PER_SEC; 314 tv.tv_usec += USEC_PER_SEC;
315 315
316 if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) { 316 if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
317 hp_sdc_transaction *curr; 317 hp_sdc_transaction *curr;
318 uint8_t tmp; 318 uint8_t tmp;
319 319
320 curr = hp_sdc.tq[hp_sdc.rcurr]; 320 curr = hp_sdc.tq[hp_sdc.rcurr];
321 /* If this turns out to be a normal failure mode 321 /* If this turns out to be a normal failure mode
322 * we'll need to figure out a way to communicate 322 * we'll need to figure out a way to communicate
323 * it back to the application. and be less verbose. 323 * it back to the application. and be less verbose.
324 */ 324 */
325 printk(KERN_WARNING PREFIX "read timeout (%ius)!\n", 325 printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
326 tv.tv_usec - hp_sdc.rtv.tv_usec); 326 (int)(tv.tv_usec - hp_sdc.rtv.tv_usec));
327 curr->idx += hp_sdc.rqty; 327 curr->idx += hp_sdc.rqty;
328 hp_sdc.rqty = 0; 328 hp_sdc.rqty = 0;
329 tmp = curr->seq[curr->actidx]; 329 tmp = curr->seq[curr->actidx];
330 curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD; 330 curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD;
331 if (tmp & HP_SDC_ACT_SEMAPHORE) 331 if (tmp & HP_SDC_ACT_SEMAPHORE)
332 if (curr->act.semaphore) 332 if (curr->act.semaphore)
333 up(curr->act.semaphore); 333 up(curr->act.semaphore);
334 334
335 if (tmp & HP_SDC_ACT_CALLBACK) { 335 if (tmp & HP_SDC_ACT_CALLBACK) {
336 /* Note this means that irqhooks may be called 336 /* Note this means that irqhooks may be called
337 * in tasklet/bh context. 337 * in tasklet/bh context.
338 */ 338 */
339 if (curr->act.irqhook) 339 if (curr->act.irqhook)
340 curr->act.irqhook(0, NULL, 0, 0); 340 curr->act.irqhook(0, NULL, 0, 0);
341 } 341 }
342 342
343 curr->actidx = curr->idx; 343 curr->actidx = curr->idx;
344 curr->idx++; 344 curr->idx++;
345 hp_sdc.rcurr = -1; 345 hp_sdc.rcurr = -1;
346 } 346 }
347 } 347 }
348 write_unlock_irq(&hp_sdc.rtq_lock); 348 write_unlock_irq(&hp_sdc.rtq_lock);
349 hp_sdc_put(); 349 hp_sdc_put();
350 } 350 }
351 351
352 unsigned long hp_sdc_put(void) 352 unsigned long hp_sdc_put(void)
353 { 353 {
354 hp_sdc_transaction *curr; 354 hp_sdc_transaction *curr;
355 uint8_t act; 355 uint8_t act;
356 int idx, curridx; 356 int idx, curridx;
357 357
358 int limit = 0; 358 int limit = 0;
359 359
360 write_lock(&hp_sdc.lock); 360 write_lock(&hp_sdc.lock);
361 361
362 /* If i8042 buffers are full, we cannot do anything that 362 /* If i8042 buffers are full, we cannot do anything that
363 requires output, so we skip to the administrativa. */ 363 requires output, so we skip to the administrativa. */
364 if (hp_sdc.ibf) { 364 if (hp_sdc.ibf) {
365 hp_sdc_status_in8(); 365 hp_sdc_status_in8();
366 if (hp_sdc.ibf) 366 if (hp_sdc.ibf)
367 goto finish; 367 goto finish;
368 } 368 }
369 369
370 anew: 370 anew:
371 /* See if we are in the middle of a sequence. */ 371 /* See if we are in the middle of a sequence. */
372 if (hp_sdc.wcurr < 0) 372 if (hp_sdc.wcurr < 0)
373 hp_sdc.wcurr = 0; 373 hp_sdc.wcurr = 0;
374 read_lock_irq(&hp_sdc.rtq_lock); 374 read_lock_irq(&hp_sdc.rtq_lock);
375 if (hp_sdc.rcurr == hp_sdc.wcurr) 375 if (hp_sdc.rcurr == hp_sdc.wcurr)
376 hp_sdc.wcurr++; 376 hp_sdc.wcurr++;
377 read_unlock_irq(&hp_sdc.rtq_lock); 377 read_unlock_irq(&hp_sdc.rtq_lock);
378 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) 378 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
379 hp_sdc.wcurr = 0; 379 hp_sdc.wcurr = 0;
380 curridx = hp_sdc.wcurr; 380 curridx = hp_sdc.wcurr;
381 381
382 if (hp_sdc.tq[curridx] != NULL) 382 if (hp_sdc.tq[curridx] != NULL)
383 goto start; 383 goto start;
384 384
385 while (++curridx != hp_sdc.wcurr) { 385 while (++curridx != hp_sdc.wcurr) {
386 if (curridx >= HP_SDC_QUEUE_LEN) { 386 if (curridx >= HP_SDC_QUEUE_LEN) {
387 curridx = -1; /* Wrap to top */ 387 curridx = -1; /* Wrap to top */
388 continue; 388 continue;
389 } 389 }
390 read_lock_irq(&hp_sdc.rtq_lock); 390 read_lock_irq(&hp_sdc.rtq_lock);
391 if (hp_sdc.rcurr == curridx) { 391 if (hp_sdc.rcurr == curridx) {
392 read_unlock_irq(&hp_sdc.rtq_lock); 392 read_unlock_irq(&hp_sdc.rtq_lock);
393 continue; 393 continue;
394 } 394 }
395 read_unlock_irq(&hp_sdc.rtq_lock); 395 read_unlock_irq(&hp_sdc.rtq_lock);
396 if (hp_sdc.tq[curridx] != NULL) 396 if (hp_sdc.tq[curridx] != NULL)
397 break; /* Found one. */ 397 break; /* Found one. */
398 } 398 }
399 if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */ 399 if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */
400 curridx = -1; 400 curridx = -1;
401 } 401 }
402 hp_sdc.wcurr = curridx; 402 hp_sdc.wcurr = curridx;
403 403
404 start: 404 start:
405 405
406 /* Check to see if the interrupt mask needs to be set. */ 406 /* Check to see if the interrupt mask needs to be set. */
407 if (hp_sdc.set_im) { 407 if (hp_sdc.set_im) {
408 hp_sdc_status_out8(hp_sdc.im | HP_SDC_CMD_SET_IM); 408 hp_sdc_status_out8(hp_sdc.im | HP_SDC_CMD_SET_IM);
409 hp_sdc.set_im = 0; 409 hp_sdc.set_im = 0;
410 goto finish; 410 goto finish;
411 } 411 }
412 412
413 if (hp_sdc.wcurr == -1) 413 if (hp_sdc.wcurr == -1)
414 goto done; 414 goto done;
415 415
416 curr = hp_sdc.tq[curridx]; 416 curr = hp_sdc.tq[curridx];
417 idx = curr->actidx; 417 idx = curr->actidx;
418 418
419 if (curr->actidx >= curr->endidx) { 419 if (curr->actidx >= curr->endidx) {
420 hp_sdc.tq[curridx] = NULL; 420 hp_sdc.tq[curridx] = NULL;
421 /* Interleave outbound data between the transactions. */ 421 /* Interleave outbound data between the transactions. */
422 hp_sdc.wcurr++; 422 hp_sdc.wcurr++;
423 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) 423 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
424 hp_sdc.wcurr = 0; 424 hp_sdc.wcurr = 0;
425 goto finish; 425 goto finish;
426 } 426 }
427 427
428 act = curr->seq[idx]; 428 act = curr->seq[idx];
429 idx++; 429 idx++;
430 430
431 if (curr->idx >= curr->endidx) { 431 if (curr->idx >= curr->endidx) {
432 if (act & HP_SDC_ACT_DEALLOC) 432 if (act & HP_SDC_ACT_DEALLOC)
433 kfree(curr); 433 kfree(curr);
434 hp_sdc.tq[curridx] = NULL; 434 hp_sdc.tq[curridx] = NULL;
435 /* Interleave outbound data between the transactions. */ 435 /* Interleave outbound data between the transactions. */
436 hp_sdc.wcurr++; 436 hp_sdc.wcurr++;
437 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) 437 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
438 hp_sdc.wcurr = 0; 438 hp_sdc.wcurr = 0;
439 goto finish; 439 goto finish;
440 } 440 }
441 441
442 while (act & HP_SDC_ACT_PRECMD) { 442 while (act & HP_SDC_ACT_PRECMD) {
443 if (curr->idx != idx) { 443 if (curr->idx != idx) {
444 idx++; 444 idx++;
445 act &= ~HP_SDC_ACT_PRECMD; 445 act &= ~HP_SDC_ACT_PRECMD;
446 break; 446 break;
447 } 447 }
448 hp_sdc_status_out8(curr->seq[idx]); 448 hp_sdc_status_out8(curr->seq[idx]);
449 curr->idx++; 449 curr->idx++;
450 /* act finished? */ 450 /* act finished? */
451 if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD) 451 if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD)
452 goto actdone; 452 goto actdone;
453 /* skip quantity field if data-out sequence follows. */ 453 /* skip quantity field if data-out sequence follows. */
454 if (act & HP_SDC_ACT_DATAOUT) 454 if (act & HP_SDC_ACT_DATAOUT)
455 curr->idx++; 455 curr->idx++;
456 goto finish; 456 goto finish;
457 } 457 }
458 if (act & HP_SDC_ACT_DATAOUT) { 458 if (act & HP_SDC_ACT_DATAOUT) {
459 int qty; 459 int qty;
460 460
461 qty = curr->seq[idx]; 461 qty = curr->seq[idx];
462 idx++; 462 idx++;
463 if (curr->idx - idx < qty) { 463 if (curr->idx - idx < qty) {
464 hp_sdc_data_out8(curr->seq[curr->idx]); 464 hp_sdc_data_out8(curr->seq[curr->idx]);
465 curr->idx++; 465 curr->idx++;
466 /* act finished? */ 466 /* act finished? */
467 if (curr->idx - idx >= qty && 467 if (curr->idx - idx >= qty &&
468 (act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT) 468 (act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT)
469 goto actdone; 469 goto actdone;
470 goto finish; 470 goto finish;
471 } 471 }
472 idx += qty; 472 idx += qty;
473 act &= ~HP_SDC_ACT_DATAOUT; 473 act &= ~HP_SDC_ACT_DATAOUT;
474 } else 474 } else
475 while (act & HP_SDC_ACT_DATAREG) { 475 while (act & HP_SDC_ACT_DATAREG) {
476 int mask; 476 int mask;
477 uint8_t w7[4]; 477 uint8_t w7[4];
478 478
479 mask = curr->seq[idx]; 479 mask = curr->seq[idx];
480 if (idx != curr->idx) { 480 if (idx != curr->idx) {
481 idx++; 481 idx++;
482 idx += !!(mask & 1); 482 idx += !!(mask & 1);
483 idx += !!(mask & 2); 483 idx += !!(mask & 2);
484 idx += !!(mask & 4); 484 idx += !!(mask & 4);
485 idx += !!(mask & 8); 485 idx += !!(mask & 8);
486 act &= ~HP_SDC_ACT_DATAREG; 486 act &= ~HP_SDC_ACT_DATAREG;
487 break; 487 break;
488 } 488 }
489 489
490 w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0]; 490 w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0];
491 w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1]; 491 w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1];
492 w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2]; 492 w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2];
493 w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3]; 493 w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3];
494 494
495 if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 || 495 if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 ||
496 w7[hp_sdc.wi - 0x70] == hp_sdc.r7[hp_sdc.wi - 0x70]) { 496 w7[hp_sdc.wi - 0x70] == hp_sdc.r7[hp_sdc.wi - 0x70]) {
497 int i = 0; 497 int i = 0;
498 498
499 /* Need to point the write index register */ 499 /* Need to point the write index register */
500 while (i < 4 && w7[i] == hp_sdc.r7[i]) 500 while (i < 4 && w7[i] == hp_sdc.r7[i])
501 i++; 501 i++;
502 502
503 if (i < 4) { 503 if (i < 4) {
504 hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i); 504 hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i);
505 hp_sdc.wi = 0x70 + i; 505 hp_sdc.wi = 0x70 + i;
506 goto finish; 506 goto finish;
507 } 507 }
508 508
509 idx++; 509 idx++;
510 if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG) 510 if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG)
511 goto actdone; 511 goto actdone;
512 512
513 curr->idx = idx; 513 curr->idx = idx;
514 act &= ~HP_SDC_ACT_DATAREG; 514 act &= ~HP_SDC_ACT_DATAREG;
515 break; 515 break;
516 } 516 }
517 517
518 hp_sdc_data_out8(w7[hp_sdc.wi - 0x70]); 518 hp_sdc_data_out8(w7[hp_sdc.wi - 0x70]);
519 hp_sdc.r7[hp_sdc.wi - 0x70] = w7[hp_sdc.wi - 0x70]; 519 hp_sdc.r7[hp_sdc.wi - 0x70] = w7[hp_sdc.wi - 0x70];
520 hp_sdc.wi++; /* write index register autoincrements */ 520 hp_sdc.wi++; /* write index register autoincrements */
521 { 521 {
522 int i = 0; 522 int i = 0;
523 523
524 while ((i < 4) && w7[i] == hp_sdc.r7[i]) 524 while ((i < 4) && w7[i] == hp_sdc.r7[i])
525 i++; 525 i++;
526 if (i >= 4) { 526 if (i >= 4) {
527 curr->idx = idx + 1; 527 curr->idx = idx + 1;
528 if ((act & HP_SDC_ACT_DURING) == 528 if ((act & HP_SDC_ACT_DURING) ==
529 HP_SDC_ACT_DATAREG) 529 HP_SDC_ACT_DATAREG)
530 goto actdone; 530 goto actdone;
531 } 531 }
532 } 532 }
533 goto finish; 533 goto finish;
534 } 534 }
535 /* We don't go any further in the command if there is a pending read, 535 /* We don't go any further in the command if there is a pending read,
536 because we don't want interleaved results. */ 536 because we don't want interleaved results. */
537 read_lock_irq(&hp_sdc.rtq_lock); 537 read_lock_irq(&hp_sdc.rtq_lock);
538 if (hp_sdc.rcurr >= 0) { 538 if (hp_sdc.rcurr >= 0) {
539 read_unlock_irq(&hp_sdc.rtq_lock); 539 read_unlock_irq(&hp_sdc.rtq_lock);
540 goto finish; 540 goto finish;
541 } 541 }
542 read_unlock_irq(&hp_sdc.rtq_lock); 542 read_unlock_irq(&hp_sdc.rtq_lock);
543 543
544 544
545 if (act & HP_SDC_ACT_POSTCMD) { 545 if (act & HP_SDC_ACT_POSTCMD) {
546 uint8_t postcmd; 546 uint8_t postcmd;
547 547
548 /* curr->idx should == idx at this point. */ 548 /* curr->idx should == idx at this point. */
549 postcmd = curr->seq[idx]; 549 postcmd = curr->seq[idx];
550 curr->idx++; 550 curr->idx++;
551 if (act & HP_SDC_ACT_DATAIN) { 551 if (act & HP_SDC_ACT_DATAIN) {
552 552
553 /* Start a new read */ 553 /* Start a new read */
554 hp_sdc.rqty = curr->seq[curr->idx]; 554 hp_sdc.rqty = curr->seq[curr->idx];
555 do_gettimeofday(&hp_sdc.rtv); 555 do_gettimeofday(&hp_sdc.rtv);
556 curr->idx++; 556 curr->idx++;
557 /* Still need to lock here in case of spurious irq. */ 557 /* Still need to lock here in case of spurious irq. */
558 write_lock_irq(&hp_sdc.rtq_lock); 558 write_lock_irq(&hp_sdc.rtq_lock);
559 hp_sdc.rcurr = curridx; 559 hp_sdc.rcurr = curridx;
560 write_unlock_irq(&hp_sdc.rtq_lock); 560 write_unlock_irq(&hp_sdc.rtq_lock);
561 hp_sdc_status_out8(postcmd); 561 hp_sdc_status_out8(postcmd);
562 goto finish; 562 goto finish;
563 } 563 }
564 hp_sdc_status_out8(postcmd); 564 hp_sdc_status_out8(postcmd);
565 goto actdone; 565 goto actdone;
566 } 566 }
567 567
568 actdone: 568 actdone:
569 if (act & HP_SDC_ACT_SEMAPHORE) 569 if (act & HP_SDC_ACT_SEMAPHORE)
570 up(curr->act.semaphore); 570 up(curr->act.semaphore);
571 else if (act & HP_SDC_ACT_CALLBACK) 571 else if (act & HP_SDC_ACT_CALLBACK)
572 curr->act.irqhook(0,NULL,0,0); 572 curr->act.irqhook(0,NULL,0,0);
573 573
574 if (curr->idx >= curr->endidx) { /* This transaction is over. */ 574 if (curr->idx >= curr->endidx) { /* This transaction is over. */
575 if (act & HP_SDC_ACT_DEALLOC) 575 if (act & HP_SDC_ACT_DEALLOC)
576 kfree(curr); 576 kfree(curr);
577 hp_sdc.tq[curridx] = NULL; 577 hp_sdc.tq[curridx] = NULL;
578 } else { 578 } else {
579 curr->actidx = idx + 1; 579 curr->actidx = idx + 1;
580 curr->idx = idx + 2; 580 curr->idx = idx + 2;
581 } 581 }
582 /* Interleave outbound data between the transactions. */ 582 /* Interleave outbound data between the transactions. */
583 hp_sdc.wcurr++; 583 hp_sdc.wcurr++;
584 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) 584 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
585 hp_sdc.wcurr = 0; 585 hp_sdc.wcurr = 0;
586 586
587 finish: 587 finish:
588 /* If by some quirk IBF has cleared and our ISR has run to 588 /* If by some quirk IBF has cleared and our ISR has run to
589 see that that has happened, do it all again. */ 589 see that that has happened, do it all again. */
590 if (!hp_sdc.ibf && limit++ < 20) 590 if (!hp_sdc.ibf && limit++ < 20)
591 goto anew; 591 goto anew;
592 592
593 done: 593 done:
594 if (hp_sdc.wcurr >= 0) 594 if (hp_sdc.wcurr >= 0)
595 tasklet_schedule(&hp_sdc.task); 595 tasklet_schedule(&hp_sdc.task);
596 write_unlock(&hp_sdc.lock); 596 write_unlock(&hp_sdc.lock);
597 597
598 return 0; 598 return 0;
599 } 599 }
600 600
601 /******* Functions called in either user or kernel context ****/ 601 /******* Functions called in either user or kernel context ****/
602 int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this) 602 int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this)
603 { 603 {
604 int i; 604 int i;
605 605
606 if (this == NULL) { 606 if (this == NULL) {
607 BUG(); 607 BUG();
608 return -EINVAL; 608 return -EINVAL;
609 } 609 }
610 610
611 /* Can't have same transaction on queue twice */ 611 /* Can't have same transaction on queue twice */
612 for (i = 0; i < HP_SDC_QUEUE_LEN; i++) 612 for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
613 if (hp_sdc.tq[i] == this) 613 if (hp_sdc.tq[i] == this)
614 goto fail; 614 goto fail;
615 615
616 this->actidx = 0; 616 this->actidx = 0;
617 this->idx = 1; 617 this->idx = 1;
618 618
619 /* Search for empty slot */ 619 /* Search for empty slot */
620 for (i = 0; i < HP_SDC_QUEUE_LEN; i++) 620 for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
621 if (hp_sdc.tq[i] == NULL) { 621 if (hp_sdc.tq[i] == NULL) {
622 hp_sdc.tq[i] = this; 622 hp_sdc.tq[i] = this;
623 tasklet_schedule(&hp_sdc.task); 623 tasklet_schedule(&hp_sdc.task);
624 return 0; 624 return 0;
625 } 625 }
626 626
627 printk(KERN_WARNING PREFIX "No free slot to add transaction.\n"); 627 printk(KERN_WARNING PREFIX "No free slot to add transaction.\n");
628 return -EBUSY; 628 return -EBUSY;
629 629
630 fail: 630 fail:
631 printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n"); 631 printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n");
632 return -EINVAL; 632 return -EINVAL;
633 } 633 }
634 634
635 int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) { 635 int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
636 unsigned long flags; 636 unsigned long flags;
637 int ret; 637 int ret;
638 638
639 write_lock_irqsave(&hp_sdc.lock, flags); 639 write_lock_irqsave(&hp_sdc.lock, flags);
640 ret = __hp_sdc_enqueue_transaction(this); 640 ret = __hp_sdc_enqueue_transaction(this);
641 write_unlock_irqrestore(&hp_sdc.lock,flags); 641 write_unlock_irqrestore(&hp_sdc.lock,flags);
642 642
643 return ret; 643 return ret;
644 } 644 }
645 645
646 int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) 646 int hp_sdc_dequeue_transaction(hp_sdc_transaction *this)
647 { 647 {
648 unsigned long flags; 648 unsigned long flags;
649 int i; 649 int i;
650 650
651 write_lock_irqsave(&hp_sdc.lock, flags); 651 write_lock_irqsave(&hp_sdc.lock, flags);
652 652
653 /* TODO: don't remove it if it's not done. */ 653 /* TODO: don't remove it if it's not done. */
654 654
655 for (i = 0; i < HP_SDC_QUEUE_LEN; i++) 655 for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
656 if (hp_sdc.tq[i] == this) 656 if (hp_sdc.tq[i] == this)
657 hp_sdc.tq[i] = NULL; 657 hp_sdc.tq[i] = NULL;
658 658
659 write_unlock_irqrestore(&hp_sdc.lock, flags); 659 write_unlock_irqrestore(&hp_sdc.lock, flags);
660 return 0; 660 return 0;
661 } 661 }
662 662
663 663
664 664
665 /********************** User context functions **************************/ 665 /********************** User context functions **************************/
666 int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) 666 int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback)
667 { 667 {
668 if (callback == NULL || hp_sdc.dev == NULL) 668 if (callback == NULL || hp_sdc.dev == NULL)
669 return -EINVAL; 669 return -EINVAL;
670 670
671 write_lock_irq(&hp_sdc.hook_lock); 671 write_lock_irq(&hp_sdc.hook_lock);
672 if (hp_sdc.timer != NULL) { 672 if (hp_sdc.timer != NULL) {
673 write_unlock_irq(&hp_sdc.hook_lock); 673 write_unlock_irq(&hp_sdc.hook_lock);
674 return -EBUSY; 674 return -EBUSY;
675 } 675 }
676 676
677 hp_sdc.timer = callback; 677 hp_sdc.timer = callback;
678 /* Enable interrupts from the timers */ 678 /* Enable interrupts from the timers */
679 hp_sdc.im &= ~HP_SDC_IM_FH; 679 hp_sdc.im &= ~HP_SDC_IM_FH;
680 hp_sdc.im &= ~HP_SDC_IM_PT; 680 hp_sdc.im &= ~HP_SDC_IM_PT;
681 hp_sdc.im &= ~HP_SDC_IM_TIMERS; 681 hp_sdc.im &= ~HP_SDC_IM_TIMERS;
682 hp_sdc.set_im = 1; 682 hp_sdc.set_im = 1;
683 write_unlock_irq(&hp_sdc.hook_lock); 683 write_unlock_irq(&hp_sdc.hook_lock);
684 684
685 tasklet_schedule(&hp_sdc.task); 685 tasklet_schedule(&hp_sdc.task);
686 686
687 return 0; 687 return 0;
688 } 688 }
689 689
690 int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) 690 int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback)
691 { 691 {
692 if (callback == NULL || hp_sdc.dev == NULL) 692 if (callback == NULL || hp_sdc.dev == NULL)
693 return -EINVAL; 693 return -EINVAL;
694 694
695 write_lock_irq(&hp_sdc.hook_lock); 695 write_lock_irq(&hp_sdc.hook_lock);
696 if (hp_sdc.hil != NULL) { 696 if (hp_sdc.hil != NULL) {
697 write_unlock_irq(&hp_sdc.hook_lock); 697 write_unlock_irq(&hp_sdc.hook_lock);
698 return -EBUSY; 698 return -EBUSY;
699 } 699 }
700 700
701 hp_sdc.hil = callback; 701 hp_sdc.hil = callback;
702 hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET); 702 hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
703 hp_sdc.set_im = 1; 703 hp_sdc.set_im = 1;
704 write_unlock_irq(&hp_sdc.hook_lock); 704 write_unlock_irq(&hp_sdc.hook_lock);
705 705
706 tasklet_schedule(&hp_sdc.task); 706 tasklet_schedule(&hp_sdc.task);
707 707
708 return 0; 708 return 0;
709 } 709 }
710 710
711 int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) 711 int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback)
712 { 712 {
713 if (callback == NULL || hp_sdc.dev == NULL) 713 if (callback == NULL || hp_sdc.dev == NULL)
714 return -EINVAL; 714 return -EINVAL;
715 715
716 write_lock_irq(&hp_sdc.hook_lock); 716 write_lock_irq(&hp_sdc.hook_lock);
717 if (hp_sdc.cooked != NULL) { 717 if (hp_sdc.cooked != NULL) {
718 write_unlock_irq(&hp_sdc.hook_lock); 718 write_unlock_irq(&hp_sdc.hook_lock);
719 return -EBUSY; 719 return -EBUSY;
720 } 720 }
721 721
722 /* Enable interrupts from the HIL MLC */ 722 /* Enable interrupts from the HIL MLC */
723 hp_sdc.cooked = callback; 723 hp_sdc.cooked = callback;
724 hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET); 724 hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
725 hp_sdc.set_im = 1; 725 hp_sdc.set_im = 1;
726 write_unlock_irq(&hp_sdc.hook_lock); 726 write_unlock_irq(&hp_sdc.hook_lock);
727 727
728 tasklet_schedule(&hp_sdc.task); 728 tasklet_schedule(&hp_sdc.task);
729 729
730 return 0; 730 return 0;
731 } 731 }
732 732
733 int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) 733 int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback)
734 { 734 {
735 write_lock_irq(&hp_sdc.hook_lock); 735 write_lock_irq(&hp_sdc.hook_lock);
736 if ((callback != hp_sdc.timer) || 736 if ((callback != hp_sdc.timer) ||
737 (hp_sdc.timer == NULL)) { 737 (hp_sdc.timer == NULL)) {
738 write_unlock_irq(&hp_sdc.hook_lock); 738 write_unlock_irq(&hp_sdc.hook_lock);
739 return -EINVAL; 739 return -EINVAL;
740 } 740 }
741 741
742 /* Disable interrupts from the timers */ 742 /* Disable interrupts from the timers */
743 hp_sdc.timer = NULL; 743 hp_sdc.timer = NULL;
744 hp_sdc.im |= HP_SDC_IM_TIMERS; 744 hp_sdc.im |= HP_SDC_IM_TIMERS;
745 hp_sdc.im |= HP_SDC_IM_FH; 745 hp_sdc.im |= HP_SDC_IM_FH;
746 hp_sdc.im |= HP_SDC_IM_PT; 746 hp_sdc.im |= HP_SDC_IM_PT;
747 hp_sdc.set_im = 1; 747 hp_sdc.set_im = 1;
748 write_unlock_irq(&hp_sdc.hook_lock); 748 write_unlock_irq(&hp_sdc.hook_lock);
749 tasklet_schedule(&hp_sdc.task); 749 tasklet_schedule(&hp_sdc.task);
750 750
751 return 0; 751 return 0;
752 } 752 }
753 753
754 int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) 754 int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback)
755 { 755 {
756 write_lock_irq(&hp_sdc.hook_lock); 756 write_lock_irq(&hp_sdc.hook_lock);
757 if ((callback != hp_sdc.hil) || 757 if ((callback != hp_sdc.hil) ||
758 (hp_sdc.hil == NULL)) { 758 (hp_sdc.hil == NULL)) {
759 write_unlock_irq(&hp_sdc.hook_lock); 759 write_unlock_irq(&hp_sdc.hook_lock);
760 return -EINVAL; 760 return -EINVAL;
761 } 761 }
762 762
763 hp_sdc.hil = NULL; 763 hp_sdc.hil = NULL;
764 /* Disable interrupts from HIL only if there is no cooked driver. */ 764 /* Disable interrupts from HIL only if there is no cooked driver. */
765 if(hp_sdc.cooked == NULL) { 765 if(hp_sdc.cooked == NULL) {
766 hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET); 766 hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
767 hp_sdc.set_im = 1; 767 hp_sdc.set_im = 1;
768 } 768 }
769 write_unlock_irq(&hp_sdc.hook_lock); 769 write_unlock_irq(&hp_sdc.hook_lock);
770 tasklet_schedule(&hp_sdc.task); 770 tasklet_schedule(&hp_sdc.task);
771 771
772 return 0; 772 return 0;
773 } 773 }
774 774
775 int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) 775 int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
776 { 776 {
777 write_lock_irq(&hp_sdc.hook_lock); 777 write_lock_irq(&hp_sdc.hook_lock);
778 if ((callback != hp_sdc.cooked) || 778 if ((callback != hp_sdc.cooked) ||
779 (hp_sdc.cooked == NULL)) { 779 (hp_sdc.cooked == NULL)) {
780 write_unlock_irq(&hp_sdc.hook_lock); 780 write_unlock_irq(&hp_sdc.hook_lock);
781 return -EINVAL; 781 return -EINVAL;
782 } 782 }
783 783
784 hp_sdc.cooked = NULL; 784 hp_sdc.cooked = NULL;
785 /* Disable interrupts from HIL only if there is no raw HIL driver. */ 785 /* Disable interrupts from HIL only if there is no raw HIL driver. */
786 if(hp_sdc.hil == NULL) { 786 if(hp_sdc.hil == NULL) {
787 hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET); 787 hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
788 hp_sdc.set_im = 1; 788 hp_sdc.set_im = 1;
789 } 789 }
790 write_unlock_irq(&hp_sdc.hook_lock); 790 write_unlock_irq(&hp_sdc.hook_lock);
791 tasklet_schedule(&hp_sdc.task); 791 tasklet_schedule(&hp_sdc.task);
792 792
793 return 0; 793 return 0;
794 } 794 }
795 795
796 /************************* Keepalive timer task *********************/ 796 /************************* Keepalive timer task *********************/
797 797
798 void hp_sdc_kicker (unsigned long data) 798 void hp_sdc_kicker (unsigned long data)
799 { 799 {
800 tasklet_schedule(&hp_sdc.task); 800 tasklet_schedule(&hp_sdc.task);
801 /* Re-insert the periodic task. */ 801 /* Re-insert the periodic task. */
802 mod_timer(&hp_sdc.kicker, jiffies + HZ); 802 mod_timer(&hp_sdc.kicker, jiffies + HZ);
803 } 803 }
804 804
805 /************************** Module Initialization ***************************/ 805 /************************** Module Initialization ***************************/
806 806
807 #if defined(__hppa__) 807 #if defined(__hppa__)
808 808
809 static const struct parisc_device_id hp_sdc_tbl[] = { 809 static const struct parisc_device_id hp_sdc_tbl[] = {
810 { 810 {
811 .hw_type = HPHW_FIO, 811 .hw_type = HPHW_FIO,
812 .hversion_rev = HVERSION_REV_ANY_ID, 812 .hversion_rev = HVERSION_REV_ANY_ID,
813 .hversion = HVERSION_ANY_ID, 813 .hversion = HVERSION_ANY_ID,
814 .sversion = 0x73, 814 .sversion = 0x73,
815 }, 815 },
816 { 0, } 816 { 0, }
817 }; 817 };
818 818
819 MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl); 819 MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl);
820 820
821 static int __init hp_sdc_init_hppa(struct parisc_device *d); 821 static int __init hp_sdc_init_hppa(struct parisc_device *d);
822 822
823 static struct parisc_driver hp_sdc_driver = { 823 static struct parisc_driver hp_sdc_driver = {
824 .name = "hp_sdc", 824 .name = "hp_sdc",
825 .id_table = hp_sdc_tbl, 825 .id_table = hp_sdc_tbl,
826 .probe = hp_sdc_init_hppa, 826 .probe = hp_sdc_init_hppa,
827 }; 827 };
828 828
829 #endif /* __hppa__ */ 829 #endif /* __hppa__ */
830 830
831 static int __init hp_sdc_init(void) 831 static int __init hp_sdc_init(void)
832 { 832 {
833 char *errstr; 833 char *errstr;
834 hp_sdc_transaction t_sync; 834 hp_sdc_transaction t_sync;
835 uint8_t ts_sync[6]; 835 uint8_t ts_sync[6];
836 struct semaphore s_sync; 836 struct semaphore s_sync;
837 837
838 rwlock_init(&hp_sdc.lock); 838 rwlock_init(&hp_sdc.lock);
839 rwlock_init(&hp_sdc.ibf_lock); 839 rwlock_init(&hp_sdc.ibf_lock);
840 rwlock_init(&hp_sdc.rtq_lock); 840 rwlock_init(&hp_sdc.rtq_lock);
841 rwlock_init(&hp_sdc.hook_lock); 841 rwlock_init(&hp_sdc.hook_lock);
842 842
843 hp_sdc.timer = NULL; 843 hp_sdc.timer = NULL;
844 hp_sdc.hil = NULL; 844 hp_sdc.hil = NULL;
845 hp_sdc.pup = NULL; 845 hp_sdc.pup = NULL;
846 hp_sdc.cooked = NULL; 846 hp_sdc.cooked = NULL;
847 hp_sdc.im = HP_SDC_IM_MASK; /* Mask maskable irqs */ 847 hp_sdc.im = HP_SDC_IM_MASK; /* Mask maskable irqs */
848 hp_sdc.set_im = 1; 848 hp_sdc.set_im = 1;
849 hp_sdc.wi = 0xff; 849 hp_sdc.wi = 0xff;
850 hp_sdc.r7[0] = 0xff; 850 hp_sdc.r7[0] = 0xff;
851 hp_sdc.r7[1] = 0xff; 851 hp_sdc.r7[1] = 0xff;
852 hp_sdc.r7[2] = 0xff; 852 hp_sdc.r7[2] = 0xff;
853 hp_sdc.r7[3] = 0xff; 853 hp_sdc.r7[3] = 0xff;
854 hp_sdc.ibf = 1; 854 hp_sdc.ibf = 1;
855 855
856 memset(&hp_sdc.tq, 0, sizeof(hp_sdc.tq)); 856 memset(&hp_sdc.tq, 0, sizeof(hp_sdc.tq));
857 857
858 hp_sdc.wcurr = -1; 858 hp_sdc.wcurr = -1;
859 hp_sdc.rcurr = -1; 859 hp_sdc.rcurr = -1;
860 hp_sdc.rqty = 0; 860 hp_sdc.rqty = 0;
861 861
862 hp_sdc.dev_err = -ENODEV; 862 hp_sdc.dev_err = -ENODEV;
863 863
864 errstr = "IO not found for"; 864 errstr = "IO not found for";
865 if (!hp_sdc.base_io) 865 if (!hp_sdc.base_io)
866 goto err0; 866 goto err0;
867 867
868 errstr = "IRQ not found for"; 868 errstr = "IRQ not found for";
869 if (!hp_sdc.irq) 869 if (!hp_sdc.irq)
870 goto err0; 870 goto err0;
871 871
872 hp_sdc.dev_err = -EBUSY; 872 hp_sdc.dev_err = -EBUSY;
873 873
874 #if defined(__hppa__) 874 #if defined(__hppa__)
875 errstr = "IO not available for"; 875 errstr = "IO not available for";
876 if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) 876 if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name))
877 goto err0; 877 goto err0;
878 #endif 878 #endif
879 879
880 errstr = "IRQ not available for"; 880 errstr = "IRQ not available for";
881 if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM, 881 if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM,
882 "HP SDC", &hp_sdc)) 882 "HP SDC", &hp_sdc))
883 goto err1; 883 goto err1;
884 884
885 errstr = "NMI not available for"; 885 errstr = "NMI not available for";
886 if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, IRQF_SHARED, 886 if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, IRQF_SHARED,
887 "HP SDC NMI", &hp_sdc)) 887 "HP SDC NMI", &hp_sdc))
888 goto err2; 888 goto err2;
889 889
890 printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", 890 printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n",
891 (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi); 891 (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
892 892
893 hp_sdc_status_in8(); 893 hp_sdc_status_in8();
894 hp_sdc_data_in8(); 894 hp_sdc_data_in8();
895 895
896 tasklet_init(&hp_sdc.task, hp_sdc_tasklet, 0); 896 tasklet_init(&hp_sdc.task, hp_sdc_tasklet, 0);
897 897
898 /* Sync the output buffer registers, thus scheduling hp_sdc_tasklet. */ 898 /* Sync the output buffer registers, thus scheduling hp_sdc_tasklet. */
899 t_sync.actidx = 0; 899 t_sync.actidx = 0;
900 t_sync.idx = 1; 900 t_sync.idx = 1;
901 t_sync.endidx = 6; 901 t_sync.endidx = 6;
902 t_sync.seq = ts_sync; 902 t_sync.seq = ts_sync;
903 ts_sync[0] = HP_SDC_ACT_DATAREG | HP_SDC_ACT_SEMAPHORE; 903 ts_sync[0] = HP_SDC_ACT_DATAREG | HP_SDC_ACT_SEMAPHORE;
904 ts_sync[1] = 0x0f; 904 ts_sync[1] = 0x0f;
905 ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0; 905 ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0;
906 t_sync.act.semaphore = &s_sync; 906 t_sync.act.semaphore = &s_sync;
907 init_MUTEX_LOCKED(&s_sync); 907 init_MUTEX_LOCKED(&s_sync);
908 hp_sdc_enqueue_transaction(&t_sync); 908 hp_sdc_enqueue_transaction(&t_sync);
909 down(&s_sync); /* Wait for t_sync to complete */ 909 down(&s_sync); /* Wait for t_sync to complete */
910 910
911 /* Create the keepalive task */ 911 /* Create the keepalive task */
912 init_timer(&hp_sdc.kicker); 912 init_timer(&hp_sdc.kicker);
913 hp_sdc.kicker.expires = jiffies + HZ; 913 hp_sdc.kicker.expires = jiffies + HZ;
914 hp_sdc.kicker.function = &hp_sdc_kicker; 914 hp_sdc.kicker.function = &hp_sdc_kicker;
915 add_timer(&hp_sdc.kicker); 915 add_timer(&hp_sdc.kicker);
916 916
917 hp_sdc.dev_err = 0; 917 hp_sdc.dev_err = 0;
918 return 0; 918 return 0;
919 err2: 919 err2:
920 free_irq(hp_sdc.irq, &hp_sdc); 920 free_irq(hp_sdc.irq, &hp_sdc);
921 err1: 921 err1:
922 release_region(hp_sdc.data_io, 2); 922 release_region(hp_sdc.data_io, 2);
923 err0: 923 err0:
924 printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", 924 printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n",
925 errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi); 925 errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
926 hp_sdc.dev = NULL; 926 hp_sdc.dev = NULL;
927 927
928 return hp_sdc.dev_err; 928 return hp_sdc.dev_err;
929 } 929 }
930 930
931 #if defined(__hppa__) 931 #if defined(__hppa__)
932 932
933 static int __init hp_sdc_init_hppa(struct parisc_device *d) 933 static int __init hp_sdc_init_hppa(struct parisc_device *d)
934 { 934 {
935 if (!d) 935 if (!d)
936 return 1; 936 return 1;
937 if (hp_sdc.dev != NULL) 937 if (hp_sdc.dev != NULL)
938 return 1; /* We only expect one SDC */ 938 return 1; /* We only expect one SDC */
939 939
940 hp_sdc.dev = d; 940 hp_sdc.dev = d;
941 hp_sdc.irq = d->irq; 941 hp_sdc.irq = d->irq;
942 hp_sdc.nmi = d->aux_irq; 942 hp_sdc.nmi = d->aux_irq;
943 hp_sdc.base_io = d->hpa.start; 943 hp_sdc.base_io = d->hpa.start;
944 hp_sdc.data_io = d->hpa.start + 0x800; 944 hp_sdc.data_io = d->hpa.start + 0x800;
945 hp_sdc.status_io = d->hpa.start + 0x801; 945 hp_sdc.status_io = d->hpa.start + 0x801;
946 946
947 return hp_sdc_init(); 947 return hp_sdc_init();
948 } 948 }
949 949
950 #endif /* __hppa__ */ 950 #endif /* __hppa__ */
951 951
952 static void hp_sdc_exit(void) 952 static void hp_sdc_exit(void)
953 { 953 {
954 write_lock_irq(&hp_sdc.lock); 954 write_lock_irq(&hp_sdc.lock);
955 955
956 /* Turn off all maskable "sub-function" irq's. */ 956 /* Turn off all maskable "sub-function" irq's. */
957 hp_sdc_spin_ibf(); 957 hp_sdc_spin_ibf();
958 sdc_writeb(HP_SDC_CMD_SET_IM | HP_SDC_IM_MASK, hp_sdc.status_io); 958 sdc_writeb(HP_SDC_CMD_SET_IM | HP_SDC_IM_MASK, hp_sdc.status_io);
959 959
960 /* Wait until we know this has been processed by the i8042 */ 960 /* Wait until we know this has been processed by the i8042 */
961 hp_sdc_spin_ibf(); 961 hp_sdc_spin_ibf();
962 962
963 free_irq(hp_sdc.nmi, &hp_sdc); 963 free_irq(hp_sdc.nmi, &hp_sdc);
964 free_irq(hp_sdc.irq, &hp_sdc); 964 free_irq(hp_sdc.irq, &hp_sdc);
965 write_unlock_irq(&hp_sdc.lock); 965 write_unlock_irq(&hp_sdc.lock);
966 966
967 del_timer(&hp_sdc.kicker); 967 del_timer(&hp_sdc.kicker);
968 968
969 tasklet_kill(&hp_sdc.task); 969 tasklet_kill(&hp_sdc.task);
970 970
971 #if defined(__hppa__) 971 #if defined(__hppa__)
972 if (unregister_parisc_driver(&hp_sdc_driver)) 972 if (unregister_parisc_driver(&hp_sdc_driver))
973 printk(KERN_WARNING PREFIX "Error unregistering HP SDC"); 973 printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
974 #endif 974 #endif
975 } 975 }
976 976
977 static int __init hp_sdc_register(void) 977 static int __init hp_sdc_register(void)
978 { 978 {
979 hp_sdc_transaction tq_init; 979 hp_sdc_transaction tq_init;
980 uint8_t tq_init_seq[5]; 980 uint8_t tq_init_seq[5];
981 struct semaphore tq_init_sem; 981 struct semaphore tq_init_sem;
982 #if defined(__mc68000__) 982 #if defined(__mc68000__)
983 mm_segment_t fs; 983 mm_segment_t fs;
984 unsigned char i; 984 unsigned char i;
985 #endif 985 #endif
986 986
987 if (hp_sdc_disabled) { 987 if (hp_sdc_disabled) {
988 printk(KERN_WARNING PREFIX "HP SDC driver disabled by no_hpsdc=1.\n"); 988 printk(KERN_WARNING PREFIX "HP SDC driver disabled by no_hpsdc=1.\n");
989 return -ENODEV; 989 return -ENODEV;
990 } 990 }
991 991
992 hp_sdc.dev = NULL; 992 hp_sdc.dev = NULL;
993 hp_sdc.dev_err = 0; 993 hp_sdc.dev_err = 0;
994 #if defined(__hppa__) 994 #if defined(__hppa__)
995 if (register_parisc_driver(&hp_sdc_driver)) { 995 if (register_parisc_driver(&hp_sdc_driver)) {
996 printk(KERN_WARNING PREFIX "Error registering SDC with system bus tree.\n"); 996 printk(KERN_WARNING PREFIX "Error registering SDC with system bus tree.\n");
997 return -ENODEV; 997 return -ENODEV;
998 } 998 }
999 #elif defined(__mc68000__) 999 #elif defined(__mc68000__)
1000 if (!MACH_IS_HP300) 1000 if (!MACH_IS_HP300)
1001 return -ENODEV; 1001 return -ENODEV;
1002 1002
1003 hp_sdc.irq = 1; 1003 hp_sdc.irq = 1;
1004 hp_sdc.nmi = 7; 1004 hp_sdc.nmi = 7;
1005 hp_sdc.base_io = (unsigned long) 0xf0428000; 1005 hp_sdc.base_io = (unsigned long) 0xf0428000;
1006 hp_sdc.data_io = (unsigned long) hp_sdc.base_io + 1; 1006 hp_sdc.data_io = (unsigned long) hp_sdc.base_io + 1;
1007 hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3; 1007 hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3;
1008 fs = get_fs(); 1008 fs = get_fs();
1009 set_fs(KERNEL_DS); 1009 set_fs(KERNEL_DS);
1010 if (!get_user(i, (unsigned char *)hp_sdc.data_io)) 1010 if (!get_user(i, (unsigned char *)hp_sdc.data_io))
1011 hp_sdc.dev = (void *)1; 1011 hp_sdc.dev = (void *)1;
1012 set_fs(fs); 1012 set_fs(fs);
1013 hp_sdc.dev_err = hp_sdc_init(); 1013 hp_sdc.dev_err = hp_sdc_init();
1014 #endif 1014 #endif
1015 if (hp_sdc.dev == NULL) { 1015 if (hp_sdc.dev == NULL) {
1016 printk(KERN_WARNING PREFIX "No SDC found.\n"); 1016 printk(KERN_WARNING PREFIX "No SDC found.\n");
1017 return hp_sdc.dev_err; 1017 return hp_sdc.dev_err;
1018 } 1018 }
1019 1019
1020 init_MUTEX_LOCKED(&tq_init_sem); 1020 init_MUTEX_LOCKED(&tq_init_sem);
1021 1021
1022 tq_init.actidx = 0; 1022 tq_init.actidx = 0;
1023 tq_init.idx = 1; 1023 tq_init.idx = 1;
1024 tq_init.endidx = 5; 1024 tq_init.endidx = 5;
1025 tq_init.seq = tq_init_seq; 1025 tq_init.seq = tq_init_seq;
1026 tq_init.act.semaphore = &tq_init_sem; 1026 tq_init.act.semaphore = &tq_init_sem;
1027 1027
1028 tq_init_seq[0] = 1028 tq_init_seq[0] =
1029 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; 1029 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
1030 tq_init_seq[1] = HP_SDC_CMD_READ_KCC; 1030 tq_init_seq[1] = HP_SDC_CMD_READ_KCC;
1031 tq_init_seq[2] = 1; 1031 tq_init_seq[2] = 1;
1032 tq_init_seq[3] = 0; 1032 tq_init_seq[3] = 0;
1033 tq_init_seq[4] = 0; 1033 tq_init_seq[4] = 0;
1034 1034
1035 hp_sdc_enqueue_transaction(&tq_init); 1035 hp_sdc_enqueue_transaction(&tq_init);
1036 1036
1037 down(&tq_init_sem); 1037 down(&tq_init_sem);
1038 up(&tq_init_sem); 1038 up(&tq_init_sem);
1039 1039
1040 if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) { 1040 if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
1041 printk(KERN_WARNING PREFIX "Error reading config byte.\n"); 1041 printk(KERN_WARNING PREFIX "Error reading config byte.\n");
1042 hp_sdc_exit(); 1042 hp_sdc_exit();
1043 return -ENODEV; 1043 return -ENODEV;
1044 } 1044 }
1045 hp_sdc.r11 = tq_init_seq[4]; 1045 hp_sdc.r11 = tq_init_seq[4];
1046 if (hp_sdc.r11 & HP_SDC_CFG_NEW) { 1046 if (hp_sdc.r11 & HP_SDC_CFG_NEW) {
1047 const char *str; 1047 const char *str;
1048 printk(KERN_INFO PREFIX "New style SDC\n"); 1048 printk(KERN_INFO PREFIX "New style SDC\n");
1049 tq_init_seq[1] = HP_SDC_CMD_READ_XTD; 1049 tq_init_seq[1] = HP_SDC_CMD_READ_XTD;
1050 tq_init.actidx = 0; 1050 tq_init.actidx = 0;
1051 tq_init.idx = 1; 1051 tq_init.idx = 1;
1052 down(&tq_init_sem); 1052 down(&tq_init_sem);
1053 hp_sdc_enqueue_transaction(&tq_init); 1053 hp_sdc_enqueue_transaction(&tq_init);
1054 down(&tq_init_sem); 1054 down(&tq_init_sem);
1055 up(&tq_init_sem); 1055 up(&tq_init_sem);
1056 if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) { 1056 if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
1057 printk(KERN_WARNING PREFIX "Error reading extended config byte.\n"); 1057 printk(KERN_WARNING PREFIX "Error reading extended config byte.\n");
1058 return -ENODEV; 1058 return -ENODEV;
1059 } 1059 }
1060 hp_sdc.r7e = tq_init_seq[4]; 1060 hp_sdc.r7e = tq_init_seq[4];
1061 HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str) 1061 HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str)
1062 printk(KERN_INFO PREFIX "Revision: %s\n", str); 1062 printk(KERN_INFO PREFIX "Revision: %s\n", str);
1063 if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) 1063 if (hp_sdc.r7e & HP_SDC_XTD_BEEPER)
1064 printk(KERN_INFO PREFIX "TI SN76494 beeper present\n"); 1064 printk(KERN_INFO PREFIX "TI SN76494 beeper present\n");
1065 if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) 1065 if (hp_sdc.r7e & HP_SDC_XTD_BBRTC)
1066 printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n"); 1066 printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n");
1067 printk(KERN_INFO PREFIX "Spunking the self test register to force PUP " 1067 printk(KERN_INFO PREFIX "Spunking the self test register to force PUP "
1068 "on next firmware reset.\n"); 1068 "on next firmware reset.\n");
1069 tq_init_seq[0] = HP_SDC_ACT_PRECMD | 1069 tq_init_seq[0] = HP_SDC_ACT_PRECMD |
1070 HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; 1070 HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
1071 tq_init_seq[1] = HP_SDC_CMD_SET_STR; 1071 tq_init_seq[1] = HP_SDC_CMD_SET_STR;
1072 tq_init_seq[2] = 1; 1072 tq_init_seq[2] = 1;
1073 tq_init_seq[3] = 0; 1073 tq_init_seq[3] = 0;
1074 tq_init.actidx = 0; 1074 tq_init.actidx = 0;
1075 tq_init.idx = 1; 1075 tq_init.idx = 1;
1076 tq_init.endidx = 4; 1076 tq_init.endidx = 4;
1077 down(&tq_init_sem); 1077 down(&tq_init_sem);
1078 hp_sdc_enqueue_transaction(&tq_init); 1078 hp_sdc_enqueue_transaction(&tq_init);
1079 down(&tq_init_sem); 1079 down(&tq_init_sem);
1080 up(&tq_init_sem); 1080 up(&tq_init_sem);
1081 } else 1081 } else
1082 printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", 1082 printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n",
1083 (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087"); 1083 (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087");
1084 1084
1085 return 0; 1085 return 0;
1086 } 1086 }
1087 1087
1088 module_init(hp_sdc_register); 1088 module_init(hp_sdc_register);
1089 module_exit(hp_sdc_exit); 1089 module_exit(hp_sdc_exit);
1090 1090
1091 /* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64) 1091 /* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64)
1092 * cycles cycles-adj time 1092 * cycles cycles-adj time
1093 * between two consecutive mfctl(16)'s: 4 n/a 63ns 1093 * between two consecutive mfctl(16)'s: 4 n/a 63ns
1094 * hp_sdc_spin_ibf when idle: 119 115 1.7us 1094 * hp_sdc_spin_ibf when idle: 119 115 1.7us
1095 * gsc_writeb status register: 83 79 1.2us 1095 * gsc_writeb status register: 83 79 1.2us
1096 * IBF to clear after sending SET_IM: 6204 6006 93us 1096 * IBF to clear after sending SET_IM: 6204 6006 93us
1097 * IBF to clear after sending LOAD_RT: 4467 4352 68us 1097 * IBF to clear after sending LOAD_RT: 4467 4352 68us
1098 * IBF to clear after sending two LOAD_RTs: 18974 18859 295us 1098 * IBF to clear after sending two LOAD_RTs: 18974 18859 295us
1099 * READ_T1, read status/data, IRQ, call handler: 35564 n/a 556us 1099 * READ_T1, read status/data, IRQ, call handler: 35564 n/a 556us
1100 * cmd to ~IBF READ_T1 2nd time right after: 5158403 n/a 81ms 1100 * cmd to ~IBF READ_T1 2nd time right after: 5158403 n/a 81ms
1101 * between IRQ received and ~IBF for above: 2578877 n/a 40ms 1101 * between IRQ received and ~IBF for above: 2578877 n/a 40ms
1102 * 1102 *
1103 * Performance stats after a run of this module configuring HIL and 1103 * Performance stats after a run of this module configuring HIL and
1104 * receiving a few mouse events: 1104 * receiving a few mouse events:
1105 * 1105 *
1106 * status in8 282508 cycles 7128 calls 1106 * status in8 282508 cycles 7128 calls
1107 * status out8 8404 cycles 341 calls 1107 * status out8 8404 cycles 341 calls
1108 * data out8 1734 cycles 78 calls 1108 * data out8 1734 cycles 78 calls
1109 * isr 174324 cycles 617 calls (includes take) 1109 * isr 174324 cycles 617 calls (includes take)
1110 * take 1241 cycles 2 calls 1110 * take 1241 cycles 2 calls
1111 * put 1411504 cycles 6937 calls 1111 * put 1411504 cycles 6937 calls
1112 * task 1655209 cycles 6937 calls (includes put) 1112 * task 1655209 cycles 6937 calls (includes put)
1113 * 1113 *
1114 */ 1114 */
1115 1115