blob: ea8b4598f4add4c6e9741422de47c563936a1d1c [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
Kyösti Mälkki9e69c872018-06-02 15:35:27 +030032static void mch_domain_read_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
Kyösti Mälkki9e69c872018-06-02 15:35:27 +030037 pci_domain_read_resources(dev);
38
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +020039 pci_tolm = find_pci_tolm(dev->link_list);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070040 mc_dev = dev->link_list->children;
41 if (mc_dev) {
42 /* Figure out which areas are/should be occupied by RAM.
43 * This is all computed in kilobytes and converted to/from
44 * the memory controller right at the edges.
45 * Having different variables in different units is
46 * too confusing to get right. Kilobytes are good up to
47 * 4 Terabytes of RAM...
48 */
49 uint16_t tolm_r, remapbase_r, remaplimit_r;
50 unsigned long tomk, tolmk;
51 unsigned long remapbasek, remaplimitk;
52 int idx;
53
54 /* Get the value of the highest DRB. This tells the end of
55 * the physical memory. The units are ticks of 64MB
56 * i.e. 1 means 64MB.
57 */
Kyösti Mälkki5bd271b2012-04-10 16:11:53 +030058 tomk = ((unsigned long)pci_read_config8(mc_dev, DRB_ROW_7)) << 16;
Stefan Reinauerb15975b2011-10-21 12:57:59 -070059 /* Compute the top of Low memory */
60 tolmk = pci_tolm >> 10;
61 if (tolmk >= tomk) {
62 /* The PCI hole does not overlap memory
63 * we won't use the remap window.
64 */
65 tolmk = tomk;
66 remapbasek = 0x3ff << 16;
67 remaplimitk = 0 << 16;
68 }
69 else {
70 /* The PCI memory hole overlaps memory
71 * setup the remap window.
72 */
73 /* Find the bottom of the remap window
74 * is it above 4G?
75 */
76 remapbasek = 4*1024*1024;
77 if (tomk > remapbasek) {
78 remapbasek = tomk;
79 }
80 /* Find the limit of the remap window */
81 remaplimitk = (remapbasek + (4*1024*1024 - tolmk) - (1 << 16));
82 }
Elyes HAOUAS15279a92016-07-28 21:05:26 +020083 /* Write the RAM configuration registers,
Stefan Reinauerb15975b2011-10-21 12:57:59 -070084 * preserving the reserved bits.
85 */
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020086 tolm_r = pci_read_config16(mc_dev, TOLM);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070087 tolm_r = ((tolmk >> 17) << 11) | (tolm_r & 0x7ff);
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020088 pci_write_config16(mc_dev, TOLM, tolm_r);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070089
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020090 remapbase_r = pci_read_config16(mc_dev, REMAPBASE);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070091 remapbase_r = (remapbasek >> 16) | (remapbase_r & 0xfc00);
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020092 pci_write_config16(mc_dev, REMAPBASE, remapbase_r);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070093
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020094 remaplimit_r = pci_read_config16(mc_dev, REMAPLIMIT);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070095 remaplimit_r = (remaplimitk >> 16) | (remaplimit_r & 0xfc00);
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +020096 pci_write_config16(mc_dev, REMAPLIMIT, remaplimit_r);
Stefan Reinauerb15975b2011-10-21 12:57:59 -070097
98 /* Report the memory regions */
99 idx = 10;
100 ram_resource(dev, idx++, 0, 640);
101 ram_resource(dev, idx++, 768, tolmk - 768);
102 if (tomk > 4*1024*1024) {
103 ram_resource(dev, idx++, 4096*1024, tomk - 4*1024*1024);
104 }
105 if (remaplimitk >= remapbasek) {
106 ram_resource(dev, idx++, remapbasek,
107 (remaplimitk + 64*1024) - remapbasek);
108 }
109
Kyösti Mälkki70d92b92017-04-19 19:57:01 +0300110 set_late_cbmem_top(tolmk * 1024);
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700111 }
Kyösti Mälkki9e69c872018-06-02 15:35:27 +0300112}
113
114static void mch_domain_set_resources(struct device *dev)
115{
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700116 assign_resources(dev->link_list);
117}
118
Elyes HAOUAS97e8b752018-05-09 17:39:47 +0200119static void intel_set_subsystem(struct device *dev,
120 unsigned vendor, unsigned device)
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +0200121{
122 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
123 ((device & 0xffff) << 16) | (vendor & 0xffff));
124}
125
126static struct pci_operations intel_pci_ops = {
127 .set_subsystem = intel_set_subsystem,
128};
129
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700130static struct device_operations pci_domain_ops = {
Kyösti Mälkki9e69c872018-06-02 15:35:27 +0300131 .read_resources = mch_domain_read_resources,
132 .set_resources = mch_domain_set_resources,
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +0200133 .enable_resources = NULL,
134 .init = NULL,
135 .scan_bus = pci_domain_scan_bus,
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +0200136 .ops_pci = &intel_pci_ops,
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700137};
138
Elyes HAOUAS97e8b752018-05-09 17:39:47 +0200139static void cpu_bus_init(struct device *dev)
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700140{
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +0200141 initialize_cpus(dev->link_list);
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700142}
143
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700144static struct device_operations cpu_bus_ops = {
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +0200145 .read_resources = DEVICE_NOOP,
146 .set_resources = DEVICE_NOOP,
147 .enable_resources = DEVICE_NOOP,
148 .init = cpu_bus_init,
149 .scan_bus = 0,
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700150};
151
152static void enable_dev(struct device *dev)
153{
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +0200154 /* Set the operations if it is a special bus type */
155 if (dev->path.type == DEVICE_PATH_DOMAIN) {
156 dev->ops = &pci_domain_ops;
157 }
158 else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
159 dev->ops = &cpu_bus_ops;
160 }
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700161}
162
Kyösti Mälkki0a0d5e82011-10-31 14:18:33 +0200163struct chip_operations northbridge_intel_e7505_ops = {
164 CHIP_NAME("Intel E7505 Northbridge")
Stefan Reinauerb15975b2011-10-21 12:57:59 -0700165 .enable_dev = enable_dev,
166};