]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
da419027 | 2 | /* |
118e58e2 | 3 | * Copyright 2017-2020 NXP |
e4e8cb71 | 4 | * Copyright 2014-2015 Freescale Semiconductor, Inc. |
da419027 | 5 | * Layerscape PCIe driver |
da419027 ML |
6 | */ |
7 | ||
f7ae49fc | 8 | #include <log.h> |
401d1c4f | 9 | #include <asm/global_data.h> |
da419027 | 10 | #include <asm/io.h> |
e4e8cb71 ML |
11 | #include <errno.h> |
12 | #include <malloc.h> | |
6e2941d7 SG |
13 | #if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \ |
14 | defined(CONFIG_ARM) | |
15 | #include <asm/arch/clock.h> | |
16 | #endif | |
a7294aba | 17 | #include "pcie_layerscape.h" |
e4e8cb71 | 18 | |
80afc63f ML |
19 | DECLARE_GLOBAL_DATA_PTR; |
20 | ||
80afc63f ML |
21 | LIST_HEAD(ls_pcie_list); |
22 | ||
118e58e2 | 23 | unsigned int dbi_readl(struct ls_pcie *pcie, unsigned int offset) |
80afc63f ML |
24 | { |
25 | return in_le32(pcie->dbi + offset); | |
26 | } | |
27 | ||
118e58e2 | 28 | void dbi_writel(struct ls_pcie *pcie, unsigned int value, unsigned int offset) |
80afc63f ML |
29 | { |
30 | out_le32(pcie->dbi + offset, value); | |
31 | } | |
32 | ||
118e58e2 | 33 | unsigned int ctrl_readl(struct ls_pcie *pcie, unsigned int offset) |
80afc63f ML |
34 | { |
35 | if (pcie->big_endian) | |
36 | return in_be32(pcie->ctrl + offset); | |
37 | else | |
38 | return in_le32(pcie->ctrl + offset); | |
39 | } | |
40 | ||
118e58e2 XB |
41 | void ctrl_writel(struct ls_pcie *pcie, unsigned int value, |
42 | unsigned int offset) | |
80afc63f ML |
43 | { |
44 | if (pcie->big_endian) | |
45 | out_be32(pcie->ctrl + offset, value); | |
46 | else | |
47 | out_le32(pcie->ctrl + offset, value); | |
48 | } | |
49 | ||
118e58e2 XB |
50 | void 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 | ||
60 | void 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 | ||
80afc63f ML |
70 | static 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 | ||
118e58e2 | 86 | int ls_pcie_link_up(struct ls_pcie *pcie) |
80afc63f ML |
87 | { |
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 | ||
118e58e2 | 97 | void ls_pcie_atu_outbound_set(struct ls_pcie *pcie, int idx, int type, |
83bf32e6 | 98 | u64 phys, u64 bus_addr, u64 size) |
80afc63f ML |
99 | { |
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 */ | |
83bf32e6 XB |
111 | void ls_pcie_atu_inbound_set(struct ls_pcie *pcie, u32 pf, u32 vf_flag, |
112 | int type, int idx, int bar, u64 phys) | |
80afc63f ML |
113 | { |
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); | |
c5174a52 | 117 | dbi_writel(pcie, type | PCIE_ATU_FUNC_NUM(pf), PCIE_ATU_CR1); |
80afc63f | 118 | dbi_writel(pcie, PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE | |
83bf32e6 XB |
119 | (vf_flag ? PCIE_ATU_FUNC_NUM_MATCH_EN : 0) | |
120 | (vf_flag ? PCIE_ATU_VFBAR_MATCH_MODE_EN : 0) | | |
80afc63f ML |
121 | PCIE_ATU_BAR_NUM(bar), PCIE_ATU_CR2); |
122 | } | |
123 | ||
80b5a662 | 124 | void ls_pcie_dump_atu(struct ls_pcie *pcie, u32 win_num, u32 type) |
80afc63f | 125 | { |
80b5a662 | 126 | int win_idx; |
80afc63f | 127 | |
80b5a662 XB |
128 | 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); | |
80afc63f ML |
131 | 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)); | |
80b5a662 XB |
135 | 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 | } | |
80afc63f ML |
143 | 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 | } |