printk_foo -> printk(BIOS_FOO, ...)
[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 <console/console.h>
21
22 #include <arch/io.h>
23
24 #include <device/device.h>
25 #include <device/pci.h>
26 #include <device/pci_ids.h>
27 #include <device/pci_ops.h>
28 #include "sb600.h"
29
30 static device_t find_sm_dev(device_t dev, u32 devfn)
31 {
32         device_t sm_dev;
33
34         sm_dev = dev_find_slot(dev->bus->secondary, devfn);
35         if (!sm_dev)
36                 return sm_dev;
37
38         if ((sm_dev->vendor != PCI_VENDOR_ID_ATI) ||
39             ((sm_dev->device != PCI_DEVICE_ID_ATI_SB600_SM))) {
40                 u32 id;
41                 id = pci_read_config32(sm_dev, PCI_VENDOR_ID);
42                 if ((id !=
43                      (PCI_VENDOR_ID_ATI | (PCI_DEVICE_ID_ATI_SB600_SM << 16))))
44                 {
45                         sm_dev = 0;
46                 }
47         }
48
49         return sm_dev;
50 }
51
52 void set_sm_enable_bits(device_t sm_dev, u32 reg_pos, u32 mask, u32 val)
53 {
54         u32 reg_old, reg;
55         reg = reg_old = pci_read_config32(sm_dev, reg_pos);
56         reg &= ~mask;
57         reg |= val;
58         if (reg != reg_old) {
59                 pci_write_config32(sm_dev, reg_pos, reg);
60         }
61 }
62
63 static void pmio_write_index(u16 port_base, u8 reg, u8 value)
64 {
65         outb(reg, port_base);
66         outb(value, port_base + 1);
67 }
68
69 static u8 pmio_read_index(u16 port_base, u8 reg)
70 {
71         outb(reg, port_base);
72         return inb(port_base + 1);
73 }
74
75 void pm_iowrite(u8 reg, u8 value)
76 {
77         pmio_write_index(PM_INDEX, reg, value);
78 }
79
80 u8 pm_ioread(u8 reg)
81 {
82         return pmio_read_index(PM_INDEX, reg);
83 }
84
85 void pm2_iowrite(u8 reg, u8 value)
86 {
87         pmio_write_index(PM2_INDEX, reg, value);
88 }
89
90 u8 pm2_ioread(u8 reg)
91 {
92         return pmio_read_index(PM2_INDEX, reg);
93 }
94
95 static void set_pmio_enable_bits(device_t sm_dev, u32 reg_pos,
96                                  u32 mask, u32 val)
97 {
98         u8 reg_old, reg;
99         reg = reg_old = pm_ioread(reg_pos);
100         reg &= ~mask;
101         reg |= val;
102         if (reg != reg_old) {
103                 pm_iowrite(reg_pos, reg);
104         }
105 }
106
107 void sb600_enable(device_t dev)
108 {
109         device_t sm_dev = 0;
110         device_t bus_dev = 0;
111         int index = -1;
112         u32 deviceid;
113         u32 vendorid;
114
115         /* struct southbridge_ati_sb600_config *conf; */
116         /* conf = dev->chip_info; */
117         int i;
118
119         u32 devfn;
120
121         printk(BIOS_DEBUG, "sb600_enable()\n");
122
123 /*
124 *       0:12.0  SATA    bit 8 of sm_dev 0xac : 1 - enable, default         + 32 * 3
125 *       0:13.1  USB-1   bit 2 of sm_dev 0x68
126 *       0:13.2  USB-2   bit 3 of sm_dev 0x68
127 *       0:13.3  USB-3   bit 4 of sm_dev 0x68
128 *       0:13.4  USB-4   bit 5 of sm_dev 0x68
129 *       0:13.5  USB2    bit 0 of sm_dev 0x68 : 1 - enable, default
130 *       0:14.0  SMBUS                                                   0
131 *       0:14.1  IDE                                                     1
132 *       0:14.2  HDA     bit 3 of pm_io 0x59 : 1 - enable, default           + 32 * 4
133 *       0:14.3  LPC     bit 20 of sm_dev 0x64 : 0 - disable, default  + 32 * 1
134 *       0:14.4  PCI                                                     4
135 *       0:14.5  ACI     bit 0 of pm_io 0x59 : 0 - enable, default
136 *       0:14.6  MCI     bit 1 of pm_io 0x59 : 0 - enable, default
137 */
138         if (dev->device == 0x0000) {
139                 vendorid = pci_read_config32(dev, PCI_VENDOR_ID);
140                 deviceid = (vendorid >> 16) & 0xffff;
141                 vendorid &= 0xffff;
142         } else {
143                 vendorid = dev->vendor;
144                 deviceid = dev->device;
145         }
146         bus_dev = dev->bus->dev;
147         if ((bus_dev->vendor == PCI_VENDOR_ID_ATI) &&
148             (bus_dev->device == PCI_DEVICE_ID_ATI_SB600_PCI)) {
149                 devfn = (bus_dev->path.pci.devfn) & ~7;
150                 sm_dev = find_sm_dev(bus_dev, devfn);
151                 if (!sm_dev)
152                         return;
153
154                 /* something under 00:01.0 */
155                 switch (dev->path.pci.devfn) {
156                 case 5 << 3:
157                         ;
158                 }
159
160                 return;
161         }
162
163         i = (dev->path.pci.devfn) & ~7;
164         i += (2 << 3);
165         for (devfn = (0x14 << 3); devfn <= i; devfn += (1 << 3)) {
166                 sm_dev = find_sm_dev(dev, devfn);
167                 if (sm_dev)
168                         break;
169         }
170         if (!sm_dev)
171                 return;
172
173         switch (dev->path.pci.devfn - (devfn - (0x14 << 3))) {
174         case (0x12 << 3) | 0:
175                 index = 8;
176                 set_sm_enable_bits(sm_dev, 0xac, 1 << index,
177                                    (dev->enabled ? 1 : 0) << index);
178                 index += 32 * 3;
179                 break;
180         case (0x13 << 3) | 0:
181         case (0x13 << 3) | 1:
182         case (0x13 << 3) | 2:
183         case (0x13 << 3) | 3:
184         case (0x13 << 3) | 4:
185         case (0x13 << 3) | 5:
186                 index = dev->path.pci.devfn & 7;
187                 index++;
188                 index %= 6;
189                 set_sm_enable_bits(sm_dev, 0x68, 1 << index,
190                                    (dev->enabled ? 1 : 0) << index);
191                 index += 32 * 2;
192                 break;
193         case (0x14 << 3) | 0:
194                 index = 0;
195                 break;
196         case (0x14 << 3) | 1:
197                 index = 1;
198                 break;
199         case (0x14 << 3) | 2:
200                 index = 3;
201                 set_pmio_enable_bits(sm_dev, 0x59, 1 << index,
202                                      (dev->enabled ? 1 : 0) << index);
203                 index += 32 * 4;
204                 break;
205         case (0x14 << 3) | 3:
206                 index = 20;
207                 set_sm_enable_bits(sm_dev, 0x64, 1 << index,
208                                    (dev->enabled ? 1 : 0) << index);
209                 index += 32 * 1;
210                 break;
211         case (0x14 << 3) | 4:
212                 index = 4;
213                 break;
214         case (0x14 << 3) | 5:
215         case (0x14 << 3) | 6:
216                 index = dev->path.pci.devfn & 7;
217                 index -= 5;
218                 set_pmio_enable_bits(sm_dev, 0x59, 1 << index,
219                                      (dev->enabled ? 0 : 1) << index);
220                 index += 32 * 4;
221                 break;
222         default:
223                 printk(BIOS_DEBUG, "unknown dev: %s deviceid=%4x\n", dev_path(dev),
224                              deviceid);
225         }
226 }
227
228 struct chip_operations southbridge_amd_sb600_ops = {
229         CHIP_NAME("ATI SB600")
230         .enable_dev = sb600_enable,
231 };