1 /* 2 * arch/arm/plat-orion/pcie.c 3 * 4 * Marvell Orion SoC PCIe handling. 5 * 6 * This file is licensed under the terms of the GNU General Public 7 * License version 2. This program is licensed "as is" without any 8 * warranty of any kind, whether express or implied. 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/pci.h> 13 #include <linux/mbus.h> 14 #include <asm/mach/pci.h> 15 #include <plat/pcie.h> 16 17 /* 18 * PCIe unit register offsets. 19 */ 20 #define PCIE_DEV_ID_OFF 0x0000 21 #define PCIE_CMD_OFF 0x0004 22 #define PCIE_DEV_REV_OFF 0x0008 23 #define PCIE_BAR_LO_OFF(n) (0x0010 + ((n) << 3)) 24 #define PCIE_BAR_HI_OFF(n) (0x0014 + ((n) << 3)) 25 #define PCIE_HEADER_LOG_4_OFF 0x0128 26 #define PCIE_BAR_CTRL_OFF(n) (0x1804 + ((n - 1) * 4)) 27 #define PCIE_WIN04_CTRL_OFF(n) (0x1820 + ((n) << 4)) 28 #define PCIE_WIN04_BASE_OFF(n) (0x1824 + ((n) << 4)) 29 #define PCIE_WIN04_REMAP_OFF(n) (0x182c + ((n) << 4)) 30 #define PCIE_WIN5_CTRL_OFF 0x1880 31 #define PCIE_WIN5_BASE_OFF 0x1884 32 #define PCIE_WIN5_REMAP_OFF 0x188c 33 #define PCIE_CONF_ADDR_OFF 0x18f8 34 #define PCIE_CONF_ADDR_EN 0x80000000 35 #define PCIE_CONF_REG(r) ((((r) & 0xf00) << 16) | ((r) & 0xfc)) 36 #define PCIE_CONF_BUS(b) (((b) & 0xff) << 16) 37 #define PCIE_CONF_DEV(d) (((d) & 0x1f) << 11) 38 #define PCIE_CONF_FUNC(f) (((f) & 0x7) << 8) 39 #define PCIE_CONF_DATA_OFF 0x18fc 40 #define PCIE_MASK_OFF 0x1910 41 #define PCIE_CTRL_OFF 0x1a00 42 #define PCIE_CTRL_X1_MODE 0x0001 43 #define PCIE_STAT_OFF 0x1a04 44 #define PCIE_STAT_DEV_OFFS 20 45 #define PCIE_STAT_DEV_MASK 0x1f 46 #define PCIE_STAT_BUS_OFFS 8 47 #define PCIE_STAT_BUS_MASK 0xff 48 #define PCIE_STAT_LINK_DOWN 1 49 50 51 u32 __init orion_pcie_dev_id(void __iomem *base) 52 { 53 return readl(base + PCIE_DEV_ID_OFF) >> 16; 54 } 55 56 u32 __init orion_pcie_rev(void __iomem *base) 57 { 58 return readl(base + PCIE_DEV_REV_OFF) & 0xff; 59 } 60 61 int orion_pcie_link_up(void __iomem *base) 62 { 63 return !(readl(base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); 64 } 65 66 int __init orion_pcie_x4_mode(void __iomem *base) 67 { 68 return !(readl(base + PCIE_CTRL_OFF) & PCIE_CTRL_X1_MODE); 69 } 70 71 int orion_pcie_get_local_bus_nr(void __iomem *base) 72 { 73 u32 stat = readl(base + PCIE_STAT_OFF); 74 75 return (stat >> PCIE_STAT_BUS_OFFS) & PCIE_STAT_BUS_MASK; 76 } 77 78 void __init orion_pcie_set_local_bus_nr(void __iomem *base, int nr) 79 { 80 u32 stat; 81 82 stat = readl(base + PCIE_STAT_OFF); 83 stat &= ~(PCIE_STAT_BUS_MASK << PCIE_STAT_BUS_OFFS); 84 stat |= nr << PCIE_STAT_BUS_OFFS; 85 writel(stat, base + PCIE_STAT_OFF); 86 } 87 88 /* 89 * Setup PCIE BARs and Address Decode Wins: 90 * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks 91 * WIN[0-3] -> DRAM bank[0-3] 92 */ 93 static void __init orion_pcie_setup_wins(void __iomem *base, 94 struct mbus_dram_target_info *dram) 95 { 96 u32 size; 97 int i; 98 99 /* 100 * First, disable and clear BARs and windows. 101 */ 102 for (i = 1; i <= 2; i++) { 103 writel(0, base + PCIE_BAR_CTRL_OFF(i)); 104 writel(0, base + PCIE_BAR_LO_OFF(i)); 105 writel(0, base + PCIE_BAR_HI_OFF(i)); 106 } 107 108 for (i = 0; i < 5; i++) { 109 writel(0, base + PCIE_WIN04_CTRL_OFF(i)); 110 writel(0, base + PCIE_WIN04_BASE_OFF(i)); 111 writel(0, base + PCIE_WIN04_REMAP_OFF(i)); 112 } 113 114 writel(0, base + PCIE_WIN5_CTRL_OFF); 115 writel(0, base + PCIE_WIN5_BASE_OFF); 116 writel(0, base + PCIE_WIN5_REMAP_OFF); 117 118 /* 119 * Setup windows for DDR banks. Count total DDR size on the fly. 120 */ 121 size = 0; 122 for (i = 0; i < dram->num_cs; i++) { 123 struct mbus_dram_window *cs = dram->cs + i; 124 125 writel(cs->base & 0xffff0000, base + PCIE_WIN04_BASE_OFF(i)); 126 writel(0, base + PCIE_WIN04_REMAP_OFF(i)); 127 writel(((cs->size - 1) & 0xffff0000) | 128 (cs->mbus_attr << 8) | 129 (dram->mbus_dram_target_id << 4) | 1, 130 base + PCIE_WIN04_CTRL_OFF(i)); 131 132 size += cs->size; 133 } 134 135 /* 136 * Round up 'size' to the nearest power of two. 137 */ 138 if ((size & (size - 1)) != 0) 139 size = 1 << fls(size); 140 141 /* 142 * Setup BAR[1] to all DRAM banks. 143 */ 144 writel(dram->cs[0].base, base + PCIE_BAR_LO_OFF(1)); 145 writel(0, base + PCIE_BAR_HI_OFF(1)); 146 writel(((size - 1) & 0xffff0000) | 1, base + PCIE_BAR_CTRL_OFF(1)); 147 } 148 149 void __init orion_pcie_setup(void __iomem *base, 150 struct mbus_dram_target_info *dram) 151 { 152 u16 cmd; 153 u32 mask; 154 155 /* 156 * Point PCIe unit MBUS decode windows to DRAM space. 157 */ 158 orion_pcie_setup_wins(base, dram); 159 160 /* 161 * Master + slave enable. 162 */ 163 cmd = readw(base + PCIE_CMD_OFF); 164 cmd |= PCI_COMMAND_IO; 165 cmd |= PCI_COMMAND_MEMORY; 166 cmd |= PCI_COMMAND_MASTER; 167 writew(cmd, base + PCIE_CMD_OFF); 168 169 /* 170 * Enable interrupt lines A-D. 171 */ 172 mask = readl(base + PCIE_MASK_OFF); 173 mask |= 0x0f000000; 174 writel(mask, base + PCIE_MASK_OFF); 175 } 176 177 int orion_pcie_rd_conf(void __iomem *base, struct pci_bus *bus, 178 u32 devfn, int where, int size, u32 *val) 179 { 180 writel(PCIE_CONF_BUS(bus->number) | 181 PCIE_CONF_DEV(PCI_SLOT(devfn)) | 182 PCIE_CONF_FUNC(PCI_FUNC(devfn)) | 183 PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN, 184 base + PCIE_CONF_ADDR_OFF); 185 186 *val = readl(base + PCIE_CONF_DATA_OFF); 187 188 if (size == 1) 189 *val = (*val >> (8 * (where & 3))) & 0xff; 190 else if (size == 2) 191 *val = (*val >> (8 * (where & 3))) & 0xffff; 192 193 return PCIBIOS_SUCCESSFUL; 194 } 195 196 int orion_pcie_rd_conf_tlp(void __iomem *base, struct pci_bus *bus, 197 u32 devfn, int where, int size, u32 *val) 198 { 199 writel(PCIE_CONF_BUS(bus->number) | 200 PCIE_CONF_DEV(PCI_SLOT(devfn)) | 201 PCIE_CONF_FUNC(PCI_FUNC(devfn)) | 202 PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN, 203 base + PCIE_CONF_ADDR_OFF); 204 205 *val = readl(base + PCIE_CONF_DATA_OFF); 206 207 if (bus->number != orion_pcie_get_local_bus_nr(base) || 208 PCI_FUNC(devfn) != 0) 209 *val = readl(base + PCIE_HEADER_LOG_4_OFF); 210 211 if (size == 1) 212 *val = (*val >> (8 * (where & 3))) & 0xff; 213 else if (size == 2) 214 *val = (*val >> (8 * (where & 3))) & 0xffff; 215 216 return PCIBIOS_SUCCESSFUL; 217 } 218 219 int orion_pcie_rd_conf_wa(void __iomem *wa_base, struct pci_bus *bus, 220 u32 devfn, int where, int size, u32 *val) 221 { 222 *val = readl(wa_base + (PCIE_CONF_BUS(bus->number) | 223 PCIE_CONF_DEV(PCI_SLOT(devfn)) | 224 PCIE_CONF_FUNC(PCI_FUNC(devfn)) | 225 PCIE_CONF_REG(where))); 226 227 if (size == 1) 228 *val = (*val >> (8 * (where & 3))) & 0xff; 229 else if (size == 2) 230 *val = (*val >> (8 * (where & 3))) & 0xffff; 231 232 return PCIBIOS_SUCCESSFUL; 233 } 234 235 int orion_pcie_wr_conf(void __iomem *base, struct pci_bus *bus, 236 u32 devfn, int where, int size, u32 val) 237 { 238 int ret = PCIBIOS_SUCCESSFUL; 239 240 writel(PCIE_CONF_BUS(bus->number) | 241 PCIE_CONF_DEV(PCI_SLOT(devfn)) | 242 PCIE_CONF_FUNC(PCI_FUNC(devfn)) | 243 PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN, 244 base + PCIE_CONF_ADDR_OFF); 245 246 if (size == 4) { 247 writel(val, base + PCIE_CONF_DATA_OFF); 248 } else if (size == 2) { 249 writew(val, base + PCIE_CONF_DATA_OFF + (where & 3)); 250 } else if (size == 1) { 251 writeb(val, base + PCIE_CONF_DATA_OFF + (where & 3)); 252 } else { 253 ret = PCIBIOS_BAD_REGISTER_NUMBER; 254 } 255 256 return ret; 257 } 258