blob: 206f54d1a51acbae529e17692d78ea6cfc3a3283 [file] [log] [blame]
Angel Pons8a3453f2020-04-02 23:48:19 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauer4885daa2011-04-26 23:47:04 +00002
3#include <stdint.h>
Kyösti Mälkki2b95da02014-02-15 10:19:23 +02004#include <stddef.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02005#include <device/pci_ops.h>
Kyösti Mälkki1d7541f2014-02-17 21:34:42 +02006#include <console/uart.h>
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +02007#include <device/pci.h>
Nicholas Chin0de34dc2023-04-20 13:23:07 -06008#include "uart8250reg.h"
Stefan Reinauer4885daa2011-04-26 23:47:04 +00009
Nicholas Chin0de34dc2023-04-20 13:23:07 -060010static int oxpcie_present;
Aaron Durbine4d7abc2017-04-16 22:05:36 -050011static DEVTREE_CONST u32 uart0_base = CONFIG_EARLY_PCI_MMIO_BASE + 0x1000;
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020012
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020013int pci_early_device_probe(u8 bus, u8 dev, u32 mmio_base)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000014{
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020015 pci_devfn_t device = PCI_DEV(bus, dev, 0);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000016
Kyösti Mälkkie0887212019-09-26 22:33:51 +030017 u32 id = pci_s_read_config32(device, PCI_VENDOR_ID);
Stefan Reinauera6087d12011-05-09 15:19:29 -070018 switch (id) {
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020019 case 0xc1181415: /* e.g. Startech PEX1S1PMINI function 0 */
Stefan Reinauera6087d12011-05-09 15:19:29 -070020 /* On this device function 0 is the parallel port, and
21 * function 3 is the serial port. So let's go look for
22 * the UART.
23 */
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020024 device = PCI_DEV(bus, dev, 3);
Kyösti Mälkkie0887212019-09-26 22:33:51 +030025 id = pci_s_read_config32(device, PCI_VENDOR_ID);
Stefan Reinauera6087d12011-05-09 15:19:29 -070026 if (id != 0xc11b1415)
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020027 return -1;
Stefan Reinauera6087d12011-05-09 15:19:29 -070028 break;
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020029 case 0xc11b1415: /* e.g. Startech PEX1S1PMINI function 3 */
Stefan Reinauera6087d12011-05-09 15:19:29 -070030 case 0xc1581415: /* e.g. Startech MPEX2S952 */
Stefan Reinauera6087d12011-05-09 15:19:29 -070031 break;
Gabe Black4d04a712011-10-05 01:52:08 -070032 default:
33 /* No UART here. */
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020034 return -1;
Stefan Reinauera6087d12011-05-09 15:19:29 -070035 }
36
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020037 /* Sanity-check, we assume fixed location. */
38 if (mmio_base != CONFIG_EARLY_PCI_MMIO_BASE)
39 return -1;
40
Stefan Reinauer4885daa2011-04-26 23:47:04 +000041 /* Setup base address on device */
Kyösti Mälkkie0887212019-09-26 22:33:51 +030042 pci_s_write_config32(device, PCI_BASE_ADDRESS_0, mmio_base);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000043
44 /* Enable memory on device */
Kyösti Mälkkie0887212019-09-26 22:33:51 +030045 u16 reg16 = pci_s_read_config16(device, PCI_COMMAND);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000046 reg16 |= PCI_COMMAND_MEMORY;
Kyösti Mälkkie0887212019-09-26 22:33:51 +030047 pci_s_write_config16(device, PCI_COMMAND, reg16);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000048
Arthur Heymans5fadb462019-11-20 21:28:15 +010049 oxpcie_present = 1;
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020050 return 0;
Stefan Reinauer4885daa2011-04-26 23:47:04 +000051}
52
Nicholas Chin0de34dc2023-04-20 13:23:07 -060053/*
54 * Stages that do not call pci_early_device_probe() identify an
55 * enabled UART with a test read. Since PCI bus enumeration
56 * has not happened PCI configuration register access is not
57 * possible here.
58 */
59static int uart_presence(uintptr_t base)
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020060{
Nicholas Chin0de34dc2023-04-20 13:23:07 -060061 /* LCR has no side-effects on reads. */
62 const u8 reg = UART8250_LCR;
63 u8 val;
64
65 if (CONFIG(DRIVERS_UART_8250MEM_32))
66 val = read32p(base + 4 * reg) & 0xff;
67 else
68 val = read8p(base + reg);
69
70 if (val == 0xff)
71 return -1;
72
73 /* Something decoded MMIO read, assume it was the UART. */
74 return 1;
75}
76
77static bool oxpcie_uart_active(void)
78{
79 if (oxpcie_present == 0)
80 oxpcie_present = uart_presence(uart0_base);
81
82 if (oxpcie_present > 0)
83 return true;
84 if (oxpcie_present < 0)
85 return false;
86
87 /* not reached */
88 return false;
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020089}
90
Felix Helde3a12472020-09-11 15:47:09 +020091uintptr_t uart_platform_base(unsigned int idx)
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020092{
Felix Helde3a12472020-09-11 15:47:09 +020093 if ((idx < 8) && oxpcie_uart_active())
Kyösti Mälkkie993ec72015-03-20 08:51:57 +020094 return uart0_base + idx * 0x200;
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020095 return 0;
96}
97
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020098void oxford_remap(u32 new_base)
99{
Kyösti Mälkkifb25f9f2018-12-26 20:15:58 +0200100#if ENV_RAMSTAGE
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200101 uart0_base = new_base + 0x1000;
Gabe Black4d04a712011-10-05 01:52:08 -0700102#endif
Kyösti Mälkkifb25f9f2018-12-26 20:15:58 +0200103}
Kyösti Mälkki3ee16682014-02-17 19:37:52 +0200104
105unsigned int uart_platform_refclk(void)
106{
107 return 62500000;
108}