Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.4-rc5 409 lines 11 kB view raw
1/* 2 * Copyright (C) 2014 Hauke Mehrtens <hauke@hauke-m.de> 3 * Copyright (C) 2015 Broadcom Corporation 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation version 2. 8 * 9 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 10 * kind, whether express or implied; without even the implied warranty 11 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15#include <linux/kernel.h> 16#include <linux/pci.h> 17#include <linux/msi.h> 18#include <linux/clk.h> 19#include <linux/module.h> 20#include <linux/mbus.h> 21#include <linux/slab.h> 22#include <linux/delay.h> 23#include <linux/interrupt.h> 24#include <linux/platform_device.h> 25#include <linux/of_address.h> 26#include <linux/of_pci.h> 27#include <linux/of_irq.h> 28#include <linux/of_platform.h> 29#include <linux/phy/phy.h> 30 31#include "pcie-iproc.h" 32 33#define CLK_CONTROL_OFFSET 0x000 34#define EP_PERST_SOURCE_SELECT_SHIFT 2 35#define EP_PERST_SOURCE_SELECT BIT(EP_PERST_SOURCE_SELECT_SHIFT) 36#define EP_MODE_SURVIVE_PERST_SHIFT 1 37#define EP_MODE_SURVIVE_PERST BIT(EP_MODE_SURVIVE_PERST_SHIFT) 38#define RC_PCIE_RST_OUTPUT_SHIFT 0 39#define RC_PCIE_RST_OUTPUT BIT(RC_PCIE_RST_OUTPUT_SHIFT) 40 41#define CFG_IND_ADDR_OFFSET 0x120 42#define CFG_IND_ADDR_MASK 0x00001ffc 43 44#define CFG_IND_DATA_OFFSET 0x124 45 46#define CFG_ADDR_OFFSET 0x1f8 47#define CFG_ADDR_BUS_NUM_SHIFT 20 48#define CFG_ADDR_BUS_NUM_MASK 0x0ff00000 49#define CFG_ADDR_DEV_NUM_SHIFT 15 50#define CFG_ADDR_DEV_NUM_MASK 0x000f8000 51#define CFG_ADDR_FUNC_NUM_SHIFT 12 52#define CFG_ADDR_FUNC_NUM_MASK 0x00007000 53#define CFG_ADDR_REG_NUM_SHIFT 2 54#define CFG_ADDR_REG_NUM_MASK 0x00000ffc 55#define CFG_ADDR_CFG_TYPE_SHIFT 0 56#define CFG_ADDR_CFG_TYPE_MASK 0x00000003 57 58#define CFG_DATA_OFFSET 0x1fc 59 60#define SYS_RC_INTX_EN 0x330 61#define SYS_RC_INTX_MASK 0xf 62 63#define PCIE_LINK_STATUS_OFFSET 0xf0c 64#define PCIE_PHYLINKUP_SHIFT 3 65#define PCIE_PHYLINKUP BIT(PCIE_PHYLINKUP_SHIFT) 66#define PCIE_DL_ACTIVE_SHIFT 2 67#define PCIE_DL_ACTIVE BIT(PCIE_DL_ACTIVE_SHIFT) 68 69#define OARR_VALID_SHIFT 0 70#define OARR_VALID BIT(OARR_VALID_SHIFT) 71#define OARR_SIZE_CFG_SHIFT 1 72#define OARR_SIZE_CFG BIT(OARR_SIZE_CFG_SHIFT) 73 74#define OARR_LO(window) (0xd20 + (window) * 8) 75#define OARR_HI(window) (0xd24 + (window) * 8) 76#define OMAP_LO(window) (0xd40 + (window) * 8) 77#define OMAP_HI(window) (0xd44 + (window) * 8) 78 79#define MAX_NUM_OB_WINDOWS 2 80 81static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) 82{ 83 struct iproc_pcie *pcie; 84#ifdef CONFIG_ARM 85 struct pci_sys_data *sys = bus->sysdata; 86 87 pcie = sys->private_data; 88#else 89 pcie = bus->sysdata; 90#endif 91 return pcie; 92} 93 94/** 95 * Note access to the configuration registers are protected at the higher layer 96 * by 'pci_lock' in drivers/pci/access.c 97 */ 98static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus, 99 unsigned int devfn, 100 int where) 101{ 102 struct iproc_pcie *pcie = iproc_data(bus); 103 unsigned slot = PCI_SLOT(devfn); 104 unsigned fn = PCI_FUNC(devfn); 105 unsigned busno = bus->number; 106 u32 val; 107 108 /* root complex access */ 109 if (busno == 0) { 110 if (slot >= 1) 111 return NULL; 112 writel(where & CFG_IND_ADDR_MASK, 113 pcie->base + CFG_IND_ADDR_OFFSET); 114 return (pcie->base + CFG_IND_DATA_OFFSET); 115 } 116 117 if (fn > 1) 118 return NULL; 119 120 /* EP device access */ 121 val = (busno << CFG_ADDR_BUS_NUM_SHIFT) | 122 (slot << CFG_ADDR_DEV_NUM_SHIFT) | 123 (fn << CFG_ADDR_FUNC_NUM_SHIFT) | 124 (where & CFG_ADDR_REG_NUM_MASK) | 125 (1 & CFG_ADDR_CFG_TYPE_MASK); 126 writel(val, pcie->base + CFG_ADDR_OFFSET); 127 128 return (pcie->base + CFG_DATA_OFFSET); 129} 130 131static struct pci_ops iproc_pcie_ops = { 132 .map_bus = iproc_pcie_map_cfg_bus, 133 .read = pci_generic_config_read32, 134 .write = pci_generic_config_write32, 135}; 136 137static void iproc_pcie_reset(struct iproc_pcie *pcie) 138{ 139 u32 val; 140 141 /* 142 * Select perst_b signal as reset source. Put the device into reset, 143 * and then bring it out of reset 144 */ 145 val = readl(pcie->base + CLK_CONTROL_OFFSET); 146 val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST & 147 ~RC_PCIE_RST_OUTPUT; 148 writel(val, pcie->base + CLK_CONTROL_OFFSET); 149 udelay(250); 150 151 val |= RC_PCIE_RST_OUTPUT; 152 writel(val, pcie->base + CLK_CONTROL_OFFSET); 153 msleep(100); 154} 155 156static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) 157{ 158 u8 hdr_type; 159 u32 link_ctrl, class, val; 160 u16 pos, link_status; 161 bool link_is_active = false; 162 163 val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET); 164 if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) { 165 dev_err(pcie->dev, "PHY or data link is INACTIVE!\n"); 166 return -ENODEV; 167 } 168 169 /* make sure we are not in EP mode */ 170 pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type); 171 if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) { 172 dev_err(pcie->dev, "in EP mode, hdr=%#02x\n", hdr_type); 173 return -EFAULT; 174 } 175 176 /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */ 177#define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c 178#define PCI_CLASS_BRIDGE_MASK 0xffff00 179#define PCI_CLASS_BRIDGE_SHIFT 8 180 pci_bus_read_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, &class); 181 class &= ~PCI_CLASS_BRIDGE_MASK; 182 class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT); 183 pci_bus_write_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, class); 184 185 /* check link status to see if link is active */ 186 pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP); 187 pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status); 188 if (link_status & PCI_EXP_LNKSTA_NLW) 189 link_is_active = true; 190 191 if (!link_is_active) { 192 /* try GEN 1 link speed */ 193#define PCI_LINK_STATUS_CTRL_2_OFFSET 0x0dc 194#define PCI_TARGET_LINK_SPEED_MASK 0xf 195#define PCI_TARGET_LINK_SPEED_GEN2 0x2 196#define PCI_TARGET_LINK_SPEED_GEN1 0x1 197 pci_bus_read_config_dword(bus, 0, 198 PCI_LINK_STATUS_CTRL_2_OFFSET, 199 &link_ctrl); 200 if ((link_ctrl & PCI_TARGET_LINK_SPEED_MASK) == 201 PCI_TARGET_LINK_SPEED_GEN2) { 202 link_ctrl &= ~PCI_TARGET_LINK_SPEED_MASK; 203 link_ctrl |= PCI_TARGET_LINK_SPEED_GEN1; 204 pci_bus_write_config_dword(bus, 0, 205 PCI_LINK_STATUS_CTRL_2_OFFSET, 206 link_ctrl); 207 msleep(100); 208 209 pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP); 210 pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, 211 &link_status); 212 if (link_status & PCI_EXP_LNKSTA_NLW) 213 link_is_active = true; 214 } 215 } 216 217 dev_info(pcie->dev, "link: %s\n", link_is_active ? "UP" : "DOWN"); 218 219 return link_is_active ? 0 : -ENODEV; 220} 221 222static void iproc_pcie_enable(struct iproc_pcie *pcie) 223{ 224 writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN); 225} 226 227/** 228 * Some iProc SoCs require the SW to configure the outbound address mapping 229 * 230 * Outbound address translation: 231 * 232 * iproc_pcie_address = axi_address - axi_offset 233 * OARR = iproc_pcie_address 234 * OMAP = pci_addr 235 * 236 * axi_addr -> iproc_pcie_address -> OARR -> OMAP -> pci_address 237 */ 238static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr, 239 u64 pci_addr, resource_size_t size) 240{ 241 struct iproc_pcie_ob *ob = &pcie->ob; 242 unsigned i; 243 u64 max_size = (u64)ob->window_size * MAX_NUM_OB_WINDOWS; 244 u64 remainder; 245 246 if (size > max_size) { 247 dev_err(pcie->dev, 248 "res size 0x%pap exceeds max supported size 0x%llx\n", 249 &size, max_size); 250 return -EINVAL; 251 } 252 253 div64_u64_rem(size, ob->window_size, &remainder); 254 if (remainder) { 255 dev_err(pcie->dev, 256 "res size %pap needs to be multiple of window size %pap\n", 257 &size, &ob->window_size); 258 return -EINVAL; 259 } 260 261 if (axi_addr < ob->axi_offset) { 262 dev_err(pcie->dev, 263 "axi address %pap less than offset %pap\n", 264 &axi_addr, &ob->axi_offset); 265 return -EINVAL; 266 } 267 268 /* 269 * Translate the AXI address to the internal address used by the iProc 270 * PCIe core before programming the OARR 271 */ 272 axi_addr -= ob->axi_offset; 273 274 for (i = 0; i < MAX_NUM_OB_WINDOWS; i++) { 275 writel(lower_32_bits(axi_addr) | OARR_VALID | 276 (ob->set_oarr_size ? 1 : 0), pcie->base + OARR_LO(i)); 277 writel(upper_32_bits(axi_addr), pcie->base + OARR_HI(i)); 278 writel(lower_32_bits(pci_addr), pcie->base + OMAP_LO(i)); 279 writel(upper_32_bits(pci_addr), pcie->base + OMAP_HI(i)); 280 281 size -= ob->window_size; 282 if (size == 0) 283 break; 284 285 axi_addr += ob->window_size; 286 pci_addr += ob->window_size; 287 } 288 289 return 0; 290} 291 292static int iproc_pcie_map_ranges(struct iproc_pcie *pcie, 293 struct list_head *resources) 294{ 295 struct resource_entry *window; 296 int ret; 297 298 resource_list_for_each_entry(window, resources) { 299 struct resource *res = window->res; 300 u64 res_type = resource_type(res); 301 302 switch (res_type) { 303 case IORESOURCE_IO: 304 case IORESOURCE_BUS: 305 break; 306 case IORESOURCE_MEM: 307 ret = iproc_pcie_setup_ob(pcie, res->start, 308 res->start - window->offset, 309 resource_size(res)); 310 if (ret) 311 return ret; 312 break; 313 default: 314 dev_err(pcie->dev, "invalid resource %pR\n", res); 315 return -EINVAL; 316 } 317 } 318 319 return 0; 320} 321 322int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) 323{ 324 int ret; 325 void *sysdata; 326 struct pci_bus *bus; 327 328 if (!pcie || !pcie->dev || !pcie->base) 329 return -EINVAL; 330 331 ret = phy_init(pcie->phy); 332 if (ret) { 333 dev_err(pcie->dev, "unable to initialize PCIe PHY\n"); 334 return ret; 335 } 336 337 ret = phy_power_on(pcie->phy); 338 if (ret) { 339 dev_err(pcie->dev, "unable to power on PCIe PHY\n"); 340 goto err_exit_phy; 341 } 342 343 iproc_pcie_reset(pcie); 344 345 if (pcie->need_ob_cfg) { 346 ret = iproc_pcie_map_ranges(pcie, res); 347 if (ret) { 348 dev_err(pcie->dev, "map failed\n"); 349 goto err_power_off_phy; 350 } 351 } 352 353#ifdef CONFIG_ARM 354 pcie->sysdata.private_data = pcie; 355 sysdata = &pcie->sysdata; 356#else 357 sysdata = pcie; 358#endif 359 360 bus = pci_create_root_bus(pcie->dev, 0, &iproc_pcie_ops, sysdata, res); 361 if (!bus) { 362 dev_err(pcie->dev, "unable to create PCI root bus\n"); 363 ret = -ENOMEM; 364 goto err_power_off_phy; 365 } 366 pcie->root_bus = bus; 367 368 ret = iproc_pcie_check_link(pcie, bus); 369 if (ret) { 370 dev_err(pcie->dev, "no PCIe EP device detected\n"); 371 goto err_rm_root_bus; 372 } 373 374 iproc_pcie_enable(pcie); 375 376 pci_scan_child_bus(bus); 377 pci_assign_unassigned_bus_resources(bus); 378 pci_fixup_irqs(pci_common_swizzle, pcie->map_irq); 379 pci_bus_add_devices(bus); 380 381 return 0; 382 383err_rm_root_bus: 384 pci_stop_root_bus(bus); 385 pci_remove_root_bus(bus); 386 387err_power_off_phy: 388 phy_power_off(pcie->phy); 389err_exit_phy: 390 phy_exit(pcie->phy); 391 return ret; 392} 393EXPORT_SYMBOL(iproc_pcie_setup); 394 395int iproc_pcie_remove(struct iproc_pcie *pcie) 396{ 397 pci_stop_root_bus(pcie->root_bus); 398 pci_remove_root_bus(pcie->root_bus); 399 400 phy_power_off(pcie->phy); 401 phy_exit(pcie->phy); 402 403 return 0; 404} 405EXPORT_SYMBOL(iproc_pcie_remove); 406 407MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>"); 408MODULE_DESCRIPTION("Broadcom iPROC PCIe common driver"); 409MODULE_LICENSE("GPL v2");