blob: 38c7d4640b6c818b4f20f24844e0ac76d722fc05 [file] [log] [blame]
Martin Roth5474eb12018-05-26 19:22:33 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
Stefan Reinauerb15975b2011-10-21 12:57:59 -070014#include <console/console.h>
15#include <arch/io.h>
16#include <stdint.h>
17#include <device/device.h>
18#include <device/pci.h>
19#include <cpu/cpu.h>
20#include <stdlib.h>
21#include <string.h>
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020022#include "e7505.h"
Stefan Reinauerb15975b2011-10-21 12:57:59 -070023#include <cbmem.h>
Vladimir Serbinenkoc7310d92014-09-01 09:45:05 +020024#include <arch/acpi.h>
25
26unsigned long acpi_fill_mcfg(unsigned long current)
27{
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +020028 /* Just a dummy */
29 return current;
Vladimir Serbinenkoc7310d92014-09-01 09:45:05 +020030}
Stefan Reinauerb15975b2011-10-21 12:57:59 -070031
Elyes HAOUAS97e8b752018-05-09 17:39:47 +020032static void pci_domain_set_resources(struct device *dev)
Stefan Reinauerb15975b2011-10-21 12:57:59 -070033{
Elyes HAOUAS97e8b752018-05-09 17:39:47 +020034 struct device *mc_dev;
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +020035 uint32_t pci_tolm;
Stefan Reinauerb15975b2011-10-21 12:57:59 -070036
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +020037 pci_tolm = find_pci_tolm(dev->link_list);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070038 mc_dev = dev->link_list->children;
39 if (mc_dev) {
40 /* Figure out which areas are/should be occupied by RAM.
41 * This is all computed in kilobytes and converted to/from
42 * the memory controller right at the edges.
43 * Having different variables in different units is
44 * too confusing to get right. Kilobytes are good up to
45 * 4 Terabytes of RAM...
46 */
47 uint16_t tolm_r, remapbase_r, remaplimit_r;
48 unsigned long tomk, tolmk;
49 unsigned long remapbasek, remaplimitk;
50 int idx;
51
52 /* Get the value of the highest DRB. This tells the end of
53 * the physical memory. The units are ticks of 64MB
54 * i.e. 1 means 64MB.
55 */
Kyösti Mälkki5bd271b2012-04-10 16:11:53 +030056 tomk = ((unsigned long)pci_read_config8(mc_dev, DRB_ROW_7)) << 16;
Stefan Reinauerb15975b2011-10-21 12:57:59 -070057 /* Compute the top of Low memory */
58 tolmk = pci_tolm >> 10;
59 if (tolmk >= tomk) {
60 /* The PCI hole does not overlap memory
61 * we won't use the remap window.
62 */
63 tolmk = tomk;
64 remapbasek = 0x3ff << 16;
65 remaplimitk = 0 << 16;
66 }
67 else {
68 /* The PCI memory hole overlaps memory
69 * setup the remap window.
70 */
71 /* Find the bottom of the remap window
72 * is it above 4G?
73 */
74 remapbasek = 4*1024*1024;
75 if (tomk > remapbasek) {
76 remapbasek = tomk;
77 }
78 /* Find the limit of the remap window */
79 remaplimitk = (remapbasek + (4*1024*1024 - tolmk) - (1 << 16));
80 }
Elyes HAOUAS15279a92016-07-28 21:05:26 +020081 /* Write the RAM configuration registers,
Stefan Reinauerb15975b2011-10-21 12:57:59 -070082 * preserving the reserved bits.
83 */
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020084 tolm_r = pci_read_config16(mc_dev, TOLM);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070085 tolm_r = ((tolmk >> 17) << 11) | (tolm_r & 0x7ff);
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020086 pci_write_config16(mc_dev, TOLM, tolm_r);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070087
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020088 remapbase_r = pci_read_config16(mc_dev, REMAPBASE);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070089 remapbase_r = (remapbasek >> 16) | (remapbase_r & 0xfc00);
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020090 pci_write_config16(mc_dev, REMAPBASE, remapbase_r);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070091
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020092 remaplimit_r = pci_read_config16(mc_dev, REMAPLIMIT);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070093 remaplimit_r = (remaplimitk >> 16) | (remaplimit_r & 0xfc00);
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020094 pci_write_config16(mc_dev, REMAPLIMIT, remaplimit_r);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070095
96 /* Report the memory regions */
97 idx = 10;
98 ram_resource(dev, idx++, 0, 640);
99 ram_resource(dev, idx++, 768, tolmk - 768);
100 if (tomk > 4*1024*1024) {
101 ram_resource(dev, idx++, 4096*1024, tomk - 4*1024*1024);
102 }
103 if (remaplimitk >= remapbasek) {
104 ram_resource(dev, idx++, remapbasek,
105 (remaplimitk + 64*1024) - remapbasek);
106 }
107
Kyösti Mälkki70d92b92017-04-19 19:57:01 +0300108 set_late_cbmem_top(tolmk * 1024);
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700109 }
110 assign_resources(dev->link_list);
111}
112
Elyes HAOUAS97e8b752018-05-09 17:39:47 +0200113static void intel_set_subsystem(struct device *dev,
114 unsigned vendor, unsigned device)
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +0200115{
116 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
117 ((device & 0xffff) << 16) | (vendor & 0xffff));
118}
119
120static struct pci_operations intel_pci_ops = {
121 .set_subsystem = intel_set_subsystem,
122};
123
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700124static struct device_operations pci_domain_ops = {
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +0200125 .read_resources = pci_domain_read_resources,
126 .set_resources = pci_domain_set_resources,
127 .enable_resources = NULL,
128 .init = NULL,
129 .scan_bus = pci_domain_scan_bus,
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +0200130 .ops_pci = &intel_pci_ops,
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700131};
132
Elyes HAOUAS97e8b752018-05-09 17:39:47 +0200133static void cpu_bus_init(struct device *dev)
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700134{
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +0200135 initialize_cpus(dev->link_list);
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700136}
137
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700138static struct device_operations cpu_bus_ops = {
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +0200139 .read_resources = DEVICE_NOOP,
140 .set_resources = DEVICE_NOOP,
141 .enable_resources = DEVICE_NOOP,
142 .init = cpu_bus_init,
143 .scan_bus = 0,
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700144};
145
146static void enable_dev(struct device *dev)
147{
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +0200148 /* Set the operations if it is a special bus type */
149 if (dev->path.type == DEVICE_PATH_DOMAIN) {
150 dev->ops = &pci_domain_ops;
151 }
152 else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
153 dev->ops = &cpu_bus_ops;
154 }
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700155}
156
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +0200157struct chip_operations northbridge_intel_e7505_ops = {
158 CHIP_NAME("Intel E7505 Northbridge")
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700159 .enable_dev = enable_dev,
160};