1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /* SPARC specific code used by the pcieb driver */
  27 
  28 #include <sys/types.h>
  29 #include <sys/ddi.h>
  30 #include <sys/kmem.h>
  31 #include <sys/sysmacros.h>
  32 #include <sys/sunddi.h>
  33 #include <sys/sunndi.h>
  34 #include <sys/pcie.h>
  35 #include <sys/pci_cap.h>
  36 #include <sys/pcie_impl.h>
  37 #include <io/pciex/pcieb.h>
  38 #include "pcieb_plx.h"
  39 
  40 /*LINTLIBRARY*/
  41 
  42 /* PLX specific functions */
  43 #ifdef  PX_PLX
  44 static void plx_ro_disable(pcieb_devstate_t *pcieb);
  45 #ifdef  PRINT_PLX_SEEPROM_CRC
  46 static void pcieb_print_plx_seeprom_crc_data(pcieb_devstate_t *pcieb_p);
  47 #endif /* PRINT_PLX_SEEPROM_CRC */
  48 #endif /* PX_PLX */
  49 
  50 int
  51 pcieb_plat_peekpoke(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
  52     void *arg, void *result)
  53 {
  54         return (ddi_ctlops(dip, rdip, ctlop, arg, result));
  55 }
  56 
  57 /*ARGSUSED*/
  58 void
  59 pcieb_set_prot_scan(dev_info_t *dip, ddi_acc_impl_t *hdlp)
  60 {
  61 }
  62 
  63 /*ARGSUSED*/
  64 void
  65 pcieb_plat_attach_workaround(dev_info_t *dip)
  66 {
  67 }
  68 
  69 int
  70 pcieb_plat_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
  71     ddi_intr_handle_impl_t *hdlp, void *result)
  72 {
  73         dev_info_t      *cdip = rdip;
  74         pci_regspec_t   *pci_rp;
  75         int             reglen, len;
  76         uint32_t        d, intr;
  77 
  78         if ((intr_op == DDI_INTROP_SUPPORTED_TYPES) ||
  79             (hdlp->ih_type != DDI_INTR_TYPE_FIXED))
  80                 goto done;
  81 
  82         /*
  83          * If the interrupt-map property is defined at this
  84          * node, it will have performed the interrupt
  85          * translation as part of the property, so no
  86          * rotation needs to be done.
  87          */
  88         if (ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
  89             "interrupt-map", &len) == DDI_PROP_SUCCESS)
  90                 goto done;
  91 
  92         cdip = pcie_get_my_childs_dip(dip, rdip);
  93 
  94         /*
  95          * Use the devices reg property to determine its
  96          * PCI bus number and device number.
  97          */
  98         if (ddi_getlongprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
  99             "reg", (caddr_t)&pci_rp, &reglen) != DDI_SUCCESS)
 100                 return (DDI_FAILURE);
 101 
 102         intr = hdlp->ih_vector;
 103 
 104         d = (pcie_ari_is_enabled(dip) == PCIE_ARI_FORW_ENABLED) ? 0 :
 105             PCI_REG_DEV_G(pci_rp[0].pci_phys_hi);
 106 
 107         /* spin the interrupt */
 108         if ((intr >= PCI_INTA) && (intr <= PCI_INTD))
 109                 hdlp->ih_vector = ((intr - 1 + (d % 4)) % 4 + 1);
 110         else
 111                 cmn_err(CE_WARN, "%s%d: %s: PCI intr=%x out of range",
 112                     ddi_driver_name(rdip), ddi_get_instance(rdip),
 113                     ddi_driver_name(dip), intr);
 114 
 115         kmem_free(pci_rp, reglen);
 116 
 117 done:
 118         /* Pass up the request to our parent. */
 119         return (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result));
 120 }
 121 
 122 int
 123 pcieb_plat_pcishpc_probe(dev_info_t *dip, ddi_acc_handle_t config_handle)
 124 {
 125         uint16_t cap_ptr;
 126         if ((PCI_CAP_LOCATE(config_handle, PCI_CAP_ID_PCI_HOTPLUG, &cap_ptr)) !=
 127             DDI_FAILURE) {
 128                 return (DDI_SUCCESS);
 129         }
 130 
 131         return (DDI_FAILURE);
 132 }
 133 
 134 /*
 135  *  Disable PM on PLX. For PLX Transitioning one port on this switch to
 136  *  low power causes links on other ports on the same station to die.
 137  *  Due to PLX erratum #34, we can't allow the downstream device go to
 138  *  non-D0 state.
 139  */
 140 boolean_t
 141 pcieb_plat_pwr_disable(dev_info_t *dip)
 142 {
 143         uint16_t vendor_id = (PCIE_DIP2UPBUS(dip)->bus_dev_ven_id) & 0xFFFF;
 144         return (IS_PLX_VENDORID(vendor_id) ? B_TRUE : B_FALSE);
 145 }
 146 
 147 /*ARGSUSED*/
 148 boolean_t
 149 pcieb_plat_msi_supported(dev_info_t *dip)
 150 {
 151         return (B_TRUE);
 152 }
 153 
 154 /*ARGSUSED*/
 155 void
 156 pcieb_plat_intr_attach(pcieb_devstate_t *pcieb)
 157 {
 158 }
 159 
 160 /*ARGSUSED*/
 161 int
 162 pcieb_plat_ctlops(dev_info_t *rdip, ddi_ctl_enum_t ctlop, void *arg)
 163 {
 164         return (DDI_SUCCESS);
 165 }
 166 
 167 void
 168 pcieb_plat_initchild(dev_info_t *child)
 169 {
 170         intptr_t ppd = NULL;
 171         /*
 172          * XXX set ppd to 1 to disable iommu BDF protection on SPARC.
 173          * It relies on unused parent private data for PCI devices.
 174          */
 175         if (ddi_prop_exists(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS,
 176             "dvma-share"))
 177                 ppd = 1;
 178 
 179         ddi_set_parent_data(child, (void *)ppd);
 180 }
 181 
 182 void
 183 pcieb_plat_uninitchild(dev_info_t *child)
 184 {
 185         /*
 186          * XXX Clear parent private data used as a flag to disable
 187          * iommu BDF protection
 188          */
 189         if ((intptr_t)ddi_get_parent_data(child) == 1)
 190                 ddi_set_parent_data(child, NULL);
 191 }
 192 
 193 #ifdef PX_PLX
 194 /*
 195  * These are PLX specific workarounds needed during attach.
 196  */
 197 void
 198 pcieb_attach_plx_workarounds(pcieb_devstate_t *pcieb)
 199 {
 200         dev_info_t      *dip = pcieb->pcieb_dip;
 201         pcie_bus_t      *bus_p = PCIE_DIP2BUS(dip);
 202         ddi_acc_handle_t        config_handle = bus_p->bus_cfg_hdl;
 203         uint_t          bus_num, primary, secondary;
 204         uint8_t         dev_type = bus_p->bus_dev_type;
 205         uint16_t        vendor_id = bus_p->bus_dev_ven_id & 0xFFFF;
 206         uint16_t        device_id = bus_p->bus_dev_ven_id >> 16;
 207         int             ce_mask = 0;
 208 
 209         if (!IS_PLX_VENDORID(vendor_id))
 210                 return;
 211 
 212         if ((device_id == PXB_DEVICE_PLX_8532) &&
 213             (bus_p->bus_rev_id <= PXB_DEVICE_PLX_AA_REV))
 214                 /* Clear hotplug capability */
 215                 bus_p->bus_hp_sup_modes = PCIE_NONE_HP_MODE;
 216 
 217         /*
 218          * Due to a PLX HW bug we need to disable the receiver error CE on all
 219          * ports. To this end we create a property "pcie_ce_mask" with value
 220          * set to PCIE_AER_CE_RECEIVER_ERR. The pcie module will check for this
 221          * property before setting the AER CE mask. Be sure to honor all other
 222          * pcie_ce_mask settings.
 223          */
 224         ce_mask = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 225             "pcie_ce_mask", 0);
 226         (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 227             "pcie_ce_mask", (PCIE_AER_CE_RECEIVER_ERR|ce_mask));
 228 
 229         /*
 230          * There is a bug in the PLX 8114 bridge, such that an 8-bit
 231          * write to the secondary bus number register will corrupt an
 232          * internal shadow copy of the primary bus number.  Reading
 233          * out the registers and writing the same values back as
 234          * 16-bits resolves the problem.  This bug was reported by
 235          * PLX as errata #19.
 236          */
 237         primary = pci_config_get8(config_handle, PCI_BCNF_PRIBUS);
 238         secondary = pci_config_get8(config_handle, PCI_BCNF_SECBUS);
 239         bus_num = (secondary << 8) | primary;
 240         pci_config_put16(config_handle, PCI_BCNF_PRIBUS, bus_num);
 241 
 242         /*
 243          * Workaround for a race condition between hotplug
 244          * initialization and actual MSI interrupt registration
 245          * for hotplug functionality. The hotplug initialization
 246          * generates an INTx interrupt for hotplug events and this
 247          * INTx interrupt may interfere with shared leaf drivers
 248          * using same INTx interrupt, which may eventually block
 249          * the leaf drivers.
 250          */
 251         if ((dev_type == PCIE_PCIECAP_DEV_TYPE_DOWN) ||
 252             (dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
 253             (dev_type == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI) ||
 254             (dev_type == PCIE_PCIECAP_DEV_TYPE_PCI2PCIE)) {
 255                 pci_config_put16(config_handle, PCI_CONF_COMM,
 256                     pci_config_get16(config_handle, PCI_CONF_COMM) |
 257                     PCI_COMM_INTX_DISABLE);
 258         }
 259 
 260         /*
 261          * Disable PLX Special Relaxed Ordering
 262          */
 263         plx_ro_disable(pcieb);
 264 
 265 #ifdef  PRINT_PLX_SEEPROM_CRC
 266         /* check seeprom CRC to ensure the platform config is right */
 267         (void) pcieb_print_plx_seeprom_crc_data(pcieb);
 268 #endif /* PRINT_PLX_SEEPROM_CRC */
 269 }
 270 
 271 /*
 272  * These are PLX specific workarounds called during child's initchild.
 273  */
 274 int
 275 pcieb_init_plx_workarounds(pcieb_devstate_t *pcieb, dev_info_t *child)
 276 {
 277         int             i;
 278         int             result = DDI_FAILURE;
 279         uint16_t        reg = 0;
 280         ddi_acc_handle_t        config_handle;
 281         uint16_t        vendor_id =
 282             (PCIE_DIP2UPBUS(pcieb->pcieb_dip))->bus_dev_ven_id & 0xFFFF;
 283 
 284         if (!IS_PLX_VENDORID(vendor_id))
 285                 return (DDI_SUCCESS);
 286 
 287         /*
 288          * Due to a PLX HW bug, a SW workaround to prevent the chip from
 289          * wedging is needed.  SW just needs to tranfer 64 TLPs from
 290          * the downstream port to the child device.
 291          * The most benign way of doing this is to read the ID register
 292          * 64 times.  This SW workaround should have minimum performance
 293          * impact and shouldn't cause a problem for all other bridges
 294          * and switches.
 295          *
 296          * The code needs to be written in a way to make sure it isn't
 297          * optimized out.
 298          */
 299         if (!pxb_tlp_count) {
 300                 result = DDI_SUCCESS;
 301                 goto done;
 302         }
 303 
 304         if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) {
 305                 result = DDI_FAILURE;
 306                 goto done;
 307         }
 308 
 309         for (i = 0; i < pxb_tlp_count; i += 1)
 310                 reg |= pci_config_get16(config_handle, PCI_CONF_VENID);
 311 
 312         if (PCIE_IS_PCIE_BDG(PCIE_DIP2BUS(pcieb->pcieb_dip)))
 313                 pcieb_set_pci_perf_parameters(child, config_handle);
 314 
 315         pci_config_teardown(&config_handle);
 316         result = DDI_SUCCESS;
 317 done:
 318         return (result);
 319 }
 320 
 321 /*
 322  * Disable PLX specific relaxed ordering mode.  Due to PLX
 323  * erratum #6, use of this mode with Cut-Through Cancellation
 324  * can result in dropped Completion type packets.
 325  *
 326  * Clear the Relaxed Ordering Mode on 8533 and 8548 switches.
 327  * To disable RO, clear bit 5 in offset 0x664, an undocumented
 328  * bit in the PLX spec, on Ports 0, 8 and 12.  Proprietary PLX
 329  * registers are normally accessible only via memspace from Port
 330  * 0.  If port 0 is attached go ahead and disable RO on Port 0,
 331  * 8 and 12, if they exist.
 332  */
 333 static void
 334 plx_ro_disable(pcieb_devstate_t *pcieb)
 335 {
 336         pcie_bus_t              *bus_p = PCIE_DIP2BUS(pcieb->pcieb_dip);
 337         dev_info_t              *dip = pcieb->pcieb_dip;
 338         uint16_t                device_id = bus_p->bus_dev_ven_id >> 16;
 339         pci_regspec_t           *reg_spec, *addr_spec;
 340         int                     rlen, alen;
 341         int                     orig_rsize, new_rsize;
 342         uint_t                  rnum, anum;
 343         ddi_device_acc_attr_t   attr;
 344         ddi_acc_handle_t        hdl;
 345         caddr_t                 regsp;
 346         uint32_t                val, port_enable;
 347         char                    *offset;
 348         char                    *port_offset;
 349 
 350         if (!((device_id == PXB_DEVICE_PLX_8533) ||
 351             (device_id == PXB_DEVICE_PLX_8548)))
 352                 return;
 353 
 354         /* You can also only do this on Port 0 */
 355         val = PCIE_CAP_GET(32, bus_p, PCIE_LINKCAP);
 356         val = (val >> PCIE_LINKCAP_PORT_NUMBER_SHIFT) &
 357             PCIE_LINKCAP_PORT_NUMBER_MASK;
 358 
 359         PCIEB_DEBUG(DBG_ATTACH, dip, "PLX RO Disable : bdf=0x%x port=%d\n",
 360             bus_p->bus_bdf, val);
 361 
 362         if (val != 0)
 363                 return;
 364 
 365         /*
 366          * Read the reg property, but allocate extra space incase we need to add
 367          * a new entry later.
 368          */
 369         if (ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
 370             &orig_rsize) != DDI_SUCCESS)
 371                 return;
 372 
 373         new_rsize = orig_rsize + sizeof (pci_regspec_t);
 374         reg_spec = kmem_alloc(new_rsize, KM_SLEEP);
 375 
 376         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
 377             (caddr_t)reg_spec, &orig_rsize) != DDI_SUCCESS)
 378                 goto fail;
 379 
 380         /* Find the mem32 reg property */
 381         rlen = orig_rsize / sizeof (pci_regspec_t);
 382         for (rnum = 0; rnum < rlen; rnum++) {
 383                 if ((reg_spec[rnum].pci_phys_hi & PCI_ADDR_MASK) ==
 384                     PCI_ADDR_MEM32)
 385                         goto fix;
 386         }
 387 
 388         /*
 389          * Mem32 reg property was not found.
 390          * Look for it in assign-address property.
 391          */
 392         addr_spec = bus_p->bus_assigned_addr;
 393         alen = bus_p->bus_assigned_entries;
 394         for (anum = 0; anum < alen; anum++) {
 395                 if ((addr_spec[anum].pci_phys_hi & PCI_ADDR_MASK) ==
 396                     PCI_ADDR_MEM32)
 397                         goto update;
 398         }
 399 
 400         /* Unable to find mem space assigned address, give up. */
 401         goto fail;
 402 
 403 update:
 404         /*
 405          * Add the mem32 access to the reg spec.
 406          * Use the last entry which was previously allocated.
 407          */
 408         reg_spec[rnum].pci_phys_hi = (addr_spec[anum].pci_phys_hi &
 409             ~PCI_REG_REL_M);
 410         reg_spec[rnum].pci_phys_mid = 0;
 411         reg_spec[rnum].pci_phys_low = 0;
 412         reg_spec[rnum].pci_size_hi = addr_spec[anum].pci_size_hi;
 413         reg_spec[rnum].pci_size_low = addr_spec[anum].pci_size_low;
 414 
 415         /* Create the new reg_spec data and update the property */
 416         if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, "reg",
 417             (int *)reg_spec, (new_rsize / sizeof (int))) != DDI_SUCCESS)
 418                 goto fail;
 419 
 420 fix:
 421         attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
 422         attr.devacc_attr_endian_flags  = DDI_STRUCTURE_LE_ACC;
 423         attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
 424 
 425         if (ddi_regs_map_setup(dip, rnum, &regsp, 0, 0, &attr,
 426             &hdl) != DDI_SUCCESS)
 427                 goto fail;
 428 
 429         /* Grab register which shows which ports are enabled */
 430         offset = (char *)regsp + PLX_INGRESS_PORT_ENABLE;
 431         port_enable = ddi_get32(hdl, (uint32_t *)offset);
 432 
 433         if ((port_enable == 0xFFFFFFFF) || (port_enable == 0))
 434                 goto done;
 435 
 436         offset = (char *)regsp + PLX_INGRESS_CONTROL_SHADOW;
 437 
 438         /* Disable RO on Port 0 */
 439         port_offset = 0x0 + offset;
 440         val = ddi_get32(hdl, (uint32_t *)port_offset);
 441         if (val & PLX_RO_MODE_BIT)
 442                 val ^= PLX_RO_MODE_BIT;
 443         ddi_put32(hdl, (uint32_t *)port_offset, val);
 444 
 445         /* Disable RO on Port 8, but make sure its enabled */
 446         if (!(port_enable & (1 << 8)))
 447                 goto port12;
 448 
 449         port_offset = (8 * 0x1000) + offset;
 450         val = ddi_get32(hdl, (uint32_t *)port_offset);
 451         if (val & PLX_RO_MODE_BIT)
 452                 val ^= PLX_RO_MODE_BIT;
 453         ddi_put32(hdl, (uint32_t *)port_offset, val);
 454 
 455 port12:
 456         /* Disable RO on Port 12, but make sure it exists */
 457         if (!(port_enable & (1 << 12)))
 458                 goto done;
 459 
 460         port_offset = (12 * 0x1000) + offset;
 461         val = ddi_get32(hdl, (uint32_t *)port_offset);
 462         if (val & PLX_RO_MODE_BIT)
 463                 val ^= PLX_RO_MODE_BIT;
 464         ddi_put32(hdl, (uint32_t *)port_offset, val);
 465 
 466         goto done;
 467 
 468 done:
 469         ddi_regs_map_free(&hdl);
 470 fail:
 471         kmem_free(reg_spec, new_rsize);
 472 }
 473 
 474 #ifdef  PRINT_PLX_SEEPROM_CRC
 475 static void
 476 pcieb_print_plx_seeprom_crc_data(pcieb_devstate_t *pcieb_p)
 477 {
 478         ddi_acc_handle_t h;
 479         dev_info_t *dip = pcieb_p->pcieb_dip;
 480         uint16_t vendorid = (PCIE_DIP2BUS(dip)->bus_dev_ven_id) & 0xFFFF;
 481         int nregs;
 482         caddr_t mp;
 483         off_t bar_size;
 484         ddi_device_acc_attr_t mattr = {
 485                 DDI_DEVICE_ATTR_V0,
 486                 DDI_STRUCTURE_LE_ACC,
 487                 DDI_STRICTORDER_ACC
 488         };
 489         uint32_t addr_reg_off = 0x260, data_reg_off = 0x264, data = 0x6BE4;
 490 
 491         if (vendorid != PXB_VENDOR_PLX)
 492                 return;
 493         if (ddi_dev_nregs(dip, &nregs) != DDI_SUCCESS)
 494                 return;
 495         if (nregs < 2)       /* check for CONF entry only, no BARs */
 496                 return;
 497         if (ddi_dev_regsize(dip, 1, &bar_size) != DDI_SUCCESS)
 498                 return;
 499         if (ddi_regs_map_setup(dip, 1, (caddr_t *)&mp, 0, bar_size,
 500             &mattr, &h) != DDI_SUCCESS)
 501                 return;
 502         ddi_put32(h, (uint32_t *)((uchar_t *)mp + addr_reg_off), data);
 503         delay(drv_sectohz(1));
 504         printf("%s#%d: EEPROM StatusReg = %x, CRC = %x\n",
 505             ddi_driver_name(dip), ddi_get_instance(dip),
 506             ddi_get32(h, (uint32_t *)((uchar_t *)mp + addr_reg_off)),
 507             ddi_get32(h, (uint32_t *)((uchar_t *)mp + data_reg_off)));
 508 #ifdef PLX_HOT_RESET_DISABLE
 509         /* prevent hot reset from propogating downstream. */
 510         data = ddi_get32(h, (uint32_t *)((uchar_t *)mp + 0x1DC));
 511         ddi_put32(h, (uint32_t *)((uchar_t *)mp + 0x1DC), data | 0x80000);
 512         delay(drv_sectohz(1));
 513         printf("%s#%d: EEPROM 0x1DC prewrite=%x postwrite=%x\n",
 514             ddi_driver_name(dip), ddi_get_instance(dip), data,
 515             ddi_get32(h, (uint32_t *)((uchar_t *)mp + 0x1DC)));
 516 #endif /* PLX_HOT_RESET_DISABLE */
 517         ddi_regs_map_free(&h);
 518 }
 519 #endif /* PRINT_PLX_SEEPROM_CRC */
 520 #endif /* PX_PLX */