|
| 1 | +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Russell King <rmk+kernel@arm.linux.org.uk> |
| 3 | +Date: Tue, 29 Nov 2016 10:13:46 +0000 |
| 4 | +Subject: mvebu/clearfog pcie updates |
| 5 | + |
| 6 | +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> |
| 7 | +--- |
| 8 | + drivers/pci/controller/pci-mvebu.c | 76 ++++++++++ |
| 9 | + drivers/pci/pci-bridge-emul.c | 2 + |
| 10 | + drivers/pci/pcie/aspm.c | 6 + |
| 11 | + drivers/pci/pcie/portdrv.c | 2 + |
| 12 | + 4 files changed, 86 insertions(+) |
| 13 | + |
| 14 | +diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c |
| 15 | +index 111111111111..222222222222 100644 |
| 16 | +--- a/drivers/pci/controller/pci-mvebu.c |
| 17 | ++++ b/drivers/pci/controller/pci-mvebu.c |
| 18 | +@@ -60,6 +60,12 @@ |
| 19 | + #define PCIE_INT_INTX(i) BIT(24+i) |
| 20 | + #define PCIE_INT_PM_PME BIT(28) |
| 21 | + #define PCIE_INT_ALL_MASK GENMASK(31, 0) |
| 22 | ++#define PCIE_MASK_ERR_COR BIT(18) |
| 23 | ++#define PCIE_MASK_ERR_NONFATAL BIT(17) |
| 24 | ++#define PCIE_MASK_ERR_FATAL BIT(16) |
| 25 | ++#define PCIE_MASK_FERR_DET BIT(10) |
| 26 | ++#define PCIE_MASK_NFERR_DET BIT(9) |
| 27 | ++#define PCIE_MASK_CORERR_DET BIT(8) |
| 28 | + #define PCIE_CTRL_OFF 0x1a00 |
| 29 | + #define PCIE_CTRL_X1_MODE 0x0001 |
| 30 | + #define PCIE_CTRL_RC_MODE BIT(1) |
| 31 | +@@ -618,6 +624,54 @@ mvebu_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge, |
| 32 | + return PCI_BRIDGE_EMUL_HANDLED; |
| 33 | + } |
| 34 | + |
| 35 | ++static void mvebu_pcie_handle_irq_change(struct mvebu_pcie_port *port) |
| 36 | ++{ |
| 37 | ++ u32 reg, old; |
| 38 | ++ u16 devctl, rtctl; |
| 39 | ++ |
| 40 | ++ /* |
| 41 | ++ * Errors from downstream devices: |
| 42 | ++ * bridge control register SERR: enables reception of errors |
| 43 | ++ * Errors from this device, or received errors: |
| 44 | ++ * command SERR: enables ERR_NONFATAL and ERR_FATAL messages |
| 45 | ++ * => when enabled, these conditions also flag SERR in status register |
| 46 | ++ * devctl CERE: enables ERR_CORR messages |
| 47 | ++ * devctl NFERE: enables ERR_NONFATAL messages |
| 48 | ++ * devctl FERE: enables ERR_FATAL messages |
| 49 | ++ * Enabled messages then have three paths: |
| 50 | ++ * 1. rtctl: enables system error indication |
| 51 | ++ * 2. root error status register updated |
| 52 | ++ * 3. root error command register: forwarding via MSI |
| 53 | ++ */ |
| 54 | ++ old = mvebu_readl(port, PCIE_INT_UNMASK_OFF); |
| 55 | ++ reg = old & ~(PCIE_INT_PM_PME | PCIE_MASK_FERR_DET | |
| 56 | ++ PCIE_MASK_NFERR_DET | PCIE_MASK_CORERR_DET | |
| 57 | ++ PCIE_MASK_ERR_COR | PCIE_MASK_ERR_NONFATAL | |
| 58 | ++ PCIE_MASK_ERR_FATAL); |
| 59 | ++ |
| 60 | ++ devctl = port->bridge.pcie_conf.devctl; |
| 61 | ++ if (devctl & PCI_EXP_DEVCTL_FERE) |
| 62 | ++ reg |= PCIE_MASK_FERR_DET | PCIE_MASK_ERR_FATAL; |
| 63 | ++ if (devctl & PCI_EXP_DEVCTL_NFERE) |
| 64 | ++ reg |= PCIE_MASK_NFERR_DET | PCIE_MASK_ERR_NONFATAL; |
| 65 | ++ if (devctl & PCI_EXP_DEVCTL_CERE) |
| 66 | ++ reg |= PCIE_MASK_CORERR_DET | PCIE_MASK_ERR_COR; |
| 67 | ++ if (port->bridge.conf.command & PCI_COMMAND_SERR) |
| 68 | ++ reg |= PCIE_MASK_FERR_DET | PCIE_MASK_NFERR_DET | |
| 69 | ++ PCIE_MASK_ERR_FATAL | PCIE_MASK_ERR_NONFATAL; |
| 70 | ++ |
| 71 | ++ if (!(port->bridge.conf.bridgectrl & PCI_BRIDGE_CTL_SERR)) |
| 72 | ++ reg &= ~(PCIE_MASK_ERR_COR | PCIE_MASK_ERR_NONFATAL | |
| 73 | ++ PCIE_MASK_ERR_FATAL); |
| 74 | ++ |
| 75 | ++ rtctl = port->bridge.pcie_conf.rootctl; |
| 76 | ++ if (rtctl & PCI_EXP_RTCTL_PMEIE) |
| 77 | ++ reg |= PCIE_INT_PM_PME; |
| 78 | ++ |
| 79 | ++ if (old != reg) |
| 80 | ++ mvebu_writel(port, reg, PCIE_INT_UNMASK_OFF); |
| 81 | ++} |
| 82 | ++ |
| 83 | + static pci_bridge_emul_read_status_t |
| 84 | + mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, |
| 85 | + int reg, u32 *value) |
| 86 | +@@ -734,6 +788,9 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, |
| 87 | + switch (reg) { |
| 88 | + case PCI_COMMAND: |
| 89 | + mvebu_writel(port, new, PCIE_CMD_OFF); |
| 90 | ++ |
| 91 | ++ if ((old ^ new) & PCI_COMMAND_SERR) |
| 92 | ++ mvebu_pcie_handle_irq_change(port); |
| 93 | + break; |
| 94 | + |
| 95 | + case PCI_IO_BASE: |
| 96 | +@@ -775,6 +832,8 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, |
| 97 | + break; |
| 98 | + |
| 99 | + case PCI_INTERRUPT_LINE: |
| 100 | ++ if (((old ^ new) >> 16) & PCI_BRIDGE_CTL_SERR) |
| 101 | ++ mvebu_pcie_handle_irq_change(port); |
| 102 | + if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) { |
| 103 | + u32 ctrl = mvebu_readl(port, PCIE_CTRL_OFF); |
| 104 | + if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16)) |
| 105 | +@@ -798,7 +857,18 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge, |
| 106 | + |
| 107 | + switch (reg) { |
| 108 | + case PCI_EXP_DEVCTL: |
| 109 | ++ /* |
| 110 | ++ * Armada370 data says these bits must always |
| 111 | ++ * be zero when in root complex mode. |
| 112 | ++ */ |
| 113 | ++ new &= ~(PCI_EXP_DEVCTL_URRE | PCI_EXP_DEVCTL_FERE | |
| 114 | ++ PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_CERE); |
| 115 | ++ |
| 116 | + mvebu_writel(port, new, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL); |
| 117 | ++ |
| 118 | ++ if ((new ^ old) & (PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_NFERE | |
| 119 | ++ PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_URRE)) |
| 120 | ++ mvebu_pcie_handle_irq_change(port); |
| 121 | + break; |
| 122 | + |
| 123 | + case PCI_EXP_LNKCTL: |
| 124 | +@@ -849,6 +919,12 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge, |
| 125 | + |
| 126 | + default: |
| 127 | + break; |
| 128 | ++ |
| 129 | ++ case PCI_EXP_RTCTL: |
| 130 | ++ if ((new ^ old) & (PCI_EXP_RTCTL_SECEE | PCI_EXP_RTCTL_SENFEE | |
| 131 | ++ PCI_EXP_RTCTL_SEFEE | PCI_EXP_RTCTL_PMEIE)) |
| 132 | ++ mvebu_pcie_handle_irq_change(port); |
| 133 | ++ break; |
| 134 | + } |
| 135 | + } |
| 136 | + |
| 137 | +diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c |
| 138 | +index 111111111111..222222222222 100644 |
| 139 | +--- a/drivers/pci/pci-bridge-emul.c |
| 140 | ++++ b/drivers/pci/pci-bridge-emul.c |
| 141 | +@@ -157,6 +157,7 @@ struct pci_bridge_reg_behavior pci_regs_behavior[PCI_STD_HEADER_SIZEOF / 4] = { |
| 142 | + .rw = (GENMASK(7, 0) | |
| 143 | + ((PCI_BRIDGE_CTL_PARITY | |
| 144 | + PCI_BRIDGE_CTL_SERR | |
| 145 | ++ /* NOTE: PCIe does not allow ISA, VGA, MASTER_ABORT */ |
| 146 | + PCI_BRIDGE_CTL_ISA | |
| 147 | + PCI_BRIDGE_CTL_VGA | |
| 148 | + PCI_BRIDGE_CTL_MASTER_ABORT | |
| 149 | +@@ -355,6 +356,7 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge, |
| 150 | + bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE; |
| 151 | + bridge->conf.cache_line_size = 0x10; |
| 152 | + bridge->conf.status = cpu_to_le16(PCI_STATUS_CAP_LIST); |
| 153 | ++ bridge->conf.bridgectrl = cpu_to_le16(PCI_BRIDGE_CTL_SERR); |
| 154 | + bridge->pci_regs_behavior = kmemdup(pci_regs_behavior, |
| 155 | + sizeof(pci_regs_behavior), |
| 156 | + GFP_KERNEL); |
| 157 | +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c |
| 158 | +index 111111111111..222222222222 100644 |
| 159 | +--- a/drivers/pci/pcie/aspm.c |
| 160 | ++++ b/drivers/pci/pcie/aspm.c |
| 161 | +@@ -617,6 +617,12 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) |
| 162 | + pcie_capability_read_dword(child, PCI_EXP_LNKCAP, &child_lnkcap); |
| 163 | + pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &parent_lnkctl); |
| 164 | + pcie_capability_read_word(child, PCI_EXP_LNKCTL, &child_lnkctl); |
| 165 | ++dev_info(&parent->dev, "up support %x enabled %x\n", |
| 166 | ++ (parent_lnkcap & PCI_EXP_LNKCAP_ASPMS) >> 10, |
| 167 | ++ !!(parent_lnkctl & PCI_EXP_LNKCTL_ASPMC)); |
| 168 | ++dev_info(&parent->dev, "dn support %x enabled %x\n", |
| 169 | ++ (child_lnkcap & PCI_EXP_LNKCAP_ASPMS) >> 10, |
| 170 | ++ !!(child_lnkctl & PCI_EXP_LNKCTL_ASPMC)); |
| 171 | + |
| 172 | + /* |
| 173 | + * Setup L0s state |
| 174 | +diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c |
| 175 | +index 111111111111..222222222222 100644 |
| 176 | +--- a/drivers/pci/pcie/portdrv.c |
| 177 | ++++ b/drivers/pci/pcie/portdrv.c |
| 178 | +@@ -335,6 +335,7 @@ static int pcie_port_device_register(struct pci_dev *dev) |
| 179 | + |
| 180 | + /* Get and check PCI Express port services */ |
| 181 | + capabilities = get_port_device_capability(dev); |
| 182 | ++dev_info(&dev->dev, "PCIe capabilities: 0x%x\n", capabilities); |
| 183 | + if (!capabilities) |
| 184 | + return 0; |
| 185 | + |
| 186 | +@@ -347,6 +348,7 @@ static int pcie_port_device_register(struct pci_dev *dev) |
| 187 | + * if that is to be used. |
| 188 | + */ |
| 189 | + status = pcie_init_service_irqs(dev, irqs, capabilities); |
| 190 | ++dev_info(&dev->dev, "init_service_irqs: %d\n", status); |
| 191 | + if (status) { |
| 192 | + capabilities &= PCIE_PORT_SERVICE_HP; |
| 193 | + if (!capabilities) |
| 194 | +-- |
| 195 | +Armbian |
| 196 | + |
0 commit comments