1/*- 2 * Copyright (c) 2008 MARVELL INTERNATIONAL LTD. 3 * Copyright (c) 2010 The FreeBSD Foundation |
4 * Copyright (c) 2010-2012 Semihalf |
5 * All rights reserved. 6 * 7 * Developed by Semihalf. 8 * 9 * Portions of this software were developed by Semihalf 10 * under sponsorship from the FreeBSD Foundation. 11 * 12 * Redistribution and use in source and binary forms, with or without --- 21 unchanged lines hidden (view full) --- 34 * SUCH DAMAGE. 35 */ 36 37/* 38 * Marvell integrated PCI/PCI-Express controller driver. 39 */ 40 41#include <sys/cdefs.h> |
42__FBSDID("$FreeBSD: head/sys/arm/mv/mv_pci.c 240489 2012-09-14 09:57:41Z gber $"); |
43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/kernel.h> 47#include <sys/lock.h> 48#include <sys/malloc.h> 49#include <sys/module.h> 50#include <sys/mutex.h> --- 34 unchanged lines hidden (view full) --- 85 86#define PCIE_REG_CFG_ADDR 0x18F8 87#define PCIE_REG_CFG_DATA 0x18FC 88#define PCIE_REG_CONTROL 0x1A00 89#define PCIE_CTRL_LINK1X 0x00000001 90#define PCIE_REG_STATUS 0x1A04 91#define PCIE_REG_IRQ_MASK 0x1910 92 |
93#define PCIE_CONTROL_ROOT_CMPLX (1 << 1) 94#define PCIE_CONTROL_HOT_RESET (1 << 24) |
95 |
96#define PCIE_LINK_TIMEOUT 1000000 |
97 |
98#define PCIE_STATUS_LINK_DOWN 1 99#define PCIE_STATUS_DEV_OFFS 16 |
100 |
101/* Minimum PCI Memory and I/O allocations taken from PCI spec (in bytes) */ 102#define PCI_MIN_IO_ALLOC 4 103#define PCI_MIN_MEM_ALLOC 16 104 105#define BITS_PER_UINT32 (NBBY * sizeof(uint32_t)) 106 |
107struct mv_pcib_softc { 108 device_t sc_dev; 109 110 struct rman sc_mem_rman; 111 bus_addr_t sc_mem_base; 112 bus_addr_t sc_mem_size; |
113 uint32_t sc_mem_map[MV_PCI_MEM_SLICE_SIZE / 114 (PCI_MIN_MEM_ALLOC * BITS_PER_UINT32)]; 115 int sc_win_target; |
116 int sc_mem_win_attr; 117 118 struct rman sc_io_rman; 119 bus_addr_t sc_io_base; 120 bus_addr_t sc_io_size; |
121 uint32_t sc_io_map[MV_PCI_IO_SLICE_SIZE / 122 (PCI_MIN_IO_ALLOC * BITS_PER_UINT32)]; |
123 int sc_io_win_attr; 124 125 struct resource *sc_res; 126 bus_space_handle_t sc_bsh; 127 bus_space_tag_t sc_bst; 128 int sc_rid; 129 130 int sc_busnr; /* Host bridge bus number */ 131 int sc_devnr; /* Host bridge device number */ 132 int sc_type; |
133 int sc_mode; /* Endpoint / Root Complex */ |
134 135 struct fdt_pci_intr sc_intr_info; 136}; 137 138/* Local forward prototypes */ 139static int mv_pcib_decode_win(phandle_t, struct mv_pcib_softc *); 140static void mv_pcib_hw_cfginit(void); 141static uint32_t mv_pcib_hw_cfgread(struct mv_pcib_softc *, u_int, u_int, 142 u_int, u_int, int); 143static void mv_pcib_hw_cfgwrite(struct mv_pcib_softc *, u_int, u_int, 144 u_int, u_int, uint32_t, int); 145static int mv_pcib_init(struct mv_pcib_softc *, int, int); 146static int mv_pcib_init_all_bars(struct mv_pcib_softc *, int, int, int, int); 147static void mv_pcib_init_bridge(struct mv_pcib_softc *, int, int, int); 148static int mv_pcib_intr_info(phandle_t, struct mv_pcib_softc *); 149static inline void pcib_write_irq_mask(struct mv_pcib_softc *, uint32_t); |
150static void mv_pcib_enable(struct mv_pcib_softc *, uint32_t); 151static int mv_pcib_mem_init(struct mv_pcib_softc *); |
152 |
153/* Forward prototypes */ 154static int mv_pcib_probe(device_t); 155static int mv_pcib_attach(device_t); 156 157static struct resource *mv_pcib_alloc_resource(device_t, device_t, int, int *, 158 u_long, u_long, u_long, u_int); 159static int mv_pcib_release_resource(device_t, device_t, int, int, 160 struct resource *); --- 24 unchanged lines hidden (view full) --- 185 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 186 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 187 188 /* pcib interface */ 189 DEVMETHOD(pcib_maxslots, mv_pcib_maxslots), 190 DEVMETHOD(pcib_read_config, mv_pcib_read_config), 191 DEVMETHOD(pcib_write_config, mv_pcib_write_config), 192 DEVMETHOD(pcib_route_interrupt, mv_pcib_route_interrupt), |
193 |
194 /* OFW bus interface */ 195 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 196 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 197 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 198 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 199 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 200 201 DEVMETHOD_END --- 28 unchanged lines hidden (view full) --- 230 return (BUS_PROBE_DEFAULT); 231} 232 233static int 234mv_pcib_attach(device_t self) 235{ 236 struct mv_pcib_softc *sc; 237 phandle_t node, parnode; |
238 uint32_t val, unit; |
239 int err; 240 241 sc = device_get_softc(self); 242 sc->sc_dev = self; |
243 unit = fdt_get_unit(self); |
244 |
245 |
246 node = ofw_bus_get_node(self); 247 parnode = OF_parent(node); 248 if (fdt_is_compatible(node, "mrvl,pcie")) { 249 sc->sc_type = MV_TYPE_PCIE; |
250 sc->sc_win_target = MV_WIN_PCIE_TARGET(unit); 251 sc->sc_mem_win_attr = MV_WIN_PCIE_MEM_ATTR(unit); 252 sc->sc_io_win_attr = MV_WIN_PCIE_IO_ATTR(unit); |
253 } else if (fdt_is_compatible(node, "mrvl,pci")) { 254 sc->sc_type = MV_TYPE_PCI; |
255 sc->sc_win_target = MV_WIN_PCI_TARGET; |
256 sc->sc_mem_win_attr = MV_WIN_PCI_MEM_ATTR; |
257 sc->sc_io_win_attr = MV_WIN_PCI_IO_ATTR; |
258 } else 259 return (ENXIO); 260 261 /* |
262 * Retrieve our mem-mapped registers range. 263 */ 264 sc->sc_rid = 0; 265 sc->sc_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &sc->sc_rid, 266 RF_ACTIVE); 267 if (sc->sc_res == NULL) { 268 device_printf(self, "could not map memory\n"); 269 return (ENXIO); 270 } 271 sc->sc_bst = rman_get_bustag(sc->sc_res); 272 sc->sc_bsh = rman_get_bushandle(sc->sc_res); 273 |
274 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_CONTROL); 275 sc->sc_mode = (val & PCIE_CONTROL_ROOT_CMPLX ? MV_MODE_ROOT : 276 MV_MODE_ENDPOINT); 277 |
278 /* |
279 * Get PCI interrupt info. 280 */ 281 if ((sc->sc_mode == MV_MODE_ROOT) && 282 (mv_pcib_intr_info(node, sc) != 0)) { 283 device_printf(self, "could not retrieve interrupt info\n"); 284 return (ENXIO); 285 } 286 287 /* |
288 * Configure decode windows for PCI(E) access. 289 */ 290 if (mv_pcib_decode_win(node, sc) != 0) 291 return (ENXIO); 292 293 mv_pcib_hw_cfginit(); 294 295 /* |
296 * Enable PCIE device. |
297 */ |
298 mv_pcib_enable(sc, unit); |
299 |
300 /* 301 * Memory management. 302 */ 303 err = mv_pcib_mem_init(sc); 304 if (err) 305 return (err); |
306 |
307 if (sc->sc_mode == MV_MODE_ROOT) { 308 err = mv_pcib_init(sc, sc->sc_busnr, 309 mv_pcib_maxslots(sc->sc_dev)); 310 if (err) 311 goto error; 312 313 device_add_child(self, "pci", -1); 314 } else { 315 sc->sc_devnr = 1; 316 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 317 PCIE_REG_STATUS, 1 << PCIE_STATUS_DEV_OFFS); 318 device_add_child(self, "pci_ep", -1); 319 } 320 321 return (bus_generic_attach(self)); 322 323error: 324 /* XXX SYS_RES_ should be released here */ 325 rman_fini(&sc->sc_mem_rman); 326 rman_fini(&sc->sc_io_rman); 327 328 return (err); 329} 330 331static void 332mv_pcib_enable(struct mv_pcib_softc *sc, uint32_t unit) 333{ 334 uint32_t val; 335#if !defined(SOC_MV_ARMADAXP) 336 int timeout; 337 338 /* 339 * Check if PCIE device is enabled. 340 */ 341 if (read_cpu_ctrl(CPU_CONTROL) & CPU_CONTROL_PCIE_DISABLE(unit)) { 342 write_cpu_ctrl(CPU_CONTROL, read_cpu_ctrl(CPU_CONTROL) & 343 ~(CPU_CONTROL_PCIE_DISABLE(unit))); 344 345 timeout = PCIE_LINK_TIMEOUT; 346 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 347 PCIE_REG_STATUS); 348 while (((val & PCIE_STATUS_LINK_DOWN) == 1) && (timeout > 0)) { 349 DELAY(1000); 350 timeout -= 1000; 351 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 352 PCIE_REG_STATUS); 353 } 354 } 355#endif 356 357 358 if (sc->sc_mode == MV_MODE_ROOT) { 359 /* 360 * Enable PCI bridge. 361 */ 362 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIR_COMMAND); 363 val |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | 364 PCIM_CMD_MEMEN | PCIM_CMD_PORTEN; 365 bus_space_write_4(sc->sc_bst, sc->sc_bsh, PCIR_COMMAND, val); 366 } 367} 368 369static int 370mv_pcib_mem_init(struct mv_pcib_softc *sc) 371{ 372 int err; 373 374 /* 375 * Memory management. 376 */ |
377 sc->sc_mem_rman.rm_type = RMAN_ARRAY; 378 err = rman_init(&sc->sc_mem_rman); 379 if (err) 380 return (err); 381 382 sc->sc_io_rman.rm_type = RMAN_ARRAY; 383 err = rman_init(&sc->sc_io_rman); 384 if (err) { --- 6 unchanged lines hidden (view full) --- 391 if (err) 392 goto error; 393 394 err = rman_manage_region(&sc->sc_io_rman, sc->sc_io_base, 395 sc->sc_io_base + sc->sc_io_size - 1); 396 if (err) 397 goto error; 398 |
399 return (0); |
400 |
401error: |
402 rman_fini(&sc->sc_mem_rman); 403 rman_fini(&sc->sc_io_rman); |
404 |
405 return (err); 406} 407 |
408static inline uint32_t 409pcib_bit_get(uint32_t *map, uint32_t bit) 410{ 411 uint32_t n = bit / BITS_PER_UINT32; 412 413 bit = bit % BITS_PER_UINT32; 414 return (map[n] & (1 << bit)); 415} 416 417static inline void 418pcib_bit_set(uint32_t *map, uint32_t bit) 419{ 420 uint32_t n = bit / BITS_PER_UINT32; 421 422 bit = bit % BITS_PER_UINT32; 423 map[n] |= (1 << bit); 424} 425 426static inline uint32_t 427pcib_map_check(uint32_t *map, uint32_t start, uint32_t bits) 428{ 429 uint32_t i; 430 431 for (i = start; i < start + bits; i++) 432 if (pcib_bit_get(map, i)) 433 return (0); 434 435 return (1); 436} 437 438static inline void 439pcib_map_set(uint32_t *map, uint32_t start, uint32_t bits) 440{ 441 uint32_t i; 442 443 for (i = start; i < start + bits; i++) 444 pcib_bit_set(map, i); 445} 446 447/* 448 * The idea of this allocator is taken from ARM No-Cache memory 449 * management code (sys/arm/arm/vm_machdep.c). 450 */ 451static bus_addr_t 452pcib_alloc(struct mv_pcib_softc *sc, uint32_t smask) 453{ 454 uint32_t bits, bits_limit, i, *map, min_alloc, size; 455 bus_addr_t addr = 0; 456 bus_addr_t base; 457 458 if (smask & 1) { 459 base = sc->sc_io_base; 460 min_alloc = PCI_MIN_IO_ALLOC; 461 bits_limit = sc->sc_io_size / min_alloc; 462 map = sc->sc_io_map; 463 smask &= ~0x3; 464 } else { 465 base = sc->sc_mem_base; 466 min_alloc = PCI_MIN_MEM_ALLOC; 467 bits_limit = sc->sc_mem_size / min_alloc; 468 map = sc->sc_mem_map; 469 smask &= ~0xF; 470 } 471 472 size = ~smask + 1; 473 bits = size / min_alloc; 474 475 for (i = 0; i + bits <= bits_limit; i += bits) 476 if (pcib_map_check(map, i, bits)) { 477 pcib_map_set(map, i, bits); 478 addr = base + (i * min_alloc); 479 return (addr); 480 } 481 482 return (addr); 483} 484 |
485static int 486mv_pcib_init_bar(struct mv_pcib_softc *sc, int bus, int slot, int func, 487 int barno) 488{ |
489 uint32_t addr, bar; |
490 int reg, width; 491 492 reg = PCIR_BAR(barno); |
493 494 /* 495 * Need to init the BAR register with 0xffffffff before correct 496 * value can be read. 497 */ 498 mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4); |
499 bar = mv_pcib_read_config(sc->sc_dev, bus, slot, func, reg, 4); 500 if (bar == 0) 501 return (1); 502 503 /* Calculate BAR size: 64 or 32 bit (in 32-bit units) */ 504 width = ((bar & 7) == 4) ? 2 : 1; 505 |
506 addr = pcib_alloc(sc, bar); 507 if (!addr) |
508 return (-1); 509 510 if (bootverbose) |
511 printf("PCI %u:%u:%u: reg %x: smask=%08x: addr=%08x\n", 512 bus, slot, func, reg, bar, addr); |
513 514 mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4); 515 if (width == 2) 516 mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg + 4, 517 0, 4); 518 519 return (width); 520} --- 132 unchanged lines hidden (view full) --- 653 switch (type) { 654 case SYS_RES_IOPORT: 655 rm = &sc->sc_io_rman; 656 break; 657 case SYS_RES_MEMORY: 658 rm = &sc->sc_mem_rman; 659 break; 660 default: |
661 return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, |
662 type, rid, start, end, count, flags)); 663 }; 664 |
665 if ((start == 0UL) && (end == ~0UL)) { 666 start = sc->sc_mem_base; 667 end = sc->sc_mem_base + sc->sc_mem_size - 1; 668 count = sc->sc_mem_size; 669 } 670 671 if ((start < sc->sc_mem_base) || (start + count - 1 != end) || 672 (end > sc->sc_mem_base + sc->sc_mem_size - 1)) 673 return (NULL); 674 |
675 res = rman_reserve_resource(rm, start, end, count, flags, child); 676 if (res == NULL) 677 return (NULL); 678 679 rman_set_rid(res, *rid); 680 rman_set_bustag(res, fdtbus_bs_tag); 681 rman_set_bushandle(res, start); 682 --- 148 unchanged lines hidden (view full) --- 831} 832 833static uint32_t 834mv_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, 835 u_int reg, int bytes) 836{ 837 struct mv_pcib_softc *sc = device_get_softc(dev); 838 |
839 /* Return ~0 if link is inactive or trying to read from Root */ 840 if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_STATUS) & 841 PCIE_STATUS_LINK_DOWN) || (slot == 0)) |
842 return (~0U); 843 844 return (mv_pcib_hw_cfgread(sc, bus, slot, func, reg, bytes)); 845} 846 847static void 848mv_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, 849 u_int reg, uint32_t val, int bytes) 850{ 851 struct mv_pcib_softc *sc = device_get_softc(dev); 852 |
853 /* Return if link is inactive or trying to write to Root */ 854 if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_STATUS) & 855 PCIE_STATUS_LINK_DOWN) || (slot == 0)) |
856 return; 857 858 mv_pcib_hw_cfgwrite(sc, bus, slot, func, reg, val, bytes); 859} 860 861static int 862mv_pcib_route_interrupt(device_t pcib, device_t dev, int pin) 863{ --- 22 unchanged lines hidden (view full) --- 886 dev = sc->sc_dev; 887 888 if ((error = fdt_pci_ranges(node, &io_space, &mem_space)) != 0) { 889 device_printf(dev, "could not retrieve 'ranges' data\n"); 890 return (error); 891 } 892 893 /* Configure CPU decoding windows */ |
894 error = decode_win_cpu_set(sc->sc_win_target, 895 sc->sc_io_win_attr, io_space.base_parent, io_space.len, ~0); |
896 if (error < 0) { 897 device_printf(dev, "could not set up CPU decode " 898 "window for PCI IO\n"); 899 return (ENXIO); 900 } |
901 error = decode_win_cpu_set(sc->sc_win_target, 902 sc->sc_mem_win_attr, mem_space.base_parent, mem_space.len, 903 mem_space.base_parent); |
904 if (error < 0) { 905 device_printf(dev, "could not set up CPU decode " 906 "windows for PCI MEM\n"); 907 return (ENXIO); 908 } 909 910 sc->sc_io_base = io_space.base_parent; 911 sc->sc_io_size = io_space.len; --- 10 unchanged lines hidden (view full) --- 922 int error; 923 924 if ((error = fdt_pci_intr_info(node, &sc->sc_intr_info)) != 0) 925 return (error); 926 927 return (0); 928} 929 |