aboutsummaryrefslogtreecommitdiff
path: root/src/mainboard/intel/jarrell/watchdog.c
blob: 7f7a03906812ff9489e61aa59e1ec824e27ca3a4 (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <device/pnp_def.h>
#include <pc80/mc146818rtc.h>

#define NSC_WD_DEV PNP_DEV(0x2e, 0xa)
#define NSC_WDBASE 0x600
#define ICH5_WDBASE 0x400
#define ICH5_GPIOBASE 0x500

static void disable_sio_watchdog(device_t dev)
{
	/* FIXME move me somewhere more appropriate */
	pnp_set_logical_device(dev);
	pnp_set_enable(dev, 1);
	pnp_set_iobase(dev, PNP_IDX_IO0, NSC_WDBASE);
	/* disable the sio watchdog */
	outb(0, NSC_WDBASE + 0);
	pnp_set_enable(dev, 0);
}

static void disable_ich5_watchdog(void)
{
	/* FIXME move me somewhere more appropriate */
	device_t dev;
	unsigned long value, base;
	dev = pci_locate_device(PCI_ID(0x8086, 0x24d0), 0);
	if (dev == PCI_DEV_INVALID) {
		die("Missing ich5?");
	}
	/* Enable I/O space */
	value = pci_read_config16(dev, 0x04);
	value |= (1 << 10);
	pci_write_config16(dev, 0x04, value);

	/* Set and enable acpibase */
	pci_write_config32(dev, 0x40, ICH5_WDBASE | 1);
	pci_write_config8(dev, 0x44, 0x10);
	base = ICH5_WDBASE + 0x60;

	/* Set bit 11 in TCO1_CNT */
	value = inw(base + 0x08);
	value |= 1 << 11;
	outw(value, base + 0x08);

	/* Clear TCO timeout status */
	outw(0x0008, base + 0x04);
	outw(0x0002, base + 0x06);
}

static void disable_jarell_frb3(void)
{
	device_t dev;
	unsigned long value, base;
	dev = pci_locate_device(PCI_ID(0x8086, 0x24d0), 0);
	if (dev == PCI_DEV_INVALID) {
		die("Missing ich5?");
	}
	/* Enable I/O space */
	value = pci_read_config16(dev, 0x04);
	value |= (1 << 0);
	pci_write_config16(dev, 0x04, value);

	/* Set gpio base */
	pci_write_config32(dev, 0x58, ICH5_GPIOBASE | 1);
	base = ICH5_GPIOBASE;

	/* Enable GPIO Bar */
	value = pci_read_config32(dev, 0x5c);
	value |= 0x10;
	pci_write_config32(dev, 0x5c, value);

	/* Configure GPIO 48 and 40 as GPIO */
	value = inl(base + 0x30);
	value |= (1 << 16) | ( 1 << 8);
	outl(value, base + 0x30);

	/* Configure GPIO 48 as Output */
	value = inl(base + 0x34);
	value &= ~(1 << 16);
	outl(value, base + 0x34);

	/* Toggle GPIO 48 high to low */
	value = inl(base + 0x38);
	value |= (1 << 16);
	outl(value, base + 0x38);
	value &= ~(1 << 16);
	outl(value, base + 0x38);

}

static void disable_watchdogs(void)
{
	disable_sio_watchdog(NSC_WD_DEV);
	disable_ich5_watchdog();
	disable_jarell_frb3();
	print_debug("Watchdogs disabled\n");
}

static void ich5_watchdog_on(void)
{
	device_t dev;
	unsigned long value, base;
	unsigned char byte;

	/* check cmos options */
	byte = cmos_read(RTC_BOOT_BYTE-1);
	if(!(byte & 1)) return; /* no boot watchdog */
	byte = cmos_read(RTC_BOOT_BYTE);
	if(!(byte & 2)) return; /* fallback so ignore */

	dev = pci_locate_device(PCI_ID(0x8086, 0x24d0), 0);
	if (dev == PCI_DEV_INVALID) {
		die("Missing ich5?");
	}
	/* Enable I/O space */
	value = pci_read_config16(dev, 0x04);
	value |= (1 << 10);
	pci_write_config16(dev, 0x04, value);

	/* Set and enable acpibase */
	pci_write_config32(dev, 0x40, ICH5_WDBASE | 1);
	pci_write_config8(dev, 0x44, 0x10);
	base = ICH5_WDBASE + 0x60;

	/* Clear TCO timeout status */
	outw(0x0008, base + 0x04);
	outw(0x0002, base + 0x06);

	/* set the time value 1 cnt = .6 sec */
	outw(0x0010, base + 0x01);
	/* reload the timer with the value */
	outw(0x0001, base + 0x00);

	/* clear bit 11 in TCO1_CNT to start watchdog */
	value = inw(base + 0x08);
	value &= ~(1 << 11);
	outw(value, base + 0x08);

	print_debug("Watchdog ICH5 enabled\n");
}