blob: 9b08e1e5da8756e09bb6bab562dc3c19c5306898 [file] [log] [blame]
Mark Kettenis59b09ba2023-01-21 20:27:58 +01001// SPDX-License-Identifier: GPL-2.0
2/*
3 * PCIe host bridge driver for Apple system-on-chips.
4 *
5 * The HW is ECAM compliant.
6 *
7 * Initialization requires enabling power and clocks, along with a
8 * number of register pokes.
9 *
10 * Copyright (C) 2021 Alyssa Rosenzweig <alyssa@rosenzweig.io>
11 * Copyright (C) 2021 Google LLC
12 * Copyright (C) 2021 Corellium LLC
13 * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
14 *
15 * Author: Alyssa Rosenzweig <alyssa@rosenzweig.io>
16 * Author: Marc Zyngier <maz@kernel.org>
17 */
18
19#include <common.h>
20#include <dm.h>
21#include <dm/device_compat.h>
22#include <dm/devres.h>
23#include <mapmem.h>
24#include <pci.h>
25#include <asm/io.h>
26#include <asm-generic/gpio.h>
27#include <linux/delay.h>
28#include <linux/iopoll.h>
29
30#define CORE_RC_PHYIF_CTL 0x00024
31#define CORE_RC_PHYIF_CTL_RUN BIT(0)
32#define CORE_RC_PHYIF_STAT 0x00028
33#define CORE_RC_PHYIF_STAT_REFCLK BIT(4)
34#define CORE_RC_CTL 0x00050
35#define CORE_RC_CTL_RUN BIT(0)
36#define CORE_RC_STAT 0x00058
37#define CORE_RC_STAT_READY BIT(0)
38#define CORE_FABRIC_STAT 0x04000
39#define CORE_FABRIC_STAT_MASK 0x001F001F
40#define CORE_LANE_CFG(port) (0x84000 + 0x4000 * (port))
41#define CORE_LANE_CFG_REFCLK0REQ BIT(0)
42#define CORE_LANE_CFG_REFCLK1REQ BIT(1)
43#define CORE_LANE_CFG_REFCLK0ACK BIT(2)
44#define CORE_LANE_CFG_REFCLK1ACK BIT(3)
45#define CORE_LANE_CFG_REFCLKEN (BIT(9) | BIT(10))
46#define CORE_LANE_CTL(port) (0x84004 + 0x4000 * (port))
47#define CORE_LANE_CTL_CFGACC BIT(15)
48
49#define PORT_LTSSMCTL 0x00080
50#define PORT_LTSSMCTL_START BIT(0)
51#define PORT_INTSTAT 0x00100
52#define PORT_INT_TUNNEL_ERR 31
53#define PORT_INT_CPL_TIMEOUT 23
54#define PORT_INT_RID2SID_MAPERR 22
55#define PORT_INT_CPL_ABORT 21
56#define PORT_INT_MSI_BAD_DATA 19
57#define PORT_INT_MSI_ERR 18
58#define PORT_INT_REQADDR_GT32 17
59#define PORT_INT_AF_TIMEOUT 15
60#define PORT_INT_LINK_DOWN 14
61#define PORT_INT_LINK_UP 12
62#define PORT_INT_LINK_BWMGMT 11
63#define PORT_INT_AER_MASK (15 << 4)
64#define PORT_INT_PORT_ERR 4
65#define PORT_INT_INTx(i) i
66#define PORT_INT_INTx_MASK 15
67#define PORT_INTMSK 0x00104
68#define PORT_INTMSKSET 0x00108
69#define PORT_INTMSKCLR 0x0010c
70#define PORT_MSICFG 0x00124
71#define PORT_MSICFG_EN BIT(0)
72#define PORT_MSICFG_L2MSINUM_SHIFT 4
73#define PORT_MSIBASE 0x00128
74#define PORT_MSIBASE_1_SHIFT 16
75#define PORT_MSIADDR 0x00168
76#define PORT_LINKSTS 0x00208
77#define PORT_LINKSTS_UP BIT(0)
78#define PORT_LINKSTS_BUSY BIT(2)
79#define PORT_LINKCMDSTS 0x00210
80#define PORT_OUTS_NPREQS 0x00284
81#define PORT_OUTS_NPREQS_REQ BIT(24)
82#define PORT_OUTS_NPREQS_CPL BIT(16)
83#define PORT_RXWR_FIFO 0x00288
84#define PORT_RXWR_FIFO_HDR GENMASK(15, 10)
85#define PORT_RXWR_FIFO_DATA GENMASK(9, 0)
86#define PORT_RXRD_FIFO 0x0028C
87#define PORT_RXRD_FIFO_REQ GENMASK(6, 0)
88#define PORT_OUTS_CPLS 0x00290
89#define PORT_OUTS_CPLS_SHRD GENMASK(14, 8)
90#define PORT_OUTS_CPLS_WAIT GENMASK(6, 0)
91#define PORT_APPCLK 0x00800
92#define PORT_APPCLK_EN BIT(0)
93#define PORT_APPCLK_CGDIS BIT(8)
94#define PORT_STATUS 0x00804
95#define PORT_STATUS_READY BIT(0)
96#define PORT_REFCLK 0x00810
97#define PORT_REFCLK_EN BIT(0)
98#define PORT_REFCLK_CGDIS BIT(8)
99#define PORT_PERST 0x00814
100#define PORT_PERST_OFF BIT(0)
101#define PORT_RID2SID(i16) (0x00828 + 4 * (i16))
102#define PORT_RID2SID_VALID BIT(31)
103#define PORT_RID2SID_SID_SHIFT 16
104#define PORT_RID2SID_BUS_SHIFT 8
105#define PORT_RID2SID_DEV_SHIFT 3
106#define PORT_RID2SID_FUNC_SHIFT 0
107#define PORT_OUTS_PREQS_HDR 0x00980
108#define PORT_OUTS_PREQS_HDR_MASK GENMASK(9, 0)
109#define PORT_OUTS_PREQS_DATA 0x00984
110#define PORT_OUTS_PREQS_DATA_MASK GENMASK(15, 0)
111#define PORT_TUNCTRL 0x00988
112#define PORT_TUNCTRL_PERST_ON BIT(0)
113#define PORT_TUNCTRL_PERST_ACK_REQ BIT(1)
114#define PORT_TUNSTAT 0x0098c
115#define PORT_TUNSTAT_PERST_ON BIT(0)
116#define PORT_TUNSTAT_PERST_ACK_PEND BIT(1)
117#define PORT_PREFMEM_ENABLE 0x00994
118
119struct apple_pcie_priv {
120 struct udevice *dev;
121 void __iomem *base;
122 void __iomem *cfg_base;
123 struct list_head ports;
124};
125
126struct apple_pcie_port {
127 struct apple_pcie_priv *pcie;
128 struct gpio_desc reset;
129 ofnode np;
130 void __iomem *base;
131 struct list_head entry;
132 int idx;
133};
134
135static void rmw_set(u32 set, void __iomem *addr)
136{
137 writel_relaxed(readl_relaxed(addr) | set, addr);
138}
139
140static void rmw_clear(u32 clr, void __iomem *addr)
141{
142 writel_relaxed(readl_relaxed(addr) & ~clr, addr);
143}
144
145static int apple_pcie_config_address(const struct udevice *bus,
146 pci_dev_t bdf, uint offset,
147 void **paddress)
148{
149 struct apple_pcie_priv *pcie = dev_get_priv(bus);
150 void *addr;
151
152 addr = pcie->cfg_base;
153 addr += PCIE_ECAM_OFFSET(PCI_BUS(bdf), PCI_DEV(bdf),
154 PCI_FUNC(bdf), offset);
155 *paddress = addr;
156
157 return 0;
158}
159
160static int apple_pcie_read_config(const struct udevice *bus, pci_dev_t bdf,
161 uint offset, ulong *valuep,
162 enum pci_size_t size)
163{
164 int ret;
165
166 ret = pci_generic_mmap_read_config(bus, apple_pcie_config_address,
167 bdf, offset, valuep, size);
168 return ret;
169}
170
171static int apple_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
172 uint offset, ulong value,
173 enum pci_size_t size)
174{
175 return pci_generic_mmap_write_config(bus, apple_pcie_config_address,
176 bdf, offset, value, size);
177}
178
179static const struct dm_pci_ops apple_pcie_ops = {
180 .read_config = apple_pcie_read_config,
181 .write_config = apple_pcie_write_config,
182};
183
184static int apple_pcie_setup_refclk(struct apple_pcie_priv *pcie,
185 struct apple_pcie_port *port)
186{
187 u32 stat;
188 int res;
189
190 res = readl_poll_sleep_timeout(pcie->base + CORE_RC_PHYIF_STAT, stat,
191 stat & CORE_RC_PHYIF_STAT_REFCLK,
192 100, 50000);
193 if (res < 0)
194 return res;
195
196 rmw_set(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx));
197 rmw_set(CORE_LANE_CFG_REFCLK0REQ, pcie->base + CORE_LANE_CFG(port->idx));
198
199 res = readl_poll_sleep_timeout(pcie->base + CORE_LANE_CFG(port->idx),
200 stat, stat & CORE_LANE_CFG_REFCLK0ACK,
201 100, 50000);
202 if (res < 0)
203 return res;
204
205 rmw_set(CORE_LANE_CFG_REFCLK1REQ, pcie->base + CORE_LANE_CFG(port->idx));
206 res = readl_poll_sleep_timeout(pcie->base + CORE_LANE_CFG(port->idx),
207 stat, stat & CORE_LANE_CFG_REFCLK1ACK,
208 100, 50000);
209
210 if (res < 0)
211 return res;
212
213 rmw_clear(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx));
214
215 rmw_set(CORE_LANE_CFG_REFCLKEN, pcie->base + CORE_LANE_CFG(port->idx));
216 rmw_set(PORT_REFCLK_EN, port->base + PORT_REFCLK);
217
218 return 0;
219}
220
221static int apple_pcie_setup_port(struct apple_pcie_priv *pcie, ofnode np)
222{
223 struct apple_pcie_port *port;
224 struct gpio_desc reset;
225 fdt_addr_t addr;
226 u32 stat, idx;
227 int ret;
228
229 ret = gpio_request_by_name_nodev(np, "reset-gpios", 0, &reset, 0);
230 if (ret)
231 return ret;
232
233 port = devm_kzalloc(pcie->dev, sizeof(*port), GFP_KERNEL);
234 if (!port)
235 return -ENOMEM;
236
237 ret = ofnode_read_u32_index(np, "reg", 0, &idx);
238 if (ret)
239 return ret;
240
241 /* Use the first reg entry to work out the port index */
242 port->idx = idx >> 11;
243 port->pcie = pcie;
244 port->reset = reset;
245 port->np = np;
246
247 addr = dev_read_addr_index(pcie->dev, port->idx + 2);
248 if (addr == FDT_ADDR_T_NONE)
249 return -EINVAL;
250 port->base = map_sysmem(addr, 0);
251
252 rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK);
253
254 /* Assert PERST# before setting up the clock */
255 dm_gpio_set_value(&reset, 1);
256
257 ret = apple_pcie_setup_refclk(pcie, port);
258 if (ret < 0)
259 return ret;
260
261 /* The minimal Tperst-clk value is 100us (PCIe CEM r5.0, 2.9.2) */
262 udelay(100);
263
264 /* Deassert PERST# */
265 rmw_set(PORT_PERST_OFF, port->base + PORT_PERST);
266 dm_gpio_set_value(&reset, 0);
267
268 /* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */
269 udelay(100 * 1000);
270
271 ret = readl_poll_sleep_timeout(port->base + PORT_STATUS, stat,
272 stat & PORT_STATUS_READY, 100, 250000);
273 if (ret < 0) {
274 dev_err(pcie->dev, "port %d ready wait timeout\n", port->idx);
275 return ret;
276 }
277
278 rmw_clear(PORT_REFCLK_CGDIS, port->base + PORT_REFCLK);
279 rmw_clear(PORT_APPCLK_CGDIS, port->base + PORT_APPCLK);
280
281 list_add_tail(&port->entry, &pcie->ports);
282
283 writel_relaxed(PORT_LTSSMCTL_START, port->base + PORT_LTSSMCTL);
284
285 /*
286 * Deliberately ignore the link not coming up as connected
287 * devices (e.g. the WiFi controller) may not be powerd up.
288 */
289 readl_poll_sleep_timeout(port->base + PORT_LINKSTS, stat,
290 (stat & PORT_LINKSTS_UP), 100, 100000);
291
292 return 0;
293}
294
295static int apple_pcie_probe(struct udevice *dev)
296{
297 struct apple_pcie_priv *pcie = dev_get_priv(dev);
298 fdt_addr_t addr;
299 ofnode of_port;
300 int i, ret;
301
302 pcie->dev = dev;
303 addr = dev_read_addr_index(dev, 0);
304 if (addr == FDT_ADDR_T_NONE)
305 return -EINVAL;
306 pcie->cfg_base = map_sysmem(addr, 0);
307
308 addr = dev_read_addr_index(dev, 1);
309 if (addr == FDT_ADDR_T_NONE)
310 return -EINVAL;
311 pcie->base = map_sysmem(addr, 0);
312
313 INIT_LIST_HEAD(&pcie->ports);
314
315 for (of_port = ofnode_first_subnode(dev_ofnode(dev));
316 ofnode_valid(of_port);
317 of_port = ofnode_next_subnode(of_port)) {
318 ret = apple_pcie_setup_port(pcie, of_port);
319 if (ret) {
320 dev_err(pcie->dev, "Port %d setup fail: %d\n", i, ret);
321 return ret;
322 }
323 }
324
325 return 0;
326}
327
328static int apple_pcie_remove(struct udevice *dev)
329{
330 struct apple_pcie_priv *pcie = dev_get_priv(dev);
331 struct apple_pcie_port *port, *tmp;
332
333 list_for_each_entry_safe(port, tmp, &pcie->ports, entry) {
334 gpio_free_list_nodev(&port->reset, 1);
335 free(port);
336 }
337
338 return 0;
339}
340
341static const struct udevice_id apple_pcie_of_match[] = {
342 { .compatible = "apple,pcie" },
343 { /* sentinel */ }
344};
345
346U_BOOT_DRIVER(apple_pcie) = {
347 .name = "apple_pcie",
348 .id = UCLASS_PCI,
349 .of_match = apple_pcie_of_match,
350 .probe = apple_pcie_probe,
351 .remove = apple_pcie_remove,
352 .priv_auto = sizeof(struct apple_pcie_priv),
353 .ops = &apple_pcie_ops,
354};