| .. | .. |
|---|
| 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[] = { |
|---|