| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * MPC83xx/85xx/86xx PCI/PCIE support routing. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 11 | 12 | * MPC83xx PCI-Express support: |
|---|
| 12 | 13 | * Tony Li <tony.li@freescale.com> |
|---|
| 13 | 14 | * Anton Vorontsov <avorontsov@ru.mvista.com> |
|---|
| 14 | | - * |
|---|
| 15 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 16 | | - * under the terms of the GNU General Public License as published by the |
|---|
| 17 | | - * Free Software Foundation; either version 2 of the License, or (at your |
|---|
| 18 | | - * option) any later version. |
|---|
| 19 | 15 | */ |
|---|
| 20 | 16 | #include <linux/kernel.h> |
|---|
| 21 | 17 | #include <linux/pci.h> |
|---|
| .. | .. |
|---|
| 40 | 36 | #include <asm/mpc85xx.h> |
|---|
| 41 | 37 | #include <asm/disassemble.h> |
|---|
| 42 | 38 | #include <asm/ppc-opcode.h> |
|---|
| 39 | +#include <asm/swiotlb.h> |
|---|
| 43 | 40 | #include <sysdev/fsl_soc.h> |
|---|
| 44 | 41 | #include <sysdev/fsl_pci.h> |
|---|
| 45 | 42 | |
|---|
| .. | .. |
|---|
| 114 | 111 | static u64 pci64_dma_offset; |
|---|
| 115 | 112 | |
|---|
| 116 | 113 | #ifdef CONFIG_SWIOTLB |
|---|
| 114 | +static void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev) |
|---|
| 115 | +{ |
|---|
| 116 | + struct pci_controller *hose = pci_bus_to_host(pdev->bus); |
|---|
| 117 | + |
|---|
| 118 | + pdev->dev.bus_dma_limit = |
|---|
| 119 | + hose->dma_window_base_cur + hose->dma_window_size - 1; |
|---|
| 120 | +} |
|---|
| 121 | + |
|---|
| 117 | 122 | static void setup_swiotlb_ops(struct pci_controller *hose) |
|---|
| 118 | 123 | { |
|---|
| 119 | | - if (ppc_swiotlb_enable) { |
|---|
| 124 | + if (ppc_swiotlb_enable) |
|---|
| 120 | 125 | hose->controller_ops.dma_dev_setup = pci_dma_dev_setup_swiotlb; |
|---|
| 121 | | - set_pci_dma_ops(&powerpc_swiotlb_dma_ops); |
|---|
| 122 | | - } |
|---|
| 123 | 126 | } |
|---|
| 124 | 127 | #else |
|---|
| 125 | 128 | static inline void setup_swiotlb_ops(struct pci_controller *hose) {} |
|---|
| 126 | 129 | #endif |
|---|
| 127 | 130 | |
|---|
| 128 | | -static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) |
|---|
| 131 | +static void fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) |
|---|
| 129 | 132 | { |
|---|
| 130 | | - if (!dev->dma_mask || !dma_supported(dev, dma_mask)) |
|---|
| 131 | | - return -EIO; |
|---|
| 132 | | - |
|---|
| 133 | 133 | /* |
|---|
| 134 | 134 | * Fix up PCI devices that are able to DMA to the large inbound |
|---|
| 135 | 135 | * mapping that allows addressing any RAM address from across PCI. |
|---|
| 136 | 136 | */ |
|---|
| 137 | 137 | if (dev_is_pci(dev) && dma_mask >= pci64_dma_offset * 2 - 1) { |
|---|
| 138 | | - set_dma_ops(dev, &dma_nommu_ops); |
|---|
| 139 | | - set_dma_offset(dev, pci64_dma_offset); |
|---|
| 138 | + dev->bus_dma_limit = 0; |
|---|
| 139 | + dev->archdata.dma_offset = pci64_dma_offset; |
|---|
| 140 | 140 | } |
|---|
| 141 | | - |
|---|
| 142 | | - *dev->dma_mask = dma_mask; |
|---|
| 143 | | - return 0; |
|---|
| 144 | 141 | } |
|---|
| 145 | 142 | |
|---|
| 146 | 143 | static int setup_one_atmu(struct ccsr_pci __iomem *pci, |
|---|
| .. | .. |
|---|
| 523 | 520 | struct resource rsrc; |
|---|
| 524 | 521 | const int *bus_range; |
|---|
| 525 | 522 | u8 hdr_type, progif; |
|---|
| 523 | + u32 class_code; |
|---|
| 526 | 524 | struct device_node *dev; |
|---|
| 527 | 525 | struct ccsr_pci __iomem *pci; |
|---|
| 528 | 526 | u16 temp; |
|---|
| .. | .. |
|---|
| 596 | 594 | PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS; |
|---|
| 597 | 595 | if (fsl_pcie_check_link(hose)) |
|---|
| 598 | 596 | hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; |
|---|
| 597 | + /* Fix Class Code to PCI_CLASS_BRIDGE_PCI_NORMAL for pre-3.0 controller */ |
|---|
| 598 | + if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0) { |
|---|
| 599 | + early_read_config_dword(hose, 0, 0, PCIE_FSL_CSR_CLASSCODE, &class_code); |
|---|
| 600 | + class_code &= 0xff; |
|---|
| 601 | + class_code |= PCI_CLASS_BRIDGE_PCI_NORMAL << 8; |
|---|
| 602 | + early_write_config_dword(hose, 0, 0, PCIE_FSL_CSR_CLASSCODE, class_code); |
|---|
| 603 | + } |
|---|
| 599 | 604 | } else { |
|---|
| 600 | 605 | /* |
|---|
| 601 | 606 | * Set PBFR(PCI Bus Function Register)[10] = 1 to |
|---|
| .. | .. |
|---|
| 1068 | 1073 | addr += mfspr(SPRN_MCAR); |
|---|
| 1069 | 1074 | |
|---|
| 1070 | 1075 | if (is_in_pci_mem_space(addr)) { |
|---|
| 1071 | | - if (user_mode(regs)) { |
|---|
| 1072 | | - pagefault_disable(); |
|---|
| 1073 | | - ret = get_user(inst, (__u32 __user *)regs->nip); |
|---|
| 1074 | | - pagefault_enable(); |
|---|
| 1075 | | - } else { |
|---|
| 1076 | | - ret = probe_kernel_address((void *)regs->nip, inst); |
|---|
| 1077 | | - } |
|---|
| 1076 | + if (user_mode(regs)) |
|---|
| 1077 | + ret = copy_from_user_nofault(&inst, |
|---|
| 1078 | + (void __user *)regs->nip, sizeof(inst)); |
|---|
| 1079 | + else |
|---|
| 1080 | + ret = get_kernel_nofault(inst, (void *)regs->nip); |
|---|
| 1078 | 1081 | |
|---|
| 1079 | 1082 | if (!ret && mcheck_handle_load(regs, inst)) { |
|---|
| 1080 | 1083 | regs->nip += 4; |
|---|