Revision: linuxbios@linuxbios.org--devel/freebios--devel--2.0--patch-30
[coreboot.git] / src / superio / smsc / lpc47b397 / superio.c
1 /* Copyright 2000  AG Electronics Ltd. */
2 /* Copyright 2003-2004 Linux Networx */
3 /* Copyright 2004 Tyan 
4  */ 
5
6 /* This code is distributed without warranty under the GPL v2 (see COPYING) */
7
8 #include <arch/io.h>
9 #include <device/device.h>
10 #include <device/pnp.h>
11 #include <console/console.h>
12 #include <device/smbus.h>
13 #include <string.h>
14 #include <bitops.h>
15 #include <uart8250.h>
16 #include <pc80/keyboard.h>
17 #include "chip.h"
18 #include "lpc47b397.h"
19
20
21 static void pnp_enter_conf_state(device_t dev) {
22         outb(0x55, dev->path.u.pnp.port);
23 }
24 static void pnp_exit_conf_state(device_t dev) {
25         outb(0xaa, dev->path.u.pnp.port);
26 }
27
28 static void pnp_write_index(unsigned long port_base, uint8_t reg, uint8_t value)
29 {
30         outb(reg, port_base);
31         outb(value, port_base + 1);
32 }
33
34 static uint8_t pnp_read_index(unsigned long port_base, uint8_t reg)
35 {
36         outb(reg, port_base);
37         return inb(port_base + 1);
38 }
39
40 static void enable_hwm_smbus(device_t dev) {
41         /* enable SensorBus register access */
42         uint8_t reg, value;
43         reg = 0xf0; 
44         value = pnp_read_config(dev, reg);
45         value |= 0x01;
46         pnp_write_config(dev, reg, value);
47
48 #if 0
49 static void dump_pnp_device(device_t dev)
50 {
51         int i;
52         print_debug("\r\n");
53
54         for(i = 0; i <= 255; i++) {
55                 uint8_t reg, val;
56                 if ((i & 0x0f) == 0) {
57                         print_debug_hex8(i);
58                         print_debug_char(':');
59                 }
60                 reg = i;
61                 if(i!=0xaa) {
62                         val = pnp_read_config(dev, reg);
63                 }
64                 else {
65                         val = 0xaa;
66                 }
67                 print_debug_char(' ');
68                 print_debug_hex8(val);
69                 if ((i & 0x0f) == 0x0f) {
70                         print_debug("\r\n");
71                 }
72         }
73 }
74 #endif
75
76
77 static void lpc47b397_init(device_t dev)
78 {
79         struct superio_smsc_lpc47b397_config *conf;
80         struct resource *res0, *res1;
81         if (!dev->enabled) {
82                 return;
83         }
84         conf = dev->chip_info;
85         switch(dev->path.u.pnp.device) {
86         case LPC47B397_SP1: 
87                 res0 = find_resource(dev, PNP_IDX_IO0);
88                 init_uart8250(res0->base, &conf->com1);
89                 break;
90         case LPC47B397_SP2:
91                 res0 = find_resource(dev, PNP_IDX_IO0);
92                 init_uart8250(res0->base, &conf->com2);
93                 break;
94         case LPC47B397_KBC:
95                 res0 = find_resource(dev, PNP_IDX_IO0);
96                 res1 = find_resource(dev, PNP_IDX_IO1);
97                 init_pc_keyboard(res0->base, res1->base, &conf->keyboard);
98                 break;
99         }
100         
101 }
102
103 void lpc47b397_pnp_set_resources(device_t dev)
104 {
105
106         pnp_enter_conf_state(dev);  
107
108         pnp_set_resources(dev);
109
110 #if 0
111         dump_pnp_device(dev);
112 #endif
113                 
114         pnp_exit_conf_state(dev);  
115         
116 }       
117         
118 void lpc47b397_pnp_enable_resources(device_t dev)
119 {       
120
121         pnp_enter_conf_state(dev);
122
123         pnp_enable_resources(dev);
124
125         switch(dev->path.u.pnp.device) {
126         case LPC47B397_HWM:
127                 printk_debug("lpc47b397 SensorBus Register Access enabled\r\n");
128                 pnp_set_logical_device(dev);
129                 enable_hwm_smbus(dev);
130                 break;
131         }
132
133 #if 0  
134         dump_pnp_device(dev);
135 #endif
136
137         pnp_exit_conf_state(dev);
138
139 }
140
141 void lpc47b397_pnp_enable(device_t dev)
142 {
143
144         pnp_enter_conf_state(dev);   
145
146         pnp_set_logical_device(dev);
147
148         if(dev->enabled) {
149                 pnp_set_enable(dev, 1);
150         }
151         else {
152                 pnp_set_enable(dev, 0);
153         }
154
155         pnp_exit_conf_state(dev);  
156         
157 }
158
159 static struct device_operations ops = {
160         .read_resources   = pnp_read_resources,
161         .set_resources    = lpc47b397_pnp_set_resources,
162         .enable_resources = lpc47b397_pnp_enable_resources,
163         .enable           = lpc47b397_pnp_enable,
164         .init             = lpc47b397_init,
165 };
166
167
168 #define HWM_INDEX 0
169 #define HWM_DATA  1
170 #define SB_INDEX  0x0b
171 #define SB_DATA0  0x0c
172 #define SB_DATA1  0x0d
173 #define SB_DATA2  0x0e
174 #define SB_DATA3  0x0f
175
176 static int lsmbus_read_byte(device_t dev, uint8_t address)
177 {
178         unsigned device;
179         struct resource *res;
180         int result;
181
182         device = dev->path.u.i2c.device;
183
184         res = find_resource(get_pbus_smbus(dev)->dev, PNP_IDX_IO0);
185
186         pnp_write_index(res->base+HWM_INDEX, 0, device); // why 0?
187         
188         result = pnp_read_index(res->base+SB_INDEX, address); // we only read it one byte one time
189         
190         return result;
191 }
192
193 static int lsmbus_write_byte(device_t dev, uint8_t address, uint8_t val)
194 {       
195         unsigned device;
196         struct resource *res;
197         
198         device = dev->path.u.i2c.device;
199         res = find_resource(get_pbus_smbus(dev)->dev, PNP_IDX_IO0);
200
201         pnp_write_index(res->base+HWM_INDEX, 0, device); // why 0?
202
203         pnp_write_index(res->base+SB_INDEX, address, val); // we only write it one byte one time
204         
205         return 0;
206 }
207
208 static struct smbus_bus_operations lops_smbus_bus = {
209 //        .recv_byte  = lsmbus_recv_byte,
210 //        .send_byte  = lsmbus_send_byte,
211         .read_byte  = lsmbus_read_byte,
212         .write_byte = lsmbus_write_byte,
213 };
214 static struct device_operations ops_hwm = {
215         .read_resources   = pnp_read_resources,
216         .set_resources    = lpc47b397_pnp_set_resources,
217         .enable_resources = lpc47b397_pnp_enable_resources,
218         .enable           = lpc47b397_pnp_enable,
219         .init             = lpc47b397_init,
220         .scan_bus         = scan_static_bus,
221         .ops_smbus_bus    = &lops_smbus_bus,
222 };
223
224 static struct pnp_info pnp_dev_info[] = {
225         { &ops, LPC47B397_FDC,  PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07f8, 0}, },
226         { &ops, LPC47B397_PP,   PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07f8, 0}, },
227         { &ops, LPC47B397_SP1,  PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
228         { &ops, LPC47B397_SP2,  PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
229         { &ops, LPC47B397_KBC,  PNP_IO0 | PNP_IO1 | PNP_IRQ0 | PNP_IRQ1, { 0x7ff, 0 }, { 0x7ff, 0x4}, },
230         { &ops_hwm, LPC47B397_HWM,  PNP_IO0, { 0x7f0, 0 }, },
231         { &ops, LPC47B397_RT,   PNP_IO0, { 0x780, 0 }, },
232 };
233
234 static void enable_dev(struct device *dev)
235 {
236         pnp_enable_devices(dev, &pnp_ops,
237                 sizeof(pnp_dev_info)/sizeof(pnp_dev_info[0]), pnp_dev_info);
238 }
239
240 struct chip_operations superio_smsc_lpc47b397_ops = {
241         CHIP_NAME("smsc lpc47b397")
242         .enable_dev = enable_dev,
243 };
244