blob: 8f1632dd47c6bd362cc8b14775e10c80e684954c [file] [log] [blame]
Stefan Reinauerb15975b2011-10-21 12:57:59 -07001#include <console/console.h>
2#include <arch/io.h>
3#include <stdint.h>
4#include <device/device.h>
5#include <device/pci.h>
6#include <cpu/cpu.h>
7#include <stdlib.h>
8#include <string.h>
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +02009#include "e7505.h"
Stefan Reinauerb15975b2011-10-21 12:57:59 -070010#include <cbmem.h>
Stefan Reinauerb15975b2011-10-21 12:57:59 -070011
12static void pci_domain_set_resources(device_t dev)
13{
14 device_t mc_dev;
15 uint32_t pci_tolm;
16
17 pci_tolm = find_pci_tolm(dev->link_list);
18 mc_dev = dev->link_list->children;
19 if (mc_dev) {
20 /* Figure out which areas are/should be occupied by RAM.
21 * This is all computed in kilobytes and converted to/from
22 * the memory controller right at the edges.
23 * Having different variables in different units is
24 * too confusing to get right. Kilobytes are good up to
25 * 4 Terabytes of RAM...
26 */
27 uint16_t tolm_r, remapbase_r, remaplimit_r;
28 unsigned long tomk, tolmk;
29 unsigned long remapbasek, remaplimitk;
30 int idx;
31
32 /* Get the value of the highest DRB. This tells the end of
33 * the physical memory. The units are ticks of 64MB
34 * i.e. 1 means 64MB.
35 */
Kyösti Mälkki5bd271b2012-04-10 16:11:53 +030036 tomk = ((unsigned long)pci_read_config8(mc_dev, DRB_ROW_7)) << 16;
Stefan Reinauerb15975b2011-10-21 12:57:59 -070037 /* Compute the top of Low memory */
38 tolmk = pci_tolm >> 10;
39 if (tolmk >= tomk) {
40 /* The PCI hole does not overlap memory
41 * we won't use the remap window.
42 */
43 tolmk = tomk;
44 remapbasek = 0x3ff << 16;
45 remaplimitk = 0 << 16;
46 }
47 else {
48 /* The PCI memory hole overlaps memory
49 * setup the remap window.
50 */
51 /* Find the bottom of the remap window
52 * is it above 4G?
53 */
54 remapbasek = 4*1024*1024;
55 if (tomk > remapbasek) {
56 remapbasek = tomk;
57 }
58 /* Find the limit of the remap window */
59 remaplimitk = (remapbasek + (4*1024*1024 - tolmk) - (1 << 16));
60 }
61 /* Write the ram configuration registers,
62 * preserving the reserved bits.
63 */
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020064 tolm_r = pci_read_config16(mc_dev, TOLM);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070065 tolm_r = ((tolmk >> 17) << 11) | (tolm_r & 0x7ff);
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020066 pci_write_config16(mc_dev, TOLM, tolm_r);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070067
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020068 remapbase_r = pci_read_config16(mc_dev, REMAPBASE);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070069 remapbase_r = (remapbasek >> 16) | (remapbase_r & 0xfc00);
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020070 pci_write_config16(mc_dev, REMAPBASE, remapbase_r);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070071
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020072 remaplimit_r = pci_read_config16(mc_dev, REMAPLIMIT);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070073 remaplimit_r = (remaplimitk >> 16) | (remaplimit_r & 0xfc00);
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020074 pci_write_config16(mc_dev, REMAPLIMIT, remaplimit_r);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070075
76 /* Report the memory regions */
77 idx = 10;
78 ram_resource(dev, idx++, 0, 640);
79 ram_resource(dev, idx++, 768, tolmk - 768);
80 if (tomk > 4*1024*1024) {
81 ram_resource(dev, idx++, 4096*1024, tomk - 4*1024*1024);
82 }
83 if (remaplimitk >= remapbasek) {
84 ram_resource(dev, idx++, remapbasek,
85 (remaplimitk + 64*1024) - remapbasek);
86 }
87
Kyösti Mälkki42f46512013-06-27 08:20:09 +030088 set_top_of_ram(tolmk * 1024);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070089 }
90 assign_resources(dev->link_list);
91}
92
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020093static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device)
94{
95 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
96 ((device & 0xffff) << 16) | (vendor & 0xffff));
97}
98
99static struct pci_operations intel_pci_ops = {
100 .set_subsystem = intel_set_subsystem,
101};
102
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700103static struct device_operations pci_domain_ops = {
104 .read_resources = pci_domain_read_resources,
105 .set_resources = pci_domain_set_resources,
106 .enable_resources = NULL,
107 .init = NULL,
108 .scan_bus = pci_domain_scan_bus,
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +0200109 .ops_pci = &intel_pci_ops,
Kyösti Mälkki33e5df32013-07-03 10:51:34 +0300110 .ops_pci_bus = pci_bus_default_ops,
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700111};
112
113static void cpu_bus_init(device_t dev)
114{
115 initialize_cpus(dev->link_list);
116}
117
118static void cpu_bus_noop(device_t dev)
119{
120}
121
122static struct device_operations cpu_bus_ops = {
123 .read_resources = cpu_bus_noop,
124 .set_resources = cpu_bus_noop,
125 .enable_resources = cpu_bus_noop,
126 .init = cpu_bus_init,
127 .scan_bus = 0,
128};
129
130static void enable_dev(struct device *dev)
131{
132 /* Set the operations if it is a special bus type */
Stefan Reinauer4aff4452013-02-12 14:17:15 -0800133 if (dev->path.type == DEVICE_PATH_DOMAIN) {
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700134 dev->ops = &pci_domain_ops;
135 }
Stefan Reinauer0aa37c42013-02-12 15:20:54 -0800136 else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700137 dev->ops = &cpu_bus_ops;
138 }
139}
140
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +0200141struct chip_operations northbridge_intel_e7505_ops = {
142 CHIP_NAME("Intel E7505 Northbridge")
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700143 .enable_dev = enable_dev,
144};