Mate Kukri | 62c2535 | 2021-06-06 14:00:57 +0100 | [diff] [blame^] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
| 3 | #include <arch/io.h> |
| 4 | #include <device/pnp_ops.h> |
| 5 | #include "sch555x.h" |
| 6 | |
| 7 | static void pnp_enter_conf_state(pnp_devfn_t dev) |
| 8 | { |
| 9 | unsigned int port = dev >> 8; |
| 10 | outb(0x55, port); |
| 11 | } |
| 12 | |
| 13 | static void pnp_exit_conf_state(pnp_devfn_t dev) |
| 14 | { |
| 15 | unsigned int port = dev >> 8; |
| 16 | outb(0xaa, port); |
| 17 | } |
| 18 | |
| 19 | static void pnp_write_config32(pnp_devfn_t dev, uint8_t offset, uint32_t value) |
| 20 | { |
| 21 | pnp_write_config(dev, offset, value & 0xff); |
| 22 | pnp_write_config(dev, offset + 1, (value >> 8) & 0xff); |
| 23 | pnp_write_config(dev, offset + 2, (value >> 16) & 0xff); |
| 24 | pnp_write_config(dev, offset + 3, (value >> 24) & 0xff); |
| 25 | } |
| 26 | |
| 27 | /* |
| 28 | * Do just enough init so that the motherboard specific magic EMI |
| 29 | * sequences can be sent before sch555x_enable_serial is called |
| 30 | */ |
| 31 | void sch555x_early_init(pnp_devfn_t global_dev) |
| 32 | { |
| 33 | pnp_enter_conf_state(global_dev); |
| 34 | |
| 35 | // Enable IRQs |
| 36 | pnp_set_logical_device(global_dev); |
| 37 | pnp_write_config(global_dev, SCH555x_DEVICE_MODE, 0x04); |
| 38 | |
| 39 | // Map EMI and runtime registers |
| 40 | pnp_devfn_t lpci_dev = PNP_DEV(global_dev >> 8, SCH555x_LDN_LPCI); |
| 41 | |
| 42 | pnp_set_logical_device(lpci_dev); |
| 43 | pnp_write_config32(lpci_dev, SCH555x_LPCI_EMI_BAR, |
| 44 | (SCH555x_EMI_IOBASE << 16) | 0x800f); |
| 45 | pnp_write_config32(lpci_dev, SCH555x_LPCI_RUNTIME_BAR, |
| 46 | (SCH555x_RUNTIME_IOBASE << 16) | 0x8a3f); |
| 47 | |
| 48 | pnp_exit_conf_state(global_dev); |
| 49 | } |
| 50 | |
| 51 | void sch555x_enable_serial(pnp_devfn_t uart_dev, uint16_t serial_iobase) |
| 52 | { |
| 53 | pnp_enter_conf_state(uart_dev); |
| 54 | |
| 55 | // Set LPCI BAR register to map UART into I/O space |
| 56 | pnp_devfn_t lpci_dev = PNP_DEV(uart_dev >> 8, SCH555x_LDN_LPCI); |
| 57 | |
| 58 | pnp_set_logical_device(lpci_dev); |
| 59 | u8 uart_bar = (uart_dev & 0xff) == SCH555x_LDN_UART1 |
| 60 | ? SCH555x_LPCI_UART1_BAR |
| 61 | : SCH555x_LPCI_UART2_BAR; |
| 62 | pnp_write_config32(lpci_dev, uart_bar, serial_iobase << 16 | 0x8707); |
| 63 | |
| 64 | // Set up the UART's configuration registers |
| 65 | pnp_set_logical_device(uart_dev); |
| 66 | pnp_set_enable(uart_dev, 1); // Activate |
| 67 | pnp_write_config(uart_dev, 0x0f, 0x02); // Config select |
| 68 | |
| 69 | pnp_exit_conf_state(uart_dev); |
| 70 | } |