Angel Pons | 182dbde | 2020-04-02 23:49:05 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Arthur Heymans | 39f8a1a | 2019-10-02 17:13:02 +0200 | [diff] [blame] | 2 | |
| 3 | #include <device/mmio.h> |
| 4 | #include <device/pci_ops.h> |
| 5 | #include <device/pci_def.h> |
Arthur Heymans | 39f8a1a | 2019-10-02 17:13:02 +0200 | [diff] [blame] | 6 | #include <southbridge/intel/common/rcba.h> |
| 7 | #include <southbridge/intel/common/pmbase.h> |
| 8 | |
| 9 | #include "pch.h" |
| 10 | |
| 11 | #define TOTAL_USB_PORTS 14 |
| 12 | |
| 13 | void early_usb_init(const struct southbridge_usb_port *portmap) |
| 14 | { |
| 15 | u32 reg32; |
| 16 | const u16 currents[] = { 0xf57, 0xf5f, 0x753, 0x75f, 0x14b, 0x74b, |
| 17 | 0x557, 0x757, 0x55f, 0x54b |
| 18 | }; |
| 19 | int i; |
| 20 | |
| 21 | /* Unlock registers. */ |
| 22 | write_pmbase16(UPRWC, read_pmbase16(UPRWC) | UPRWC_WR_EN); |
| 23 | |
| 24 | for (i = 0; i < TOTAL_USB_PORTS; i++) |
| 25 | RCBA32_AND_OR(USBIR0 + 4 * i, ~0xfff, currents[portmap[i].current]); |
| 26 | |
| 27 | /* USB Initialization Registers. We follow what EDS recommends here. |
| 28 | TODO maybe vendor firmware values are better? */ |
| 29 | RCBA32(USBIRC) &= ~(1 << 8); |
| 30 | RCBA32_OR(USBIRA, (7 << 12) | (7 << 8) | (7 << 4) | (2 << 0)); |
| 31 | RCBA32_AND_OR(USBIRB, ~0x617f0, (3 << 17) | (1 << 12) | (1 << 10) |
| 32 | | (1 << 8) | (4 << 4)); |
| 33 | /* Set to Rate Matching Hub Mode to make PCI devices appear. */ |
| 34 | RCBA32(0x3598) = 0; |
| 35 | |
| 36 | reg32 = 0; |
Angel Pons | 77f340a | 2020-10-17 18:39:04 +0200 | [diff] [blame] | 37 | for (i = 0; i < TOTAL_USB_PORTS; i++) { |
Arthur Heymans | 39f8a1a | 2019-10-02 17:13:02 +0200 | [diff] [blame] | 38 | if (!portmap[i].enabled) |
| 39 | reg32 |= (1 << i); |
Angel Pons | 77f340a | 2020-10-17 18:39:04 +0200 | [diff] [blame] | 40 | } |
Arthur Heymans | 39f8a1a | 2019-10-02 17:13:02 +0200 | [diff] [blame] | 41 | RCBA32(USBPDO) = reg32; |
| 42 | reg32 = 0; |
| 43 | /* The OC pins of the first 8 USB ports are mapped in USBOCM1 */ |
Angel Pons | 77f340a | 2020-10-17 18:39:04 +0200 | [diff] [blame] | 44 | for (i = 0; i < 8; i++) { |
Arthur Heymans | 39f8a1a | 2019-10-02 17:13:02 +0200 | [diff] [blame] | 45 | if (portmap[i].enabled && portmap[i].oc_pin >= 0) |
| 46 | reg32 |= (1 << (i + 8 * portmap[i].oc_pin)); |
Angel Pons | 77f340a | 2020-10-17 18:39:04 +0200 | [diff] [blame] | 47 | } |
Arthur Heymans | 39f8a1a | 2019-10-02 17:13:02 +0200 | [diff] [blame] | 48 | RCBA32(USBOCM1) = reg32; |
| 49 | reg32 = 0; |
| 50 | /* The OC pins of the remainder 6 USB ports are mapped in USBOCM2 */ |
Angel Pons | 77f340a | 2020-10-17 18:39:04 +0200 | [diff] [blame] | 51 | for (i = 8; i < TOTAL_USB_PORTS; i++) { |
Arthur Heymans | 39f8a1a | 2019-10-02 17:13:02 +0200 | [diff] [blame] | 52 | if (portmap[i].enabled && portmap[i].oc_pin >= 4) |
| 53 | reg32 |= (1 << (i - 8 + 8 * (portmap[i].oc_pin - 4))); |
Angel Pons | 77f340a | 2020-10-17 18:39:04 +0200 | [diff] [blame] | 54 | } |
Arthur Heymans | 39f8a1a | 2019-10-02 17:13:02 +0200 | [diff] [blame] | 55 | RCBA32(USBOCM2) = reg32; |
| 56 | |
| 57 | /* Relock registers. */ |
| 58 | write_pmbase16(UPRWC, 0); |
| 59 | } |