blob: d7da9294e665a435760f5eb85ebb1e2b5724f1d5 [file] [log] [blame]
Lee Leahy4dd34ee2016-05-02 14:31:02 -07001/*
2 * This file is part of the coreboot project.
3 *
Lee Leahy4dd34ee2016-05-02 14:31:02 -07004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <console/console.h>
16#include <device/pci_ids.h>
17#include <soc/pci_devs.h>
18#include <soc/reg_access.h>
19
20/* USB Phy Registers */
21#define USB2_GLOBAL_PORT 0x4001
22#define USB2_PLL1 0x7F02
23#define USB2_PLL2 0x7F03
24#define USB2_COMPBG 0x7F04
25
Lee Leahyf8841122016-05-22 09:23:49 -070026/* EHCI Packet Buffer OUT/IN Thresholds, values in number of DWORDs */
27#define EHCI_OUT_THRESHOLD_VALUE 0x7f
28#define EHCI_IN_THRESHOLD_VALUE 0x7f
29
Lee Leahyfd456582016-05-22 09:55:22 -070030/* Platform init USB device interrupt masks */
31#define V_IOH_USBDEVICE_D_INTR_MSK_UDC_REG (0x0000007f)
32#define V_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG \
33 (B_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG_OUT_EP_MASK \
34 | B_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG_IN_EP_MASK)
35
Lee Leahy4dd34ee2016-05-02 14:31:02 -070036/* In order to configure the USB PHY to use clk120 (ickusbcoreclk) as PLL
37 * reference clock and Port2 as a USB device port, the following sequence must
38 * be followed
39 */
Lee Leahyfd456582016-05-22 09:55:22 -070040static const struct reg_script ehci_init_script[] = {
Lee Leahy4dd34ee2016-05-02 14:31:02 -070041
Lee Leahyf8841122016-05-22 09:23:49 -070042 /* Set packet buffer OUT/IN thresholds */
43 REG_MMIO_RMW32(R_IOH_EHCI_INSNREG01,
44 ~(B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_MASK
45 | B_IOH_EHCI_INSNREG01_IN_THRESHOLD_MASK),
46 (EHCI_OUT_THRESHOLD_VALUE
47 << B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_BP)
48 | (EHCI_IN_THRESHOLD_VALUE
49 << B_IOH_EHCI_INSNREG01_IN_THRESHOLD_BP)),
50
Lee Leahy4dd34ee2016-05-02 14:31:02 -070051 /* Sighting #4930631 PDNRESCFG [8:7] of USB2_GLOBAL_PORT = 11b.
52 * For port 0 & 1 as host and port 2 as device.
53 */
54 REG_USB_RXW(USB2_GLOBAL_PORT, ~(BIT8 | BIT7 | BIT1), (BIT8 | BIT7)),
55
56 /*
57 * Sighting #4930653 Required BIOS change on Disconnect vref to change
58 * to 600mV.
59 */
60 REG_USB_RXW(USB2_COMPBG, ~(BIT10 | BIT9 | BIT8 | BIT7),
61 (BIT10 | BIT7)),
62
63 /* Sideband register write to USB AFE (Phy)
64 * (pllbypass) to bypass/Disable PLL before switch
65 */
66 REG_USB_OR(USB2_PLL2, BIT29),
67
68 /* Sideband register write to USB AFE (Phy)
69 * (coreclksel) to select 120MHz (ickusbcoreclk) clk source.
70 * (Default 0 to select 96MHz (ickusbclk96_npad/ppad))
71 */
72 REG_USB_OR(USB2_PLL1, BIT1),
73
74 /* Sideband register write to USB AFE (Phy)
75 * (divide by 8) to achieve internal 480MHz clock
76 * for 120MHz input refclk. (Default: 4'b1000 (divide by 10) for 96MHz)
77 */
78 REG_USB_RXW(USB2_PLL1, ~(BIT6 | BIT5 | BIT4 | BIT3), BIT6),
79
80 /* Sideband register write to USB AFE (Phy)
81 * Clear (pllbypass)
82 */
83 REG_USB_AND(USB2_PLL2, ~BIT29),
84
85 /* Sideband register write to USB AFE (Phy)
86 * Set (startlock) to force the PLL FSM to restart the lock
87 * sequence due to input clock/freq switch.
88 */
89 REG_USB_OR(USB2_PLL2, BIT24),
90 REG_SCRIPT_END
91};
92
Lee Leahyfd456582016-05-22 09:55:22 -070093static const struct reg_script usb_device_port_init_script[] = {
94
95 /* Mask and clear controller interrupts */
96 REG_MMIO_WRITE32(R_IOH_USBDEVICE_D_INTR_MSK_UDC_REG,
97 V_IOH_USBDEVICE_D_INTR_MSK_UDC_REG),
98 REG_MMIO_WRITE32(R_IOH_USBDEVICE_D_INTR_UDC_REG,
99 V_IOH_USBDEVICE_D_INTR_MSK_UDC_REG),
100
101 /* Mask and clear end point interrupts */
102 REG_MMIO_WRITE32(R_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG,
103 V_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG),
104 REG_MMIO_WRITE32(R_IOH_USBDEVICE_EP_INTR_UDC_REG,
105 V_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG),
106 REG_SCRIPT_END
107};
108
Elyes HAOUAS696545d2018-05-25 13:11:37 +0200109static void init(struct device *dev)
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700110{
Lee Leahyfd456582016-05-22 09:55:22 -0700111 if ((dev->path.pci.devfn & 7) == EHCI_FUNC) {
112 printk(BIOS_INFO, "Initializing USB PLLs\n");
113 reg_script_run_on_dev(dev, ehci_init_script);
114 } else {
115 printk(BIOS_INFO, "Initializing USB device port\n");
116 reg_script_run_on_dev(dev, usb_device_port_init_script);
117 }
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700118}
119
120static struct device_operations device_ops = {
121 .read_resources = pci_dev_read_resources,
122 .set_resources = pci_dev_set_resources,
123 .enable_resources = pci_dev_enable_resources,
124 .init = init,
125};
126
127static const struct pci_driver driver __pci_driver = {
128 .ops = &device_ops,
129 .vendor = PCI_VENDOR_ID_INTEL,
130 .device = EHCI_DEVID,
131};