Andrew Wu | 0651072 | 2013-06-21 21:37:05 +0800 | [diff] [blame^] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
| 4 | * Copyright (C) 2013 DMP Electronics Inc. |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; version 2 of the License. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program; if not, write to the Free Software |
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 18 | */ |
| 19 | |
| 20 | #include <console/console.h> |
| 21 | #include <arch/io.h> |
| 22 | #include <stdint.h> |
| 23 | #include <device/device.h> |
| 24 | #include <device/pci.h> |
| 25 | #include <device/pci_ids.h> |
| 26 | #include <cbmem.h> |
| 27 | #include <pc80/mc146818rtc.h> |
| 28 | #include "chip.h" |
| 29 | #include "northbridge.h" |
| 30 | |
| 31 | #define SPI_BASE 0xfc00 |
| 32 | |
| 33 | static void northbridge_init(device_t dev) |
| 34 | { |
| 35 | printk(BIOS_DEBUG, "Vortex86EX northbridge early init ...\n"); |
| 36 | // enable F0A/ECA/E8A/E4A/E0A/C4A/C0A shadow read/writable. |
| 37 | pci_write_config32(dev, NB_REG_MAR, 0x3ff000f0); |
| 38 | // enable C0000h - C3FFFh/C4000h - C7FFF can be in L1 cache selection. |
| 39 | pci_write_config32(dev, NB_REG_HOST_CTL, (1 << 18) | (1 << 19)); |
| 40 | // Set SPI register base. |
| 41 | pci_write_config16(dev, NB_REG_SPI_BASE, SPI_BASE | 1); |
| 42 | } |
| 43 | |
| 44 | static struct device_operations northbridge_operations = { |
| 45 | .set_resources = pci_dev_set_resources, |
| 46 | .enable_resources = pci_dev_enable_resources, |
| 47 | .init = northbridge_init |
| 48 | }; |
| 49 | |
| 50 | static const struct pci_driver northbridge_driver_6021 __pci_driver = { |
| 51 | .ops = &northbridge_operations, |
| 52 | .vendor = PCI_VENDOR_ID_RDC, |
| 53 | .device = 0x6021, /* DX CPU N/B ID */ |
| 54 | }; |
| 55 | |
| 56 | static const struct pci_driver northbridge_driver_6025 __pci_driver = { |
| 57 | .ops = &northbridge_operations, |
| 58 | .vendor = PCI_VENDOR_ID_RDC, |
| 59 | .device = 0x6025, /* EX CPU N/B ID */ |
| 60 | }; |
| 61 | |
| 62 | /* Set CMOS register 15h/16h/17h/18h for base/extended |
| 63 | * memory size. */ |
| 64 | static void set_cmos_memory_size(unsigned long sizek) |
| 65 | { |
| 66 | unsigned long ext_mem_size; |
| 67 | u8 ext_mem_size_hb, ext_mem_size_lb; |
| 68 | /* calculate memory size between 1M - 65M. */ |
| 69 | ext_mem_size = sizek - 1024; |
| 70 | if (ext_mem_size > 65535) |
| 71 | ext_mem_size = 65535; |
| 72 | ext_mem_size_hb = (u8) (ext_mem_size >> 8); |
| 73 | ext_mem_size_lb = (u8) (ext_mem_size & 0xff); |
| 74 | /* Base memory is always 640K. */ |
| 75 | cmos_write(0x80, 0x15); |
| 76 | cmos_write(0x02, 0x16); |
| 77 | /* Write extended memory size. */ |
| 78 | cmos_write(ext_mem_size_lb, 0x17); |
| 79 | cmos_write(ext_mem_size_hb, 0x18); |
| 80 | /* register 0x30(48) is RTC_BOOT_BYTE for coreboot, |
| 81 | * don't touch it. */ |
| 82 | } |
| 83 | |
| 84 | static void pci_domain_set_resources(device_t dev) |
| 85 | { |
| 86 | device_t mc_dev; |
| 87 | uint32_t pci_tolm; |
| 88 | |
| 89 | printk(BIOS_SPEW, "Entering vortex86ex pci_domain_set_resources.\n"); |
| 90 | |
| 91 | pci_tolm = find_pci_tolm(dev->link_list); |
| 92 | mc_dev = dev->link_list->children; |
| 93 | if (mc_dev) { |
| 94 | unsigned long tomk, tolmk; |
| 95 | int idx; |
| 96 | int ss; |
| 97 | /* Get DDRII size setting from northbridge register. */ |
| 98 | /* SS = 0 for 2MB, 1 for 4MB, 2 for 8MB, 3 for 16MB ... */ |
| 99 | ss = pci_read_config16(mc_dev, 0x6c); |
| 100 | ss = ((ss >> 8) & 0xf); |
| 101 | tomk = (2 * 1024) << ss; |
| 102 | printk(BIOS_DEBUG, "I would set ram size to %ld Mbytes\n", (tomk >> 10)); |
| 103 | /* Compute the top of Low memory */ |
| 104 | tolmk = pci_tolm >> 10; |
| 105 | if (tolmk >= tomk) |
| 106 | /* The PCI hole does does not overlap the memory. |
| 107 | */ |
| 108 | tolmk = tomk; |
| 109 | |
| 110 | high_tables_base = (tolmk * 1024) - HIGH_MEMORY_SIZE; |
| 111 | high_tables_size = HIGH_MEMORY_SIZE; |
| 112 | printk(BIOS_DEBUG, "tom: %lx, high_tables_base: %llx, high_tables_size: %llx\n", |
| 113 | tomk * 1024, high_tables_base, high_tables_size); |
| 114 | |
| 115 | /* Report the memory regions */ |
| 116 | idx = 10; |
| 117 | ram_resource(dev, idx++, 0, 640); /* first 640k */ |
| 118 | ram_resource(dev, idx++, 768, tolmk - 768); /* leave a hole for vga */ |
| 119 | set_cmos_memory_size(tolmk); |
| 120 | } |
| 121 | assign_resources(dev->link_list); |
| 122 | } |
| 123 | |
| 124 | static struct device_operations pci_domain_ops = { |
| 125 | .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, |
| 130 | }; |
| 131 | |
| 132 | static void enable_dev(struct device *dev) |
| 133 | { |
| 134 | printk(BIOS_SPEW, "In vortex86ex enable_dev for device %s.\n", dev_path(dev)); |
| 135 | |
| 136 | /* Set the operations if it is a special bus type */ |
| 137 | if (dev->path.type == DEVICE_PATH_DOMAIN) { |
| 138 | dev->ops = &pci_domain_ops; |
| 139 | pci_set_method(dev); |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | struct chip_operations northbridge_dmp_vortex86ex_ops = { |
| 144 | CHIP_NAME("DMP Vortex86EX Northbridge") |
| 145 | .enable_dev = enable_dev, |
| 146 | }; |