blob: 0525ecbea6498cbac12a7a981b429790dfaeb3c6 [file] [log] [blame]
Neil Armstrong06e006b2021-03-25 15:49:21 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Amlogic DesignWare based PCIe host controller driver
4 *
5 * Copyright (c) 2021 BayLibre, SAS
6 * Author: Neil Armstrong <narmstrong@baylibre.com>
7 *
8 * Based on pcie_dw_rockchip.c
9 * Copyright (c) 2021 Rockchip, Inc.
10 */
11
12#include <common.h>
13#include <clk.h>
14#include <dm.h>
15#include <generic-phy.h>
16#include <pci.h>
17#include <power-domain.h>
18#include <reset.h>
19#include <syscon.h>
20#include <asm/global_data.h>
21#include <asm/io.h>
22#include <asm-generic/gpio.h>
23#include <dm/device_compat.h>
24#include <linux/iopoll.h>
25#include <linux/delay.h>
26#include <linux/log2.h>
27#include <linux/bitfield.h>
28
29#include "pcie_dw_common.h"
30
31DECLARE_GLOBAL_DATA_PTR;
32
33/**
34 * struct meson_pcie - Amlogic Meson DW PCIe controller state
35 *
36 * @pci: The common PCIe DW structure
37 * @meson_cfg_base: The base address of vendor regs
38 * @phy
39 * @clk_port
40 * @clk_general
41 * @clk_pclk
42 * @rsts
43 * @rst_gpio: The #PERST signal for slot
44 */
45struct meson_pcie {
46 /* Must be first member of the struct */
47 struct pcie_dw dw;
48 void *meson_cfg_base;
49 struct phy phy;
50 struct clk clk_port;
51 struct clk clk_general;
52 struct clk clk_pclk;
53 struct reset_ctl_bulk rsts;
54 struct gpio_desc rst_gpio;
55};
56
57#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */
58
59#define PCIE_CAP_MAX_PAYLOAD_SIZE(x) ((x) << 5)
60#define PCIE_CAP_MAX_READ_REQ_SIZE(x) ((x) << 12)
61
62/* PCIe specific config registers */
63#define PCIE_CFG0 0x0
64#define APP_LTSSM_ENABLE BIT(7)
65
66#define PCIE_CFG_STATUS12 0x30
67#define IS_SMLH_LINK_UP(x) ((x) & (1 << 6))
68#define IS_RDLH_LINK_UP(x) ((x) & (1 << 16))
69#define IS_LTSSM_UP(x) ((((x) >> 10) & 0x1f) == 0x11)
70
71#define PCIE_CFG_STATUS17 0x44
72#define PM_CURRENT_STATE(x) (((x) >> 7) & 0x1)
73
74#define WAIT_LINKUP_TIMEOUT 4000
75#define PORT_CLK_RATE 100000000UL
76#define MAX_PAYLOAD_SIZE 256
77#define MAX_READ_REQ_SIZE 256
78#define PCIE_RESET_DELAY 500
79#define PCIE_SHARED_RESET 1
80#define PCIE_NORMAL_RESET 0
81
82enum pcie_data_rate {
83 PCIE_GEN1,
84 PCIE_GEN2,
85 PCIE_GEN3,
86 PCIE_GEN4
87};
88
89/* Parameters for the waiting for #perst signal */
90#define PERST_WAIT_US 1000000
91
92static inline u32 meson_cfg_readl(struct meson_pcie *priv, u32 reg)
93{
94 return readl(priv->meson_cfg_base + reg);
95}
96
97static inline void meson_cfg_writel(struct meson_pcie *priv, u32 val, u32 reg)
98{
99 writel(val, priv->meson_cfg_base + reg);
100}
101
102/**
103 * meson_pcie_configure() - Configure link
104 *
105 * @meson_pcie: Pointer to the PCI controller state
106 *
107 * Configure the link mode and width
108 */
109static void meson_pcie_configure(struct meson_pcie *priv)
110{
111 u32 val;
112
113 dw_pcie_dbi_write_enable(&priv->dw, true);
114
115 val = readl(priv->dw.dbi_base + PCIE_PORT_LINK_CONTROL);
116 val &= ~PORT_LINK_FAST_LINK_MODE;
117 val |= PORT_LINK_DLL_LINK_EN;
118 val &= ~PORT_LINK_MODE_MASK;
119 val |= PORT_LINK_MODE_1_LANES;
120 writel(val, priv->dw.dbi_base + PCIE_PORT_LINK_CONTROL);
121
122 val = readl(priv->dw.dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
123 val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
124 val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
125 writel(val, priv->dw.dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
126
127 dw_pcie_dbi_write_enable(&priv->dw, false);
128}
129
130static inline void meson_pcie_enable_ltssm(struct meson_pcie *priv)
131{
132 u32 val;
133
134 val = meson_cfg_readl(priv, PCIE_CFG0);
135 val |= APP_LTSSM_ENABLE;
136 meson_cfg_writel(priv, val, PCIE_CFG0);
137}
138
139static int meson_pcie_wait_link_up(struct meson_pcie *priv)
140{
141 u32 speed_okay = 0;
142 u32 cnt = 0;
143 u32 state12, state17, smlh_up, ltssm_up, rdlh_up;
144
145 do {
146 state12 = meson_cfg_readl(priv, PCIE_CFG_STATUS12);
147 state17 = meson_cfg_readl(priv, PCIE_CFG_STATUS17);
148 smlh_up = IS_SMLH_LINK_UP(state12);
149 rdlh_up = IS_RDLH_LINK_UP(state12);
150 ltssm_up = IS_LTSSM_UP(state12);
151
152 if (PM_CURRENT_STATE(state17) < PCIE_GEN3)
153 speed_okay = 1;
154
155 if (smlh_up)
156 debug("%s: smlh_link_up is on\n", __func__);
157 if (rdlh_up)
158 debug("%s: rdlh_link_up is on\n", __func__);
159 if (ltssm_up)
160 debug("%s: ltssm_up is on\n", __func__);
161 if (speed_okay)
162 debug("%s: speed_okay\n", __func__);
163
164 if (smlh_up && rdlh_up && ltssm_up && speed_okay)
165 return 0;
166
167 cnt++;
168
169 udelay(10);
170 } while (cnt < WAIT_LINKUP_TIMEOUT);
171
172 printf("%s: error: wait linkup timeout\n", __func__);
173 return -EIO;
174}
175
176/**
177 * meson_pcie_link_up() - Wait for the link to come up
178 *
179 * @meson_pcie: Pointer to the PCI controller state
180 * @cap_speed: Desired link speed
181 *
182 * Return: 1 (true) for active line and negative (false) for no link (timeout)
183 */
184static int meson_pcie_link_up(struct meson_pcie *priv, u32 cap_speed)
185{
186 /* DW link configurations */
187 meson_pcie_configure(priv);
188
189 /* Reset the device */
190 if (dm_gpio_is_valid(&priv->rst_gpio)) {
191 dm_gpio_set_value(&priv->rst_gpio, 1);
192 /*
193 * Minimal is 100ms from spec but we see
194 * some wired devices need much more, such as 600ms.
195 * Add a enough delay to cover all cases.
196 */
197 udelay(PERST_WAIT_US);
198 dm_gpio_set_value(&priv->rst_gpio, 0);
199 }
200
201 /* Enable LTSSM */
202 meson_pcie_enable_ltssm(priv);
203
204 return meson_pcie_wait_link_up(priv);
205}
206
207static int meson_size_to_payload(int size)
208{
209 /*
210 * dwc supports 2^(val+7) payload size, which val is 0~5 default to 1.
211 * So if input size is not 2^order alignment or less than 2^7 or bigger
212 * than 2^12, just set to default size 2^(1+7).
213 */
214 if (!is_power_of_2(size) || size < 128 || size > 4096) {
215 debug("%s: payload size %d, set to default 256\n", __func__, size);
216 return 1;
217 }
218
219 return fls(size) - 8;
220}
221
222static void meson_set_max_payload(struct meson_pcie *priv, int size)
223{
224 u32 val;
225 u16 offset = dm_pci_find_capability(priv->dw.dev, PCI_CAP_ID_EXP);
226 int max_payload_size = meson_size_to_payload(size);
227
228 dw_pcie_dbi_write_enable(&priv->dw, true);
229
230 val = readl(priv->dw.dbi_base + offset + PCI_EXP_DEVCTL);
231 val &= ~PCI_EXP_DEVCTL_PAYLOAD;
232 writel(val, priv->dw.dbi_base + offset + PCI_EXP_DEVCTL);
233
234 val = readl(priv->dw.dbi_base + offset + PCI_EXP_DEVCTL);
235 val |= PCIE_CAP_MAX_PAYLOAD_SIZE(max_payload_size);
236 writel(val, priv->dw.dbi_base + PCI_EXP_DEVCTL);
237
238 dw_pcie_dbi_write_enable(&priv->dw, false);
239}
240
241static void meson_set_max_rd_req_size(struct meson_pcie *priv, int size)
242{
243 u32 val;
244 u16 offset = dm_pci_find_capability(priv->dw.dev, PCI_CAP_ID_EXP);
245 int max_rd_req_size = meson_size_to_payload(size);
246
247 dw_pcie_dbi_write_enable(&priv->dw, true);
248
249 val = readl(priv->dw.dbi_base + offset + PCI_EXP_DEVCTL);
250 val &= ~PCI_EXP_DEVCTL_PAYLOAD;
251 writel(val, priv->dw.dbi_base + offset + PCI_EXP_DEVCTL);
252
253 val = readl(priv->dw.dbi_base + offset + PCI_EXP_DEVCTL);
254 val |= PCIE_CAP_MAX_READ_REQ_SIZE(max_rd_req_size);
255 writel(val, priv->dw.dbi_base + PCI_EXP_DEVCTL);
256
257 dw_pcie_dbi_write_enable(&priv->dw, false);
258}
259
260static int meson_pcie_init_port(struct udevice *dev)
261{
262 int ret;
263 struct meson_pcie *priv = dev_get_priv(dev);
264
265 ret = generic_phy_init(&priv->phy);
266 if (ret) {
267 dev_err(dev, "failed to init phy (ret=%d)\n", ret);
268 return ret;
269 }
270
271 ret = generic_phy_power_on(&priv->phy);
272 if (ret) {
273 dev_err(dev, "failed to power on phy (ret=%d)\n", ret);
274 goto err_exit_phy;
275 }
276
277 ret = generic_phy_reset(&priv->phy);
278 if (ret) {
279 dev_err(dev, "failed to reset phy (ret=%d)\n", ret);
280 goto err_exit_phy;
281 }
282
283 ret = reset_assert_bulk(&priv->rsts);
284 if (ret) {
285 dev_err(dev, "failed to assert resets (ret=%d)\n", ret);
286 goto err_power_off_phy;
287 }
288
289 udelay(PCIE_RESET_DELAY);
290
291 ret = reset_deassert_bulk(&priv->rsts);
292 if (ret) {
293 dev_err(dev, "failed to deassert resets (ret=%d)\n", ret);
294 goto err_power_off_phy;
295 }
296
297 udelay(PCIE_RESET_DELAY);
298
299 ret = clk_set_rate(&priv->clk_port, PORT_CLK_RATE);
300 if (ret) {
301 dev_err(dev, "failed to set port clk rate (ret=%d)\n", ret);
302 goto err_deassert_bulk;
303 }
304
305 ret = clk_enable(&priv->clk_general);
306 if (ret) {
307 dev_err(dev, "failed to enable clk general (ret=%d)\n", ret);
308 goto err_deassert_bulk;
309 }
310
311 ret = clk_enable(&priv->clk_pclk);
312 if (ret) {
313 dev_err(dev, "failed to enable pclk (ret=%d)\n", ret);
314 goto err_deassert_bulk;
315 }
316
317 meson_set_max_payload(priv, MAX_PAYLOAD_SIZE);
318 meson_set_max_rd_req_size(priv, MAX_READ_REQ_SIZE);
319
320 pcie_dw_setup_host(&priv->dw);
321
322 ret = meson_pcie_link_up(priv, LINK_SPEED_GEN_2);
323 if (ret < 0)
324 goto err_link_up;
325
326 return 0;
327err_link_up:
328 clk_disable(&priv->clk_port);
329 clk_disable(&priv->clk_general);
330 clk_disable(&priv->clk_pclk);
331err_deassert_bulk:
332 reset_assert_bulk(&priv->rsts);
333err_power_off_phy:
334 generic_phy_power_off(&priv->phy);
335err_exit_phy:
336 generic_phy_exit(&priv->phy);
337
338 return ret;
339}
340
341static int meson_pcie_parse_dt(struct udevice *dev)
342{
343 struct meson_pcie *priv = dev_get_priv(dev);
344 int ret;
345
346 priv->dw.dbi_base = (void *)dev_read_addr_index(dev, 0);
347 if (!priv->dw.dbi_base)
348 return -ENODEV;
349
350 dev_dbg(dev, "ELBI address is 0x%p\n", priv->dw.dbi_base);
351
352 priv->meson_cfg_base = (void *)dev_read_addr_index(dev, 1);
353 if (!priv->meson_cfg_base)
354 return -ENODEV;
355
356 dev_dbg(dev, "CFG address is 0x%p\n", priv->meson_cfg_base);
357
358 ret = gpio_request_by_name(dev, "reset-gpios", 0,
359 &priv->rst_gpio, GPIOD_IS_OUT);
360 if (ret) {
361 dev_err(dev, "failed to find reset-gpios property\n");
362 return ret;
363 }
364
365 ret = reset_get_bulk(dev, &priv->rsts);
366 if (ret) {
367 dev_err(dev, "Can't get reset: %d\n", ret);
368 return ret;
369 }
370
371 ret = clk_get_by_name(dev, "port", &priv->clk_port);
372 if (ret) {
373 dev_err(dev, "Can't get port clock: %d\n", ret);
374 return ret;
375 }
376
377 ret = clk_get_by_name(dev, "general", &priv->clk_general);
378 if (ret) {
379 dev_err(dev, "Can't get port clock: %d\n", ret);
380 return ret;
381 }
382
383 ret = clk_get_by_name(dev, "pclk", &priv->clk_pclk);
384 if (ret) {
385 dev_err(dev, "Can't get port clock: %d\n", ret);
386 return ret;
387 }
388
389 ret = generic_phy_get_by_index(dev, 0, &priv->phy);
390 if (ret) {
391 dev_err(dev, "failed to get pcie phy (ret=%d)\n", ret);
392 return ret;
393 }
394
395 return 0;
396}
397
398/**
399 * meson_pcie_probe() - Probe the PCIe bus for active link
400 *
401 * @dev: A pointer to the device being operated on
402 *
403 * Probe for an active link on the PCIe bus and configure the controller
404 * to enable this port.
405 *
406 * Return: 0 on success, else -ENODEV
407 */
408static int meson_pcie_probe(struct udevice *dev)
409{
410 struct meson_pcie *priv = dev_get_priv(dev);
411 struct udevice *ctlr = pci_get_controller(dev);
412 struct pci_controller *hose = dev_get_uclass_priv(ctlr);
413 int ret = 0;
414
415 priv->dw.first_busno = dev_seq(dev);
416 priv->dw.dev = dev;
417
418 ret = meson_pcie_parse_dt(dev);
419 if (ret)
420 return ret;
421
422 ret = meson_pcie_init_port(dev);
423 if (ret) {
424 dm_gpio_free(dev, &priv->rst_gpio);
425 return ret;
426 }
427
428 printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n",
429 dev_seq(dev), pcie_dw_get_link_speed(&priv->dw),
430 pcie_dw_get_link_width(&priv->dw),
431 hose->first_busno);
432
433 return pcie_dw_prog_outbound_atu_unroll(&priv->dw,
434 PCIE_ATU_REGION_INDEX0,
435 PCIE_ATU_TYPE_MEM,
436 priv->dw.mem.phys_start,
437 priv->dw.mem.bus_start,
438 priv->dw.mem.size);
439}
440
441static const struct dm_pci_ops meson_pcie_ops = {
442 .read_config = pcie_dw_read_config,
443 .write_config = pcie_dw_write_config,
444};
445
446static const struct udevice_id meson_pcie_ids[] = {
447 { .compatible = "amlogic,axg-pcie" },
448 { .compatible = "amlogic,g12a-pcie" },
449 { }
450};
451
452U_BOOT_DRIVER(meson_dw_pcie) = {
453 .name = "pcie_dw_meson",
454 .id = UCLASS_PCI,
455 .of_match = meson_pcie_ids,
456 .ops = &meson_pcie_ops,
457 .probe = meson_pcie_probe,
458 .priv_auto = sizeof(struct meson_pcie),
459};