summaryrefslogtreecommitdiff
path: root/src/southbridge/via/vt8231/ide.c
blob: 3b402477d58f06df9324c7a2f62a5170ae292e1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ops.h>
#include <device/pci_ids.h>
#include "chip.h"

static void ide_init(struct device *dev)
{
	struct southbridge_via_vt8231_config *conf = (struct southbridge_via_vt8231_config *)dev->chip_info;
	unsigned char enables;

	if (!conf->enable_native_ide) {
		// Run the IDE controller in 'compatibility mode - i.e. don't use PCI
		// interrupts.  Using PCI ints confuses linux for some reason.
		/* Setting reg 0x42 here does not work. It is set in mainboard/romstage.c
		* It probably can only be changed while the IDE is disabled
		* or it is possibly a timing issue. Ben Hewson 29 Apr 2007.
		*/

		/*
		printk(BIOS_INFO, "%s: enabling compatibility IDE addresses\n", __func__);
		enables = pci_read_config8(dev, 0x42);
		printk(BIOS_DEBUG, "enables in reg 0x42 0x%x\n", enables);
		enables &= ~0xc0;		// compatibility mode
		pci_write_config8(dev, 0x42, enables);
		enables = pci_read_config8(dev, 0x42);
		printk(BIOS_DEBUG, "enables in reg 0x42 read back as 0x%x\n", enables);
		*/
	}

	enables = pci_read_config8(dev, 0x40);
	printk(BIOS_DEBUG, "enables in reg 0x40 0x%x\n", enables);
	enables |= 3;
	pci_write_config8(dev, 0x40, enables);
	enables = pci_read_config8(dev, 0x40);
	printk(BIOS_DEBUG, "enables in reg 0x40 read back as 0x%x\n", enables);

	// Enable prefetch buffers
	enables = pci_read_config8(dev, 0x41);
	enables |= 0xf0;
	pci_write_config8(dev, 0x41, enables);

	// Lower thresholds (cause award does it)
	enables = pci_read_config8(dev, 0x43);
	enables &= ~0x0f;
	enables |=  0x05;
	pci_write_config8(dev, 0x43, enables);

	// PIO read prefetch counter (cause award does it)
	pci_write_config8(dev, 0x44, 0x18);

	// Use memory read multiple
	pci_write_config8(dev, 0x45, 0x1c);

	// address decoding.
	// we want "flexible", i.e. 1f0-1f7 etc. or native PCI
	// kevinh@ispiri.com - the standard linux drivers seem ass slow when
	// used in native mode - I've changed back to classic
	enables = pci_read_config8(dev, 0x9);
	printk(BIOS_DEBUG, "enables in reg 0x9 0x%x\n", enables);
	// by the book, set the low-order nibble to 0xa.
	if (conf->enable_native_ide) {
		enables &= ~0xf;
		// cf/cg silicon needs an 'f' here.
		enables |= 0xf;
	} else {
		enables &= ~0x5;
	}

	pci_write_config8(dev, 0x9, enables);
	enables = pci_read_config8(dev, 0x9);
	printk(BIOS_DEBUG, "enables in reg 0x9 read back as 0x%x\n", enables);

	// standard bios sets master bit.
	enables = pci_read_config8(dev, 0x4);
	printk(BIOS_DEBUG, "command in reg 0x4 0x%x\n", enables);
	enables |= 7;

	// No need for stepping - kevinh@ispiri.com
	enables &= ~0x80;

	pci_write_config8(dev, 0x4, enables);
	enables = pci_read_config8(dev, 0x4);
	printk(BIOS_DEBUG, "command in reg 0x4 reads back as 0x%x\n", enables);

	if (!conf->enable_native_ide) {
		// Use compatibility mode - per award bios
		pci_write_config32(dev, 0x10, 0x0);
		pci_write_config32(dev, 0x14, 0x0);
		pci_write_config32(dev, 0x18, 0x0);
		pci_write_config32(dev, 0x1c, 0x0);

		// Force interrupts to use compat mode - just like Award bios
		pci_write_config8(dev, 0x3d, 00);
		pci_write_config8(dev, 0x3c, 0xff);
	}
}

static struct device_operations ide_ops = {
	.read_resources   = pci_dev_read_resources,
	.set_resources    = pci_dev_set_resources,
	.enable_resources = pci_dev_enable_resources,
	.init		  = ide_init,
	.enable           = 0,
	.ops_pci          = 0,
};

static const struct pci_driver northbridge_driver __pci_driver = {
	.ops	= &ide_ops,
	.vendor = PCI_VENDOR_ID_VIA,
	.device = PCI_DEVICE_ID_VIA_82C586_1,
};