Angel Pons | 4b42983 | 2020-04-02 23:48:50 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Vladimir Serbinenko | c6f6be0 | 2013-11-12 22:32:08 +0100 | [diff] [blame] | 2 | |
Vladimir Serbinenko | bd89699 | 2014-01-02 10:10:14 +0100 | [diff] [blame] | 3 | #define __SIMPLE_DEVICE__ |
| 4 | |
Vladimir Serbinenko | c6f6be0 | 2013-11-12 22:32:08 +0100 | [diff] [blame] | 5 | #include <types.h> |
Angel Pons | ce3e638 | 2020-08-03 18:57:34 +0200 | [diff] [blame] | 6 | #include <commonlib/helpers.h> |
Vladimir Serbinenko | c6f6be0 | 2013-11-12 22:32:08 +0100 | [diff] [blame] | 7 | #include <device/device.h> |
Kyösti Mälkki | f1b58b7 | 2019-03-01 13:43:02 +0200 | [diff] [blame] | 8 | #include <device/pci_ops.h> |
Angel Pons | 95de231 | 2020-02-17 13:08:53 +0100 | [diff] [blame] | 9 | #include "ironlake.h" |
Vladimir Serbinenko | c6f6be0 | 2013-11-12 22:32:08 +0100 | [diff] [blame] | 10 | |
Angel Pons | ce3e638 | 2020-08-03 18:57:34 +0200 | [diff] [blame] | 11 | static int decode_pcie_bar(u32 *const base, u32 *const len) |
Vladimir Serbinenko | c6f6be0 | 2013-11-12 22:32:08 +0100 | [diff] [blame] | 12 | { |
Angel Pons | ce3e638 | 2020-08-03 18:57:34 +0200 | [diff] [blame] | 13 | *base = 0; |
| 14 | *len = 0; |
Vladimir Serbinenko | c6f6be0 | 2013-11-12 22:32:08 +0100 | [diff] [blame] | 15 | |
Angel Pons | ce3e638 | 2020-08-03 18:57:34 +0200 | [diff] [blame] | 16 | const u32 pciexbar_reg = pci_read_config32(QPI_SAD, SAD_PCIEXBAR); |
Vladimir Serbinenko | c6f6be0 | 2013-11-12 22:32:08 +0100 | [diff] [blame] | 17 | |
Vladimir Serbinenko | c6f6be0 | 2013-11-12 22:32:08 +0100 | [diff] [blame] | 18 | if (!(pciexbar_reg & (1 << 0))) |
Angel Pons | ce3e638 | 2020-08-03 18:57:34 +0200 | [diff] [blame] | 19 | return 0; |
Vladimir Serbinenko | c6f6be0 | 2013-11-12 22:32:08 +0100 | [diff] [blame] | 20 | |
| 21 | switch ((pciexbar_reg >> 1) & 3) { |
Angel Pons | ce3e638 | 2020-08-03 18:57:34 +0200 | [diff] [blame] | 22 | case 0: /* 256MB */ |
| 23 | *base = pciexbar_reg & (0x0f << 28); |
| 24 | *len = 256 * MiB; |
| 25 | return 1; |
| 26 | case 1: /* 128M */ |
| 27 | *base = pciexbar_reg & (0x1f << 27); |
| 28 | *len = 128 * MiB; |
| 29 | return 1; |
| 30 | case 2: /* 64M */ |
| 31 | *base = pciexbar_reg & (0x3f << 26); |
| 32 | *len = 64 * MiB; |
| 33 | return 1; |
Vladimir Serbinenko | c6f6be0 | 2013-11-12 22:32:08 +0100 | [diff] [blame] | 34 | } |
| 35 | |
Angel Pons | ce3e638 | 2020-08-03 18:57:34 +0200 | [diff] [blame] | 36 | return 0; |
| 37 | } |
| 38 | |
| 39 | unsigned long acpi_fill_mcfg(unsigned long current) |
| 40 | { |
| 41 | u32 length, pciexbar; |
| 42 | |
| 43 | if (!decode_pcie_bar(&pciexbar, &length)) |
Vladimir Serbinenko | c6f6be0 | 2013-11-12 22:32:08 +0100 | [diff] [blame] | 44 | return current; |
| 45 | |
Angel Pons | ce3e638 | 2020-08-03 18:57:34 +0200 | [diff] [blame] | 46 | const int max_buses = length / MiB; |
| 47 | |
Vladimir Serbinenko | c6f6be0 | 2013-11-12 22:32:08 +0100 | [diff] [blame] | 48 | current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current, |
| 49 | pciexbar, 0x0, 0x0, max_buses - 1); |
| 50 | |
| 51 | return current; |
| 52 | } |