blob: 25b5272d4ed791ac80055cbb555fd60c3cff2353 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Minghuan Lianda419022014-10-31 13:43:44 +08002/*
Xiaowei Bao118e58e2020-07-09 23:31:33 +08003 * Copyright 2017-2020 NXP
Minghuan Liane4e8cb72015-01-21 17:29:20 +08004 * Copyright 2014-2015 Freescale Semiconductor, Inc.
Minghuan Lianda419022014-10-31 13:43:44 +08005 * Layerscape PCIe driver
Minghuan Lianda419022014-10-31 13:43:44 +08006 */
7
8#include <common.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -06009#include <log.h>
Minghuan Lianda419022014-10-31 13:43:44 +080010#include <asm/io.h>
Minghuan Liane4e8cb72015-01-21 17:29:20 +080011#include <errno.h>
12#include <malloc.h>
Simon Glass6e2941d2017-05-17 08:23:06 -060013#if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \
14 defined(CONFIG_ARM)
15#include <asm/arch/clock.h>
16#endif
Hou Zhiqianga7294ab2016-12-13 14:54:16 +080017#include "pcie_layerscape.h"
Minghuan Liane4e8cb72015-01-21 17:29:20 +080018
Minghuan Lian80afc632016-12-13 14:54:17 +080019DECLARE_GLOBAL_DATA_PTR;
20
Minghuan Lian80afc632016-12-13 14:54:17 +080021LIST_HEAD(ls_pcie_list);
22
Xiaowei Bao118e58e2020-07-09 23:31:33 +080023unsigned int dbi_readl(struct ls_pcie *pcie, unsigned int offset)
Minghuan Lian80afc632016-12-13 14:54:17 +080024{
25 return in_le32(pcie->dbi + offset);
26}
27
Xiaowei Bao118e58e2020-07-09 23:31:33 +080028void dbi_writel(struct ls_pcie *pcie, unsigned int value, unsigned int offset)
Minghuan Lian80afc632016-12-13 14:54:17 +080029{
30 out_le32(pcie->dbi + offset, value);
31}
32
Xiaowei Bao118e58e2020-07-09 23:31:33 +080033unsigned int ctrl_readl(struct ls_pcie *pcie, unsigned int offset)
Minghuan Lian80afc632016-12-13 14:54:17 +080034{
35 if (pcie->big_endian)
36 return in_be32(pcie->ctrl + offset);
37 else
38 return in_le32(pcie->ctrl + offset);
39}
40
Xiaowei Bao118e58e2020-07-09 23:31:33 +080041void ctrl_writel(struct ls_pcie *pcie, unsigned int value,
42 unsigned int offset)
Minghuan Lian80afc632016-12-13 14:54:17 +080043{
44 if (pcie->big_endian)
45 out_be32(pcie->ctrl + offset, value);
46 else
47 out_le32(pcie->ctrl + offset, value);
48}
49
Xiaowei Bao118e58e2020-07-09 23:31:33 +080050void ls_pcie_dbi_ro_wr_en(struct ls_pcie *pcie)
51{
52 u32 reg, val;
53
54 reg = PCIE_MISC_CONTROL_1_OFF;
55 val = dbi_readl(pcie, reg);
56 val |= PCIE_DBI_RO_WR_EN;
57 dbi_writel(pcie, val, reg);
58}
59
60void ls_pcie_dbi_ro_wr_dis(struct ls_pcie *pcie)
61{
62 u32 reg, val;
63
64 reg = PCIE_MISC_CONTROL_1_OFF;
65 val = dbi_readl(pcie, reg);
66 val &= ~PCIE_DBI_RO_WR_EN;
67 dbi_writel(pcie, val, reg);
68}
69
Minghuan Lian80afc632016-12-13 14:54:17 +080070static int ls_pcie_ltssm(struct ls_pcie *pcie)
71{
72 u32 state;
73 uint svr;
74
75 svr = get_svr();
76 if (((svr >> SVR_VAR_PER_SHIFT) & SVR_LS102XA_MASK) == SVR_LS102XA) {
77 state = ctrl_readl(pcie, LS1021_PEXMSCPORTSR(pcie->idx));
78 state = (state >> LS1021_LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
79 } else {
80 state = ctrl_readl(pcie, PCIE_PF_DBG) & LTSSM_STATE_MASK;
81 }
82
83 return state;
84}
85
Xiaowei Bao118e58e2020-07-09 23:31:33 +080086int ls_pcie_link_up(struct ls_pcie *pcie)
Minghuan Lian80afc632016-12-13 14:54:17 +080087{
88 int ltssm;
89
90 ltssm = ls_pcie_ltssm(pcie);
91 if (ltssm < LTSSM_PCIE_L0)
92 return 0;
93
94 return 1;
95}
96
Xiaowei Bao118e58e2020-07-09 23:31:33 +080097void ls_pcie_atu_outbound_set(struct ls_pcie *pcie, int idx, int type,
Xiaowei Bao83bf32e2020-07-09 23:31:39 +080098 u64 phys, u64 bus_addr, u64 size)
Minghuan Lian80afc632016-12-13 14:54:17 +080099{
100 dbi_writel(pcie, PCIE_ATU_REGION_OUTBOUND | idx, PCIE_ATU_VIEWPORT);
101 dbi_writel(pcie, (u32)phys, PCIE_ATU_LOWER_BASE);
102 dbi_writel(pcie, phys >> 32, PCIE_ATU_UPPER_BASE);
103 dbi_writel(pcie, (u32)phys + size - 1, PCIE_ATU_LIMIT);
104 dbi_writel(pcie, (u32)bus_addr, PCIE_ATU_LOWER_TARGET);
105 dbi_writel(pcie, bus_addr >> 32, PCIE_ATU_UPPER_TARGET);
106 dbi_writel(pcie, type, PCIE_ATU_CR1);
107 dbi_writel(pcie, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
108}
109
110/* Use bar match mode and MEM type as default */
Xiaowei Bao83bf32e2020-07-09 23:31:39 +0800111void ls_pcie_atu_inbound_set(struct ls_pcie *pcie, u32 pf, u32 vf_flag,
112 int type, int idx, int bar, u64 phys)
Minghuan Lian80afc632016-12-13 14:54:17 +0800113{
114 dbi_writel(pcie, PCIE_ATU_REGION_INBOUND | idx, PCIE_ATU_VIEWPORT);
115 dbi_writel(pcie, (u32)phys, PCIE_ATU_LOWER_TARGET);
116 dbi_writel(pcie, phys >> 32, PCIE_ATU_UPPER_TARGET);
Xiaowei Baoc5174a52020-07-09 23:31:36 +0800117 dbi_writel(pcie, type | PCIE_ATU_FUNC_NUM(pf), PCIE_ATU_CR1);
Minghuan Lian80afc632016-12-13 14:54:17 +0800118 dbi_writel(pcie, PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE |
Xiaowei Bao83bf32e2020-07-09 23:31:39 +0800119 (vf_flag ? PCIE_ATU_FUNC_NUM_MATCH_EN : 0) |
120 (vf_flag ? PCIE_ATU_VFBAR_MATCH_MODE_EN : 0) |
Minghuan Lian80afc632016-12-13 14:54:17 +0800121 PCIE_ATU_BAR_NUM(bar), PCIE_ATU_CR2);
122}
123
Xiaowei Bao80b5a662020-07-09 23:31:40 +0800124void ls_pcie_dump_atu(struct ls_pcie *pcie, u32 win_num, u32 type)
Minghuan Lian80afc632016-12-13 14:54:17 +0800125{
Xiaowei Bao80b5a662020-07-09 23:31:40 +0800126 int win_idx;
Minghuan Lian80afc632016-12-13 14:54:17 +0800127
Xiaowei Bao80b5a662020-07-09 23:31:40 +0800128 for (win_idx = 0; win_idx < win_num; win_idx++) {
129 dbi_writel(pcie, type | win_idx, PCIE_ATU_VIEWPORT);
130 debug("iATU%d:\n", win_idx);
Minghuan Lian80afc632016-12-13 14:54:17 +0800131 debug("\tLOWER PHYS 0x%08x\n",
132 dbi_readl(pcie, PCIE_ATU_LOWER_BASE));
133 debug("\tUPPER PHYS 0x%08x\n",
134 dbi_readl(pcie, PCIE_ATU_UPPER_BASE));
Xiaowei Bao80b5a662020-07-09 23:31:40 +0800135 if (type == PCIE_ATU_REGION_OUTBOUND) {
136 debug("\tLOWER BUS 0x%08x\n",
137 dbi_readl(pcie, PCIE_ATU_LOWER_TARGET));
138 debug("\tUPPER BUS 0x%08x\n",
139 dbi_readl(pcie, PCIE_ATU_UPPER_TARGET));
140 debug("\tLIMIT 0x%08x\n",
141 dbi_readl(pcie, PCIE_ATU_LIMIT));
142 }
Minghuan Lian80afc632016-12-13 14:54:17 +0800143 debug("\tCR1 0x%08x\n",
144 dbi_readl(pcie, PCIE_ATU_CR1));
145 debug("\tCR2 0x%08x\n",
146 dbi_readl(pcie, PCIE_ATU_CR2));
147 }
148}