blob: 8df09bcb7654e838c9edd280af18dc7c349a2a8c [file] [log] [blame]
arch import user (historical)98d0d302005-07-06 17:13:46 +00001/*
Uwe Hermann8af6d552010-10-17 19:13:18 +00002 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2004 Tyan Computer
5 * Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
arch import user (historical)98d0d302005-07-06 17:13:46 +000015 */
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000016
arch import user (historical)98d0d302005-07-06 17:13:46 +000017#include <console/console.h>
18#include <device/device.h>
19#include <delay.h>
20#include <device/pci.h>
21#include <device/pci_ids.h>
22#include <device/pci_ops.h>
Kyösti Mälkki413e3da2015-02-03 08:05:55 +020023#include "chip.h"
arch import user (historical)98d0d302005-07-06 17:13:46 +000024
Myles Watsonfa12b672009-04-30 22:45:41 +000025#ifndef CK804_SATA_RESET_FOR_ATAPI
26#define CK804_SATA_RESET_FOR_ATAPI 0
27#endif
28
Myles Watsonc4ddbff2009-02-09 17:52:54 +000029#if CK804_SATA_RESET_FOR_ATAPI
arch import user (historical)98d0d302005-07-06 17:13:46 +000030static void sata_com_reset(struct device *dev, unsigned reset)
31// reset = 1 : reset
32// reset = 0 : clear
33{
Uwe Hermann7e2fbd52011-01-04 17:36:55 +000034 u32 *base;
35 u32 dword;
arch import user (historical)98d0d302005-07-06 17:13:46 +000036 int loop;
37
Uwe Hermann7e2fbd52011-01-04 17:36:55 +000038 base = (u32 *) pci_read_config32(dev, 0x24);
arch import user (historical)98d0d302005-07-06 17:13:46 +000039
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000040 printk(BIOS_DEBUG, "base = %08lx\n", base);
arch import user (historical)98d0d302005-07-06 17:13:46 +000041
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000042 if (reset) {
43 *(base + 4) = 0xffffffff;
44 *(base + 0x44) = 0xffffffff;
Myles Watson64caf362008-09-18 16:27:00 +000045 }
arch import user (historical)98d0d302005-07-06 17:13:46 +000046
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000047 dword = *(base + 8);
Myles Watson64caf362008-09-18 16:27:00 +000048 dword &= ~(0xf);
49 dword |= reset;
arch import user (historical)98d0d302005-07-06 17:13:46 +000050
Myles Watson64caf362008-09-18 16:27:00 +000051 *(base + 8) = dword;
52 *(base + 0x48) = dword;
arch import user (historical)98d0d302005-07-06 17:13:46 +000053
54#if 0
55 udelay(1000);
56 dword &= ~(0xf);
Myles Watson64caf362008-09-18 16:27:00 +000057 *(base + 8) = dword;
58 *(base + 0x48) = dword;
arch import user (historical)98d0d302005-07-06 17:13:46 +000059#endif
arch import user (historical)98d0d302005-07-06 17:13:46 +000060
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000061 if (reset)
62 return;
arch import user (historical)98d0d302005-07-06 17:13:46 +000063
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000064 dword = *(base + 0);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +000065 printk(BIOS_DEBUG, "*(base+0)=%08x\n", dword);
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000066 if (dword == 0x113) {
67 loop = 200000; // 2
arch import user (historical)98d0d302005-07-06 17:13:46 +000068 do {
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000069 dword = *(base + 4);
70 if ((dword & 0x10000) != 0)
71 break;
arch import user (historical)98d0d302005-07-06 17:13:46 +000072 udelay(10);
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000073 } while (--loop > 0);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +000074 printk(BIOS_DEBUG, "loop=%d, *(base+4)=%08x\n", loop, dword);
arch import user (historical)98d0d302005-07-06 17:13:46 +000075 }
arch import user (historical)98d0d302005-07-06 17:13:46 +000076
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000077 dword = *(base + 0x40);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +000078 printk(BIOS_DEBUG, "*(base+0x40)=%08x\n", dword);
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000079 if (dword == 0x113) {
80 loop = 200000; //2
81 do {
82 dword = *(base + 0x44);
83 if ((dword & 0x10000) != 0)
84 break;
arch import user (historical)98d0d302005-07-06 17:13:46 +000085 udelay(10);
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000086 } while (--loop > 0);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +000087 printk(BIOS_DEBUG, "loop=%d, *(base+0x44)=%08x\n", loop, dword);
arch import user (historical)98d0d302005-07-06 17:13:46 +000088 }
arch import user (historical)98d0d302005-07-06 17:13:46 +000089}
Myles Watsonc4ddbff2009-02-09 17:52:54 +000090#endif
arch import user (historical)98d0d302005-07-06 17:13:46 +000091
92static void sata_init(struct device *dev)
93{
Uwe Hermann7e2fbd52011-01-04 17:36:55 +000094 u32 dword;
arch import user (historical)98d0d302005-07-06 17:13:46 +000095 struct southbridge_nvidia_ck804_config *conf;
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000096
arch import user (historical)98d0d302005-07-06 17:13:46 +000097 conf = dev->chip_info;
98
Myles Watson64caf362008-09-18 16:27:00 +000099 dword = pci_read_config32(dev, 0x50);
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000100 /* Ensure prefetch is disabled. */
Myles Watson64caf362008-09-18 16:27:00 +0000101 dword &= ~((1 << 15) | (1 << 13));
102 if (conf->sata1_enable) {
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000103 /* Enable secondary SATA interface. */
104 dword |= (1 << 0);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000105 printk(BIOS_DEBUG, "SATA S \t");
Myles Watson64caf362008-09-18 16:27:00 +0000106 }
107 if (conf->sata0_enable) {
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000108 /* Enable primary SATA interface. */
109 dword |= (1 << 1);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000110 printk(BIOS_DEBUG, "SATA P \n");
Myles Watson64caf362008-09-18 16:27:00 +0000111 }
Yinghai Lu5dab7d62005-10-01 07:32:04 +0000112#if 0
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000113 /* Write back */
114 dword |= (1 << 12);
115 dword |= (1 << 14);
Yinghai Lu5dab7d62005-10-01 07:32:04 +0000116#endif
arch import user (historical)98d0d302005-07-06 17:13:46 +0000117
Yinghai Lu5dab7d62005-10-01 07:32:04 +0000118#if 0
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000119 /* ADMA */
120 dword |= (1 << 16);
121 dword |= (1 << 17);
arch import user (historical)98d0d302005-07-06 17:13:46 +0000122#endif
123
Myles Watson64caf362008-09-18 16:27:00 +0000124#if 1
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000125 /* DO NOT relay OK and PAGE_FRNDLY_DTXFR_CNT. */
126 dword &= ~(0x1f << 24);
127 dword |= (0x15 << 24);
arch import user (historical)98d0d302005-07-06 17:13:46 +0000128#endif
Myles Watson64caf362008-09-18 16:27:00 +0000129 pci_write_config32(dev, 0x50, dword);
arch import user (historical)98d0d302005-07-06 17:13:46 +0000130
Yinghai Lu5dab7d62005-10-01 07:32:04 +0000131#if 0
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000132 /* SLUMBER_DURING_D3 */
Myles Watson64caf362008-09-18 16:27:00 +0000133 dword = pci_read_config32(dev, 0x7c);
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000134 dword &= ~(1 << 4);
Myles Watson64caf362008-09-18 16:27:00 +0000135 pci_write_config32(dev, 0x7c, dword);
arch import user (historical)98d0d302005-07-06 17:13:46 +0000136
137 dword = pci_read_config32(dev, 0xd0);
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000138 dword &= ~(0xff << 24);
139 dword |= (0x68 << 24);
arch import user (historical)98d0d302005-07-06 17:13:46 +0000140 pci_write_config32(dev, 0xd0, dword);
141
Myles Watson64caf362008-09-18 16:27:00 +0000142 dword = pci_read_config32(dev, 0xe0);
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000143 dword &= ~(0xff << 24);
144 dword |= (0x68 << 24);
arch import user (historical)98d0d302005-07-06 17:13:46 +0000145 pci_write_config32(dev, 0xe0, dword);
146#endif
147
Myles Watson64caf362008-09-18 16:27:00 +0000148 dword = pci_read_config32(dev, 0xf8);
149 dword |= 2;
150 pci_write_config32(dev, 0xf8, dword);
arch import user (historical)98d0d302005-07-06 17:13:46 +0000151
Myles Watsonc4ddbff2009-02-09 17:52:54 +0000152#if CK804_SATA_RESET_FOR_ATAPI
arch import user (historical)98d0d302005-07-06 17:13:46 +0000153 dword = pci_read_config32(dev, 0xac);
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000154 dword &= ~((1 << 13) | (1 << 14));
155 dword |= (1 << 13) | (0 << 14);
arch import user (historical)98d0d302005-07-06 17:13:46 +0000156 pci_write_config32(dev, 0xac, dword);
157
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000158 sata_com_reset(dev, 1); /* For discover some s-atapi device. */
arch import user (historical)98d0d302005-07-06 17:13:46 +0000159#endif
arch import user (historical)98d0d302005-07-06 17:13:46 +0000160}
161
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000162static struct device_operations sata_ops = {
arch import user (historical)98d0d302005-07-06 17:13:46 +0000163 .read_resources = pci_dev_read_resources,
164 .set_resources = pci_dev_set_resources,
165 .enable_resources = pci_dev_enable_resources,
arch import user (historical)98d0d302005-07-06 17:13:46 +0000166 .init = sata_init,
167 .scan_bus = 0,
Jonathan Kollaschc7f3f802010-10-29 15:56:04 +0000168 .ops_pci = &ck804_pci_ops,
arch import user (historical)98d0d302005-07-06 17:13:46 +0000169};
170
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000171static const struct pci_driver sata0_driver __pci_driver = {
arch import user (historical)98d0d302005-07-06 17:13:46 +0000172 .ops = &sata_ops,
173 .vendor = PCI_VENDOR_ID_NVIDIA,
174 .device = PCI_DEVICE_ID_NVIDIA_CK804_SATA0,
175};
176
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000177static const struct pci_driver sata1_driver __pci_driver = {
Myles Watson64caf362008-09-18 16:27:00 +0000178 .ops = &sata_ops,
179 .vendor = PCI_VENDOR_ID_NVIDIA,
180 .device = PCI_DEVICE_ID_NVIDIA_CK804_SATA1,
arch import user (historical)98d0d302005-07-06 17:13:46 +0000181};