Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
Aaron Lwe | fcb2a31 | 2008-05-19 12:17:43 +0000 | [diff] [blame] | 4 | * Copyright (C) 2008 VIA Technologies, Inc. |
| 5 | * (Written by Aaron Lwe <aaron.lwe@gmail.com> for VIA) |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 6 | * Copyright (C) 2007 Corey Osgood <corey.osgood@gmail.com> |
| 7 | * |
| 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License as published by |
| 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | * (at your option) any later version. |
| 12 | * |
| 13 | * This program is distributed in the hope that it will be useful, |
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | * GNU General Public License for more details. |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 17 | */ |
| 18 | |
| 19 | #include <console/console.h> |
| 20 | #include <arch/io.h> |
| 21 | #include <stdint.h> |
| 22 | #include <device/device.h> |
| 23 | #include <device/pci.h> |
| 24 | #include <device/pci_ids.h> |
| 25 | #include <stdlib.h> |
| 26 | #include <string.h> |
Ronald G. Minnich | 5079a0d | 2012-11-27 11:32:38 -0800 | [diff] [blame] | 27 | #include <lib.h> |
Stefan Reinauer | fd611f9 | 2013-02-27 23:45:20 +0100 | [diff] [blame] | 28 | #include <cbmem.h> |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 29 | #include <cpu/cpu.h> |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 30 | #include "northbridge.h" |
| 31 | #include "cn700.h" |
| 32 | |
| 33 | static void memctrl_init(device_t dev) |
| 34 | { |
Aaron Lwe | fcb2a31 | 2008-05-19 12:17:43 +0000 | [diff] [blame] | 35 | device_t vlink_dev; |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 36 | u16 reg16; |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 37 | u8 ranks, pagec, paged, pagee, pagef, shadowreg; |
| 38 | |
| 39 | /* Set up the VGA framebuffer size. */ |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 40 | reg16 = (log2(CONFIG_VIDEO_MB) << 12) | (1 << 15); |
| 41 | pci_write_config16(dev, 0xa0, reg16); |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 42 | |
| 43 | /* Set up VGA timers. */ |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 44 | pci_write_config8(dev, 0xa2, 0x44); |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 45 | |
Aaron Lwe | fcb2a31 | 2008-05-19 12:17:43 +0000 | [diff] [blame] | 46 | for (ranks = 0x4b; ranks >= 0x48; ranks--) { |
| 47 | if (pci_read_config8(dev, ranks)) { |
| 48 | ranks -= 0x48; |
| 49 | break; |
| 50 | } |
| 51 | } |
| 52 | if (ranks == 0x47) |
| 53 | ranks = 0x00; |
| 54 | reg16 = 0xaae0; |
| 55 | reg16 |= ranks; |
| 56 | /* GMINT Misc. FrameBuffer rank */ |
| 57 | pci_write_config16(dev, 0xb0, reg16); |
| 58 | /* AGPCINT Misc. */ |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 59 | pci_write_config8(dev, 0xb8, 0x08); |
Aaron Lwe | fcb2a31 | 2008-05-19 12:17:43 +0000 | [diff] [blame] | 60 | |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 61 | /* Shadow RAM */ |
Aaron Lwe | fcb2a31 | 2008-05-19 12:17:43 +0000 | [diff] [blame] | 62 | pagec = 0xff, paged = 0xff, pagee = 0xff, pagef = 0x30; |
| 63 | /* PAGE C, D, E are all read write enable */ |
| 64 | pci_write_config8(dev, 0x80, pagec); |
| 65 | pci_write_config8(dev, 0x81, paged); |
| 66 | pci_write_config8(dev, 0x82, pagee); |
| 67 | /* PAGE F are read/writable */ |
| 68 | shadowreg = pci_read_config8(dev, 0x83); |
| 69 | shadowreg |= pagef; |
| 70 | pci_write_config8(dev, 0x83, shadowreg); |
| 71 | /* vlink mirror */ |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 72 | vlink_dev = dev_find_device(PCI_VENDOR_ID_VIA, |
| 73 | PCI_DEVICE_ID_VIA_CN700_VLINK, 0); |
Aaron Lwe | fcb2a31 | 2008-05-19 12:17:43 +0000 | [diff] [blame] | 74 | if (vlink_dev) { |
| 75 | pci_write_config8(vlink_dev, 0x61, pagec); |
| 76 | pci_write_config8(vlink_dev, 0x62, paged); |
| 77 | pci_write_config8(vlink_dev, 0x64, pagee); |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 78 | |
Aaron Lwe | fcb2a31 | 2008-05-19 12:17:43 +0000 | [diff] [blame] | 79 | shadowreg = pci_read_config8(vlink_dev, 0x63); |
| 80 | shadowreg |= pagef; |
| 81 | pci_write_config8(vlink_dev, 0x63, shadowreg); |
| 82 | } |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 83 | } |
| 84 | |
| 85 | static const struct device_operations memctrl_operations = { |
Edward O'Callaghan | d204073 | 2014-10-31 08:26:21 +1100 | [diff] [blame] | 86 | .read_resources = DEVICE_NOOP, |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 87 | .init = memctrl_init, |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 88 | }; |
| 89 | |
| 90 | static const struct pci_driver memctrl_driver __pci_driver = { |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 91 | .ops = &memctrl_operations, |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 92 | .vendor = PCI_VENDOR_ID_VIA, |
| 93 | .device = PCI_DEVICE_ID_VIA_CN700_MEMCTRL, |
| 94 | }; |
| 95 | |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 96 | static void pci_domain_set_resources(device_t dev) |
| 97 | { |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 98 | /* The order is important to find the correct RAM size. */ |
| 99 | static const u8 ramregs[] = { 0x43, 0x42, 0x41, 0x40 }; |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 100 | device_t mc_dev; |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 101 | u32 pci_tolm; |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 102 | |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 103 | printk(BIOS_SPEW, "Entering cn700 pci_domain_set_resources.\n"); |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 104 | |
Myles Watson | 894a347 | 2010-06-09 22:41:35 +0000 | [diff] [blame] | 105 | pci_tolm = find_pci_tolm(dev->link_list); |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 106 | mc_dev = dev_find_device(PCI_VENDOR_ID_VIA, |
| 107 | PCI_DEVICE_ID_VIA_CN700_MEMCTRL, 0); |
Aaron Lwe | fcb2a31 | 2008-05-19 12:17:43 +0000 | [diff] [blame] | 108 | |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 109 | if (mc_dev) { |
| 110 | unsigned long tomk, tolmk; |
| 111 | unsigned char rambits; |
| 112 | int i, idx; |
| 113 | |
Aaron Lwe | fcb2a31 | 2008-05-19 12:17:43 +0000 | [diff] [blame] | 114 | /* |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 115 | * Once the register value is not zero, the RAM size is |
| 116 | * this register's value multiply 64 * 1024 * 1024. |
Aaron Lwe | fcb2a31 | 2008-05-19 12:17:43 +0000 | [diff] [blame] | 117 | */ |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 118 | for (rambits = 0, i = 0; i < ARRAY_SIZE(ramregs); i++) { |
Aaron Lwe | fcb2a31 | 2008-05-19 12:17:43 +0000 | [diff] [blame] | 119 | rambits = pci_read_config8(mc_dev, ramregs[i]); |
| 120 | if (rambits != 0) |
| 121 | break; |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 122 | } |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 123 | |
Aaron Lwe | fcb2a31 | 2008-05-19 12:17:43 +0000 | [diff] [blame] | 124 | tomk = rambits * 64 * 1024; |
Corey Osgood | f976548 | 2010-08-01 17:20:20 +0000 | [diff] [blame] | 125 | printk(BIOS_DEBUG, "tomk is 0x%lx\n", tomk); |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 126 | /* Compute the Top Of Low Memory (TOLM), in Kb. */ |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 127 | tolmk = pci_tolm >> 10; |
| 128 | if (tolmk >= tomk) { |
| 129 | /* The PCI hole does does not overlap the memory. */ |
| 130 | tolmk = tomk; |
| 131 | } |
Stefan Reinauer | b5fb0c5 | 2009-04-30 13:58:42 +0000 | [diff] [blame] | 132 | |
Kyösti Mälkki | 42f4651 | 2013-06-27 08:20:09 +0300 | [diff] [blame] | 133 | set_top_of_ram((tolmk - CONFIG_VIDEO_MB * 1024) * 1024); |
Stefan Reinauer | b5fb0c5 | 2009-04-30 13:58:42 +0000 | [diff] [blame] | 134 | |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 135 | /* Report the memory regions. */ |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 136 | idx = 10; |
| 137 | /* TODO: Hole needed? */ |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 138 | ram_resource(dev, idx++, 0, 640); /* First 640k */ |
| 139 | /* Leave a hole for VGA, 0xa0000 - 0xc0000 */ |
| 140 | ram_resource(dev, idx++, 768, |
| 141 | (tolmk - 768 - CONFIG_VIDEO_MB * 1024)); |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 142 | } |
Myles Watson | 894a347 | 2010-06-09 22:41:35 +0000 | [diff] [blame] | 143 | assign_resources(dev->link_list); |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 144 | } |
| 145 | |
Stefan Reinauer | 3c8ac78 | 2010-04-03 13:33:01 +0000 | [diff] [blame] | 146 | static struct device_operations pci_domain_ops = { |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 147 | .read_resources = pci_domain_read_resources, |
| 148 | .set_resources = pci_domain_set_resources, |
Myles Watson | 7eac445 | 2010-06-17 16:16:56 +0000 | [diff] [blame] | 149 | .enable_resources = NULL, |
| 150 | .init = NULL, |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 151 | .scan_bus = pci_domain_scan_bus, |
Kyösti Mälkki | 33e5df3 | 2013-07-03 10:51:34 +0300 | [diff] [blame] | 152 | .ops_pci_bus = pci_bus_default_ops, |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 153 | }; |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 154 | |
| 155 | static void cpu_bus_init(device_t dev) |
| 156 | { |
Myles Watson | 894a347 | 2010-06-09 22:41:35 +0000 | [diff] [blame] | 157 | initialize_cpus(dev->link_list); |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 158 | } |
| 159 | |
Stefan Reinauer | 3c8ac78 | 2010-04-03 13:33:01 +0000 | [diff] [blame] | 160 | static struct device_operations cpu_bus_ops = { |
Edward O'Callaghan | d204073 | 2014-10-31 08:26:21 +1100 | [diff] [blame] | 161 | .read_resources = DEVICE_NOOP, |
| 162 | .set_resources = DEVICE_NOOP, |
| 163 | .enable_resources = DEVICE_NOOP, |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 164 | .init = cpu_bus_init, |
| 165 | .scan_bus = 0, |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 166 | }; |
| 167 | |
| 168 | static void enable_dev(struct device *dev) |
| 169 | { |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 170 | printk(BIOS_SPEW, "In cn700 enable_dev for device %s.\n", dev_path(dev)); |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 171 | |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 172 | /* Set the operations if it is a special bus type. */ |
Stefan Reinauer | 4aff445 | 2013-02-12 14:17:15 -0800 | [diff] [blame] | 173 | if (dev->path.type == DEVICE_PATH_DOMAIN) { |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 174 | dev->ops = &pci_domain_ops; |
Stefan Reinauer | 0aa37c4 | 2013-02-12 15:20:54 -0800 | [diff] [blame] | 175 | } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) { |
Uwe Hermann | ea7b518 | 2008-10-09 17:08:32 +0000 | [diff] [blame] | 176 | dev->ops = &cpu_bus_ops; |
| 177 | } |
Corey Osgood | bd3f93e | 2008-02-21 00:56:14 +0000 | [diff] [blame] | 178 | } |
| 179 | |
| 180 | struct chip_operations northbridge_via_cn700_ops = { |
| 181 | CHIP_NAME("VIA CN700 Northbridge") |
| 182 | .enable_dev = enable_dev, |
| 183 | }; |