9a65f3830a68ff52f2a6b69e99f1ff77051e7bce
[coreboot.git] / src / southbridge / amd / sb600 / sb600.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2008 Advanced Micro Devices, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20 #include <types.h>
21 #include <lib.h>
22 #include <console.h>
23 #include <device/pci.h>
24 #include <msr.h>
25 #include <legacy.h>
26 #include <device/pci_ids.h>
27 #include <statictree.h>
28 #include <config.h>
29 #include "sb600.h"
30
31 static struct device * find_sm_dev(struct device * dev, u32 devfn)
32 {
33         struct device * sm_dev;
34
35         sm_dev = dev_find_slot(dev->bus->secondary, devfn);
36         if (!sm_dev)
37                 return sm_dev;
38
39         if ((sm_dev->vendor != PCI_VENDOR_ID_ATI) ||
40             ((sm_dev->device != PCI_DEVICE_ID_ATI_SB600_SM))) {
41                 u32 id;
42                 id = pci_read_config32(sm_dev, PCI_VENDOR_ID);
43                 if ((id !=
44                      (PCI_VENDOR_ID_ATI | (PCI_DEVICE_ID_ATI_SB600_SM << 16))))
45                 {
46                         sm_dev = 0;
47                 }
48         }
49
50         return sm_dev;
51 }
52
53 void set_sm_enable_bits(struct device * sm_dev, u32 reg_pos, u32 mask, u32 val)
54 {
55         u32 reg_old, reg;
56         reg = reg_old = pci_read_config32(sm_dev, reg_pos);
57         reg &= ~mask;
58         reg |= val;
59         if (reg != reg_old) {
60                 pci_write_config32(sm_dev, reg_pos, reg);
61         }
62 }
63
64 static void pmio_write_index(unsigned long port_base, u8 reg, u8 value)
65 {
66         outb(reg, port_base);
67         outb(value, port_base + 1);
68 }
69
70 static u8 pmio_read_index(unsigned long port_base, u8 reg)
71 {
72         outb(reg, port_base);
73         return inb(port_base + 1);
74 }
75
76 void pm_iowrite(u8 reg, u8 value)
77 {
78         unsigned long port_base = 0xcd6;
79         pmio_write_index(port_base, reg, value);
80 }
81
82 u8 pm_ioread(u8 reg)
83 {
84         unsigned long port_base = 0xcd6;
85         return pmio_read_index(port_base, reg);
86 }
87
88 void pm2_iowrite(u8 reg, u8 value)
89 {
90         unsigned long port_base = 0xcd0;
91         pmio_write_index(port_base, reg, value);
92 }
93
94 u8 pm2_ioread(u8 reg)
95 {
96         unsigned long port_base = 0xcd0;
97         return pmio_read_index(port_base, reg);
98 }
99
100 static void set_pmio_enable_bits(struct device * sm_dev, u32 reg_pos,
101                                  u32 mask, u32 val)
102 {
103         u8 reg_old, reg;
104         reg = reg_old = pm_ioread(reg_pos);
105         reg &= ~mask;
106         reg |= val;
107         if (reg != reg_old) {
108                 pm_iowrite(reg_pos, reg);
109         }
110 }
111
112 void sb600_enable(struct device * dev)
113 {
114         struct device * sm_dev = 0;
115         struct device * bus_dev = 0;
116         int index = -1;
117         u32 deviceid;
118         u32 vendorid;
119
120         /* struct southbridge_ati_sb600_config *conf; */
121         /* conf = dev->chip_info; */
122         int i;
123
124         u32 devfn;
125
126         printk(BIOS_DEBUG, "sb600_enable()\n");
127
128 /*
129 *       0:12.0  SATA    bit 8 of sm_dev 0xac : 1 - enable, default         + 32 * 3
130 *       0:13.1  USB-1   bit 2 of sm_dev 0x68
131 *       0:13.2  USB-2   bit 3 of sm_dev 0x68
132 *       0:13.3  USB-3   bit 4 of sm_dev 0x68
133 *       0:13.4  USB-4   bit 5 of sm_dev 0x68
134 *       0:13.5  USB2    bit 0 of sm_dev 0x68 : 1 - enable, default
135 *       0:14.0  SMBUS                                                   0
136 *       0:14.1  IDE                                                     1
137 *       0:14.2  HDA     bit 3 of pm_io 0x59 : 1 - enable, default           + 32 * 4
138 *       0:14.3  LPC     bit 20 of sm_dev 0x64 : 0 - disable, default  + 32 * 1
139 *       0:14.4  PCI                                                     4
140 *       0:14.5  ACI     bit 0 of pm_io 0x59 : 0 - enable, default
141 *       0:14.6  MCI     bit 1 of pm_io 0x59 : 0 - enable, default
142 */
143         if (dev->device == 0x0000) {
144                 vendorid = pci_read_config32(dev, PCI_VENDOR_ID);
145                 deviceid = (vendorid >> 16) & 0xffff;
146                 vendorid &= 0xffff;
147         } else {
148                 vendorid = dev->vendor;
149                 deviceid = dev->device;
150         }
151         bus_dev = dev->bus->dev;
152         if ((bus_dev->vendor == PCI_VENDOR_ID_ATI) &&
153             (bus_dev->device == PCI_DEVICE_ID_ATI_SB600_PCI)) {
154                 devfn = (bus_dev->path.pci.devfn) & ~7;
155                 sm_dev = find_sm_dev(bus_dev, devfn);
156                 if (!sm_dev)
157                         return;
158
159                 /* something under 00:01.0 */
160                 switch (dev->path.pci.devfn) {
161                 case 5 << 3:
162                         ;
163                 }
164
165                 return;
166         }
167
168         i = (dev->path.pci.devfn) & ~7;
169         i += (2 << 3);
170         for (devfn = (0x14 << 3); devfn <= i; devfn += (1 << 3)) {
171                 sm_dev = find_sm_dev(dev, devfn);
172                 if (sm_dev)
173                         break;
174         }
175         if (!sm_dev)
176                 return;
177
178         switch (dev->path.pci.devfn - (devfn - (0x14 << 3))) {
179         case (0x12 << 3) | 0:
180                 index = 8;
181                 set_sm_enable_bits(sm_dev, 0xac, 1 << index,
182                                    (dev->enabled ? 1 : 0) << index);
183                 index += 32 * 3;
184                 break;
185         case (0x13 << 3) | 0:
186         case (0x13 << 3) | 1:
187         case (0x13 << 3) | 2:
188         case (0x13 << 3) | 3:
189         case (0x13 << 3) | 4:
190         case (0x13 << 3) | 5:
191                 index = dev->path.pci.devfn & 7;
192                 index++;
193                 index %= 6;
194                 set_sm_enable_bits(sm_dev, 0x68, 1 << index,
195                                    (dev->enabled ? 1 : 0) << index);
196                 index += 32 * 2;
197                 break;
198         case (0x14 << 3) | 0:
199                 index = 0;
200                 break;
201         case (0x14 << 3) | 1:
202                 index = 1;
203                 break;
204         case (0x14 << 3) | 2:
205                 index = 3;
206                 set_pmio_enable_bits(sm_dev, 0x59, 1 << index,
207                                      (dev->enabled ? 1 : 0) << index);
208                 index += 32 * 4;
209                 break;
210         case (0x14 << 3) | 3:
211                 index = 20;
212                 set_sm_enable_bits(sm_dev, 0x64, 1 << index,
213                                    (dev->enabled ? 1 : 0) << index);
214                 index += 32 * 1;
215                 break;
216         case (0x14 << 3) | 4:
217                 index = 4;
218                 break;
219         case (0x14 << 3) | 5:
220         case (0x14 << 3) | 6:
221                 index = dev->path.pci.devfn & 7;
222                 index -= 5;
223                 set_pmio_enable_bits(sm_dev, 0x59, 1 << index,
224                                      (dev->enabled ? 0 : 1) << index);
225                 index += 32 * 4;
226                 break;
227         default:
228                 printk(BIOS_DEBUG, "unknown dev: %s deviceid=%4x\n", dev_path(dev),
229                              deviceid);
230         }
231 }
232
233 struct device_operations sb600 = {
234         .id = {.type = DEVICE_ID_PCI,
235                 {.pci = {.vendor = PCI_VENDOR_ID_AMD,
236                               .device = xz}}},
237         .constructor             = default_device_constructor,
238         .phase3_scan             = 0,
239         .phase4_enable_disable           = sb600_enable,
240         .phase4_read_resources   = pci_dev_read_resources,
241         .phase4_set_resources    = pci_dev_set_resources,
242         .phase6_init             = NULL,
243         .ops_pci                 = &pci_dev_ops_pci,
244 };