blob: 21bafba3b0eeffb720cc6ac0b930ea8ce3fe34fb [file] [log] [blame]
Mark Kettenisbdebb002023-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
Mark Kettenis159f4152023-05-02 21:30:41 +020040
41#define CORE_PHY_DEFAULT_BASE(port) (0x84000 + 0x4000 * (port))
42
43#define PHY_LANE_CFG 0x00000
44#define PHY_LANE_CFG_REFCLK0REQ BIT(0)
45#define PHY_LANE_CFG_REFCLK1REQ BIT(1)
46#define PHY_LANE_CFG_REFCLK0ACK BIT(2)
47#define PHY_LANE_CFG_REFCLK1ACK BIT(3)
48#define PHY_LANE_CFG_REFCLKEN (BIT(9) | BIT(10))
49#define PHY_LANE_CFG_REFCLKCGEN (BIT(30) | BIT(31))
50#define PHY_LANE_CTL 0x00004
51#define PHY_LANE_CTL_CFGACC BIT(15)
Mark Kettenisbdebb002023-01-21 20:27:58 +010052
53#define PORT_LTSSMCTL 0x00080
54#define PORT_LTSSMCTL_START BIT(0)
55#define PORT_INTSTAT 0x00100
56#define PORT_INT_TUNNEL_ERR 31
57#define PORT_INT_CPL_TIMEOUT 23
58#define PORT_INT_RID2SID_MAPERR 22
59#define PORT_INT_CPL_ABORT 21
60#define PORT_INT_MSI_BAD_DATA 19
61#define PORT_INT_MSI_ERR 18
62#define PORT_INT_REQADDR_GT32 17
63#define PORT_INT_AF_TIMEOUT 15
64#define PORT_INT_LINK_DOWN 14
65#define PORT_INT_LINK_UP 12
66#define PORT_INT_LINK_BWMGMT 11
67#define PORT_INT_AER_MASK (15 << 4)
68#define PORT_INT_PORT_ERR 4
69#define PORT_INT_INTx(i) i
70#define PORT_INT_INTx_MASK 15
71#define PORT_INTMSK 0x00104
72#define PORT_INTMSKSET 0x00108
73#define PORT_INTMSKCLR 0x0010c
74#define PORT_MSICFG 0x00124
75#define PORT_MSICFG_EN BIT(0)
76#define PORT_MSICFG_L2MSINUM_SHIFT 4
77#define PORT_MSIBASE 0x00128
78#define PORT_MSIBASE_1_SHIFT 16
79#define PORT_MSIADDR 0x00168
80#define PORT_LINKSTS 0x00208
81#define PORT_LINKSTS_UP BIT(0)
82#define PORT_LINKSTS_BUSY BIT(2)
83#define PORT_LINKCMDSTS 0x00210
84#define PORT_OUTS_NPREQS 0x00284
85#define PORT_OUTS_NPREQS_REQ BIT(24)
86#define PORT_OUTS_NPREQS_CPL BIT(16)
87#define PORT_RXWR_FIFO 0x00288
88#define PORT_RXWR_FIFO_HDR GENMASK(15, 10)
89#define PORT_RXWR_FIFO_DATA GENMASK(9, 0)
90#define PORT_RXRD_FIFO 0x0028C
91#define PORT_RXRD_FIFO_REQ GENMASK(6, 0)
92#define PORT_OUTS_CPLS 0x00290
93#define PORT_OUTS_CPLS_SHRD GENMASK(14, 8)
94#define PORT_OUTS_CPLS_WAIT GENMASK(6, 0)
95#define PORT_APPCLK 0x00800
96#define PORT_APPCLK_EN BIT(0)
97#define PORT_APPCLK_CGDIS BIT(8)
98#define PORT_STATUS 0x00804
99#define PORT_STATUS_READY BIT(0)
100#define PORT_REFCLK 0x00810
101#define PORT_REFCLK_EN BIT(0)
102#define PORT_REFCLK_CGDIS BIT(8)
103#define PORT_PERST 0x00814
104#define PORT_PERST_OFF BIT(0)
105#define PORT_RID2SID(i16) (0x00828 + 4 * (i16))
106#define PORT_RID2SID_VALID BIT(31)
107#define PORT_RID2SID_SID_SHIFT 16
108#define PORT_RID2SID_BUS_SHIFT 8
109#define PORT_RID2SID_DEV_SHIFT 3
110#define PORT_RID2SID_FUNC_SHIFT 0
111#define PORT_OUTS_PREQS_HDR 0x00980
112#define PORT_OUTS_PREQS_HDR_MASK GENMASK(9, 0)
113#define PORT_OUTS_PREQS_DATA 0x00984
114#define PORT_OUTS_PREQS_DATA_MASK GENMASK(15, 0)
115#define PORT_TUNCTRL 0x00988
116#define PORT_TUNCTRL_PERST_ON BIT(0)
117#define PORT_TUNCTRL_PERST_ACK_REQ BIT(1)
118#define PORT_TUNSTAT 0x0098c
119#define PORT_TUNSTAT_PERST_ON BIT(0)
120#define PORT_TUNSTAT_PERST_ACK_PEND BIT(1)
121#define PORT_PREFMEM_ENABLE 0x00994
122
Mark Kettenis159f4152023-05-02 21:30:41 +0200123struct reg_info {
124 u32 phy_lane_ctl;
125 u32 port_refclk;
126 u32 port_perst;
127};
128
129const struct reg_info t8103_hw = {
130 .phy_lane_ctl = PHY_LANE_CTL,
131 .port_refclk = PORT_REFCLK,
132 .port_perst = PORT_PERST,
133};
134
135#define PORT_T602X_PERST 0x082c
136
137const struct reg_info t602x_hw = {
138 .phy_lane_ctl = 0,
139 .port_refclk = 0,
140 .port_perst = PORT_T602X_PERST,
141};
142
Mark Kettenisbdebb002023-01-21 20:27:58 +0100143struct apple_pcie_priv {
144 struct udevice *dev;
145 void __iomem *base;
146 void __iomem *cfg_base;
147 struct list_head ports;
Mark Kettenis159f4152023-05-02 21:30:41 +0200148 const struct reg_info *hw;
Mark Kettenisbdebb002023-01-21 20:27:58 +0100149};
150
151struct apple_pcie_port {
152 struct apple_pcie_priv *pcie;
153 struct gpio_desc reset;
154 ofnode np;
155 void __iomem *base;
Mark Kettenis159f4152023-05-02 21:30:41 +0200156 void __iomem *phy;
Mark Kettenisbdebb002023-01-21 20:27:58 +0100157 struct list_head entry;
158 int idx;
159};
160
161static void rmw_set(u32 set, void __iomem *addr)
162{
163 writel_relaxed(readl_relaxed(addr) | set, addr);
164}
165
166static void rmw_clear(u32 clr, void __iomem *addr)
167{
168 writel_relaxed(readl_relaxed(addr) & ~clr, addr);
169}
170
171static int apple_pcie_config_address(const struct udevice *bus,
172 pci_dev_t bdf, uint offset,
173 void **paddress)
174{
175 struct apple_pcie_priv *pcie = dev_get_priv(bus);
176 void *addr;
177
178 addr = pcie->cfg_base;
179 addr += PCIE_ECAM_OFFSET(PCI_BUS(bdf), PCI_DEV(bdf),
180 PCI_FUNC(bdf), offset);
181 *paddress = addr;
182
183 return 0;
184}
185
186static int apple_pcie_read_config(const struct udevice *bus, pci_dev_t bdf,
187 uint offset, ulong *valuep,
188 enum pci_size_t size)
189{
190 int ret;
191
192 ret = pci_generic_mmap_read_config(bus, apple_pcie_config_address,
193 bdf, offset, valuep, size);
194 return ret;
195}
196
197static int apple_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
198 uint offset, ulong value,
199 enum pci_size_t size)
200{
201 return pci_generic_mmap_write_config(bus, apple_pcie_config_address,
202 bdf, offset, value, size);
203}
204
205static const struct dm_pci_ops apple_pcie_ops = {
206 .read_config = apple_pcie_read_config,
207 .write_config = apple_pcie_write_config,
208};
209
210static int apple_pcie_setup_refclk(struct apple_pcie_priv *pcie,
211 struct apple_pcie_port *port)
212{
213 u32 stat;
214 int res;
215
Mark Kettenis159f4152023-05-02 21:30:41 +0200216 if (pcie->hw->phy_lane_ctl)
217 rmw_set(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl);
218
219 rmw_set(PHY_LANE_CFG_REFCLK0REQ, port->phy + PHY_LANE_CFG);
220
221 res = readl_poll_sleep_timeout(port->phy + PHY_LANE_CFG,
222 stat, stat & PHY_LANE_CFG_REFCLK0ACK,
Mark Kettenisbdebb002023-01-21 20:27:58 +0100223 100, 50000);
224 if (res < 0)
225 return res;
226
Mark Kettenis159f4152023-05-02 21:30:41 +0200227 rmw_set(PHY_LANE_CFG_REFCLK1REQ, port->phy + PHY_LANE_CFG);
228 res = readl_poll_sleep_timeout(port->phy + PHY_LANE_CFG,
229 stat, stat & PHY_LANE_CFG_REFCLK1ACK,
Mark Kettenisbdebb002023-01-21 20:27:58 +0100230 100, 50000);
231
232 if (res < 0)
233 return res;
234
Mark Kettenis159f4152023-05-02 21:30:41 +0200235 if (pcie->hw->phy_lane_ctl)
236 rmw_clear(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl);
Mark Kettenisbdebb002023-01-21 20:27:58 +0100237
Mark Kettenis159f4152023-05-02 21:30:41 +0200238 rmw_set(PHY_LANE_CFG_REFCLKEN, port->phy + PHY_LANE_CFG);
239
240 if (pcie->hw->port_refclk)
241 rmw_set(PORT_REFCLK_EN, port->base + pcie->hw->port_refclk);
Mark Kettenisbdebb002023-01-21 20:27:58 +0100242
243 return 0;
244}
245
246static int apple_pcie_setup_port(struct apple_pcie_priv *pcie, ofnode np)
247{
248 struct apple_pcie_port *port;
249 struct gpio_desc reset;
250 fdt_addr_t addr;
251 u32 stat, idx;
252 int ret;
Mark Kettenis159f4152023-05-02 21:30:41 +0200253 char name[16];
Mark Kettenisbdebb002023-01-21 20:27:58 +0100254
255 ret = gpio_request_by_name_nodev(np, "reset-gpios", 0, &reset, 0);
256 if (ret)
257 return ret;
258
259 port = devm_kzalloc(pcie->dev, sizeof(*port), GFP_KERNEL);
260 if (!port)
261 return -ENOMEM;
262
263 ret = ofnode_read_u32_index(np, "reg", 0, &idx);
264 if (ret)
265 return ret;
266
267 /* Use the first reg entry to work out the port index */
268 port->idx = idx >> 11;
269 port->pcie = pcie;
270 port->reset = reset;
271 port->np = np;
272
Mark Kettenis159f4152023-05-02 21:30:41 +0200273 snprintf(name, sizeof(name), "port%d", port->idx);
274 addr = dev_read_addr_name(pcie->dev, name);
275 if (addr == FDT_ADDR_T_NONE)
276 addr = dev_read_addr_index(pcie->dev, port->idx + 2);
Mark Kettenisbdebb002023-01-21 20:27:58 +0100277 if (addr == FDT_ADDR_T_NONE)
278 return -EINVAL;
279 port->base = map_sysmem(addr, 0);
280
Mark Kettenis159f4152023-05-02 21:30:41 +0200281 snprintf(name, sizeof(name), "phy%d", port->idx);
282 addr = dev_read_addr_name(pcie->dev, name);
283 if (addr == FDT_ADDR_T_NONE)
284 port->phy = pcie->base + CORE_PHY_DEFAULT_BASE(port->idx);
285 else
286 port->phy = map_sysmem(addr, 0);
287
Mark Kettenisbdebb002023-01-21 20:27:58 +0100288 rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK);
289
290 /* Assert PERST# before setting up the clock */
291 dm_gpio_set_value(&reset, 1);
292
293 ret = apple_pcie_setup_refclk(pcie, port);
294 if (ret < 0)
295 return ret;
296
297 /* The minimal Tperst-clk value is 100us (PCIe CEM r5.0, 2.9.2) */
298 udelay(100);
299
300 /* Deassert PERST# */
Mark Kettenis159f4152023-05-02 21:30:41 +0200301 rmw_set(PORT_PERST_OFF, port->base + pcie->hw->port_perst);
Mark Kettenisbdebb002023-01-21 20:27:58 +0100302 dm_gpio_set_value(&reset, 0);
303
304 /* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */
305 udelay(100 * 1000);
306
307 ret = readl_poll_sleep_timeout(port->base + PORT_STATUS, stat,
308 stat & PORT_STATUS_READY, 100, 250000);
309 if (ret < 0) {
310 dev_err(pcie->dev, "port %d ready wait timeout\n", port->idx);
311 return ret;
312 }
313
Mark Kettenisbdebb002023-01-21 20:27:58 +0100314 list_add_tail(&port->entry, &pcie->ports);
315
316 writel_relaxed(PORT_LTSSMCTL_START, port->base + PORT_LTSSMCTL);
317
318 /*
319 * Deliberately ignore the link not coming up as connected
320 * devices (e.g. the WiFi controller) may not be powerd up.
321 */
322 readl_poll_sleep_timeout(port->base + PORT_LINKSTS, stat,
323 (stat & PORT_LINKSTS_UP), 100, 100000);
324
Mark Kettenis159f4152023-05-02 21:30:41 +0200325 if (pcie->hw->port_refclk)
326 rmw_clear(PORT_REFCLK_CGDIS, port->base + PORT_REFCLK);
327 else
328 rmw_set(PHY_LANE_CFG_REFCLKCGEN, port->phy + PHY_LANE_CFG);
329 rmw_clear(PORT_APPCLK_CGDIS, port->base + PORT_APPCLK);
330
Mark Kettenisbdebb002023-01-21 20:27:58 +0100331 return 0;
332}
333
334static int apple_pcie_probe(struct udevice *dev)
335{
336 struct apple_pcie_priv *pcie = dev_get_priv(dev);
337 fdt_addr_t addr;
338 ofnode of_port;
339 int i, ret;
340
Mark Kettenis159f4152023-05-02 21:30:41 +0200341 pcie->hw = (struct reg_info *)dev_get_driver_data(dev);
342
Mark Kettenisbdebb002023-01-21 20:27:58 +0100343 pcie->dev = dev;
344 addr = dev_read_addr_index(dev, 0);
345 if (addr == FDT_ADDR_T_NONE)
346 return -EINVAL;
347 pcie->cfg_base = map_sysmem(addr, 0);
348
349 addr = dev_read_addr_index(dev, 1);
350 if (addr == FDT_ADDR_T_NONE)
351 return -EINVAL;
352 pcie->base = map_sysmem(addr, 0);
353
354 INIT_LIST_HEAD(&pcie->ports);
355
356 for (of_port = ofnode_first_subnode(dev_ofnode(dev));
357 ofnode_valid(of_port);
358 of_port = ofnode_next_subnode(of_port)) {
Janne Grunau6ee2c8a2023-03-13 14:46:11 +0100359 if (!ofnode_is_enabled(of_port))
360 continue;
Mark Kettenisbdebb002023-01-21 20:27:58 +0100361 ret = apple_pcie_setup_port(pcie, of_port);
362 if (ret) {
363 dev_err(pcie->dev, "Port %d setup fail: %d\n", i, ret);
364 return ret;
365 }
366 }
367
368 return 0;
369}
370
371static int apple_pcie_remove(struct udevice *dev)
372{
373 struct apple_pcie_priv *pcie = dev_get_priv(dev);
374 struct apple_pcie_port *port, *tmp;
375
376 list_for_each_entry_safe(port, tmp, &pcie->ports, entry) {
377 gpio_free_list_nodev(&port->reset, 1);
378 free(port);
379 }
380
381 return 0;
382}
383
384static const struct udevice_id apple_pcie_of_match[] = {
Mark Kettenis159f4152023-05-02 21:30:41 +0200385 { .compatible = "apple,t6020-pcie", .data = (ulong)&t602x_hw },
386 { .compatible = "apple,pcie", .data = (ulong)&t8103_hw },
Mark Kettenisbdebb002023-01-21 20:27:58 +0100387 { /* sentinel */ }
388};
389
390U_BOOT_DRIVER(apple_pcie) = {
391 .name = "apple_pcie",
392 .id = UCLASS_PCI,
393 .of_match = apple_pcie_of_match,
394 .probe = apple_pcie_probe,
395 .remove = apple_pcie_remove,
396 .priv_auto = sizeof(struct apple_pcie_priv),
397 .ops = &apple_pcie_ops,
398};