summaryrefslogtreecommitdiff
path: root/src/northbridge/dmp/vortex86ex/northbridge.c
blob: fcebed84c6f5727d974ef8340a179475c68998e5 (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
/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2013 DMP Electronics Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <console/console.h>
#include <arch/io.h>
#include <stdint.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <cbmem.h>
#include <pc80/mc146818rtc.h>
#include "chip.h"
#include "northbridge.h"

#define SPI_BASE 0xfc00

static void northbridge_init(device_t dev)
{
	printk(BIOS_DEBUG, "Vortex86EX northbridge early init ...\n");
	// enable F0A/ECA/E8A/E4A/E0A/C4A/C0A shadow read/writable.
	pci_write_config32(dev, NB_REG_MAR, 0x3ff000f0);
	// enable C0000h - C3FFFh/C4000h - C7FFF can be in L1 cache selection.
	pci_write_config32(dev, NB_REG_HOST_CTL, (1 << 18) | (1 << 19));
	// Set SPI register base.
	pci_write_config16(dev, NB_REG_SPI_BASE, SPI_BASE | 1);
}

static struct device_operations northbridge_operations = {
	.set_resources    = pci_dev_set_resources,
	.enable_resources = pci_dev_enable_resources,
	.init             = northbridge_init
};

static const struct pci_driver northbridge_driver_6025 __pci_driver = {
	.ops = &northbridge_operations,
	.vendor = PCI_VENDOR_ID_RDC,
	.device = 0x6025,	/* EX CPU N/B ID */
};

/* Set CMOS register 15h/16h/17h/18h for base/extended
 * memory size. */
static void set_cmos_memory_size(unsigned long sizek)
{
	unsigned long ext_mem_size;
	u8 ext_mem_size_hb, ext_mem_size_lb;
	/* calculate memory size between 1M - 65M. */
	ext_mem_size = sizek - 1024;
	if (ext_mem_size > 65535)
		ext_mem_size = 65535;
	ext_mem_size_hb = (u8) (ext_mem_size >> 8);
	ext_mem_size_lb = (u8) (ext_mem_size & 0xff);
	/* Base memory is always 640K. */
	cmos_write(0x80, 0x15);
	cmos_write(0x02, 0x16);
	/* Write extended memory size. */
	cmos_write(ext_mem_size_lb, 0x17);
	cmos_write(ext_mem_size_hb, 0x18);
	/* register 0x30(48) is RTC_BOOT_BYTE for coreboot,
	 * don't touch it. */
}

static void pci_domain_set_resources(device_t dev)
{
	device_t mc_dev;
	uint32_t pci_tolm;

	printk(BIOS_SPEW, "Entering vortex86ex pci_domain_set_resources.\n");

	pci_tolm = find_pci_tolm(dev->link_list);
	mc_dev = dev->link_list->children;
	if (mc_dev) {
		unsigned long tomk, tolmk;
		int idx;
		int ss;
		/* Get DDRII size setting from northbridge register. */
		/* SS = 0 for 2MB, 1 for 4MB, 2 for 8MB, 3 for 16MB ... */
		ss = pci_read_config16(mc_dev, 0x6c);
		ss = ((ss >> 8) & 0xf);
		tomk = (2 * 1024) << ss;
		printk(BIOS_DEBUG, "I would set ram size to %ld Mbytes\n", (tomk >> 10));
		/* Compute the top of Low memory */
		tolmk = pci_tolm >> 10;
		if (tolmk >= tomk)
			/* The PCI hole does does not overlap the memory.
			 */
			tolmk = tomk;

		set_top_of_ram(tolmk * 1024);

		/* Report the memory regions */
		idx = 10;
		ram_resource(dev, idx++, 0, 640);	/* first 640k */
		ram_resource(dev, idx++, 768, tolmk - 768);	/* leave a hole for vga */
		set_cmos_memory_size(tolmk);
	}
	assign_resources(dev->link_list);
}

static struct device_operations pci_domain_ops = {
	.read_resources   = pci_domain_read_resources,
	.set_resources    = pci_domain_set_resources,
	.enable_resources = NULL,
	.init             = NULL,
	.scan_bus         = pci_domain_scan_bus,
	.ops_pci_bus      = pci_bus_default_ops,
};

static void enable_dev(struct device *dev)
{
	printk(BIOS_SPEW, "In vortex86ex enable_dev for device %s.\n", dev_path(dev));

	/* Set the operations if it is a special bus type */
	if (dev->path.type == DEVICE_PATH_DOMAIN) {
		dev->ops = &pci_domain_ops;
	}
}

struct chip_operations northbridge_dmp_vortex86ex_ops = {
	CHIP_NAME("DMP Vortex86EX Northbridge")
	.enable_dev = enable_dev,
};