.. | .. |
---|
98 | 98 | void __iomem *reg; |
---|
99 | 99 | struct resource mem_res; |
---|
100 | 100 | struct resource *cfg_res; |
---|
101 | | - unsigned busnr; |
---|
102 | 101 | int irq; |
---|
103 | | - unsigned long window_size; |
---|
104 | | - unsigned long window_addr; |
---|
105 | | - unsigned long window_pci; |
---|
106 | 102 | }; |
---|
107 | 103 | |
---|
108 | 104 | /* PCI configuration space operations */ |
---|
109 | 105 | static void __iomem *rcar_pci_cfg_base(struct pci_bus *bus, unsigned int devfn, |
---|
110 | 106 | int where) |
---|
111 | 107 | { |
---|
112 | | - struct pci_sys_data *sys = bus->sysdata; |
---|
113 | | - struct rcar_pci_priv *priv = sys->private_data; |
---|
| 108 | + struct rcar_pci_priv *priv = bus->sysdata; |
---|
114 | 109 | int slot, val; |
---|
115 | 110 | |
---|
116 | | - if (sys->busnr != bus->number || PCI_FUNC(devfn)) |
---|
| 111 | + if (!pci_is_root_bus(bus) || PCI_FUNC(devfn)) |
---|
117 | 112 | return NULL; |
---|
118 | 113 | |
---|
119 | 114 | /* Only one EHCI/OHCI device built-in */ |
---|
.. | .. |
---|
130 | 125 | |
---|
131 | 126 | iowrite32(val, priv->reg + RCAR_AHBPCI_WIN1_CTR_REG); |
---|
132 | 127 | return priv->reg + (slot >> 1) * 0x100 + where; |
---|
133 | | -} |
---|
134 | | - |
---|
135 | | -/* PCI interrupt mapping */ |
---|
136 | | -static int rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
---|
137 | | -{ |
---|
138 | | - struct pci_sys_data *sys = dev->bus->sysdata; |
---|
139 | | - struct rcar_pci_priv *priv = sys->private_data; |
---|
140 | | - int irq; |
---|
141 | | - |
---|
142 | | - irq = of_irq_parse_and_map_pci(dev, slot, pin); |
---|
143 | | - if (!irq) |
---|
144 | | - irq = priv->irq; |
---|
145 | | - |
---|
146 | | - return irq; |
---|
147 | 128 | } |
---|
148 | 129 | |
---|
149 | 130 | #ifdef CONFIG_PCI_DEBUG |
---|
.. | .. |
---|
189 | 170 | #endif |
---|
190 | 171 | |
---|
191 | 172 | /* PCI host controller setup */ |
---|
192 | | -static int rcar_pci_setup(int nr, struct pci_sys_data *sys) |
---|
| 173 | +static void rcar_pci_setup(struct rcar_pci_priv *priv) |
---|
193 | 174 | { |
---|
194 | | - struct rcar_pci_priv *priv = sys->private_data; |
---|
| 175 | + struct pci_host_bridge *bridge = pci_host_bridge_from_priv(priv); |
---|
195 | 176 | struct device *dev = priv->dev; |
---|
196 | 177 | void __iomem *reg = priv->reg; |
---|
| 178 | + struct resource_entry *entry; |
---|
| 179 | + unsigned long window_size; |
---|
| 180 | + unsigned long window_addr; |
---|
| 181 | + unsigned long window_pci; |
---|
197 | 182 | u32 val; |
---|
198 | | - int ret; |
---|
| 183 | + |
---|
| 184 | + entry = resource_list_first_type(&bridge->dma_ranges, IORESOURCE_MEM); |
---|
| 185 | + if (!entry) { |
---|
| 186 | + window_addr = 0x40000000; |
---|
| 187 | + window_pci = 0x40000000; |
---|
| 188 | + window_size = SZ_1G; |
---|
| 189 | + } else { |
---|
| 190 | + window_addr = entry->res->start; |
---|
| 191 | + window_pci = entry->res->start - entry->offset; |
---|
| 192 | + window_size = resource_size(entry->res); |
---|
| 193 | + } |
---|
199 | 194 | |
---|
200 | 195 | pm_runtime_enable(dev); |
---|
201 | 196 | pm_runtime_get_sync(dev); |
---|
202 | 197 | |
---|
203 | 198 | val = ioread32(reg + RCAR_PCI_UNIT_REV_REG); |
---|
204 | | - dev_info(dev, "PCI: bus%u revision %x\n", sys->busnr, val); |
---|
| 199 | + dev_info(dev, "PCI: revision %x\n", val); |
---|
205 | 200 | |
---|
206 | 201 | /* Disable Direct Power Down State and assert reset */ |
---|
207 | 202 | val = ioread32(reg + RCAR_USBCTR_REG) & ~RCAR_USBCTR_DIRPD; |
---|
.. | .. |
---|
214 | 209 | RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST); |
---|
215 | 210 | |
---|
216 | 211 | /* Setup PCIAHB window1 size */ |
---|
217 | | - switch (priv->window_size) { |
---|
| 212 | + switch (window_size) { |
---|
218 | 213 | case SZ_2G: |
---|
219 | 214 | val |= RCAR_USBCTR_PCIAHB_WIN1_2G; |
---|
220 | 215 | break; |
---|
.. | .. |
---|
226 | 221 | break; |
---|
227 | 222 | default: |
---|
228 | 223 | pr_warn("unknown window size %ld - defaulting to 256M\n", |
---|
229 | | - priv->window_size); |
---|
230 | | - priv->window_size = SZ_256M; |
---|
231 | | - /* fall-through */ |
---|
| 224 | + window_size); |
---|
| 225 | + window_size = SZ_256M; |
---|
| 226 | + fallthrough; |
---|
232 | 227 | case SZ_256M: |
---|
233 | 228 | val |= RCAR_USBCTR_PCIAHB_WIN1_256M; |
---|
234 | 229 | break; |
---|
.. | .. |
---|
245 | 240 | iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG); |
---|
246 | 241 | |
---|
247 | 242 | /* PCI-AHB mapping */ |
---|
248 | | - iowrite32(priv->window_addr | RCAR_PCIAHB_PREFETCH16, |
---|
| 243 | + iowrite32(window_addr | RCAR_PCIAHB_PREFETCH16, |
---|
249 | 244 | reg + RCAR_PCIAHB_WIN1_CTR_REG); |
---|
250 | 245 | |
---|
251 | 246 | /* AHB-PCI mapping: OHCI/EHCI registers */ |
---|
.. | .. |
---|
256 | 251 | iowrite32(RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG, |
---|
257 | 252 | reg + RCAR_AHBPCI_WIN1_CTR_REG); |
---|
258 | 253 | /* Set PCI-AHB Window1 address */ |
---|
259 | | - iowrite32(priv->window_pci | PCI_BASE_ADDRESS_MEM_PREFETCH, |
---|
| 254 | + iowrite32(window_pci | PCI_BASE_ADDRESS_MEM_PREFETCH, |
---|
260 | 255 | reg + PCI_BASE_ADDRESS_1); |
---|
261 | 256 | /* Set AHB-PCI bridge PCI communication area address */ |
---|
262 | 257 | val = priv->cfg_res->start + RCAR_AHBPCI_PCICOM_OFFSET; |
---|
.. | .. |
---|
271 | 266 | iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME, |
---|
272 | 267 | reg + RCAR_PCI_INT_ENABLE_REG); |
---|
273 | 268 | |
---|
274 | | - if (priv->irq > 0) |
---|
275 | | - rcar_pci_setup_errirq(priv); |
---|
276 | | - |
---|
277 | | - /* Add PCI resources */ |
---|
278 | | - pci_add_resource(&sys->resources, &priv->mem_res); |
---|
279 | | - ret = devm_request_pci_bus_resources(dev, &sys->resources); |
---|
280 | | - if (ret < 0) |
---|
281 | | - return ret; |
---|
282 | | - |
---|
283 | | - /* Setup bus number based on platform device id / of bus-range */ |
---|
284 | | - sys->busnr = priv->busnr; |
---|
285 | | - return 1; |
---|
| 269 | + rcar_pci_setup_errirq(priv); |
---|
286 | 270 | } |
---|
287 | 271 | |
---|
288 | 272 | static struct pci_ops rcar_pci_ops = { |
---|
.. | .. |
---|
291 | 275 | .write = pci_generic_config_write, |
---|
292 | 276 | }; |
---|
293 | 277 | |
---|
294 | | -static int rcar_pci_parse_map_dma_ranges(struct rcar_pci_priv *pci, |
---|
295 | | - struct device_node *np) |
---|
296 | | -{ |
---|
297 | | - struct device *dev = pci->dev; |
---|
298 | | - struct of_pci_range range; |
---|
299 | | - struct of_pci_range_parser parser; |
---|
300 | | - int index = 0; |
---|
301 | | - |
---|
302 | | - /* Failure to parse is ok as we fall back to defaults */ |
---|
303 | | - if (of_pci_dma_range_parser_init(&parser, np)) |
---|
304 | | - return 0; |
---|
305 | | - |
---|
306 | | - /* Get the dma-ranges from DT */ |
---|
307 | | - for_each_of_pci_range(&parser, &range) { |
---|
308 | | - /* Hardware only allows one inbound 32-bit range */ |
---|
309 | | - if (index) |
---|
310 | | - return -EINVAL; |
---|
311 | | - |
---|
312 | | - pci->window_addr = (unsigned long)range.cpu_addr; |
---|
313 | | - pci->window_pci = (unsigned long)range.pci_addr; |
---|
314 | | - pci->window_size = (unsigned long)range.size; |
---|
315 | | - |
---|
316 | | - /* Catch HW limitations */ |
---|
317 | | - if (!(range.flags & IORESOURCE_PREFETCH)) { |
---|
318 | | - dev_err(dev, "window must be prefetchable\n"); |
---|
319 | | - return -EINVAL; |
---|
320 | | - } |
---|
321 | | - if (pci->window_addr) { |
---|
322 | | - u32 lowaddr = 1 << (ffs(pci->window_addr) - 1); |
---|
323 | | - |
---|
324 | | - if (lowaddr < pci->window_size) { |
---|
325 | | - dev_err(dev, "invalid window size/addr\n"); |
---|
326 | | - return -EINVAL; |
---|
327 | | - } |
---|
328 | | - } |
---|
329 | | - index++; |
---|
330 | | - } |
---|
331 | | - |
---|
332 | | - return 0; |
---|
333 | | -} |
---|
334 | | - |
---|
335 | 278 | static int rcar_pci_probe(struct platform_device *pdev) |
---|
336 | 279 | { |
---|
337 | 280 | struct device *dev = &pdev->dev; |
---|
338 | 281 | struct resource *cfg_res, *mem_res; |
---|
339 | 282 | struct rcar_pci_priv *priv; |
---|
| 283 | + struct pci_host_bridge *bridge; |
---|
340 | 284 | void __iomem *reg; |
---|
341 | | - struct hw_pci hw; |
---|
342 | | - void *hw_private[1]; |
---|
| 285 | + |
---|
| 286 | + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*priv)); |
---|
| 287 | + if (!bridge) |
---|
| 288 | + return -ENOMEM; |
---|
| 289 | + |
---|
| 290 | + priv = pci_host_bridge_priv(bridge); |
---|
| 291 | + bridge->sysdata = priv; |
---|
343 | 292 | |
---|
344 | 293 | cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
345 | 294 | reg = devm_ioremap_resource(dev, cfg_res); |
---|
.. | .. |
---|
353 | 302 | if (mem_res->start & 0xFFFF) |
---|
354 | 303 | return -EINVAL; |
---|
355 | 304 | |
---|
356 | | - priv = devm_kzalloc(dev, sizeof(struct rcar_pci_priv), GFP_KERNEL); |
---|
357 | | - if (!priv) |
---|
358 | | - return -ENOMEM; |
---|
359 | | - |
---|
360 | 305 | priv->mem_res = *mem_res; |
---|
361 | 306 | priv->cfg_res = cfg_res; |
---|
362 | 307 | |
---|
.. | .. |
---|
369 | 314 | return priv->irq; |
---|
370 | 315 | } |
---|
371 | 316 | |
---|
372 | | - /* default window addr and size if not specified in DT */ |
---|
373 | | - priv->window_addr = 0x40000000; |
---|
374 | | - priv->window_pci = 0x40000000; |
---|
375 | | - priv->window_size = SZ_1G; |
---|
| 317 | + bridge->ops = &rcar_pci_ops; |
---|
376 | 318 | |
---|
377 | | - if (dev->of_node) { |
---|
378 | | - struct resource busnr; |
---|
379 | | - int ret; |
---|
| 319 | + pci_add_flags(PCI_REASSIGN_ALL_BUS); |
---|
380 | 320 | |
---|
381 | | - ret = of_pci_parse_bus_range(dev->of_node, &busnr); |
---|
382 | | - if (ret < 0) { |
---|
383 | | - dev_err(dev, "failed to parse bus-range\n"); |
---|
384 | | - return ret; |
---|
385 | | - } |
---|
| 321 | + rcar_pci_setup(priv); |
---|
386 | 322 | |
---|
387 | | - priv->busnr = busnr.start; |
---|
388 | | - if (busnr.end != busnr.start) |
---|
389 | | - dev_warn(dev, "only one bus number supported\n"); |
---|
390 | | - |
---|
391 | | - ret = rcar_pci_parse_map_dma_ranges(priv, dev->of_node); |
---|
392 | | - if (ret < 0) { |
---|
393 | | - dev_err(dev, "failed to parse dma-range\n"); |
---|
394 | | - return ret; |
---|
395 | | - } |
---|
396 | | - } else { |
---|
397 | | - priv->busnr = pdev->id; |
---|
398 | | - } |
---|
399 | | - |
---|
400 | | - hw_private[0] = priv; |
---|
401 | | - memset(&hw, 0, sizeof(hw)); |
---|
402 | | - hw.nr_controllers = ARRAY_SIZE(hw_private); |
---|
403 | | - hw.io_optional = 1; |
---|
404 | | - hw.private_data = hw_private; |
---|
405 | | - hw.map_irq = rcar_pci_map_irq; |
---|
406 | | - hw.ops = &rcar_pci_ops; |
---|
407 | | - hw.setup = rcar_pci_setup; |
---|
408 | | - pci_common_init_dev(dev, &hw); |
---|
409 | | - return 0; |
---|
| 323 | + return pci_host_probe(bridge); |
---|
410 | 324 | } |
---|
411 | 325 | |
---|
412 | 326 | static const struct of_device_id rcar_pci_of_match[] = { |
---|