please forgive me... ;)
[coreboot.git] / src / arch / i386 / boot / acpi.c
1 /*
2  * LinuxBIOS ACPI Table support
3  * written by Stefan Reinauer <stepan@openbios.org>
4  * (C) 2004 SUSE LINUX AG
5  */
6
7 #include <console/console.h>
8 #include <string.h>
9 #include <arch/acpi.h>
10
11 #define RSDP_SIG              "RSD PTR "  /* RSDT Pointer signature */
12 #define RSDP_NAME             "RSDP"
13
14 #define RSDT_NAME             "RSDT"
15 #define HPET_NAME             "HPET"
16 #define RSDT_TABLE            "  RSDT  "
17 #define HPET_TABLE            "AMD64   "
18
19 #define OEM_ID                "LXBIOS"
20 #define ASLC                  "NONE"
21
22 static u8 acpi_checksum(u8 *table, u32 length)
23 {
24         u8 ret=0;
25         while (length--) {
26                 ret += *table;
27                 table++;
28         }
29         return ret;
30 }
31
32 static void acpi_add_table(acpi_rsdt_t *rsdt, void *table)
33 {
34         int i;
35
36         for (i=0; i<8; i++) {
37                 if(rsdt->entry[i]==0) {
38                         rsdt->entry[i]=(u32)table;
39                         /* fix checksum */
40                         /* hope this won't get optimized away */
41                         rsdt->header.checksum=0;
42                         rsdt->header.checksum=acpi_checksum((u8 *)rsdt,
43                                         rsdt->header.length);
44                         
45                         printk_debug("ACPI: added table %d/8\n",i);
46                         return;
47                 }
48         }
49
50         printk_warning("ACPI: could not ACPI table. failed.\n");
51 }
52
53 static void acpi_create_hpet(acpi_hpet_t *hpet)
54 {
55 #define HPET_ADDR  0xfed00000ULL
56         acpi_header_t *header=&(hpet->header);
57         acpi_addr_t *addr=&(hpet->addr);
58         
59         /* fill out header fields */
60         memcpy(header->signature, HPET_NAME, 4);
61         memcpy(header->oem_id, OEM_ID, 6);
62         memcpy(header->oem_table_id, HPET_TABLE, 8);
63         memcpy(header->asl_compiler_id, ASLC, 4);
64         
65         header->length = sizeof(acpi_hpet_t);
66         header->revision = 1;
67
68         /* fill out HPET address */
69         addr->space_id          = 0; /* Memory */
70         addr->bit_width         = 64;
71         addr->bit_offset        = 0;
72         addr->addrl             = HPET_ADDR & 0xffffffff;
73         addr->addrh             = HPET_ADDR >> 32;
74
75         hpet->id        = 0x102282a0; /* AMD ? */
76         hpet->number    = 0;
77         hpet->min_tick  = 4096;
78         
79 }
80
81 static void acpi_write_rsdt(acpi_rsdt_t *rsdt)
82
83         acpi_header_t *header=&(rsdt->header);
84         
85         /* fill out header fields */
86         memcpy(header->signature, RSDT_NAME, 4);
87         memcpy(header->oem_id, OEM_ID, 6);
88         memcpy(header->oem_table_id, RSDT_TABLE, 8);
89         memcpy(header->asl_compiler_id, ASLC, 4);
90         
91         header->length = sizeof(acpi_rsdt_t);
92         header->revision = 1;
93         
94         /* fill out entries */
95
96         // entries are filled in later, we come with an empty set.
97         
98         /* fix checksum */
99         
100         header->checksum        = acpi_checksum((void *)rsdt, sizeof(acpi_rsdt_t));
101 }
102
103 static void acpi_write_rsdp(acpi_rsdp_t *rsdp, acpi_rsdt_t *rsdt)
104 {
105         memcpy(rsdp->signature, RSDP_SIG, 8);
106         memcpy(rsdp->oem_id, OEM_ID, 6);
107         
108         rsdp->length            = sizeof(acpi_rsdp_t);
109         rsdp->rsdt_address      = (u32)rsdt;
110         rsdp->checksum          = acpi_checksum((void *)rsdp, sizeof(acpi_rsdp_t));
111         
112 }
113
114 unsigned long write_acpi_tables(unsigned long start)
115 {
116         unsigned long current = start;
117         acpi_rsdp_t *rsdp;
118         acpi_rsdt_t *rsdt;
119         acpi_hpet_t *hpet;
120         
121         printk_info("ACPI: Writing ACPI tables at %lx...\n", start);
122
123         /* We need at least an RSDP and an RSDT Table */
124         rsdp = (acpi_rsdp_t *) current;
125         current += sizeof(acpi_rsdp_t);
126         rsdt = (acpi_rsdt_t *) current;
127         current += sizeof(acpi_rsdt_t);
128
129         /* clear all table memory */
130         memset((void *)start, 0, current - start);
131         
132         acpi_write_rsdp(rsdp, rsdt);
133         acpi_write_rsdt(rsdt);
134         
135         /*
136          * We explicitly add these tables later on:
137          */
138 #define HAVE_ACPI_HPET
139 #ifdef HAVE_ACPI_HPET
140         printk_debug("ACPI:    * HPET\n");
141
142         hpet = (acpi_hpet_t *) current;
143         current += sizeof(acpi_hpet_t);
144         
145         acpi_create_hpet(hpet);
146         acpi_add_table(rsdt,hpet);
147 #endif
148         printk_info("ACPI: done.\n");
149         return current;
150 }
151