blob: b084b0a14fb57370593f97292b5e10cc5d634ab0 [file] [log] [blame]
Angel Ponsc3f58f62020-04-05 15:46:41 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Duncan Laurie3c9f1742013-11-01 13:34:00 -07002
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpi.h>
Duncan Laurie3c9f1742013-11-01 13:34:00 -07004#include <device/device.h>
5#include <device/pci.h>
6#include <device/pci_ids.h>
7#include <stdint.h>
8#include <reg_script.h>
9
Julius Werner18ea2d32014-10-07 16:42:17 -070010#include <soc/iomap.h>
11#include <soc/iosf.h>
12#include <soc/pci_devs.h>
Angel Ponsb5320b22020-07-07 18:27:30 +020013#include <soc/pm.h>
Julius Werner18ea2d32014-10-07 16:42:17 -070014#include <soc/ramstage.h>
15#include <soc/ehci.h>
Duncan Laurie3c9f1742013-11-01 13:34:00 -070016
17#include "chip.h"
18
Aaron Durbin616f3942013-12-10 17:12:44 -080019static const struct reg_script ehci_init_script[] = {
Duncan Laurie3c9f1742013-11-01 13:34:00 -070020 /* Enable S0 PLL shutdown
21 * D29:F0:7A[12,10,7,6,4,3,2,1]=11111111b */
22 REG_PCI_OR16(0x7a, 0x14de),
23 /* Enable SB local clock gating
24 * D29:F0:7C[14,3,2]=111b (14 set in clock gating step) */
25 REG_PCI_OR32(0x7c, 0x0000000c),
26 REG_PCI_OR32(0x8c, 0x00000001),
27 /* Enable dynamic clock gating 0x4001=0xCE */
28 REG_IOSF_RMW(IOSF_PORT_USBPHY, 0x4001, 0xFFFFFF00, 0xCE),
29 /* Magic RCBA register set sequence */
30 /* RCBA + 0x200=0x1 */
31 REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x200, 0x00000001),
32 /* RCBA + 0x204=0x2 */
33 REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x204, 0x00000002),
34 /* RCBA + 0x208=0x0 */
35 REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x208, 0x00000000),
36 /* RCBA + 0x240[4,3,2,1,0]=00000b */
37 REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x240, ~0x0000001f, 0),
38 /* RCBA + 0x318[9,8,6,5,4,3,2,1,0]=000000111b */
39 REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x318, ~0x00000378, 0x00000007),
40 /* RCBA + 0x31c[3,2,1,0]=0011b */
41 REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x31c, ~0x0000000c, 0x00000003),
42 REG_SCRIPT_END
43};
44
Aaron Durbin616f3942013-12-10 17:12:44 -080045static const struct reg_script ehci_clock_gating_script[] = {
Duncan Laurie3c9f1742013-11-01 13:34:00 -070046 /* Enable SB local clock gating */
47 REG_PCI_OR32(0x7c, 0x00004000),
48 /* RCBA + 0x284=0xbe (step B0+) */
49 REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x284, 0x000000be),
50 REG_SCRIPT_END
51};
52
Aaron Durbin616f3942013-12-10 17:12:44 -080053static const struct reg_script ehci_disable_script[] = {
Duncan Laurie3c9f1742013-11-01 13:34:00 -070054 /* Clear Run/Stop Bit */
55 REG_RES_RMW32(PCI_BASE_ADDRESS_0, USB2CMD, ~USB2CMD_RS, 0),
56 /* Wait for HC Halted */
57 REG_RES_POLL32(PCI_BASE_ADDRESS_0, USB2STS,
58 USB2STS_HCHALT, USB2STS_HCHALT, 10000),
59 /* Disable Interrupts */
60 REG_PCI_OR32(EHCI_CMD_STS, INTRDIS),
61 /* Disable Asynchronous and Periodic Scheduler */
62 REG_RES_RMW32(PCI_BASE_ADDRESS_0, USB2CMD,
63 ~(USB2CMD_ASE | USB2CMD_PSE), 0),
64 /* Disable port wake */
65 REG_PCI_RMW32(EHCI_SBRN_FLA_PWC, ~(PORTWKIMP | PORTWKCAPMASK), 0),
66 /* Set Function Disable bit in RCBA */
67 REG_MMIO_OR32(RCBA_BASE_ADDRESS + RCBA_FUNC_DIS, RCBA_EHCI_DIS),
68 REG_SCRIPT_END
69};
70
Aaron Durbin616f3942013-12-10 17:12:44 -080071static const struct reg_script ehci_hc_reset[] = {
72 REG_RES_OR16(PCI_BASE_ADDRESS_0, USB2CMD, USB2CMD_HCRESET),
73 REG_SCRIPT_END
74};
75
Elyes HAOUAS17a3ceb2018-05-22 10:42:28 +020076static void usb2_phy_init(struct device *dev)
Duncan Laurie3c9f1742013-11-01 13:34:00 -070077{
Kyösti Mälkki8950cfb2019-07-13 22:16:25 +030078 struct soc_intel_baytrail_config *config = config_of(dev);
Kane Chen374f27b2014-07-17 11:31:57 -070079 u32 usb2_comp_bg = (config->usb2_comp_bg == 0 ?
80 0x4700 : config->usb2_comp_bg);
Duncan Laurie3c9f1742013-11-01 13:34:00 -070081 struct reg_script usb2_phy_script[] = {
82 /* USB3PHYInit() */
Kane Chen314c4c32014-07-17 09:51:50 -070083 REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_COMPBG,
Kane Chen374f27b2014-07-17 11:31:57 -070084 usb2_comp_bg),
Duncan Laurie3c9f1742013-11-01 13:34:00 -070085 /* Per port phy settings, set in devicetree.cb */
86 REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE0,
87 config->usb2_per_port_lane0),
88 REG_IOSF_WRITE(IOSF_PORT_USBPHY,
89 USBPHY_PER_PORT_RCOMP_HS_PULLUP0,
90 config->usb2_per_port_rcomp_hs_pullup0),
91 REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE1,
92 config->usb2_per_port_lane1),
93 REG_IOSF_WRITE(IOSF_PORT_USBPHY,
94 USBPHY_PER_PORT_RCOMP_HS_PULLUP1,
95 config->usb2_per_port_rcomp_hs_pullup1),
96 REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE2,
97 config->usb2_per_port_lane2),
98 REG_IOSF_WRITE(IOSF_PORT_USBPHY,
99 USBPHY_PER_PORT_RCOMP_HS_PULLUP2,
100 config->usb2_per_port_rcomp_hs_pullup2),
101 REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE3,
102 config->usb2_per_port_lane3),
103 REG_IOSF_WRITE(IOSF_PORT_USBPHY,
104 USBPHY_PER_PORT_RCOMP_HS_PULLUP3,
105 config->usb2_per_port_rcomp_hs_pullup3),
106 REG_SCRIPT_END
107 };
108 reg_script_run(usb2_phy_script);
109}
110
Elyes HAOUAS17a3ceb2018-05-22 10:42:28 +0200111static void ehci_init(struct device *dev)
Duncan Laurie3c9f1742013-11-01 13:34:00 -0700112{
Kyösti Mälkki8950cfb2019-07-13 22:16:25 +0300113 struct soc_intel_baytrail_config *config = config_of(dev);
Duncan Laurie3c9f1742013-11-01 13:34:00 -0700114 struct reg_script ehci_hc_init[] = {
Duncan Laurie3c9f1742013-11-01 13:34:00 -0700115 /* Controller init */
116 REG_SCRIPT_NEXT(ehci_init_script),
117 /* Enable clock gating */
118 REG_SCRIPT_NEXT(ehci_clock_gating_script),
119 /*
120 * Disable ports if requested
121 */
122 /* Open per-port disable control override */
123 REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~0, UPRWC_WR_EN),
124 REG_PCI_WRITE8(EHCI_USB2PDO, config->usb2_port_disable_mask),
125 /* Close per-port disable control override */
126 REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~UPRWC_WR_EN, 0),
127 REG_SCRIPT_END
128 };
129
130 /* Don't reset controller in S3 resume path */
Kyösti Mälkkic3ed8862014-06-19 19:50:51 +0300131 if (!acpi_is_wakeup_s3())
Aaron Durbin616f3942013-12-10 17:12:44 -0800132 reg_script_run_on_dev(dev, ehci_hc_reset);
Duncan Laurie3c9f1742013-11-01 13:34:00 -0700133
134 /* Disable controller if ports are routed to XHCI */
135 if (config->usb_route_to_xhci) {
136 /* Disable controller */
Aaron Durbin616f3942013-12-10 17:12:44 -0800137 reg_script_run_on_dev(dev, ehci_disable_script);
Duncan Laurie3c9f1742013-11-01 13:34:00 -0700138
139 /* Hide device with southcluster function */
140 dev->enabled = 0;
141 southcluster_enable_dev(dev);
142 } else {
143 /* Initialize EHCI controller */
Aaron Durbin616f3942013-12-10 17:12:44 -0800144 reg_script_run_on_dev(dev, ehci_hc_init);
Duncan Laurie3c9f1742013-11-01 13:34:00 -0700145 }
146
147 /* Setup USB2 PHY based on board config */
148 usb2_phy_init(dev);
149}
150
151static struct device_operations ehci_device_ops = {
152 .read_resources = pci_dev_read_resources,
153 .set_resources = pci_dev_set_resources,
154 .enable_resources = pci_dev_enable_resources,
155 .init = ehci_init,
156 .ops_pci = &soc_pci_ops,
157};
158
159static const struct pci_driver baytrail_ehci __pci_driver = {
160 .ops = &ehci_device_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100161 .vendor = PCI_VID_INTEL,
Duncan Laurie3c9f1742013-11-01 13:34:00 -0700162 .device = EHCI_DEVID
163};