Update DEP-5 uri
[debian/omnibook.git] / ec.c
1 /*
2  * ec.c -- low level functions to access Embedded Controller,
3  * 
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2, or (at your option) any
7  * later version.
8  * 
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * Written by Soós Péter <sp@osb.hu>, 2002-2004
15  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
16  */
17
18 #include "omnibook.h"
19
20 #include <linux/types.h>
21 #include <linux/delay.h>
22 #include <linux/sched.h>
23 #include <linux/spinlock.h>
24 #include <linux/ioport.h>
25
26 #include <asm/io.h>
27 #include "hardware.h"
28
29 /*
30  * Interrupt control
31  */
32
33 static DEFINE_SPINLOCK(omnibook_ec_lock);
34
35 /*
36  * Registers of the embedded controller
37  */
38
39 #define OMNIBOOK_EC_DATA                0x62
40 #define OMNIBOOK_EC_SC                  0x66
41
42 /*
43  * Embedded controller status register bits
44  */
45
46 #define OMNIBOOK_EC_STAT_OBF            0x01    /* Output buffer full */
47 #define OMNIBOOK_EC_STAT_IBF            0x02    /* Input buffer full */
48
49
50 /*
51  * Embedded controller commands
52  */
53
54 #define OMNIBOOK_EC_CMD_READ            0x80
55 #define OMNIBOOK_EC_CMD_WRITE           0x81
56
57 /*
58  * Wait for embedded controller buffer
59  */
60
61 static int omnibook_ec_wait(u8 event)
62 {
63         int timeout = OMNIBOOK_TIMEOUT;
64
65         switch (event) {
66         case OMNIBOOK_EC_STAT_OBF:
67                 while (!(inb(OMNIBOOK_EC_SC) & event) && timeout--)
68                         mdelay(1);
69                 break;
70         case OMNIBOOK_EC_STAT_IBF:
71                 while ((inb(OMNIBOOK_EC_SC) & event) && timeout--)
72                         mdelay(1);
73                 break;
74         default:
75                 return -EINVAL;
76         }
77         if (timeout > 0)
78                 return 0;
79         return -ETIME;
80 }
81
82 /*
83  * Read from the embedded controller
84  * Decide at run-time if we can use the much cleaner ACPI EC driver instead of
85  * this implementation, this is the case if ACPI has been compiled and is not
86  * disabled.
87  */
88
89 static int omnibook_ec_read(const struct omnibook_operation *io_op, u8 * data)
90 {
91         int retval;
92
93 #ifdef CONFIG_ACPI_EC
94         if (likely(!acpi_disabled)) {
95                 retval = ec_read((u8) io_op->read_addr, data);
96                 if (io_op->read_mask)
97                         *data &= io_op->read_mask;
98 //              dprintk("ACPI EC read at %lx success %i.\n", io_op->read_addr, retval);
99                 return retval;
100         }
101 #endif
102         spin_lock_irq(&omnibook_ec_lock);
103         retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
104         if (retval)
105                 goto end;
106         outb(OMNIBOOK_EC_CMD_READ, OMNIBOOK_EC_SC);
107         retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
108         if (retval)
109                 goto end;
110         outb((u8) io_op->read_addr, OMNIBOOK_EC_DATA);
111         retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_OBF);
112         if (retval)
113                 goto end;
114         *data = inb(OMNIBOOK_EC_DATA);
115         if (io_op->read_mask)
116                 *data &= io_op->read_mask;
117       end:
118         spin_unlock_irq(&omnibook_ec_lock);
119 //      dprintk("Custom EC read at %lx success %i.\n", io_op->read_addr, retval);
120         return retval;
121 }
122
123 /*
124  * Write to the embedded controller:
125  * If OMNIBOOK_LEGACY is set, decide at run-time if we can use the much cleaner 
126  * ACPI EC driver instead of this legacy implementation. 
127  * This is the case if ACPI has been compiled and is not
128  * disabled.
129  * If OMNIBOOK_LEGACY is unset, we drop our custoim implementation
130  */
131
132 static int omnibook_ec_write(const struct omnibook_operation *io_op, u8 data)
133 {
134         int retval;
135
136 #ifdef CONFIG_ACPI_EC
137         if (likely(!acpi_disabled)) {
138                 retval = ec_write((u8) io_op->write_addr, data);
139 //              dprintk("ACPI EC write at %lx success %i.\n", io_op->write_addr, retval);
140                 return retval;
141         }
142 #endif
143
144         spin_lock_irq(&omnibook_ec_lock);
145         retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
146         if (retval)
147                 goto end;
148         outb(OMNIBOOK_EC_CMD_WRITE, OMNIBOOK_EC_SC);
149         retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
150         if (retval)
151                 goto end;
152         outb((u8) io_op->write_addr, OMNIBOOK_EC_DATA);
153         retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
154         if (retval)
155                 goto end;
156         outb(data, OMNIBOOK_EC_DATA);
157       end:
158         spin_unlock_irq(&omnibook_ec_lock);
159 //      dprintk("Custom EC write at %lx success %i.\n", io_op->write_addr, retval);
160         return retval;
161 }
162
163 static int omnibook_ec_display(const struct omnibook_operation *io_op, unsigned int *state)
164 {
165         int retval;
166         u8 raw_state;
167
168         retval = __backend_byte_read(io_op, &raw_state);
169         if (retval < 0)
170                 return retval;
171
172         *state = !!(raw_state & DISPLAY_CRT_DET);
173
174         return DISPLAY_CRT_DET;
175 }
176
177 /*
178  * Backend interface declarations
179  */
180
181 struct omnibook_backend ec_backend = {
182         .name = "ec",
183         .byte_read = omnibook_ec_read,
184         .byte_write = omnibook_ec_write,
185         .display_get = omnibook_ec_display,
186 };
187
188 /* End of file */