source: trunk/src/mainboard/roda/rk886ex/m3885.c

Last change on this file was 6304, checked in by stuge, 5 years ago

Add new ec subdir for Embedded Controllers and common ACPI EC support

Adds a new src/ec subdir for embedded controllers (mostly found in laptops)
and converts Getac P470 and Roda RK886EX to use the new ACPI EC instead
of having their own copies of those functions.

Signed-off-by: Sven Schnelle <svens@…>
Acked-by: Peter Stuge <peter@…>

File size: 11.3 KB
Line 
1/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2009 coresystems GmbH
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19 * MA 02110-1301 USA
20 */
21
22#include <types.h>
23#include <stdlib.h>
24#include <console/console.h>
25#include <arch/io.h>
26#include <delay.h>
27
28#include <ec/acpi/ec.h>
29#include "m3885.h"
30
31#define TH0LOW  80
32#define TH0HIGH 85
33#define TH0CRIT 120
34#define TH1LOW  75
35#define TH1HIGH 80
36
37static u8 variables[] = {
38     /* Offs,  AND,   OR */
39        0x08, 0x48, 0x6C,  // Keyboard ScanCode Set & LED Data (kState1)
40        0x0a, 0x01, 0x00,  // Keyboard Shift flags (kState3)
41        0x0c, 0x80, 0x08,  // Keyboard State flags (kState5)
42        0x11, 0xff, 0x06,  // Make/Break Debounce #'s (debounce)
43        0x13, 0xff, 0x00,  // HotKey1 ScanCode (hotKey1)
44        0x14, 0xff, 0x00,  // HotKey2 ScanCode (hotKey2)
45        0x15, 0xff, 0x3f,  // HotKey3 ScanCode (hotKey3)
46        0x16, 0xff, 0x00,  // HotKey4 ScanCode (hotKey4)
47        0x17, 0xff, 0x00,  // HotKey5 ScanCode (hotKey5)
48        0x18, 0xff, 0x0e,  // HotKey6 ScanCode (hotKey6)
49        0x19, 0xff, 0x9f,  // HotKey1 Task = c5 Command Data (keyTsk1)
50        0x1a, 0xff, 0x9f,  // HotKey2 Task = c5 Command Data (keyTsk2)
51        0x1b, 0xff, 0x6a,  // HotKey3 Task = c5 Command Data (keyTsk3)
52        0x1c, 0xff, 0x9f,  // HotKey4 Task = c5 Command Data (keyTsk4)
53        0x1d, 0xff, 0x9f,  // HotKey5 Task = c5 Command Data (keyTsk5)
54        0x1e, 0xff, 0x87,  // FuncKey Task = c5 Command Data (funcTsk)
55        0x1f, 0xff, 0x9f,  // Delayed Task = c5 Command Data (dlyTsk1)
56        0x20, 0xff, 0x9f,  // Wake-Up Task = c5 Command Data (wakeTsk)
57        //
58        0x21, 0xff, 0x08,  // WigglePin Pulse Width * 2.4ms (tmPulse)
59        0x24, 0xff, 0x30,  // Keyboard State Flags (kState7)
60        //
61        0x2b, 0xff, 0x00,  //
62        0x2c, 0xff, 0x80,  // Set Fn-Key 8
63        0x2d, 0xff, 0x02,  // Set Fn-Key 9
64        0x2e, 0xff, 0x00,  // Set Fn-Key 1-8 task  (0 = SMI)
65        0x2f, 0xff, 0x00,  // Set Fn-Key 9-12 task (1 = SCI)
66};
67
68static u8 matrix[] = {
69        0xc1,0xc0,0xd8,0xdb,0xbf,0x05,0x76,0xbf,  // (0x00-0x07)
70        0xbf,0x80,0x78,0xbf,0xbf,0x07,0x88,0xc2,  // (0x08-0x0f)
71        0x03,0x09,0xd9,0x16,0xbf,0x06,0x0e,0x81,  // (0x10-0x17)
72        0xbf,0xbf,0xee,0xbf,0xbf,0x55,0x9a,0x89,  // (0x18-0x1f)
73        0x1e,0x15,0x36,0xda,0xe8,0xbf,0x0d,0xbf,  // (0x20-0x27)
74        0xbf,0xbf,0xbf,0xa3,0xbf,0x4e,0x66,0x8b,  // (0x28-0x2f)
75        0x1d,0x2e,0xe6,0xe7,0xe5,0x1c,0x58,0xbf,  // (0x30-0x37)
76        0x82,0xbf,0xf0,0xbf,0xbf,0x5b,0x5d,0x8c,  // (0x38-0x3f)
77        0x22,0x25,0x2c,0x35,0xe1,0x1a,0x96,0xbf,  // (0x40-0x47)
78        0xbf,0xbf,0xec,0xbf,0xbf,0x54,0xf1,0x8f,  // (0x48-0x4f)
79        0x1b,0x2a,0x2b,0x32,0xe9,0x31,0x29,0x61,  // (0x50-0x57)
80        0xbf,0xbf,0x8d,0xbf,0x86,0xc3,0x92,0x93,  // (0x58-0x5f)
81        0x21,0x23,0x34,0x33,0x41,0xe0,0xbf,0xbf,  // (0x60-0x67)
82        0xbf,0x85,0xeb,0xbf,0xb6,0xbf,0x91,0xbf,  // (0x68-0x6f)
83        0x26,0x24,0x2d,0xe3,0xe2,0xe4,0xbf,0xbf,  // (0x70-0x77)
84        0x87,0xbf,0xea,0xbf,0xbf,0x52,0x90,0x8e,  // (0x78-0x7f)
85};
86
87static u8 function_ram[] = {
88        0x04,0xbd,0x0c,0xbe,0x7e,0x9a,0x8a,0xb6,  // (0xc0-0xc3)
89        0x92,0x8f,0x93,0x8e,0x81,0x86,0x82,0x87,  // (0xc4-0xc7)
90        0x8a,0x9a,0x8d,0x7e,0x88,0x84,0x7e,0x78,  // (0xc8-0xcb)
91        0x77,0x07,0x77,0x98,0x89,0xb2,0x05,0x9b,  // (0xcc-0xcf)
92        0x78,0x84,0x07,0x88,0x8a,0x7e,0x05,0xa6,  // (0xd0-0xd3)
93        0x06,0xa7,0x04,0xa8,0x0c,0xa9,0x03,0xaa,  // (0xd4-0xd7)
94        0x0b,0xc1,0x83,0xc0,0x0a,0xad,0x01,0xae,  // (0xd8-0xdb)
95        0x09,0xaf,0x78,0xb0,0x07,0xb1,0x1a,0x61,  // (0xdc-0xdf)
96        0x3b,0x69,0x42,0x72,0x4b,0x7a,0x3c,0x6b,  // (0xe0-0xe3)
97        0x43,0x73,0x44,0x74,0x3d,0x6c,0x3e,0x75,  // (0xe4-0xe7)
98        0x46,0x7d,0x3a,0x70,0x49,0x71,0x4a,0x94,  // (0xe8-0xeb)
99        0x4c,0x79,0x4c,0x7c,0x45,0x7c,0x45,0x79,  // (0xec-0xef)
100        0x4d,0x7b,0x5a,0x95,0x4c,0x7b,0x45,0x7b,  // (0xf0-0xf3)
101        0x4d,0x79,0x4d,0x7c,0x4e,0x7b,0x54,0x95,  // (0xf4-0xf7)
102        0x52,0x7c,0x45,0x94,0x4a,0x79,0xb3,0x95,  // (0xf8-0xfb)
103        0xb4,0x7b,0xb5,0x7c,0x00,0x00,0x55,0x79,  // (0xfc-0xff)
104};
105
106
107#define KBD_DATA        0x60
108#define KBD_SC          0x64
109
110#define   KBD_IBF       (1 << 1) // 1: input buffer full (data ready for ec)
111#define   KBD_OBF       (1 << 0) // 1: output buffer full (data ready for host)
112
113static int send_kbd_command(u8 command)
114{
115        int timeout;
116
117        timeout = 0x7ff;
118        while ((inb(KBD_SC) & KBD_IBF) && --timeout) {
119                udelay(10);
120                if ((timeout & 0xff) == 0)
121                        printk(BIOS_SPEW, ".");
122        }
123        if (!timeout) {
124                printk(BIOS_DEBUG, "Timeout while sending command 0x%02x to EC!\n",
125                                command);
126                // return -1;
127        }
128
129        outb(command, KBD_SC);
130        return 0;
131}
132
133static int send_kbd_data(u8 data)
134{
135        int timeout;
136
137        timeout = 0x7ff;
138        while ((inb(KBD_SC) & KBD_IBF) && --timeout) { // wait for IBF = 0
139                udelay(10);
140                if ((timeout & 0xff) == 0)
141                        printk(BIOS_SPEW, ".");
142        }
143        if (!timeout) {
144                printk(BIOS_DEBUG, "Timeout while sending data 0x%02x to EC!\n",
145                                data);
146                // return -1;
147        }
148
149        outb(data, KBD_DATA);
150
151        return 0;
152}
153
154
155static u8 recv_kbd_data(void)
156{
157        int timeout;
158        u8 data;
159
160        timeout = 0x7fff;
161        while (--timeout) { // Wait for OBF = 1
162                if (inb(KBD_SC) & KBD_OBF) {
163                        break;
164                }
165                udelay(10);
166                if ((timeout & 0xff) == 0)
167                        printk(BIOS_SPEW, ".");
168        }
169        if (!timeout) {
170                printk(BIOS_DEBUG, "\nTimeout while receiving data from EC!\n");
171                // return -1;
172        }
173
174        data = inb(KBD_DATA);
175
176        return data;
177}
178
179
180static u8 m3885_get_variable(u8 index)
181{
182        u8 ret;
183
184        send_kbd_command(0xb8);
185        send_kbd_data(index);
186        send_kbd_command(0xbc);
187        send_kbd_command(0xff);
188        ret = recv_kbd_data();
189        printk(BIOS_SPEW, "m3885: get variable %02x = %02x\n", index, ret);
190        return ret;
191}
192
193static void m3885_set_variable(u8 index, u8 data)
194{
195        printk(BIOS_SPEW, "m3885: set variable %02x = %02x\n", index, data);
196        send_kbd_command(0xb8);
197        send_kbd_data(index);
198        send_kbd_command(0xbd);
199        send_kbd_data(data);
200}
201
202static void m3885_set_proc_ram(u8 index, u8 data)
203{
204        printk(BIOS_SPEW, "m3885: set procram %02x = %02x\n", index, data);
205        send_kbd_command(0xb8);
206        send_kbd_data(index);
207        send_kbd_command(0xbb);
208        send_kbd_data(data);
209}
210
211static u8 m3885_get_proc_ram(u8 index)
212{
213        u8 ret;
214
215        send_kbd_command(0xb8);
216        send_kbd_data(index);
217        send_kbd_command(0xba);
218        // send_kbd_command(0xff);
219        ret = recv_kbd_data();
220        printk(BIOS_SPEW, "m3885: get procram %02x = %02x\n", index, ret);
221        return ret;
222}
223
224static u8 m3885_read_port(void)
225{
226        u8 reg8;
227
228        reg8 = m3885_get_variable(0x0c);
229        reg8 &= ~(7 << 4);
230        reg8 |= (4 << 4);       // bank 4
231        m3885_set_variable(0x0c, reg8);
232
233        /* P6YSTATE */
234        return m3885_get_proc_ram(0xf8);
235}
236
237void m3885_configure_multikey(void)
238{
239        int i;
240        u8 reg8;
241        u8 kstate5_flags, offs, maxvars;
242
243        /* ram bank 0 */
244        kstate5_flags = m3885_get_variable(0x0c);
245        m3885_set_variable(0x0c, kstate5_flags & ~(7 << 4));
246
247        /* Write Matrix to bank 0 */
248        for (i=0; i < ARRAY_SIZE(matrix); i++) {
249                m3885_set_proc_ram(i + 0x80, matrix[i]);
250        }
251
252
253        /* ram bank 2 */
254        m3885_set_variable(0x0c, (kstate5_flags & (~(7 << 4))) | (2 << 4));
255
256        /* Get the number of variables */
257        maxvars = m3885_get_variable(0x00);
258        printk(BIOS_DEBUG, "M388x has %d variables in bank 2.\n", maxvars);
259        if (maxvars >= 35) {
260                offs = m3885_get_variable(0x23);
261                if ((offs > 0xc0) || (offs < 0x80)) {
262                        printk(BIOS_DEBUG, "M388x does not have a valid ram offset (0x%x)\n", offs);
263                } else {
264                        printk(BIOS_DEBUG, "Writing Fn-Table to M388x RAM offset 0x%x\n", offs);
265                        for (i=0; i < ARRAY_SIZE(function_ram); i++) {
266                                m3885_set_proc_ram(i + offs, function_ram[i]);
267                        }
268                }
269        } else {
270                printk(BIOS_DEBUG, "Could not load Function-RAM (%d).\n", maxvars);
271        }
272
273        // restore original bank
274        m3885_set_variable(0x0c, kstate5_flags);
275        maxvars = m3885_get_variable(0x00);
276        printk(BIOS_DEBUG, "M388x has %d variables in original bank.\n", maxvars);
277        for (i=0; i<ARRAY_SIZE(variables); i+=3) {
278                if(variables[i + 0] > maxvars)
279                        continue;
280                reg8 = m3885_get_variable(variables[i + 0]);
281                reg8 &= ~(variables[i + 1]);
282                reg8 |= variables[i + 2]; //  & ~variables[i + 1];
283                m3885_set_variable(variables[i + 0], reg8);
284        }
285
286        /* OEM Init */
287
288        /* Set Bank 1 */
289        m3885_set_variable(0x0c, (kstate5_flags & ~(7 << 4)) | (1 << 4));
290
291        /* Set SMI# at P5.1 */
292        /* SMI Control -> p5.1 = EXTSMI# */
293        m3885_set_proc_ram(0xff, 0xc1);
294
295        /* Set Fn-Key Task 0 -> SMI#/SCI */
296        m3885_set_proc_ram(0x6d, 0x81);
297
298        /* Set Fn-Key Task 1 -> SCI */
299        m3885_set_proc_ram(0x6c, 0x80);
300
301        /* Number of Thermal Sensors */
302        m3885_set_proc_ram(0xf2, 0x02);
303
304        /* Critical Task */
305        m3885_set_proc_ram(0xf3, 0x5d);
306
307        /* Thermal Polling Period */
308        m3885_set_proc_ram(0xf9, 0x0a);
309
310        /* ReadPort */
311        // m3885_set_variable(0x0c, (kstate5_flags & ~(7 << 4)) | (4 << 4));
312
313        /* AC PRESN# */
314        if (m3885_read_port() & (1 << 0))
315                reg8 = 0x8a;
316        else
317                reg8 = 0x9a;
318        m3885_set_proc_ram(0xd0, reg8); // P60SPEC
319
320        /* SENSE1# */
321        if (m3885_read_port() & (1 << 2))
322                reg8 = 0x8a;
323        else
324                reg8 = 0x9a;
325        m3885_set_proc_ram(0xd2, reg8); // P62SPEC
326
327        /* SENSE2# */
328        if (m3885_read_port() & (1 << 3))
329                reg8 = 0x8a;
330        else
331                reg8 = 0x9a;
332        m3885_set_proc_ram(0xd3, reg8); // P63SPEC
333
334        /* Low Active Port */
335        m3885_set_proc_ram(0xd1, 0x88); // P61SPEC
336        m3885_set_proc_ram(0xd6, 0x88); // P66SPEC
337        m3885_set_proc_ram(0xd7, 0x88); // P67SPEC
338
339        /* High Active Port */
340        m3885_set_proc_ram(0xd4, 0x98); // P64SPEC
341        m3885_set_proc_ram(0xd5, 0x98); // P65SPEC
342
343        /* Set P60TASK-P67TASK */
344        /* SCI */
345        m3885_set_proc_ram(0xda, 0x80); // P62TASK SENSE1#
346        m3885_set_proc_ram(0xdb, 0x80); // P63TASK SENSE2#
347        m3885_set_proc_ram(0xdd, 0x80); // P65TASK PROCHOT
348        m3885_set_proc_ram(0xde, 0x80); // P65TASK THERMTRIP#
349        m3885_set_proc_ram(0xdf, 0x80); // P65TASK PME#
350        /* SMI/SCI */
351        m3885_set_proc_ram(0xd8, 0x81); // P60TASK, AC_PRESN#
352        m3885_set_proc_ram(0xd9, 0x81); // P61TASK, LID#
353        m3885_set_proc_ram(0xdc, 0x81); // P64TASK, FDD/LPT#
354
355        /* Thermal */
356        /* Bank 5 */
357        m3885_set_variable(0x0c, (kstate5_flags & ~(7 << 4)) | (5 << 4));
358
359        /* Thermal 0: Active cooling, Speed Step Down */
360        m3885_set_proc_ram(0x81, 0x9c);    // THRM0
361        m3885_set_proc_ram(0x82, 0x01);    // THRM0 CMD
362        m3885_set_proc_ram(0x84, TH0LOW);  // THRM0 LOW
363        m3885_set_proc_ram(0x85, TH0HIGH); // THRM0 HIGH
364        m3885_set_proc_ram(0x86, 0x81);    // Set Task SMI#/SCI
365        m3885_set_proc_ram(0x87, TH0CRIT); // THRM0 CRIT
366
367        /* Thermal 1: Passive cooling, Fan On */
368        m3885_set_proc_ram(0x89, 0x9c);    // THRM1
369        m3885_set_proc_ram(0x8a, 0x01);    // THRM1 CMD
370        m3885_set_proc_ram(0x8c, TH1LOW);  // THRM1 LOW
371        m3885_set_proc_ram(0x8d, TH1HIGH); // THRM1 HIGH
372        m3885_set_proc_ram(0x8e, 0x81);    // Set Task SMI#/SCI
373
374        /* Switch Task to SMI */
375        udelay(100 * 1000); // 100ms
376        outb(KBD_SC, 0xca);
377        udelay(100 * 1000); // 100ms
378        outb(KBD_DATA, 0x17);
379
380        /* Set P22 to high level, keyboard backlight default off */
381        udelay(100 * 1000); // 100ms
382        outb(KBD_SC, 0xc5);
383        udelay(100 * 1000); // 100ms
384        outb(KBD_DATA, 0x4a);
385}
386
387u8 m3885_gpio(u8 value)
388{
389#if 0
390        int timeout;
391#endif
392
393        /* First write data */
394        ec_write(M3885_CMDAT1, value);
395
396        /* Issue command: ACCESS GPIO */
397        ec_write(M3885_CMCMD, 0xc5);
398
399#if 0
400        /* CMCMD is 0 when the command is completed */
401        timeout = 0xf;
402        while (ec_read(M3885_CMCMD) && --timeout) {
403                udelay(10);
404                printk(BIOS_DEBUG, ".");
405        }
406        if (!timeout) {
407                printk(BIOS_DEBUG, "\nTimeout while waiting for M3885 command!\n");
408        }
409
410        /* If it was a read function: Pin state */
411        return ec_read(M3885_CMDAT1);
412#else
413        return 0;
414#endif
415}
416
Note: See TracBrowser for help on using the repository browser.