hh.org updates
[hh.org.git] / arch / arm / mach-pxa / magician / magician_ts.c
blob255622dc595c958240392ec7500f2fbce129ee86
1 /* Touch screen driver for the TI something-or-other
3 * Copyright © 2005 SDG Systems, LLC
5 * Based on code that was based on the SAMCOP driver.
6 * Copyright © 2003, 2004 Compaq Computer Corporation.
8 * Use consistent with the GNU GPL is permitted,
9 * provided that this copyright notice is
10 * preserved in its entirety in all copies and derived works.
12 * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
13 * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
14 * FITNESS FOR ANY PARTICULAR PURPOSE.
16 * Author: Keith Packard <keith.packard@hp.com>
17 * May 2003
19 * Updates:
21 * 2004-02-11 Michael Opdenacker Renamed names from samcop to shamcop,
22 * Goal:support HAMCOP and SAMCOP.
23 * 2004-02-14 Michael Opdenacker Temporary fix for device id handling
25 * 2005-02-18 Aric Blumer Converted basic structure to support hx4700
27 * 2005-06-07 Aric Blumer Added tssim device handling so we can
28 * hook in the fbvncserver.
31 #include <linux/module.h>
32 #include <linux/version.h>
34 #include <linux/init.h>
35 #include <linux/fs.h>
36 #include <linux/cdev.h>
37 #include <linux/interrupt.h>
38 #include <linux/irq.h>
39 #include <linux/sched.h>
40 #include <linux/pm.h>
41 #include <linux/delay.h>
42 #include <linux/input.h>
43 #include <linux/platform_device.h>
44 //#include <linux/battery.h>
46 #include <asm/arch/hardware.h>
47 #include <asm/io.h>
49 #include <asm/arch/pxa-regs.h>
50 #include <asm/arch/magician.h>
52 enum touchscreen_state {
53 STATE_WAIT_FOR_TOUCH, /* Waiting for a PEN interrupt */
54 STATE_SAMPLING_X, /* Actively sampling ADC */
55 STATE_SAMPLING_Y, /* Actively sampling ADC */
56 STATE_SAMPLING_Z, /* Actively sampling ADC */
59 struct touchscreen_data {
60 enum touchscreen_state state;
61 struct timer_list timer;
62 int irq;
63 struct input_dev *input;
66 static unsigned long poll_sample_time = 10; /* Sample every 10 milliseconds */
68 static struct touchscreen_data *ts_data;
70 #define TS_SAMPLES 5
72 module_param(poll_sample_time, ulong, 0644);
73 MODULE_PARM_DESC(poll_sample_time, "Poll sample time");
75 static inline void
76 report_touchpanel(struct touchscreen_data *ts, int pressure, int x, int y)
78 input_report_abs(ts->input, ABS_PRESSURE, pressure);
79 input_report_abs(ts->input, ABS_X, x);
80 input_report_abs(ts->input, ABS_Y, y);
81 input_sync(ts->input);
84 static struct work_struct serial_work;
86 static irqreturn_t pen_isr(int irq, void *irq_desc)
88 /* struct touchscreen_data *ts = dev_id->data; */
89 struct touchscreen_data *ts = ts_data;
91 if (irq == MAGICIAN_IRQ(TOUCHPANEL_IRQ_N)) {
93 if (ts->state == STATE_WAIT_FOR_TOUCH) {
95 * There is ground bounce or noise or something going on here:
96 * when you write to the SSP port to get the X and Y values, it
97 * causes a TOUCHPANEL_IRQ_N interrupt to occur. So if that
98 * happens, we can check to make sure the pen is actually down and
99 * disregard the interrupt if it's not.
101 if (GET_MAGICIAN_GPIO(TOUCHPANEL_IRQ_N) == 0) {
103 * Disable the pen interrupt. It's reenabled when the user lifts the
104 * pen.
106 disable_irq(MAGICIAN_IRQ(TOUCHPANEL_IRQ_N));
108 ts->state = STATE_SAMPLING_X;
109 schedule_work(&serial_work);
111 } else {
112 /* Shouldn't happen */
113 printk(KERN_ERR "Unexpected ts interrupt\n");
117 return IRQ_HANDLED;
120 static void ssp_init(void)
123 pxa_set_cken(CKEN3_SSP2, 1);
125 /* *** Set up the SPI Registers *** */
126 SSCR0_P2 = (1 << 20) /* Extended Data Size Select */
127 |(6 << 8) /* Serial Clock Rate */
128 |(0 << 7) /* Synchronous Serial Enable (Disable for now) */
129 |(0 << 4) /* Motorola SPI Interface */
130 |(7 << 0) /* Data Size Select (24-bit) */
132 SSCR1_P2 = 0;
133 SSPSP_P2 = 0;
135 /* Clear the Status */
136 SSSR_P2 = SSSR_P2 & 0x00fcfffc;
138 /* Now enable it */
139 SSCR0_P2 = (1 << 20) /* Extended Data Size Select */
140 |(6 << 8) /* Serial Clock Rate */
141 |(1 << 7) /* Synchronous Serial Enable */
142 |(0 << 4) /* Motorola SPI Interface */
143 |(7 << 0) /* Data Size Select (24-bit) */
145 /* enable_irq(MAGICIAN_IRQ(TOUCHPANEL_IRQ_N)); */
148 DECLARE_MUTEX(serial_mutex);
150 static void start_read(void *in)
152 struct touchscreen_data *touch = in;
153 unsigned long inc = (poll_sample_time * HZ) / 1000;
154 int i;
155 int command, samples;
157 down(&serial_mutex);
159 /* Write here to the serial port.
160 * Then we have to wait for poll_sample_time before we read out the serial
161 * port. Then, when we read it out, we check to see if the pen is still
162 * down. If so, then we issue another request here.
165 switch (touch->state) {
166 case STATE_SAMPLING_X:
167 command = 0xd10000;
168 samples = 14;
169 break;
170 case STATE_SAMPLING_Y:
171 command = 0x910000;
172 samples = 12;
173 break;
174 case STATE_SAMPLING_Z:
175 command = 0xc00000;
176 samples = 1;
179 for (i = 0; i < (samples - 1); i++) {
180 while (!(SSSR_P2 & (1 << 2))) ;
181 /* It's not full. Write the command for X/Y/Z */
182 SSDR_P2 = command;
184 while (!(SSSR_P2 & (1 << 2))) ;
185 /* Write the command for X/Y/Z, turn off ADC */
186 SSDR_P2 = command & ~(0x10000);
189 * Enable the timer. We should get an interrupt, but we want keep a timer
190 * to ensure that we can detect missing data
192 mod_timer(&touch->timer, jiffies + inc);
195 static int do_delta_calc(int x1, int y1, int x2, int y2, int x3, int y3)
197 /* This is based on Jamey Hicks' description on IRC. */
198 int dx2_a, dy2_a, dx2_b, dy2_b;
200 dx2_a = x2 - x1;
201 dx2_a = dx2_a * dx2_a; /* If dx2_a was negative, it's not now */
202 dy2_a = y2 - y1;
203 dy2_a = dy2_a * dy2_a; /* If dy2_a was negative, it's not now */
205 dx2_b = x3 - x2;
206 dx2_b = dx2_b * dx2_b; /* If dx2_b was negative, it's not now */
207 dy2_b = y3 - y2;
208 dy2_b = dy2_b * dy2_b; /* If dy2_b was negative, it's not now */
210 #if 0
211 /* This was described in the algorithm by Jamey, but it doesn't do much
212 * good.
214 if (dx2_a + dy2_a < dx2_b + dy2_b)
215 return 0;
216 #endif
218 /* dx2_a + dy2_a is the distance squared */
219 if (((dx2_a + dy2_a) > 8000)
220 || ((dx2_b + dy2_b) > 8000)
222 return 0;
223 } else {
224 return 1;
227 if ((dx2_b + dy2_b) > 5000) {
228 return 0;
229 } else {
230 return 1;
234 static void ts_timer_callback(unsigned long data)
236 struct touchscreen_data *ts = (struct touchscreen_data *)data;
237 static int x, y;
238 int ssrval;
239 int samples;
241 switch (ts->state) {
242 case STATE_SAMPLING_X:
243 samples = 14;
244 break;
245 case STATE_SAMPLING_Y:
246 samples = 12;
247 break;
248 case STATE_SAMPLING_Z:
249 samples = 1;
253 * Check here to see if there is anything in the SPI FIFO. If so,
254 * return it if there has been a change. If not, then we have a
255 * timeout. Generate an erro somehow.
257 ssrval = SSSR_P2;
258 if (ssrval & (1 << 3)) { /* Look at Rx Not Empty bit */
259 int number_of_entries_in_fifo;
261 /* The FIFO is not emtpy. Good! Now make sure there are at least two
262 * entries. */
264 number_of_entries_in_fifo = ((ssrval >> 12) & 0xf) + 1;
266 if (number_of_entries_in_fifo < samples) {
267 /* Not ready yet. Come back later. */
268 unsigned long inc = (poll_sample_time * HZ) / 1000;
269 mod_timer(&ts->timer, jiffies + inc);
270 return;
273 if (number_of_entries_in_fifo == samples) {
274 int i, result, keep;
275 int X[14], Y[12], Z2;
277 switch (ts->state) {
278 case STATE_SAMPLING_X:
279 for (i = 0; i < 14; i++)
280 X[13 - i] = SSDR_P2 & 0xffff;
281 x = (2 * X[0] + X[1] + X[2]) / 4;
282 ts->state = STATE_SAMPLING_Y;
283 break;
284 case STATE_SAMPLING_Y:
285 for (i = 0; i < 12; i++)
286 Y[11 - i] = SSDR_P2 & 0xffff;
287 y = (2 * Y[0] + Y[1] + Y[2]) / 4;
288 ts->state = STATE_SAMPLING_Z;
289 break;
290 case STATE_SAMPLING_Z:
291 Z2 = SSDR_P2 & 0xffff;
292 ts->state = STATE_SAMPLING_X;
295 up(&serial_mutex);
297 keep = 1;
298 #if 0
299 keep = 0;
300 x = y = 0;
302 result = 0;
303 if (do_delta_calc(X[0], Y[0], X[1], Y[1], X[2], Y[2])) {
304 result |= (1 << 2);
306 if (do_delta_calc(X[1], Y[1], X[2], Y[2], X[3], Y[3])) {
307 result |= (1 << 1);
309 if (do_delta_calc(X[2], Y[2], X[3], Y[3], X[4], Y[4])) {
310 result |= (1 << 0);
312 switch (result) {
313 case 0:
314 /* Take average of point 0 and point 3 */
315 X[2] = (X[1] + X[3]) / 2;
316 Y[2] = (Y[1] + Y[3]) / 2;
317 /* don't keep */
318 break;
319 case 1:
320 /* Just ignore this one */
321 break;
322 case 2:
323 case 3:
324 case 6:
325 /* keep this sample */
326 x = (X[1] + (2 * X[2]) + X[3]) / 4;
327 y = (Y[1] + (2 * Y[2]) + Y[3]) / 4;
328 keep = 1;
329 break;
330 case 4:
331 X[1] = (X[0] + X[2]) / 2;
332 Y[1] = (Y[0] + Y[2]) / 2;
333 /* don't keep */
334 break;
335 case 5:
336 case 7:
337 x = (X[0] + (4 * X[1]) + (6 * X[2]) +
338 (4 * X[3]) + X[4]) >> 4;
339 y = (Y[0] + (4 * Y[1]) + (6 * Y[2]) +
340 (4 * Y[3]) + Y[4]) >> 4;
341 keep = 1;
342 break;
344 #endif
345 if (GET_MAGICIAN_GPIO(TOUCHPANEL_IRQ_N) == 0) {
346 /* Still down */
347 if (keep) {
348 report_touchpanel(ts, 1, x, y);
350 start_read(ts);
351 } else {
352 /* Up */
353 report_touchpanel(ts, 0, 0, 0);
354 ts->state = STATE_WAIT_FOR_TOUCH;
355 /* Re-enable pen down interrupt */
356 enable_irq(MAGICIAN_IRQ(TOUCHPANEL_IRQ_N));
359 } else {
360 /* We have an error! Too many entries. */
361 printk(KERN_ERR "TS: Expected %d entries. Got %d\n", 2,
362 number_of_entries_in_fifo);
363 /* Try to clear the FIFO */
364 while (number_of_entries_in_fifo--) {
365 (void)SSDR_P2;
367 up(&serial_mutex);
368 if (GET_MAGICIAN_GPIO(TOUCHPANEL_IRQ_N) == 0) {
369 start_read(ts);
371 return;
373 } else {
374 /* Not ready yet. Come back later. */
375 unsigned long inc = (poll_sample_time * HZ) / 1000;
376 printk("wait some more\n");
377 mod_timer(&ts->timer, jiffies + inc);
378 return;
382 static int ts_probe(struct platform_device *dev)
384 int retval;
385 struct touchscreen_data *ts;
386 unsigned int irq;
387 int err;
389 ts = ts_data = kmalloc(sizeof(*ts), GFP_KERNEL);
390 if (ts == NULL) {
391 printk(KERN_NOTICE "magician_ts: unable to allocate memory\n");
392 return -ENOMEM;
394 memset(ts, 0, sizeof(*ts));
396 /* *** Set up the input subsystem stuff *** */
397 // memset(ts->input, 0, sizeof(struct input_dev));
398 ts->input = input_allocate_device();
399 if (ts->input == NULL) {
400 printk(KERN_NOTICE
401 "magician_ts: unable to allocation touchscreen input\n");
402 kfree(ts);
403 return -ENOMEM;
405 ts->input->evbit[0] = BIT(EV_ABS);
406 ts->input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
407 ts->input->absmin[ABS_X] = 0;
408 ts->input->absmax[ABS_X] = 32767;
409 ts->input->absmin[ABS_Y] = 0;
410 ts->input->absmax[ABS_Y] = 32767;
411 ts->input->absmin[ABS_PRESSURE] = 0;
412 ts->input->absmax[ABS_PRESSURE] = 1;
414 ts->input->name = "magician_ts";
415 ts->input->private = ts;
417 input_register_device(ts->input);
419 ts->timer.function = ts_timer_callback;
420 ts->timer.data = (unsigned long)ts;
421 ts->state = STATE_WAIT_FOR_TOUCH;
422 init_timer(&ts->timer);
424 INIT_WORK(&serial_work, start_read, ts);
426 platform_set_drvdata(dev, ts);
428 /* *** Initialize the SSP interface *** */
429 ssp_init();
431 down(&serial_mutex);
432 /* Make sure the device is in such a state that it can give pen
433 * interrupts. */
434 while (!(SSSR_P2 & (1 << 2))) ;
435 SSDR_P2 = 0xd00000;
437 for (retval = 0; retval < 100; retval++) {
438 if (SSSR_P2 & (1 << 3)) {
439 while (SSSR_P2 & (1 << 3)) {
440 (void)SSDR_P2;
442 break;
444 mdelay(1);
446 up(&serial_mutex);
448 ts->irq = MAGICIAN_IRQ(TOUCHPANEL_IRQ_N);
449 retval = request_irq(ts->irq, pen_isr, SA_INTERRUPT, "magician_ts", ts);
450 if (retval) {
451 printk("Unable to get interrupt\n");
452 input_unregister_device(ts->input);
453 return -ENODEV;
455 set_irq_type(ts->irq, IRQT_FALLING);
457 return 0;
460 static int ts_remove(struct platform_device *dev)
462 int i;
463 struct touchscreen_data *ts = platform_get_drvdata(dev);
465 input_unregister_device(ts->input);
466 del_timer_sync(&ts->timer);
467 free_irq(ts->irq, ts);
469 kfree(ts);
470 pxa_set_cken(CKEN3_SSP2, 0);
471 return 0;
474 static int ts_suspend(struct platform_device *dev, pm_message_t state)
476 disable_irq(MAGICIAN_IRQ(TOUCHPANEL_IRQ_N));
477 return 0;
480 static int ts_resume(struct platform_device *dev)
482 struct touchscreen_data *ts = platform_get_drvdata(dev);
484 ts->state = STATE_WAIT_FOR_TOUCH;
485 ssp_init();
486 enable_irq(MAGICIAN_IRQ(TOUCHPANEL_IRQ_N));
488 return 0;
491 static struct platform_driver ts_driver = {
492 .probe = ts_probe,
493 .remove = ts_remove,
494 .suspend = ts_suspend,
495 .resume = ts_resume,
496 .driver = {
497 .name = "magician-ts",
501 static int tssim_init(void);
503 static int ts_module_init(void)
505 printk(KERN_NOTICE "HTC Magician Touch Screen Driver\n");
506 if (tssim_init()) {
507 printk(KERN_NOTICE " TS Simulator Not Installed\n");
508 } else {
509 printk(KERN_NOTICE " TS Simulator Installed\n");
511 return platform_driver_register(&ts_driver);
514 static void tssim_exit(void);
516 static void ts_module_cleanup(void)
518 tssim_exit();
519 platform_driver_unregister(&ts_driver);
522 /************* Code for Touch Screen Simulation for FBVNC Server **********/
523 static dev_t dev;
524 static struct cdev *cdev;
526 static long a0 = -1122, a2 = 33588528, a4 = 1452, a5 = -2970720, a6 = 65536;
528 /* The input into the input subsystem is prior to correction from calibration.
529 * So we have to undo the effects of the calibration. It's actually a
530 * complicated equation where the calibrated value of X depends on the
531 * uncalibrated values of X and Y. Fortunately, at least on the magician, the
532 * multiplier for the Y value is zero, so I assume that here. It is a shame
533 * that the tslib does not allow multiple inputs. Then we could do another
534 * driver for this (as it was originally) that give input that does not
535 * require calibration.
537 static int
538 tssim_ioctl(struct inode *inode, struct file *fp, unsigned int ioctlnum,
539 unsigned long parm)
541 switch (ioctlnum) {
542 case 0:
543 a0 = parm;
544 break;
545 case 1:
546 break;
547 case 2:
548 a2 = parm;
549 break;
550 case 3:
551 break;
552 case 4:
553 a4 = parm;
554 break;
555 case 5:
556 a5 = parm;
557 break;
558 case 6:
559 a6 = parm;
560 printk(KERN_DEBUG
561 "a0 = %ld, a2 = %ld, a4 = %ld, a5 = %ld, a6 = %ld\n", a0,
562 a2, a4, a5, a6);
563 break;
564 default:
565 return -ENOTTY;
567 return 0;
570 static int tssim_open(struct inode *inode, struct file *fp)
572 /* Nothing to do here */
573 return 0;
576 static ssize_t
577 tssim_write(struct file *fp, const char __user * data, size_t bytes,
578 loff_t * offset)
580 unsigned long pressure;
581 long y;
582 long x;
584 x = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
585 data += 4;
586 y = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
587 data += 4;
588 pressure = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
589 data += 4;
591 input_report_abs(ts_data->input, ABS_PRESSURE, pressure ? 1 : 0);
592 input_report_abs(ts_data->input, ABS_X, ((x * a6) - a2) / a0);
593 input_report_abs(ts_data->input, ABS_Y, ((y * a6) - a5) / a4);
594 input_sync(ts_data->input);
596 return bytes;
599 int tssim_close(struct inode *inode, struct file *fp)
601 return 0;
604 struct file_operations fops = {
605 THIS_MODULE,
606 .write = tssim_write,
607 .open = tssim_open,
608 .release = tssim_close,
609 .ioctl = tssim_ioctl,
612 #if 0
613 static int battery_class;
615 static int get_min_voltage(struct battery *b)
617 return 1000;
619 static int get_max_voltage(struct battery *b)
621 return 1400; /* mV */
623 static int get_max_charge(struct battery *b)
625 return 100;
627 static int get_voltage(struct battery *b)
629 static int battery_sample;
631 if (!down_interruptible(&serial_mutex)) {
632 int i;
633 int ssrval;
635 while (!(SSSR_P2 & (1 << 2))) ;
636 SSDR_P2 = 0xe70000;
637 while (!(SSSR_P2 & (1 << 2))) ;
638 SSDR_P2 = 0xe70000;
639 while (!(SSSR_P2 & (1 << 2))) ;
640 SSDR_P2 = 0xd00000; /* Dummy command to allow pen interrupts again */
642 for (i = 0; i < 10; i++) {
643 ssrval = SSSR_P2;
644 if (ssrval & (1 << 3)) { /* Look at Rx Not Empty bit */
645 int number_of_entries_in_fifo;
647 number_of_entries_in_fifo =
648 ((ssrval >> 12) & 0xf) + 1;
649 if (number_of_entries_in_fifo == 3) {
650 break;
653 msleep(1);
656 if (i < 1000) {
657 (void)SSDR_P2;
658 battery_sample = SSDR_P2 & 0xfff;
659 (void)SSDR_P2;
660 } else {
661 /* Make sure the FIFO is empty */
662 while (SSSR_P2 & (1 << 3)) {
663 (void)SSDR_P2;
665 battery_sample = -1;
667 up(&serial_mutex);
670 return battery_sample;
672 static int get_charge(struct battery *b)
674 // return 100;
675 static int battery_sample;
676 static int temperature_sample;
677 static int temperature_sample2;
679 if (!down_interruptible(&serial_mutex)) {
680 int i;
681 int ssrval;
683 while (!(SSSR_P2 & (1 << 2))) ;
684 SSDR_P2 = 0xa70000; // e is AUX 1(110), a is BAT 1(010)
685 while (!(SSSR_P2 & (1 << 2))) ;
686 SSDR_P2 = 0xa70000;
687 while (!(SSSR_P2 & (1 << 2))) ;
688 SSDR_P2 = 0xd00000; /* Dummy command to allow pen interrupts again */
690 for (i = 0; i < 10; i++) {
691 ssrval = SSSR_P2;
692 if (ssrval & (1 << 3)) { /* Look at Rx Not Empty bit */
693 int number_of_entries_in_fifo;
695 number_of_entries_in_fifo =
696 ((ssrval >> 12) & 0xf) + 1;
697 if (number_of_entries_in_fifo == 3) {
698 break;
701 msleep(1);
704 if (i < 1000) {
705 (void)SSDR_P2;
706 battery_sample = SSDR_P2 & 0xfff;
707 (void)SSDR_P2;
708 } else {
709 /* Make sure the FIFO is empty */
710 while (SSSR_P2 & (1 << 3)) {
711 (void)SSDR_P2;
713 battery_sample = -1;
715 up(&serial_mutex);
718 printk("VBAT: %d\n", battery_sample);
720 if (!down_interruptible(&serial_mutex)) {
721 int i;
722 int ssrval;
724 while (!(SSSR_P2 & (1 << 2))) ;
725 SSDR_P2 = 0x870000; // e is AUX 1(110), 8 is TEMP0 1(000)
726 while (!(SSSR_P2 & (1 << 2))) ;
727 SSDR_P2 = 0x870000;
728 while (!(SSSR_P2 & (1 << 2))) ;
729 SSDR_P2 = 0xd00000; /* Dummy command to allow pen interrupts again */
731 for (i = 0; i < 10; i++) {
732 ssrval = SSSR_P2;
733 if (ssrval & (1 << 3)) { /* Look at Rx Not Empty bit */
734 int number_of_entries_in_fifo;
736 number_of_entries_in_fifo =
737 ((ssrval >> 12) & 0xf) + 1;
738 if (number_of_entries_in_fifo == 3) {
739 break;
742 msleep(1);
745 if (i < 1000) {
746 (void)SSDR_P2;
747 temperature_sample = SSDR_P2 & 0xfff;
748 (void)SSDR_P2;
749 } else {
750 /* Make sure the FIFO is empty */
751 while (SSSR_P2 & (1 << 3)) {
752 (void)SSDR_P2;
754 temperature_sample = -1;
756 up(&serial_mutex);
759 printk("TEMP0: %d\n", temperature_sample);
761 if (!down_interruptible(&serial_mutex)) {
762 int i;
763 int ssrval;
765 while (!(SSSR_P2 & (1 << 2))) ;
766 SSDR_P2 = 0x870000; // e is AUX 1(110), 8 is TEMP0 1(000)
767 while (!(SSSR_P2 & (1 << 2))) ;
768 SSDR_P2 = 0x870000;
769 while (!(SSSR_P2 & (1 << 2))) ;
770 SSDR_P2 = 0xd00000; /* Dummy command to allow pen interrupts again */
772 for (i = 0; i < 10; i++) {
773 ssrval = SSSR_P2;
774 if (ssrval & (1 << 3)) { /* Look at Rx Not Empty bit */
775 int number_of_entries_in_fifo;
777 number_of_entries_in_fifo =
778 ((ssrval >> 12) & 0xf) + 1;
779 if (number_of_entries_in_fifo == 3) {
780 break;
783 msleep(1);
786 if (i < 1000) {
787 (void)SSDR_P2;
788 temperature_sample = SSDR_P2 & 0xfff;
789 (void)SSDR_P2;
790 } else {
791 /* Make sure the FIFO is empty */
792 while (SSSR_P2 & (1 << 3)) {
793 (void)SSDR_P2;
795 temperature_sample = -1;
797 up(&serial_mutex);
800 printk("TEMP1: %d\n", temperature_sample2);
802 return 100;
804 static int get_status(struct battery *b)
806 // return 1;
809 static struct battery magician_power = {
810 .name = "magician_backup",
811 .id = "backup",
812 .get_min_voltage = get_min_voltage,
813 .get_min_current = 0,
814 .get_min_charge = 0,
815 .get_max_voltage = get_max_voltage,
816 .get_max_current = 0,
817 .get_max_charge = get_max_charge,
818 .get_temp = 0,
819 .get_voltage = get_voltage,
820 .get_current = 0,
821 .get_charge = get_charge,
822 .get_status = get_status,
825 static int
826 battery_class_uevent(struct class_device *dev, char **envp, int num_envp,
827 char *buffer, int buffer_size)
829 return 0;
832 static void battery_class_release(struct class_device *dev)
836 static void battery_class_class_release(struct class *class)
839 #endif
841 static int tssim_init(void)
843 int retval;
845 retval = alloc_chrdev_region(&dev, 0, 1, "tssim");
846 if (retval) {
847 printk(KERN_ERR "TSSIM Unable to allocate device numbers\n");
848 return retval;
851 cdev = cdev_alloc();
852 cdev->owner = THIS_MODULE;
853 cdev->ops = &fops;
854 retval = cdev_add(cdev, dev, 1);
855 if (retval) {
856 printk(KERN_ERR "Unable to add cdev\n");
857 unregister_chrdev_region(dev, 1);
858 return retval;
861 #if 0
862 battery_class = 0;
863 if (battery_class_register(&magician_power)) {
864 printk(KERN_ERR
865 "magician_ts: Could not register battery class\n");
866 } else {
867 battery_class = 1;
868 magician_power.class_dev.class->uevent = battery_class_uevent;
869 magician_power.class_dev.class->release = battery_class_release;
870 magician_power.class_dev.class->class_release =
871 battery_class_class_release;
873 #endif
875 return 0;
878 static void tssim_exit(void)
880 cdev_del(cdev);
881 unregister_chrdev_region(dev, 1);
882 #if 0
883 if (battery_class) {
884 battery_class_unregister(&magician_power);
886 #endif
887 return;
890 module_init(ts_module_init);
891 module_exit(ts_module_cleanup);
893 MODULE_LICENSE("GPL");
894 MODULE_AUTHOR("Aric Blumer, SDG Systems, LLC");
895 MODULE_DESCRIPTION("HTC Magician Touch Screen Driver");