Intel E7501 P64H2 ICH5R support
[coreboot.git] / src / superio / winbond / w83627hf / superio.c
1 /* Copyright 2000  AG Electronics Ltd. */
2 /* Copyright 2003-2004 Linux Networx */
3 /* Copyright 2004 Tyan 
4    By LYH change from PC87360 */
5 /* This code is distributed without warranty under the GPL v2 (see COPYING) */
6
7 #include <arch/io.h>
8 #include <device/device.h>
9 #include <device/pnp.h>
10 #include <device/chip.h>
11 #include <console/console.h>
12 #include <string.h>
13 #include <bitops.h>
14 #include <uart8250.h>
15 #include <pc80/keyboard.h>
16 #include "chip.h"
17 #include "w83627hf.h"
18
19
20 void pnp_enter_ext_func_mode(device_t dev) {
21         outb(0x87, dev->path.u.pnp.port);
22         outb(0x87, dev->path.u.pnp.port);
23 }
24 void pnp_exit_ext_func_mode(device_t dev) {
25         outb(0xaa, dev->path.u.pnp.port);
26 }
27
28 void pnp_write_hwm(unsigned long port_base, uint8_t reg, uint8_t value)
29 {
30         outb(reg, port_base+5);
31         outb(value, port_base+6);
32 }
33
34 uint8_t pnp_read_hwm(unsigned long port_base, uint8_t reg)
35 {
36         outb(reg, port_base + 5);
37         return inb(port_base + 6);
38 }       
39
40 static void enable_hwm_smbus(device_t dev) {
41         uint8_t reg, value;
42         reg = 0x2b;
43         value = pnp_read_config(dev, reg);
44         value &= 0x3f;
45         pnp_write_config(dev, reg, value);
46 }
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 static void init_hwm(unsigned long base)
77 {
78         uint8_t  reg, value;
79         int i;
80
81         unsigned  hwm_reg_values[] = {
82 //             reg                mask             data
83               0x40     ,       0xff    ,       0x81,  //  ; Start Hardware Monitoring for WIN627
84               0x48     ,       0xaa    ,       0x2a,  //  ; Program SIO SMBus BAR to 54h>>1     
85 //              0x48     ,       0xc8    ,       0x48,  //  ; Program SIO SMBus BAR to 90h>>1
86               0x4A     ,       0x21    ,       0x21,  //  ; Program T2 SMBus BAR to 92h>>1 &
87                                                      //  ; Program T3 SMBus BAR to 94h>>1
88               0x4E     ,       0x80    ,       0x00,  
89               0x43     ,       0x00    ,       0xFF,
90               0x44     ,       0x00    ,       0x3F,
91               0x4C     ,       0xBF    ,       0x18,
92               0x4D     ,       0xFF    ,       0x80   //  ; Turn Off Beep
93                                                                             
94         };
95
96         for(i = 0; i<  sizeof(hwm_reg_values)/sizeof(hwm_reg_values[0]); i+=3 ) { 
97                 reg = hwm_reg_values[i];        
98                 value = pnp_read_hwm(base, reg);                
99                 value &= 0xff & hwm_reg_values[i+1];
100                 value |= 0xff & hwm_reg_values[i+2];
101 #if 0
102                 printk_debug("base = 0x%04x, reg = 0x%02x, value = 0x%02x\r\n", base,reg,value);
103 #endif
104                 pnp_write_hwm(base,reg, value);
105         }
106 }
107
108
109 static void w83627hf_init(device_t dev)
110 {
111         struct superio_winbond_w83627hf_config *conf;
112         struct resource *res0, *res1;
113         if (!dev->enabled) {
114                 return;
115         }
116         conf = dev->chip->chip_info;
117         switch(dev->path.u.pnp.device) {
118         case W83627HF_SP1: 
119                 res0 = get_resource(dev, PNP_IDX_IO0);
120                 init_uart8250(res0->base, &conf->com1);
121                 break;
122         case W83627HF_SP2:
123                 res0 = get_resource(dev, PNP_IDX_IO0);
124                 init_uart8250(res0->base, &conf->com2);
125                 break;
126         case W83627HF_KBC:
127                 res0 = get_resource(dev, PNP_IDX_IO0);
128                 res1 = get_resource(dev, PNP_IDX_IO1);
129                 init_pc_keyboard(res0->base, res1->base, &conf->keyboard);
130                 break;
131         case W83627HF_HWM:
132                 res0 = get_resource(dev, PNP_IDX_IO0);
133                 init_hwm(res0->base);
134                 break;
135         }
136         
137 }
138
139 void w83627hf_pnp_set_resources(device_t dev)
140 {
141
142         pnp_enter_ext_func_mode(dev);  
143
144         pnp_set_resources(dev);
145
146 #if 0
147         dump_pnp_device(dev);
148 #endif
149                 
150         pnp_exit_ext_func_mode(dev);  
151         
152 }       
153         
154 void w83627hf_pnp_enable_resources(device_t dev)
155 {       
156         pnp_enter_ext_func_mode(dev);  
157         
158         pnp_enable_resources(dev);               
159
160         switch(dev->path.u.pnp.device) {
161         case W83627HF_HWM:
162                 //set the pin 91,92 as I2C bus
163                 printk_debug("w83627hf hwm smbus enabled\r\n");
164                 enable_hwm_smbus(dev);
165                 break;
166         }
167
168 #if 0  
169         dump_pnp_device(dev);
170 #endif
171
172         pnp_exit_ext_func_mode(dev);  
173
174 }
175
176 void w83627hf_pnp_enable(device_t dev)
177 {
178
179         if (!dev->enabled) {
180                 pnp_enter_ext_func_mode(dev);   
181
182                 pnp_set_logical_device(dev);
183                 pnp_set_enable(dev, 0);
184
185                 pnp_exit_ext_func_mode(dev);  
186         }
187 }
188
189 static struct device_operations ops = {
190         .read_resources   = pnp_read_resources,
191         .set_resources    = w83627hf_pnp_set_resources,
192         .enable_resources = w83627hf_pnp_enable_resources,
193         .enable           = w83627hf_pnp_enable,
194         .init             = w83627hf_init,
195 };
196
197 static struct pnp_info pnp_dev_info[] = {
198         { &ops, W83627HF_FDC,  PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07f8, 0}, },
199         { &ops, W83627HF_PP,   PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07f8, 0}, },
200         { &ops, W83627HF_SP1,  PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
201         { &ops, W83627HF_SP2,  PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
202         // No 4 { 0,},
203         { &ops, W83627HF_KBC,  PNP_IO0 | PNP_IO1 | PNP_IRQ0 | PNP_IRQ1, { 0x7ff, 0 }, { 0x7ff, 0x4}, },
204         { &ops, W83627HF_CIR, PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
205         { &ops, W83627HF_GAME_MIDI_GPIO1, PNP_IO0 | PNP_IO1 | PNP_IRQ0, { 0x7ff, 0 }, {0x7fe, 4} },
206         { &ops, W83627HF_GPIO2,},
207         { &ops, W83627HF_GPIO3,},
208         { &ops, W83627HF_ACPI, PNP_IRQ0,  },
209         { &ops, W83627HF_HWM,  PNP_IO0 | PNP_IRQ0, { 0xff8, 0 } },
210 };
211
212 static void enumerate(struct chip *chip)
213 {
214         pnp_enumerate(chip, sizeof(pnp_dev_info)/sizeof(pnp_dev_info[0]), 
215                 &pnp_ops, pnp_dev_info);
216 }
217
218 struct chip_control superio_winbond_w83627hf_control = {
219         .enumerate = enumerate,
220         .name      = "Winbond w83627hf"
221 };
222