2 * This file is part of the coreboot project.
4 * Copyright (C) 2008 Advanced Micro Devices, Inc.
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.
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.
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
23 #include <device/pci.h>
26 #include <device/pci_ids.h>
27 #include <statictree.h>
31 static void sata_init(struct device *dev)
37 u16 sata_bar0, sata_bar1, sata_bar2, sata_bar3, sata_bar4;
39 struct southbridge_ati_sb600_sata_dts_config *conf;
40 conf = dev->device_configuration;
42 struct device * sm_dev;
43 /* SATA SMBus Disable */
44 /* sm_dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); */
45 sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
46 /* Disable SATA SMBUS */
47 byte = pci_read_config8(sm_dev, 0xad);
49 /* Enable SATA and power saving */
50 byte = pci_read_config8(sm_dev, 0xad);
53 pci_write_config8(sm_dev, 0xad, byte);
54 /* Set the interrupt Mapping to INTG# */
55 byte = pci_read_config8(sm_dev, 0xaf);
57 pci_write_config8(sm_dev, 0xaf, byte);
59 /* get base addresss */
60 sata_bar5 = (u8 *) (pci_read_config32(dev, 0x24) & ~0x3FF);
61 sata_bar0 = pci_read_config16(dev, 0x10) & ~0x7;
62 sata_bar1 = pci_read_config16(dev, 0x14) & ~0x7;
63 sata_bar2 = pci_read_config16(dev, 0x18) & ~0x7;
64 sata_bar3 = pci_read_config16(dev, 0x1C) & ~0x7;
65 sata_bar4 = pci_read_config16(dev, 0x20) & ~0x7;
67 printk(BIOS_DEBUG, "sata_bar0=%x\n", sata_bar0); /* 3030 */
68 printk(BIOS_DEBUG, "sata_bar1=%x\n", sata_bar1); /* 3070 */
69 printk(BIOS_DEBUG, "sata_bar2=%x\n", sata_bar2); /* 3040 */
70 printk(BIOS_DEBUG, "sata_bar3=%x\n", sata_bar3); /* 3080 */
71 printk(BIOS_DEBUG, "sata_bar4=%x\n", sata_bar4); /* 3000 */
72 printk(BIOS_DEBUG, "sata_bar5=%x\n", sata_bar5); /* e0309000 */
74 /* Program the 2C to 0x43801002 */
76 pci_write_config32(dev, 0x2c, dword);
79 word = pci_read_config16(dev, 0x04);
81 pci_write_config16(dev, 0x04, word);
83 /* Dynamic power saving */
84 byte = pci_read_config8(dev, 0x40);
86 pci_write_config8(dev, 0x40, byte);
88 /* Set SATA Operation Mode, Set to IDE mode */
89 byte = pci_read_config8(dev, 0x40);
92 pci_write_config8(dev, 0x40, byte);
95 pci_write_config32(dev, 0x8, dword);
97 byte = pci_read_config8(dev, 0x40);
99 pci_write_config8(dev, 0x40, byte);
101 /* Enable the SATA watchdog counter */
102 byte = pci_read_config8(dev, 0x44);
104 pci_write_config8(dev, 0x44, byte);
106 /* Program the watchdog counter to 0x10 */
108 pci_write_config8(dev, 0x46, byte);
110 /* RPR6.5 Program the PHY Global Control to 0x2C00 for A13 */
112 pci_write_config16(dev, 0x86, word);
114 /* RPR6.5 Program the Phy Tuning4Ports */
116 pci_write_config32(dev, 0x88, dword);
117 pci_write_config32(dev, 0x8c, dword);
118 pci_write_config32(dev, 0x90, dword);
119 pci_write_config32(dev, 0x94, dword);
122 pci_write_config8(dev, 0xA5, byte);
123 pci_write_config8(dev, 0xAD, byte);
124 pci_write_config8(dev, 0xB5, byte);
125 pci_write_config8(dev, 0xBD, byte);
128 word = pci_read_config16(dev, 0x42);
130 pci_write_config16(dev, 0x42, word);
132 dword = pci_read_config32(dev, 0x40);
134 pci_write_config32(dev, 0x40, dword);
136 /* Enable the I/O ,MM ,BusMaster access for SATA */
137 byte = pci_read_config8(dev, 0x4);
139 pci_write_config8(dev, 0x4, byte);
141 /* RPR6.6 SATA drive detection. Currently we detect Primary Master Device only */
142 /* Use BAR5+0x1A8,BAR0+0x6 for Primary Slave */
143 /* Use BAR5+0x228,BAR0+0x6 for Secondary Master */
144 /* Use BAR5+0x2A8,BAR0+0x6 for Secondary Slave */
146 byte = readb(sata_bar5 + 0x128);
147 printk(BIOS_DEBUG, "byte=%x\n", byte);
150 outb(0xA0, sata_bar0 + 0x6);
151 while ((inb(sata_bar0 + 0x6) != 0xA0)
152 || ((inb(sata_bar0 + 0x7) & 0x88) != 0)) {
154 printk(BIOS_DEBUG, "0x6=%x,0x7=%x\n", inb(sata_bar0 + 0x6),
155 inb(sata_bar0 + 0x7));
156 printk(BIOS_DEBUG, "drive detection fail,trying...\n");
158 printk(BIOS_DEBUG, "Primary master device is ready\n");
160 printk(BIOS_DEBUG, "No Primary master SATA drive on Slot0\n");
163 /* Below is CIM InitSataLateFar */
164 /* Enable interrupts from the HBA */
165 byte = readb(sata_bar5 + 0x4);
167 writeb(byte, (sata_bar5 + 0x4));
169 /* Clear error status */
170 writel(0xFFFFFFFF, (sata_bar5 + 0x130));
171 writel(0xFFFFFFFF, (sata_bar5 + 0x1b0));
172 writel(0xFFFFFFFF, (sata_bar5 + 0x230));
173 writel(0xFFFFFFFF, (sata_bar5 + 0x2b0));
175 /* Clear SATA status,Firstly we get the AcpiGpe0BlkAddr */
176 /* ????? why CIM does not set the AcpiGpe0BlkAddr , but use it??? */
179 /* word = pm_ioread(0x28); */
180 /* byte = pm_ioread(0x29); */
181 /* word |= byte<<8; */
182 /* printk(BIOS_DEBUG, "AcpiGpe0Blk addr = %x\n", word); */
183 /* writel(0x80000000 , word); */
186 static struct pci_operations lops_pci = {
187 /* .set_subsystem = pci_dev_set_subsystem, */
190 struct device_operations amd8111_ide = {
191 .id = {.type = DEVICE_ID_PCI,
192 {.pci = {.vendor = PCI_VENDOR_ID_ATI,
193 .device = PCI_DEVICE_ID_ATI_SB600_SATA}}},
194 .constructor = default_device_constructor,
195 .phase4_read_resources = pci_dev_read_resources,
196 .phase4_set_resources = pci_dev_set_resources,
197 .phase5_enable_resources = pci_dev_enable_resources,
198 .phase6_init = sata_init,