diff options
-rw-r--r-- | drivers/pci/host/pci-mvebu.c | 97 |
1 files changed, 55 insertions, 42 deletions
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 10c0895e42b3..73b6baea4879 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c | |||
@@ -140,29 +140,39 @@ struct mvebu_pcie_port { | |||
140 | size_t iowin_size; | 140 | size_t iowin_size; |
141 | }; | 141 | }; |
142 | 142 | ||
143 | static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg) | ||
144 | { | ||
145 | writel(val, port->base + reg); | ||
146 | } | ||
147 | |||
148 | static inline u32 mvebu_readl(struct mvebu_pcie_port *port, u32 reg) | ||
149 | { | ||
150 | return readl(port->base + reg); | ||
151 | } | ||
152 | |||
143 | static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port) | 153 | static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port) |
144 | { | 154 | { |
145 | return !(readl(port->base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); | 155 | return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); |
146 | } | 156 | } |
147 | 157 | ||
148 | static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr) | 158 | static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr) |
149 | { | 159 | { |
150 | u32 stat; | 160 | u32 stat; |
151 | 161 | ||
152 | stat = readl(port->base + PCIE_STAT_OFF); | 162 | stat = mvebu_readl(port, PCIE_STAT_OFF); |
153 | stat &= ~PCIE_STAT_BUS; | 163 | stat &= ~PCIE_STAT_BUS; |
154 | stat |= nr << 8; | 164 | stat |= nr << 8; |
155 | writel(stat, port->base + PCIE_STAT_OFF); | 165 | mvebu_writel(port, stat, PCIE_STAT_OFF); |
156 | } | 166 | } |
157 | 167 | ||
158 | static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr) | 168 | static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr) |
159 | { | 169 | { |
160 | u32 stat; | 170 | u32 stat; |
161 | 171 | ||
162 | stat = readl(port->base + PCIE_STAT_OFF); | 172 | stat = mvebu_readl(port, PCIE_STAT_OFF); |
163 | stat &= ~PCIE_STAT_DEV; | 173 | stat &= ~PCIE_STAT_DEV; |
164 | stat |= nr << 16; | 174 | stat |= nr << 16; |
165 | writel(stat, port->base + PCIE_STAT_OFF); | 175 | mvebu_writel(port, stat, PCIE_STAT_OFF); |
166 | } | 176 | } |
167 | 177 | ||
168 | /* | 178 | /* |
@@ -180,33 +190,34 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) | |||
180 | 190 | ||
181 | /* First, disable and clear BARs and windows. */ | 191 | /* First, disable and clear BARs and windows. */ |
182 | for (i = 1; i < 3; i++) { | 192 | for (i = 1; i < 3; i++) { |
183 | writel(0, port->base + PCIE_BAR_CTRL_OFF(i)); | 193 | mvebu_writel(port, 0, PCIE_BAR_CTRL_OFF(i)); |
184 | writel(0, port->base + PCIE_BAR_LO_OFF(i)); | 194 | mvebu_writel(port, 0, PCIE_BAR_LO_OFF(i)); |
185 | writel(0, port->base + PCIE_BAR_HI_OFF(i)); | 195 | mvebu_writel(port, 0, PCIE_BAR_HI_OFF(i)); |
186 | } | 196 | } |
187 | 197 | ||
188 | for (i = 0; i < 5; i++) { | 198 | for (i = 0; i < 5; i++) { |
189 | writel(0, port->base + PCIE_WIN04_CTRL_OFF(i)); | 199 | mvebu_writel(port, 0, PCIE_WIN04_CTRL_OFF(i)); |
190 | writel(0, port->base + PCIE_WIN04_BASE_OFF(i)); | 200 | mvebu_writel(port, 0, PCIE_WIN04_BASE_OFF(i)); |
191 | writel(0, port->base + PCIE_WIN04_REMAP_OFF(i)); | 201 | mvebu_writel(port, 0, PCIE_WIN04_REMAP_OFF(i)); |
192 | } | 202 | } |
193 | 203 | ||
194 | writel(0, port->base + PCIE_WIN5_CTRL_OFF); | 204 | mvebu_writel(port, 0, PCIE_WIN5_CTRL_OFF); |
195 | writel(0, port->base + PCIE_WIN5_BASE_OFF); | 205 | mvebu_writel(port, 0, PCIE_WIN5_BASE_OFF); |
196 | writel(0, port->base + PCIE_WIN5_REMAP_OFF); | 206 | mvebu_writel(port, 0, PCIE_WIN5_REMAP_OFF); |
197 | 207 | ||
198 | /* Setup windows for DDR banks. Count total DDR size on the fly. */ | 208 | /* Setup windows for DDR banks. Count total DDR size on the fly. */ |
199 | size = 0; | 209 | size = 0; |
200 | for (i = 0; i < dram->num_cs; i++) { | 210 | for (i = 0; i < dram->num_cs; i++) { |
201 | const struct mbus_dram_window *cs = dram->cs + i; | 211 | const struct mbus_dram_window *cs = dram->cs + i; |
202 | 212 | ||
203 | writel(cs->base & 0xffff0000, | 213 | mvebu_writel(port, cs->base & 0xffff0000, |
204 | port->base + PCIE_WIN04_BASE_OFF(i)); | 214 | PCIE_WIN04_BASE_OFF(i)); |
205 | writel(0, port->base + PCIE_WIN04_REMAP_OFF(i)); | 215 | mvebu_writel(port, 0, PCIE_WIN04_REMAP_OFF(i)); |
206 | writel(((cs->size - 1) & 0xffff0000) | | 216 | mvebu_writel(port, |
207 | (cs->mbus_attr << 8) | | 217 | ((cs->size - 1) & 0xffff0000) | |
208 | (dram->mbus_dram_target_id << 4) | 1, | 218 | (cs->mbus_attr << 8) | |
209 | port->base + PCIE_WIN04_CTRL_OFF(i)); | 219 | (dram->mbus_dram_target_id << 4) | 1, |
220 | PCIE_WIN04_CTRL_OFF(i)); | ||
210 | 221 | ||
211 | size += cs->size; | 222 | size += cs->size; |
212 | } | 223 | } |
@@ -216,41 +227,40 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) | |||
216 | size = 1 << fls(size); | 227 | size = 1 << fls(size); |
217 | 228 | ||
218 | /* Setup BAR[1] to all DRAM banks. */ | 229 | /* Setup BAR[1] to all DRAM banks. */ |
219 | writel(dram->cs[0].base, port->base + PCIE_BAR_LO_OFF(1)); | 230 | mvebu_writel(port, dram->cs[0].base, PCIE_BAR_LO_OFF(1)); |
220 | writel(0, port->base + PCIE_BAR_HI_OFF(1)); | 231 | mvebu_writel(port, 0, PCIE_BAR_HI_OFF(1)); |
221 | writel(((size - 1) & 0xffff0000) | 1, | 232 | mvebu_writel(port, ((size - 1) & 0xffff0000) | 1, |
222 | port->base + PCIE_BAR_CTRL_OFF(1)); | 233 | PCIE_BAR_CTRL_OFF(1)); |
223 | } | 234 | } |
224 | 235 | ||
225 | static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) | 236 | static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) |
226 | { | 237 | { |
227 | u16 cmd; | 238 | u32 cmd, mask; |
228 | u32 mask; | ||
229 | 239 | ||
230 | /* Point PCIe unit MBUS decode windows to DRAM space. */ | 240 | /* Point PCIe unit MBUS decode windows to DRAM space. */ |
231 | mvebu_pcie_setup_wins(port); | 241 | mvebu_pcie_setup_wins(port); |
232 | 242 | ||
233 | /* Master + slave enable. */ | 243 | /* Master + slave enable. */ |
234 | cmd = readw(port->base + PCIE_CMD_OFF); | 244 | cmd = mvebu_readl(port, PCIE_CMD_OFF); |
235 | cmd |= PCI_COMMAND_IO; | 245 | cmd |= PCI_COMMAND_IO; |
236 | cmd |= PCI_COMMAND_MEMORY; | 246 | cmd |= PCI_COMMAND_MEMORY; |
237 | cmd |= PCI_COMMAND_MASTER; | 247 | cmd |= PCI_COMMAND_MASTER; |
238 | writew(cmd, port->base + PCIE_CMD_OFF); | 248 | mvebu_writel(port, cmd, PCIE_CMD_OFF); |
239 | 249 | ||
240 | /* Enable interrupt lines A-D. */ | 250 | /* Enable interrupt lines A-D. */ |
241 | mask = readl(port->base + PCIE_MASK_OFF); | 251 | mask = mvebu_readl(port, PCIE_MASK_OFF); |
242 | mask |= PCIE_MASK_ENABLE_INTS; | 252 | mask |= PCIE_MASK_ENABLE_INTS; |
243 | writel(mask, port->base + PCIE_MASK_OFF); | 253 | mvebu_writel(port, mask, PCIE_MASK_OFF); |
244 | } | 254 | } |
245 | 255 | ||
246 | static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port, | 256 | static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port, |
247 | struct pci_bus *bus, | 257 | struct pci_bus *bus, |
248 | u32 devfn, int where, int size, u32 *val) | 258 | u32 devfn, int where, int size, u32 *val) |
249 | { | 259 | { |
250 | writel(PCIE_CONF_ADDR(bus->number, devfn, where), | 260 | mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where), |
251 | port->base + PCIE_CONF_ADDR_OFF); | 261 | PCIE_CONF_ADDR_OFF); |
252 | 262 | ||
253 | *val = readl(port->base + PCIE_CONF_DATA_OFF); | 263 | *val = mvebu_readl(port, PCIE_CONF_DATA_OFF); |
254 | 264 | ||
255 | if (size == 1) | 265 | if (size == 1) |
256 | *val = (*val >> (8 * (where & 3))) & 0xff; | 266 | *val = (*val >> (8 * (where & 3))) & 0xff; |
@@ -264,21 +274,24 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port, | |||
264 | struct pci_bus *bus, | 274 | struct pci_bus *bus, |
265 | u32 devfn, int where, int size, u32 val) | 275 | u32 devfn, int where, int size, u32 val) |
266 | { | 276 | { |
267 | int ret = PCIBIOS_SUCCESSFUL; | 277 | u32 _val, shift = 8 * (where & 3); |
268 | 278 | ||
269 | writel(PCIE_CONF_ADDR(bus->number, devfn, where), | 279 | mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where), |
270 | port->base + PCIE_CONF_ADDR_OFF); | 280 | PCIE_CONF_ADDR_OFF); |
281 | _val = mvebu_readl(port, PCIE_CONF_DATA_OFF); | ||
271 | 282 | ||
272 | if (size == 4) | 283 | if (size == 4) |
273 | writel(val, port->base + PCIE_CONF_DATA_OFF); | 284 | _val = val; |
274 | else if (size == 2) | 285 | else if (size == 2) |
275 | writew(val, port->base + PCIE_CONF_DATA_OFF + (where & 3)); | 286 | _val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift); |
276 | else if (size == 1) | 287 | else if (size == 1) |
277 | writeb(val, port->base + PCIE_CONF_DATA_OFF + (where & 3)); | 288 | _val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift); |
278 | else | 289 | else |
279 | ret = PCIBIOS_BAD_REGISTER_NUMBER; | 290 | return PCIBIOS_BAD_REGISTER_NUMBER; |
280 | 291 | ||
281 | return ret; | 292 | mvebu_writel(port, _val, PCIE_CONF_DATA_OFF); |
293 | |||
294 | return PCIBIOS_SUCCESSFUL; | ||
282 | } | 295 | } |
283 | 296 | ||
284 | static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | 297 | static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) |