]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'pci/next'
authorThierry Reding <treding@nvidia.com>
Thu, 24 Oct 2013 12:33:38 +0000 (14:33 +0200)
committerThierry Reding <treding@nvidia.com>
Thu, 24 Oct 2013 12:33:38 +0000 (14:33 +0200)
34 files changed:
Documentation/PCI/pci.txt
Documentation/devicetree/bindings/pci/designware-pcie.txt
MAINTAINERS
arch/powerpc/kernel/eeh.c
arch/powerpc/sysdev/fsl_pci.c
arch/x86/pci/fixup.c
drivers/acpi/apei/apei-base.c
drivers/acpi/bus.c
drivers/acpi/pci_root.c
drivers/pci/host/Kconfig
drivers/pci/host/Makefile
drivers/pci/host/pci-exynos.c
drivers/pci/host/pci-imx6.c [new file with mode: 0644]
drivers/pci/host/pci-tegra.c
drivers/pci/host/pcie-designware.c
drivers/pci/host/pcie-designware.h
drivers/pci/hotplug/acpi_pcihp.c
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp_core.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/acpiphp_ibm.c
drivers/pci/hotplug/shpchp.h
drivers/pci/pci.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/setup-bus.c
drivers/scsi/bfa/bfad.c
drivers/scsi/csiostor/csio_hw.c
drivers/scsi/qla2xxx/qla_mr.c
drivers/scsi/qla2xxx/qla_os.c
include/linux/acpi.h
include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
include/linux/pci.h
include/uapi/linux/pci_regs.h

index bccf602a87f5c2054b146c826725ac183863a8ad..6f458564d625a3d82601703ceed6a814e9e14585 100644 (file)
@@ -525,8 +525,9 @@ corresponding register block for you.
 6. Other interesting functions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-pci_find_slot()                        Find pci_dev corresponding to given bus and
-                               slot numbers.
+pci_get_domain_bus_and_slot()  Find pci_dev corresponding to given domain,
+                               bus and slot and number. If the device is
+                               found, its reference count is increased.
 pci_set_power_state()          Set PCI Power Management state (0=D0 ... 3=D3)
 pci_find_capability()          Find specified capability in device's capability
                                list.
@@ -582,7 +583,8 @@ having sane locking.
 
 pci_find_device()      Superseded by pci_get_device()
 pci_find_subsys()      Superseded by pci_get_subsys()
-pci_find_slot()                Superseded by pci_get_slot()
+pci_find_slot()                Superseded by pci_get_domain_bus_and_slot()
+pci_get_slot()         Superseded by pci_get_domain_bus_and_slot()
 
 
 The alternative is the traditional PCI device driver that walks PCI
index e216af356847c05ac4ab9f2e9a6ae887b1939f2a..d5d26d443693ce70db814c9466bbc72d87d6b7fe 100644 (file)
@@ -3,7 +3,7 @@
 Required properties:
 - compatible: should contain "snps,dw-pcie" to identify the
        core, plus an identifier for the specific instance, such
-       as "samsung,exynos5440-pcie".
+       as "samsung,exynos5440-pcie" or "fsl,imx6q-pcie".
 - reg: base addresses and lengths of the pcie controller,
        the phy controller, additional register for the phy controller.
 - interrupts: interrupt values for level interrupt,
@@ -21,6 +21,11 @@ Required properties:
 - num-lanes: number of lanes to use
 - reset-gpio: gpio pin number of power good signal
 
+Optional properties for fsl,imx6q-pcie
+- power-on-gpio: gpio pin number of power-enable signal
+- wake-up-gpio: gpio pin number of incoming wakeup signal
+- disable-gpio: gpio pin number of outgoing rfkill/endpoint disable signal
+
 Example:
 
 SoC specific DT Entry:
index cf205aec574c57abfb0552bdcd1b11a34bd24ffa..a8fd9746c27f4a85b6bfa949b2db4611228bb3c4 100644 (file)
@@ -6379,6 +6379,12 @@ S:       Supported
 F:     Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
 F:     drivers/pci/host/pci-tegra.c
 
+PCI DRIVER FOR SAMSUNG EXYNOS
+M:     Jingoo Han <jg1.han@samsung.com>
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     drivers/pci/host/pci-exynos.c
+
 PCMCIA SUBSYSTEM
 P:     Linux PCMCIA Team
 L:     linux-pcmcia@lists.infradead.org
index 1fb331db34c848a899f5652623cdd2e5bf71d7d9..58906d7f4c4950b5830f9706ba01cc1c3c8985f0 100644 (file)
@@ -189,8 +189,7 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
        }
 
        /* If PCI-E capable, dump PCI-E cap 10, and the AER */
-       cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
-       if (cap) {
+       if (pci_is_pcie(dev)) {
                n += scnprintf(buf+n, len-n, "pci-e cap10:\n");
                printk(KERN_WARNING
                       "EEH: PCI-E capabilities and status follow:\n");
index ccfb50ddfe38f7242b071c6519aaa1eb43daf6a2..92e7258478d8eafcc7f3c7655446601ce4fa61d1 100644 (file)
@@ -45,7 +45,7 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev)
        u8 hdr_type;
 
        /* if we aren't a PCIe don't bother */
-       if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
+       if (!pci_is_pcie(dev))
                return;
 
        /* if we aren't in host mode don't bother */
index f5809fa2753e69246f8d361d844c212e03d139e9..b046e070e08868f72e62b5ce804ffedd1689cc03 100644 (file)
@@ -231,7 +231,7 @@ static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int wh
        offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)];
 
        if ((offset) && (where == offset))
-               value = value & 0xfffffffc;
+               value = value & ~PCI_EXP_LNKCTL_ASPMC;
 
        return raw_pci_write(pci_domain_nr(bus), bus->number,
                                                devfn, where, size, value);
@@ -252,7 +252,7 @@ static struct pci_ops quirk_pcie_aspm_ops = {
  */
 static void pcie_rootport_aspm_quirk(struct pci_dev *pdev)
 {
-       int cap_base, i;
+       int i;
        struct pci_bus  *pbus;
        struct pci_dev *dev;
 
@@ -278,7 +278,7 @@ static void pcie_rootport_aspm_quirk(struct pci_dev *pdev)
                for (i = GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i)
                        quirk_aspm_offset[i] = 0;
 
-               pbus->ops = pbus->parent->ops;
+               pci_bus_set_ops(pbus, pbus->parent->ops);
        } else {
                /*
                 * If devices are attached to the root port at power-up or
@@ -286,13 +286,15 @@ static void pcie_rootport_aspm_quirk(struct pci_dev *pdev)
                 * each root port to save the register offsets and replace the
                 * bus ops.
                 */
-               list_for_each_entry(dev, &pbus->devices, bus_list) {
+               list_for_each_entry(dev, &pbus->devices, bus_list)
                        /* There are 0 to 8 devices attached to this bus */
-                       cap_base = pci_find_capability(dev, PCI_CAP_ID_EXP);
-                       quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)] = cap_base + 0x10;
-               }
-               pbus->ops = &quirk_pcie_aspm_ops;
+                       quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)] =
+                               dev->pcie_cap + PCI_EXP_LNKCTL;
+
+               pci_bus_set_ops(pbus, &quirk_pcie_aspm_ops);
+               dev_info(&pbus->dev, "writes to ASPM control bits will be ignored\n");
        }
+
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PA,     pcie_rootport_aspm_quirk);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_MCH_PA1,    pcie_rootport_aspm_quirk);
index 46f80e2c92f7da893ff28f5993d89fa01efc323a..6d2c49b86b7fa82434bdb0b2ce1906c95dce00ca 100644 (file)
@@ -758,9 +758,9 @@ int apei_osc_setup(void)
                .cap.pointer    = capbuf,
        };
 
-       capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
-       capbuf[OSC_SUPPORT_TYPE] = 1;
-       capbuf[OSC_CONTROL_TYPE] = 0;
+       capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
+       capbuf[OSC_SUPPORT_DWORD] = 1;
+       capbuf[OSC_CONTROL_DWORD] = 0;
 
        if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))
            || ACPI_FAILURE(acpi_run_osc(handle, &context)))
index b587ec8257b2190758eca2b8b3306a933d4ae16d..fbcfaa682c157dc6a6edcc5ab61b59c55a0cc269 100644 (file)
@@ -255,7 +255,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
                        acpi_print_osc_error(handle, context,
                                "_OSC invalid revision");
                if (errors & OSC_CAPABILITIES_MASK_ERROR) {
-                       if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE]
+                       if (((u32 *)context->cap.pointer)[OSC_QUERY_DWORD]
                            & OSC_QUERY_ENABLE)
                                goto out_success;
                        status = AE_SUPPORT;
@@ -295,30 +295,30 @@ static void acpi_bus_osc_support(void)
        };
        acpi_handle handle;
 
-       capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
-       capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
+       capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
+       capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
 #if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\
                        defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
-       capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT;
+       capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT;
 #endif
 
 #if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
-       capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT;
+       capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
 #endif
 
 #ifdef ACPI_HOTPLUG_OST
-       capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_HOTPLUG_OST_SUPPORT;
+       capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
 #endif
 
        if (!ghes_disable)
-               capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_APEI_SUPPORT;
+               capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
        if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
                return;
        if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
                u32 *capbuf_ret = context.ret.pointer;
-               if (context.ret.length > OSC_SUPPORT_TYPE)
+               if (context.ret.length > OSC_SUPPORT_DWORD)
                        osc_sb_apei_support_acked =
-                               capbuf_ret[OSC_SUPPORT_TYPE] & OSC_SB_APEI_SUPPORT;
+                               capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
                kfree(context.ret.pointer);
        }
        /* do we need to check other returned cap? Sounds no */
index d3874f4256534d06aeb0fdb9f364e5f5851963f3..924ad92852c1a7fa69ea26f0ac8c2aaeb9d254fd 100644 (file)
@@ -49,10 +49,10 @@ static int acpi_pci_root_add(struct acpi_device *device,
                             const struct acpi_device_id *not_used);
 static void acpi_pci_root_remove(struct acpi_device *device);
 
-#define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \
-                               | OSC_ACTIVE_STATE_PWR_SUPPORT \
-                               | OSC_CLOCK_PWR_CAPABILITY_SUPPORT \
-                               | OSC_MSI_SUPPORT)
+#define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \
+                               | OSC_PCI_ASPM_SUPPORT \
+                               | OSC_PCI_CLOCK_PM_SUPPORT \
+                               | OSC_PCI_MSI_SUPPORT)
 
 static const struct acpi_device_id root_device_ids[] = {
        {"PNP0A03", 0},
@@ -127,6 +127,55 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle,
        return AE_OK;
 }
 
+struct pci_osc_bit_struct {
+       u32 bit;
+       char *desc;
+};
+
+static struct pci_osc_bit_struct pci_osc_support_bit[] = {
+       { OSC_PCI_EXT_CONFIG_SUPPORT, "ExtendedConfig" },
+       { OSC_PCI_ASPM_SUPPORT, "ASPM" },
+       { OSC_PCI_CLOCK_PM_SUPPORT, "ClockPM" },
+       { OSC_PCI_SEGMENT_GROUPS_SUPPORT, "Segments" },
+       { OSC_PCI_MSI_SUPPORT, "MSI" },
+};
+
+static struct pci_osc_bit_struct pci_osc_control_bit[] = {
+       { OSC_PCI_EXPRESS_NATIVE_HP_CONTROL, "PCIeHotplug" },
+       { OSC_PCI_SHPC_NATIVE_HP_CONTROL, "SHPCHotplug" },
+       { OSC_PCI_EXPRESS_PME_CONTROL, "PME" },
+       { OSC_PCI_EXPRESS_AER_CONTROL, "AER" },
+       { OSC_PCI_EXPRESS_CAPABILITY_CONTROL, "PCIeCapability" },
+};
+
+static void decode_osc_bits(struct acpi_pci_root *root, char *msg, u32 word,
+                           struct pci_osc_bit_struct *table, int size)
+{
+       char buf[80];
+       int i, len = 0;
+       struct pci_osc_bit_struct *entry;
+
+       buf[0] = '\0';
+       for (i = 0, entry = table; i < size; i++, entry++)
+               if (word & entry->bit)
+                       len += snprintf(buf + len, sizeof(buf) - len, "%s%s",
+                                       len ? " " : "", entry->desc);
+
+       dev_info(&root->device->dev, "_OSC: %s [%s]\n", msg, buf);
+}
+
+static void decode_osc_support(struct acpi_pci_root *root, char *msg, u32 word)
+{
+       decode_osc_bits(root, msg, word, pci_osc_support_bit,
+                       ARRAY_SIZE(pci_osc_support_bit));
+}
+
+static void decode_osc_control(struct acpi_pci_root *root, char *msg, u32 word)
+{
+       decode_osc_bits(root, msg, word, pci_osc_control_bit,
+                       ARRAY_SIZE(pci_osc_control_bit));
+}
+
 static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766";
 
 static acpi_status acpi_pci_run_osc(acpi_handle handle,
@@ -158,14 +207,14 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
        support &= OSC_PCI_SUPPORT_MASKS;
        support |= root->osc_support_set;
 
-       capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
-       capbuf[OSC_SUPPORT_TYPE] = support;
+       capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
+       capbuf[OSC_SUPPORT_DWORD] = support;
        if (control) {
                *control &= OSC_PCI_CONTROL_MASKS;
-               capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set;
+               capbuf[OSC_CONTROL_DWORD] = *control | root->osc_control_set;
        } else {
                /* Run _OSC query only with existing controls. */
-               capbuf[OSC_CONTROL_TYPE] = root->osc_control_set;
+               capbuf[OSC_CONTROL_DWORD] = root->osc_control_set;
        }
 
        status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
@@ -180,11 +229,7 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
 static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags)
 {
        acpi_status status;
-       acpi_handle tmp;
 
-       status = acpi_get_handle(root->device->handle, "_OSC", &tmp);
-       if (ACPI_FAILURE(status))
-               return status;
        mutex_lock(&osc_lock);
        status = acpi_pci_query_osc(root, flags, NULL);
        mutex_unlock(&osc_lock);
@@ -316,9 +361,8 @@ EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
 acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req)
 {
        struct acpi_pci_root *root;
-       acpi_status status;
+       acpi_status status = AE_OK;
        u32 ctrl, capbuf[3];
-       acpi_handle tmp;
 
        if (!mask)
                return AE_BAD_PARAMETER;
@@ -331,10 +375,6 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req)
        if (!root)
                return AE_NOT_EXIST;
 
-       status = acpi_get_handle(handle, "_OSC", &tmp);
-       if (ACPI_FAILURE(status))
-               return status;
-
        mutex_lock(&osc_lock);
 
        *mask = ctrl | root->osc_control_set;
@@ -349,17 +389,21 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req)
                        goto out;
                if (ctrl == *mask)
                        break;
+               decode_osc_control(root, "platform does not support",
+                                  ctrl & ~(*mask));
                ctrl = *mask;
        }
 
        if ((ctrl & req) != req) {
+               decode_osc_control(root, "not requesting control; platform does not support",
+                                  req & ~(ctrl));
                status = AE_SUPPORT;
                goto out;
        }
 
-       capbuf[OSC_QUERY_TYPE] = 0;
-       capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set;
-       capbuf[OSC_CONTROL_TYPE] = ctrl;
+       capbuf[OSC_QUERY_DWORD] = 0;
+       capbuf[OSC_SUPPORT_DWORD] = root->osc_support_set;
+       capbuf[OSC_CONTROL_DWORD] = ctrl;
        status = acpi_pci_run_osc(handle, capbuf, mask);
        if (ACPI_SUCCESS(status))
                root->osc_control_set = *mask;
@@ -369,6 +413,87 @@ out:
 }
 EXPORT_SYMBOL(acpi_pci_osc_control_set);
 
+static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
+                                int *clear_aspm)
+{
+       u32 support, control, requested;
+       acpi_status status;
+       struct acpi_device *device = root->device;
+       acpi_handle handle = device->handle;
+
+       /*
+        * All supported architectures that use ACPI have support for
+        * PCI domains, so we indicate this in _OSC support capabilities.
+        */
+       support = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
+       if (pci_ext_cfg_avail())
+               support |= OSC_PCI_EXT_CONFIG_SUPPORT;
+       if (pcie_aspm_support_enabled())
+               support |= OSC_PCI_ASPM_SUPPORT | OSC_PCI_CLOCK_PM_SUPPORT;
+       if (pci_msi_enabled())
+               support |= OSC_PCI_MSI_SUPPORT;
+
+       decode_osc_support(root, "OS supports", support);
+       status = acpi_pci_osc_support(root, support);
+       if (ACPI_FAILURE(status)) {
+               dev_info(&device->dev, "_OSC failed (%s); disabling ASPM\n",
+                        acpi_format_exception(status));
+               *no_aspm = 1;
+               return;
+       }
+
+       if (pcie_ports_disabled) {
+               dev_info(&device->dev, "PCIe port services disabled; not requesting _OSC control\n");
+               return;
+       }
+
+       if ((support & ACPI_PCIE_REQ_SUPPORT) != ACPI_PCIE_REQ_SUPPORT) {
+               decode_osc_support(root, "not requesting OS control; OS requires",
+                                  ACPI_PCIE_REQ_SUPPORT);
+               return;
+       }
+
+       control = OSC_PCI_EXPRESS_CAPABILITY_CONTROL
+               | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
+               | OSC_PCI_EXPRESS_PME_CONTROL;
+
+       if (pci_aer_available()) {
+               if (aer_acpi_firmware_first())
+                       dev_info(&device->dev,
+                                "PCIe AER handled by firmware\n");
+               else
+                       control |= OSC_PCI_EXPRESS_AER_CONTROL;
+       }
+
+       requested = control;
+       status = acpi_pci_osc_control_set(handle, &control,
+                                         OSC_PCI_EXPRESS_CAPABILITY_CONTROL);
+       if (ACPI_SUCCESS(status)) {
+               decode_osc_control(root, "OS now controls", control);
+               if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
+                       /*
+                        * We have ASPM control, but the FADT indicates
+                        * that it's unsupported. Clear it.
+                        */
+                       *clear_aspm = 1;
+               }
+       } else {
+               decode_osc_control(root, "OS requested", requested);
+               decode_osc_control(root, "platform willing to grant", control);
+               dev_info(&device->dev, "_OSC failed (%s); disabling ASPM\n",
+                       acpi_format_exception(status));
+
+               /*
+                * We want to disable ASPM here, but aspm_disabled
+                * needs to remain in its state from boot so that we
+                * properly handle PCIe 1.1 devices.  So we set this
+                * flag here, to defer the action until after the ACPI
+                * root scan.
+                */
+               *no_aspm = 1;
+       }
+}
+
 static int acpi_pci_root_add(struct acpi_device *device,
                             const struct acpi_device_id *not_used)
 {
@@ -376,9 +501,8 @@ static int acpi_pci_root_add(struct acpi_device *device,
        acpi_status status;
        int result;
        struct acpi_pci_root *root;
-       u32 flags, base_flags;
        acpi_handle handle = device->handle;
-       bool no_aspm = false, clear_aspm = false;
+       int no_aspm = 0, clear_aspm = 0;
 
        root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
        if (!root)
@@ -431,81 +555,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
 
        root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle);
 
-       /*
-        * All supported architectures that use ACPI have support for
-        * PCI domains, so we indicate this in _OSC support capabilities.
-        */
-       flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
-       acpi_pci_osc_support(root, flags);
-
-       if (pci_ext_cfg_avail())
-               flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
-       if (pcie_aspm_support_enabled()) {
-               flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
-               OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
-       }
-       if (pci_msi_enabled())
-               flags |= OSC_MSI_SUPPORT;
-       if (flags != base_flags) {
-               status = acpi_pci_osc_support(root, flags);
-               if (ACPI_FAILURE(status)) {
-                       dev_info(&device->dev, "ACPI _OSC support "
-                               "notification failed, disabling PCIe ASPM\n");
-                       no_aspm = true;
-                       flags = base_flags;
-               }
-       }
-
-       if (!pcie_ports_disabled
-           && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
-               flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
-                       | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
-                       | OSC_PCI_EXPRESS_PME_CONTROL;
-
-               if (pci_aer_available()) {
-                       if (aer_acpi_firmware_first())
-                               dev_dbg(&device->dev,
-                                       "PCIe errors handled by BIOS.\n");
-                       else
-                               flags |= OSC_PCI_EXPRESS_AER_CONTROL;
-               }
-
-               dev_info(&device->dev,
-                       "Requesting ACPI _OSC control (0x%02x)\n", flags);
-
-               status = acpi_pci_osc_control_set(handle, &flags,
-                                      OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
-               if (ACPI_SUCCESS(status)) {
-                       dev_info(&device->dev,
-                               "ACPI _OSC control (0x%02x) granted\n", flags);
-                       if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
-                               /*
-                                * We have ASPM control, but the FADT indicates
-                                * that it's unsupported. Clear it.
-                                */
-                               clear_aspm = true;
-                       }
-               } else {
-                       dev_info(&device->dev,
-                               "ACPI _OSC request failed (%s), "
-                               "returned control mask: 0x%02x\n",
-                               acpi_format_exception(status), flags);
-                       dev_info(&device->dev,
-                                "ACPI _OSC control for PCIe not granted, disabling ASPM\n");
-                       /*
-                        * We want to disable ASPM here, but aspm_disabled
-                        * needs to remain in its state from boot so that we
-                        * properly handle PCIe 1.1 devices.  So we set this
-                        * flag here, to defer the action until after the ACPI
-                        * root scan.
-                        */
-                       no_aspm = true;
-               }
-       } else {
-               dev_info(&device->dev,
-                        "Unable to request _OSC control "
-                        "(_OSC support mask: 0x%02x)\n", flags);
-       }
+       negotiate_os_control(root, &no_aspm, &clear_aspm);
 
        /*
         * TBD: Need PCI interface for enumeration/configuration of roots.
index 3d950481112634fc847d61fef187efc86503a189..efa24d9a33615a1268e83212fc3a04844806497f 100644 (file)
@@ -15,6 +15,12 @@ config PCI_EXYNOS
        select PCIEPORTBUS
        select PCIE_DW
 
+config PCI_IMX6
+       bool "Freescale i.MX6 PCIe controller"
+       depends on SOC_IMX6Q
+       select PCIEPORTBUS
+       select PCIE_DW
+
 config PCI_TEGRA
        bool "NVIDIA Tegra PCIe controller"
        depends on ARCH_TEGRA
index c9a997b2690dc9532e7654ae804c0697652679ae..287d6a053dda4b0a2d61dd85e5a0bc19349fee4f 100644 (file)
@@ -1,4 +1,5 @@
 obj-$(CONFIG_PCIE_DW) += pcie-designware.o
 obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
+obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
 obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
 obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
index 94e096bb2d0a3e88d66634ea201dc4e546f03b7e..ee692c2c3d73fa83e4815b8648aafc81386fd8e1 100644 (file)
@@ -48,6 +48,7 @@ struct exynos_pcie {
 #define PCIE_IRQ_SPECIAL               0x008
 #define PCIE_IRQ_EN_PULSE              0x00c
 #define PCIE_IRQ_EN_LEVEL              0x010
+#define IRQ_MSI_ENABLE                 (0x1 << 2)
 #define PCIE_IRQ_EN_SPECIAL            0x014
 #define PCIE_PWR_RESET                 0x018
 #define PCIE_CORE_RESET                        0x01c
@@ -77,18 +78,28 @@ struct exynos_pcie {
 #define PCIE_PHY_PLL_BIAS              0x00c
 #define PCIE_PHY_DCC_FEEDBACK          0x014
 #define PCIE_PHY_PLL_DIV_1             0x05c
+#define PCIE_PHY_COMMON_POWER          0x064
+#define PCIE_PHY_COMMON_PD_CMN         (0x1 << 3)
 #define PCIE_PHY_TRSV0_EMP_LVL         0x084
 #define PCIE_PHY_TRSV0_DRV_LVL         0x088
 #define PCIE_PHY_TRSV0_RXCDR           0x0ac
+#define PCIE_PHY_TRSV0_POWER           0x0c4
+#define PCIE_PHY_TRSV0_PD_TSV          (0x1 << 7)
 #define PCIE_PHY_TRSV0_LVCC            0x0dc
 #define PCIE_PHY_TRSV1_EMP_LVL         0x144
 #define PCIE_PHY_TRSV1_RXCDR           0x16c
+#define PCIE_PHY_TRSV1_POWER           0x184
+#define PCIE_PHY_TRSV1_PD_TSV          (0x1 << 7)
 #define PCIE_PHY_TRSV1_LVCC            0x19c
 #define PCIE_PHY_TRSV2_EMP_LVL         0x204
 #define PCIE_PHY_TRSV2_RXCDR           0x22c
+#define PCIE_PHY_TRSV2_POWER           0x244
+#define PCIE_PHY_TRSV2_PD_TSV          (0x1 << 7)
 #define PCIE_PHY_TRSV2_LVCC            0x25c
 #define PCIE_PHY_TRSV3_EMP_LVL         0x2c4
 #define PCIE_PHY_TRSV3_RXCDR           0x2ec
+#define PCIE_PHY_TRSV3_POWER           0x304
+#define PCIE_PHY_TRSV3_PD_TSV          (0x1 << 7)
 #define PCIE_PHY_TRSV3_LVCC            0x31c
 
 static inline void exynos_elb_writel(struct exynos_pcie *pcie, u32 val, u32 reg)
@@ -202,6 +213,58 @@ static void exynos_pcie_deassert_phy_reset(struct pcie_port *pp)
        exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET);
 }
 
+static void exynos_pcie_power_on_phy(struct pcie_port *pp)
+{
+       u32 val;
+       struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
+
+       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER);
+       val &= ~PCIE_PHY_COMMON_PD_CMN;
+       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER);
+
+       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER);
+       val &= ~PCIE_PHY_TRSV0_PD_TSV;
+       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER);
+
+       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER);
+       val &= ~PCIE_PHY_TRSV1_PD_TSV;
+       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER);
+
+       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER);
+       val &= ~PCIE_PHY_TRSV2_PD_TSV;
+       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER);
+
+       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER);
+       val &= ~PCIE_PHY_TRSV3_PD_TSV;
+       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER);
+}
+
+static void exynos_pcie_power_off_phy(struct pcie_port *pp)
+{
+       u32 val;
+       struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
+
+       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER);
+       val |= PCIE_PHY_COMMON_PD_CMN;
+       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER);
+
+       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER);
+       val |= PCIE_PHY_TRSV0_PD_TSV;
+       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER);
+
+       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER);
+       val |= PCIE_PHY_TRSV1_PD_TSV;
+       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER);
+
+       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER);
+       val |= PCIE_PHY_TRSV2_PD_TSV;
+       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER);
+
+       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER);
+       val |= PCIE_PHY_TRSV3_PD_TSV;
+       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER);
+}
+
 static void exynos_pcie_init_phy(struct pcie_port *pp)
 {
        struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
@@ -270,6 +333,9 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)
        /* de-assert phy reset */
        exynos_pcie_deassert_phy_reset(pp);
 
+       /* power on phy */
+       exynos_pcie_power_on_phy(pp);
+
        /* initialize phy */
        exynos_pcie_init_phy(pp);
 
@@ -302,6 +368,9 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)
                                                       PCIE_PHY_PLL_LOCKED);
                                dev_info(pp->dev, "PLL Locked: 0x%x\n", val);
                        }
+                       /* power off phy */
+                       exynos_pcie_power_off_phy(pp);
+
                        dev_err(pp->dev, "PCIe Link Fail\n");
                        return -EINVAL;
                }
@@ -342,9 +411,36 @@ static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
+static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg)
+{
+       struct pcie_port *pp = arg;
+
+       dw_handle_msi_irq(pp);
+
+       return IRQ_HANDLED;
+}
+
+static void exynos_pcie_msi_init(struct pcie_port *pp)
+{
+       u32 val;
+       struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
+
+       dw_pcie_msi_init(pp);
+
+       /* enable MSI interrupt */
+       val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL);
+       val |= IRQ_MSI_ENABLE;
+       exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL);
+       return;
+}
+
 static void exynos_pcie_enable_interrupts(struct pcie_port *pp)
 {
        exynos_pcie_enable_irq_pulse(pp);
+
+       if (IS_ENABLED(CONFIG_PCI_MSI))
+               exynos_pcie_msi_init(pp);
+
        return;
 }
 
@@ -430,6 +526,22 @@ static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev)
                return ret;
        }
 
+       if (IS_ENABLED(CONFIG_PCI_MSI)) {
+               pp->msi_irq = platform_get_irq(pdev, 0);
+               if (!pp->msi_irq) {
+                       dev_err(&pdev->dev, "failed to get msi irq\n");
+                       return -ENODEV;
+               }
+
+               ret = devm_request_irq(&pdev->dev, pp->msi_irq,
+                                       exynos_pcie_msi_irq_handler,
+                                       IRQF_SHARED, "exynos-pcie", pp);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to request msi irq\n");
+                       return ret;
+               }
+       }
+
        pp->root_bus_nr = -1;
        pp->ops = &exynos_pcie_host_ops;
 
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
new file mode 100644 (file)
index 0000000..5afa922
--- /dev/null
@@ -0,0 +1,575 @@
+/*
+ * PCIe host controller driver for Freescale i.MX6 SoCs
+ *
+ * Copyright (C) 2013 Kosagi
+ *             http://www.kosagi.com
+ *
+ * Author: Sean Cross <xobs@kosagi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/resource.h>
+#include <linux/signal.h>
+#include <linux/types.h>
+
+#include "pcie-designware.h"
+
+#define to_imx6_pcie(x)        container_of(x, struct imx6_pcie, pp)
+
+struct imx6_pcie {
+       int                     reset_gpio;
+       int                     power_on_gpio;
+       int                     wake_up_gpio;
+       int                     disable_gpio;
+       struct clk              *lvds_gate;
+       struct clk              *sata_ref_100m;
+       struct clk              *pcie_ref_125m;
+       struct clk              *pcie_axi;
+       struct pcie_port        pp;
+       struct regmap           *iomuxc_gpr;
+       void __iomem            *mem_base;
+};
+
+/* PCIe Port Logic registers (memory-mapped) */
+#define PL_OFFSET 0x700
+#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
+#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
+
+#define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
+#define PCIE_PHY_CTRL_DATA_LOC 0
+#define PCIE_PHY_CTRL_CAP_ADR_LOC 16
+#define PCIE_PHY_CTRL_CAP_DAT_LOC 17
+#define PCIE_PHY_CTRL_WR_LOC 18
+#define PCIE_PHY_CTRL_RD_LOC 19
+
+#define PCIE_PHY_STAT (PL_OFFSET + 0x110)
+#define PCIE_PHY_STAT_ACK_LOC 16
+
+/* PHY registers (not memory-mapped) */
+#define PCIE_PHY_RX_ASIC_OUT 0x100D
+
+#define PHY_RX_OVRD_IN_LO 0x1005
+#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
+#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3)
+
+static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val)
+{
+       u32 val;
+       u32 max_iterations = 10;
+       u32 wait_counter = 0;
+
+       do {
+               val = readl(dbi_base + PCIE_PHY_STAT);
+               val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1;
+               wait_counter++;
+
+               if (val == exp_val)
+                       return 0;
+
+               udelay(1);
+       } while (wait_counter < max_iterations);
+
+       return -ETIMEDOUT;
+}
+
+static int pcie_phy_wait_ack(void __iomem *dbi_base, int addr)
+{
+       u32 val;
+       int ret;
+
+       val = addr << PCIE_PHY_CTRL_DATA_LOC;
+       writel(val, dbi_base + PCIE_PHY_CTRL);
+
+       val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC);
+       writel(val, dbi_base + PCIE_PHY_CTRL);
+
+       ret = pcie_phy_poll_ack(dbi_base, 1);
+       if (ret)
+               return ret;
+
+       val = addr << PCIE_PHY_CTRL_DATA_LOC;
+       writel(val, dbi_base + PCIE_PHY_CTRL);
+
+       ret = pcie_phy_poll_ack(dbi_base, 0);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
+static int pcie_phy_read(void __iomem *dbi_base, int addr , int *data)
+{
+       u32 val, phy_ctl;
+       int ret;
+
+       ret = pcie_phy_wait_ack(dbi_base, addr);
+       if (ret)
+               return ret;
+
+       /* assert Read signal */
+       phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC;
+       writel(phy_ctl, dbi_base + PCIE_PHY_CTRL);
+
+       ret = pcie_phy_poll_ack(dbi_base, 1);
+       if (ret)
+               return ret;
+
+       val = readl(dbi_base + PCIE_PHY_STAT);
+       *data = val & 0xffff;
+
+       /* deassert Read signal */
+       writel(0x00, dbi_base + PCIE_PHY_CTRL);
+
+       ret = pcie_phy_poll_ack(dbi_base, 0);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int pcie_phy_write(void __iomem *dbi_base, int addr, int data)
+{
+       u32 var;
+       int ret;
+
+       /* write addr */
+       /* cap addr */
+       ret = pcie_phy_wait_ack(dbi_base, addr);
+       if (ret)
+               return ret;
+
+       var = data << PCIE_PHY_CTRL_DATA_LOC;
+       writel(var, dbi_base + PCIE_PHY_CTRL);
+
+       /* capture data */
+       var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC);
+       writel(var, dbi_base + PCIE_PHY_CTRL);
+
+       ret = pcie_phy_poll_ack(dbi_base, 1);
+       if (ret)
+               return ret;
+
+       /* deassert cap data */
+       var = data << PCIE_PHY_CTRL_DATA_LOC;
+       writel(var, dbi_base + PCIE_PHY_CTRL);
+
+       /* wait for ack de-assertion */
+       ret = pcie_phy_poll_ack(dbi_base, 0);
+       if (ret)
+               return ret;
+
+       /* assert wr signal */
+       var = 0x1 << PCIE_PHY_CTRL_WR_LOC;
+       writel(var, dbi_base + PCIE_PHY_CTRL);
+
+       /* wait for ack */
+       ret = pcie_phy_poll_ack(dbi_base, 1);
+       if (ret)
+               return ret;
+
+       /* deassert wr signal */
+       var = data << PCIE_PHY_CTRL_DATA_LOC;
+       writel(var, dbi_base + PCIE_PHY_CTRL);
+
+       /* wait for ack de-assertion */
+       ret = pcie_phy_poll_ack(dbi_base, 0);
+       if (ret)
+               return ret;
+
+       writel(0x0, dbi_base + PCIE_PHY_CTRL);
+
+       return 0;
+}
+
+/*  Added for PCI abort handling */
+static int imx6q_pcie_abort_handler(unsigned long addr,
+               unsigned int fsr, struct pt_regs *regs)
+{
+       /*
+        * If it was an imprecise abort, then we need to correct the
+        * return address to be _after_ the instruction.
+        */
+       if (fsr & (1 << 10))
+               regs->ARM_pc += 4;
+       return 0;
+}
+
+static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
+{
+       struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+                       IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                       IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+                       IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
+
+       gpio_set_value(imx6_pcie->reset_gpio, 0);
+       msleep(100);
+       gpio_set_value(imx6_pcie->reset_gpio, 1);
+
+       return 0;
+}
+
+static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
+{
+       struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+       int ret;
+
+       if (gpio_is_valid(imx6_pcie->power_on_gpio))
+               gpio_set_value(imx6_pcie->power_on_gpio, 1);
+
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+                       IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+                       IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
+
+       ret = clk_prepare_enable(imx6_pcie->sata_ref_100m);
+       if (ret) {
+               dev_err(pp->dev, "unable to enable sata_ref_100m\n");
+               goto err_sata_ref;
+       }
+
+       ret = clk_prepare_enable(imx6_pcie->pcie_ref_125m);
+       if (ret) {
+               dev_err(pp->dev, "unable to enable pcie_ref_125m\n");
+               goto err_pcie_ref;
+       }
+
+       ret = clk_prepare_enable(imx6_pcie->lvds_gate);
+       if (ret) {
+               dev_err(pp->dev, "unable to enable lvds_gate\n");
+               goto err_lvds_gate;
+       }
+
+       ret = clk_prepare_enable(imx6_pcie->pcie_axi);
+       if (ret) {
+               dev_err(pp->dev, "unable to enable pcie_axi\n");
+               goto err_pcie_axi;
+       }
+
+       /* allow the clocks to stabilize */
+       usleep_range(200, 500);
+
+       return 0;
+
+err_pcie_axi:
+       clk_disable_unprepare(imx6_pcie->lvds_gate);
+err_lvds_gate:
+       clk_disable_unprepare(imx6_pcie->pcie_ref_125m);
+err_pcie_ref:
+       clk_disable_unprepare(imx6_pcie->sata_ref_100m);
+err_sata_ref:
+       return ret;
+
+}
+
+static void imx6_pcie_init_phy(struct pcie_port *pp)
+{
+       struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                       IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
+
+       /* configure constant input signal to the pcie ctrl and phy */
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                       IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                       IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
+
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                       IMX6Q_GPR8_TX_DEEMPH_GEN1, 0 << 0);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                       IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, 0 << 6);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                       IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, 20 << 12);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                       IMX6Q_GPR8_TX_SWING_FULL, 127 << 18);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                       IMX6Q_GPR8_TX_SWING_LOW, 127 << 25);
+}
+
+static void imx6_pcie_host_init(struct pcie_port *pp)
+{
+       int count = 0;
+       struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+
+       imx6_pcie_assert_core_reset(pp);
+
+       imx6_pcie_init_phy(pp);
+
+       imx6_pcie_deassert_core_reset(pp);
+
+       dw_pcie_setup_rc(pp);
+
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                       IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
+
+       while (!dw_pcie_link_up(pp)) {
+               usleep_range(100, 1000);
+               count++;
+               if (count >= 10) {
+                       dev_err(pp->dev, "phy link never came up\n");
+                       dev_dbg(pp->dev,
+                               "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
+                               readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
+                               readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
+                       break;
+               }
+       }
+
+       return;
+}
+
+static int imx6_pcie_link_up(struct pcie_port *pp)
+{
+       u32 rc, ltssm, rx_valid, temp;
+
+       /* link is debug bit 36, debug register 1 starts at bit 32 */
+       rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & (0x1 << (36 - 32));
+       if (rc)
+               return -EAGAIN;
+
+       /*
+        * From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
+        * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2).
+        * If (MAC/LTSSM.state == Recovery.RcvrLock)
+        * && (PHY/rx_valid==0) then pulse PHY/rx_reset. Transition
+        * to gen2 is stuck
+        */
+       pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
+       ltssm = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0) & 0x3F;
+
+       if (rx_valid & 0x01)
+               return 0;
+
+       if (ltssm != 0x0d)
+               return 0;
+
+       dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n");
+
+       pcie_phy_read(pp->dbi_base,
+               PHY_RX_OVRD_IN_LO, &temp);
+       temp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN
+               | PHY_RX_OVRD_IN_LO_RX_PLL_EN);
+       pcie_phy_write(pp->dbi_base,
+               PHY_RX_OVRD_IN_LO, temp);
+
+       usleep_range(2000, 3000);
+
+       pcie_phy_read(pp->dbi_base,
+               PHY_RX_OVRD_IN_LO, &temp);
+       temp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN
+               | PHY_RX_OVRD_IN_LO_RX_PLL_EN);
+       pcie_phy_write(pp->dbi_base,
+               PHY_RX_OVRD_IN_LO, temp);
+
+       return 0;
+}
+
+static struct pcie_host_ops imx6_pcie_host_ops = {
+       .link_up = imx6_pcie_link_up,
+       .host_init = imx6_pcie_host_init,
+};
+
+static int imx6_add_pcie_port(struct pcie_port *pp,
+                       struct platform_device *pdev)
+{
+       int ret;
+
+       pp->irq = platform_get_irq(pdev, 0);
+       if (!pp->irq) {
+               dev_err(&pdev->dev, "failed to get irq\n");
+               return -ENODEV;
+       }
+
+       pp->root_bus_nr = -1;
+       pp->ops = &imx6_pcie_host_ops;
+
+       spin_lock_init(&pp->conf_lock);
+       ret = dw_pcie_host_init(pp);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to initialize host\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int __init imx6_pcie_probe(struct platform_device *pdev)
+{
+       struct imx6_pcie *imx6_pcie;
+       struct pcie_port *pp;
+       struct device_node *np = pdev->dev.of_node;
+       struct resource *dbi_base;
+       int ret;
+
+       imx6_pcie = devm_kzalloc(&pdev->dev, sizeof(*imx6_pcie), GFP_KERNEL);
+       if (!imx6_pcie)
+               return -ENOMEM;
+
+       pp = &imx6_pcie->pp;
+       pp->dev = &pdev->dev;
+
+       /* Added for PCI abort handling */
+       hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
+               "imprecise external abort");
+
+       dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!dbi_base) {
+               dev_err(&pdev->dev, "dbi_base memory resource not found\n");
+               return -ENODEV;
+       }
+
+       pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
+       if (IS_ERR(pp->dbi_base)) {
+               dev_err(&pdev->dev, "unable to remap dbi_base\n");
+               ret = PTR_ERR(pp->dbi_base);
+               goto err;
+       }
+
+       /* Fetch GPIOs */
+       imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
+       if (!gpio_is_valid(imx6_pcie->reset_gpio)) {
+               dev_err(&pdev->dev, "no reset-gpio defined\n");
+               ret = -ENODEV;
+       }
+       ret = devm_gpio_request_one(&pdev->dev,
+                               imx6_pcie->reset_gpio,
+                               GPIOF_OUT_INIT_LOW,
+                               "PCIe reset");
+       if (ret) {
+               dev_err(&pdev->dev, "unable to get reset gpio\n");
+               goto err;
+       }
+
+       imx6_pcie->power_on_gpio = of_get_named_gpio(np, "power-on-gpio", 0);
+       if (gpio_is_valid(imx6_pcie->power_on_gpio)) {
+               ret = devm_gpio_request_one(&pdev->dev,
+                                       imx6_pcie->power_on_gpio,
+                                       GPIOF_OUT_INIT_LOW,
+                                       "PCIe power enable");
+               if (ret) {
+                       dev_err(&pdev->dev, "unable to get power-on gpio\n");
+                       goto err;
+               }
+       }
+
+       imx6_pcie->wake_up_gpio = of_get_named_gpio(np, "wake-up-gpio", 0);
+       if (gpio_is_valid(imx6_pcie->wake_up_gpio)) {
+               ret = devm_gpio_request_one(&pdev->dev,
+                                       imx6_pcie->wake_up_gpio,
+                                       GPIOF_IN,
+                                       "PCIe wake up");
+               if (ret) {
+                       dev_err(&pdev->dev, "unable to get wake-up gpio\n");
+                       goto err;
+               }
+       }
+
+       imx6_pcie->disable_gpio = of_get_named_gpio(np, "disable-gpio", 0);
+       if (gpio_is_valid(imx6_pcie->disable_gpio)) {
+               ret = devm_gpio_request_one(&pdev->dev,
+                                       imx6_pcie->disable_gpio,
+                                       GPIOF_OUT_INIT_HIGH,
+                                       "PCIe disable endpoint");
+               if (ret) {
+                       dev_err(&pdev->dev, "unable to get disable-ep gpio\n");
+                       goto err;
+               }
+       }
+
+       /* Fetch clocks */
+       imx6_pcie->lvds_gate = devm_clk_get(&pdev->dev, "lvds_gate");
+       if (IS_ERR(imx6_pcie->lvds_gate)) {
+               dev_err(&pdev->dev,
+                       "lvds_gate clock select missing or invalid\n");
+               ret = PTR_ERR(imx6_pcie->lvds_gate);
+               goto err;
+       }
+
+       imx6_pcie->sata_ref_100m = devm_clk_get(&pdev->dev, "sata_ref_100m");
+       if (IS_ERR(imx6_pcie->sata_ref_100m)) {
+               dev_err(&pdev->dev,
+                       "sata_ref_100m clock source missing or invalid\n");
+               ret = PTR_ERR(imx6_pcie->sata_ref_100m);
+               goto err;
+       }
+
+       imx6_pcie->pcie_ref_125m = devm_clk_get(&pdev->dev, "pcie_ref_125m");
+       if (IS_ERR(imx6_pcie->pcie_ref_125m)) {
+               dev_err(&pdev->dev,
+                       "pcie_ref_125m clock source missing or invalid\n");
+               ret = PTR_ERR(imx6_pcie->pcie_ref_125m);
+               goto err;
+       }
+
+       imx6_pcie->pcie_axi = devm_clk_get(&pdev->dev, "pcie_axi");
+       if (IS_ERR(imx6_pcie->pcie_axi)) {
+               dev_err(&pdev->dev,
+                       "pcie_axi clock source missing or invalid\n");
+               ret = PTR_ERR(imx6_pcie->pcie_axi);
+               goto err;
+       }
+
+       /* Grab GPR config register range */
+       imx6_pcie->iomuxc_gpr =
+                syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+       if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
+               dev_err(&pdev->dev, "unable to find iomuxc registers\n");
+               ret = PTR_ERR(imx6_pcie->iomuxc_gpr);
+               goto err;
+       }
+
+       ret = imx6_add_pcie_port(pp, pdev);
+       if (ret < 0)
+               goto err;
+
+       platform_set_drvdata(pdev, imx6_pcie);
+       return 0;
+
+err:
+       return ret;
+}
+
+static const struct of_device_id imx6_pcie_of_match[] = {
+       { .compatible = "fsl,imx6q-pcie", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, imx6_pcie_of_match);
+
+static struct platform_driver imx6_pcie_driver = {
+       .driver = {
+               .name   = "imx6q-pcie",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(imx6_pcie_of_match),
+       },
+};
+
+/* Freescale PCIe driver does not allow module unload */
+
+static int __init imx6_pcie_init(void)
+{
+       return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe);
+}
+module_init(imx6_pcie_init);
+
+MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>");
+MODULE_DESCRIPTION("Freescale i.MX6 PCIe host controller driver");
+MODULE_LICENSE("GPL v2");
index 2e9888a0635aea41ac5e310ae39e35b564d4874f..7c4f38dd42ba6a5ef868e24e7b033998284fb4ec 100644 (file)
@@ -408,7 +408,7 @@ static void __iomem *tegra_pcie_bus_map(struct tegra_pcie *pcie,
 
        list_for_each_entry(bus, &pcie->busses, list)
                if (bus->nr == busnr)
-                       return bus->area->addr;
+                       return (void __iomem *)bus->area->addr;
 
        bus = tegra_pcie_bus_alloc(pcie, busnr);
        if (IS_ERR(bus))
@@ -416,7 +416,7 @@ static void __iomem *tegra_pcie_bus_map(struct tegra_pcie *pcie,
 
        list_add_tail(&bus->list, &pcie->busses);
 
-       return bus->area->addr;
+       return (void __iomem *)bus->area->addr;
 }
 
 static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus,
index c10e9ac9bbbc81849d8e4fba538ba3b58a96aad5..896301788e9d0253bb22828f8725bb4a40d7510a 100644 (file)
  * published by the Free Software Foundation.
  */
 
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/msi.h>
 #include <linux/of_address.h>
 #include <linux/pci.h>
 #include <linux/pci_regs.h>
@@ -142,6 +145,204 @@ int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
        return ret;
 }
 
+static struct irq_chip dw_msi_irq_chip = {
+       .name = "PCI-MSI",
+       .irq_enable = unmask_msi_irq,
+       .irq_disable = mask_msi_irq,
+       .irq_mask = mask_msi_irq,
+       .irq_unmask = unmask_msi_irq,
+};
+
+/* MSI int handler */
+void dw_handle_msi_irq(struct pcie_port *pp)
+{
+       unsigned long val;
+       int i, pos;
+
+       for (i = 0; i < MAX_MSI_CTRLS; i++) {
+               dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4,
+                               (u32 *)&val);
+               if (val) {
+                       pos = 0;
+                       while ((pos = find_next_bit(&val, 32, pos)) != 32) {
+                               generic_handle_irq(pp->msi_irq_start
+                                       + (i * 32) + pos);
+                               pos++;
+                       }
+               }
+               dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, val);
+       }
+}
+
+void dw_pcie_msi_init(struct pcie_port *pp)
+{
+       pp->msi_data = __get_free_pages(GFP_KERNEL, 0);
+
+       /* program the msi_data */
+       dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4,
+                       virt_to_phys((void *)pp->msi_data));
+       dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, 0);
+}
+
+static int find_valid_pos0(struct pcie_port *pp, int msgvec, int pos, int *pos0)
+{
+       int flag = 1;
+
+       do {
+               pos = find_next_zero_bit(pp->msi_irq_in_use,
+                               MAX_MSI_IRQS, pos);
+               /*if you have reached to the end then get out from here.*/
+               if (pos == MAX_MSI_IRQS)
+                       return -ENOSPC;
+               /*
+                * Check if this position is at correct offset.nvec is always a
+                * power of two. pos0 must be nvec bit alligned.
+                */
+               if (pos % msgvec)
+                       pos += msgvec - (pos % msgvec);
+               else
+                       flag = 0;
+       } while (flag);
+
+       *pos0 = pos;
+       return 0;
+}
+
+static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
+{
+       int res, bit, irq, pos0, pos1, i;
+       u32 val;
+       struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+
+       if (!pp) {
+               BUG();
+               return -EINVAL;
+       }
+
+       pos0 = find_first_zero_bit(pp->msi_irq_in_use,
+                       MAX_MSI_IRQS);
+       if (pos0 % no_irqs) {
+               if (find_valid_pos0(pp, no_irqs, pos0, &pos0))
+                       goto no_valid_irq;
+       }
+       if (no_irqs > 1) {
+               pos1 = find_next_bit(pp->msi_irq_in_use,
+                               MAX_MSI_IRQS, pos0);
+               /* there must be nvec number of consecutive free bits */
+               while ((pos1 - pos0) < no_irqs) {
+                       if (find_valid_pos0(pp, no_irqs, pos1, &pos0))
+                               goto no_valid_irq;
+                       pos1 = find_next_bit(pp->msi_irq_in_use,
+                                       MAX_MSI_IRQS, pos0);
+               }
+       }
+
+       irq = (pp->msi_irq_start + pos0);
+
+       if ((irq + no_irqs) > (pp->msi_irq_start + MAX_MSI_IRQS-1))
+               goto no_valid_irq;
+
+       i = 0;
+       while (i < no_irqs) {
+               set_bit(pos0 + i, pp->msi_irq_in_use);
+               irq_alloc_descs((irq + i), (irq + i), 1, 0);
+               irq_set_msi_desc(irq + i, desc);
+               /*Enable corresponding interrupt in MSI interrupt controller */
+               res = ((pos0 + i) / 32) * 12;
+               bit = (pos0 + i) % 32;
+               dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
+               val |= 1 << bit;
+               dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+               i++;
+       }
+
+       *pos = pos0;
+       return irq;
+
+no_valid_irq:
+       *pos = pos0;
+       return -ENOSPC;
+}
+
+static void clear_irq(unsigned int irq)
+{
+       int res, bit, val, pos;
+       struct irq_desc *desc;
+       struct msi_desc *msi;
+       struct pcie_port *pp;
+
+       /* get the port structure */
+       desc = irq_to_desc(irq);
+       msi = irq_desc_get_msi_desc(desc);
+       pp = sys_to_pcie(msi->dev->bus->sysdata);
+       if (!pp) {
+               BUG();
+               return;
+       }
+
+       pos = irq - pp->msi_irq_start;
+
+       irq_free_desc(irq);
+
+       clear_bit(pos, pp->msi_irq_in_use);
+
+       /* Disable corresponding interrupt on MSI interrupt controller */
+       res = (pos / 32) * 12;
+       bit = pos % 32;
+       dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
+       val &= ~(1 << bit);
+       dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+}
+
+static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
+                       struct msi_desc *desc)
+{
+       int irq, pos, msgvec;
+       u16 msg_ctr;
+       struct msi_msg msg;
+       struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+
+       if (!pp) {
+               BUG();
+               return -EINVAL;
+       }
+
+       pci_read_config_word(pdev, desc->msi_attrib.pos+PCI_MSI_FLAGS,
+                               &msg_ctr);
+       msgvec = (msg_ctr&PCI_MSI_FLAGS_QSIZE) >> 4;
+       if (msgvec == 0)
+               msgvec = (msg_ctr & PCI_MSI_FLAGS_QMASK) >> 1;
+       if (msgvec > 5)
+               msgvec = 0;
+
+       irq = assign_irq((1 << msgvec), desc, &pos);
+       if (irq < 0)
+               return irq;
+
+       msg_ctr &= ~PCI_MSI_FLAGS_QSIZE;
+       msg_ctr |= msgvec << 4;
+       pci_write_config_word(pdev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
+                               msg_ctr);
+       desc->msi_attrib.multiple = msgvec;
+
+       msg.address_lo = virt_to_phys((void *)pp->msi_data);
+       msg.address_hi = 0x0;
+       msg.data = pos;
+       write_msi_msg(irq, &msg);
+
+       return 0;
+}
+
+static void dw_msi_teardown_irq(struct msi_chip *chip, unsigned int irq)
+{
+       clear_irq(irq);
+}
+
+static struct msi_chip dw_pcie_msi_chip = {
+       .setup_irq = dw_msi_setup_irq,
+       .teardown_irq = dw_msi_teardown_irq,
+};
+
 int dw_pcie_link_up(struct pcie_port *pp)
 {
        if (pp->ops->link_up)
@@ -150,6 +351,20 @@ int dw_pcie_link_up(struct pcie_port *pp)
                return 0;
 }
 
+static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
+                       irq_hw_number_t hwirq)
+{
+       irq_set_chip_and_handler(irq, &dw_msi_irq_chip, handle_simple_irq);
+       irq_set_chip_data(irq, domain->host_data);
+       set_irq_flags(irq, IRQF_VALID);
+
+       return 0;
+}
+
+static const struct irq_domain_ops msi_domain_ops = {
+       .map = dw_pcie_msi_map,
+};
+
 int __init dw_pcie_host_init(struct pcie_port *pp)
 {
        struct device_node *np = pp->dev->of_node;
@@ -157,6 +372,8 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
        struct of_pci_range_parser parser;
        u32 val;
 
+       struct irq_domain *irq_domain;
+
        if (of_pci_range_parser_init(&parser, np)) {
                dev_err(pp->dev, "missing ranges property\n");
                return -EINVAL;
@@ -223,6 +440,18 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
                return -EINVAL;
        }
 
+       if (IS_ENABLED(CONFIG_PCI_MSI)) {
+               irq_domain = irq_domain_add_linear(pp->dev->of_node,
+                                       MAX_MSI_IRQS, &msi_domain_ops,
+                                       &dw_pcie_msi_chip);
+               if (!irq_domain) {
+                       dev_err(pp->dev, "irq domain init failed\n");
+                       return -ENXIO;
+               }
+
+               pp->msi_irq_start = irq_find_mapping(irq_domain, 0);
+       }
+
        if (pp->ops->host_init)
                pp->ops->host_init(pp);
 
@@ -485,10 +714,21 @@ int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return pp->irq;
 }
 
+static void dw_pcie_add_bus(struct pci_bus *bus)
+{
+       if (IS_ENABLED(CONFIG_PCI_MSI)) {
+               struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+
+               dw_pcie_msi_chip.dev = pp->dev;
+               bus->msi = &dw_pcie_msi_chip;
+       }
+}
+
 static struct hw_pci dw_pci = {
        .setup          = dw_pcie_setup,
        .scan           = dw_pcie_scan_bus,
        .map_irq        = dw_pcie_map_irq,
+       .add_bus        = dw_pcie_add_bus,
 };
 
 void dw_pcie_setup_rc(struct pcie_port *pp)
index 133820f1da971ecc19997b5e6e245f3cc992aaa4..faccbbf31907c11b01971f3105ff7ea29c9339e7 100644 (file)
@@ -20,6 +20,14 @@ struct pcie_port_info {
        phys_addr_t     mem_bus_addr;
 };
 
+/*
+ * Maximum number of MSI IRQs can be 256 per controller. But keep
+ * it 32 as of now. Probably we will never need more than 32. If needed,
+ * then increment it in multiple of 32.
+ */
+#define MAX_MSI_IRQS                   32
+#define MAX_MSI_CTRLS                  (MAX_MSI_IRQS / 32)
+
 struct pcie_port {
        struct device           *dev;
        u8                      root_bus_nr;
@@ -38,6 +46,10 @@ struct pcie_port {
        int                     irq;
        u32                     lanes;
        struct pcie_host_ops    *ops;
+       int                     msi_irq;
+       int                     msi_irq_start;
+       unsigned long           msi_data;
+       DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
 };
 
 struct pcie_host_ops {
@@ -57,6 +69,8 @@ int cfg_read(void __iomem *addr, int where, int size, u32 *val);
 int cfg_write(void __iomem *addr, int where, int size, u32 val);
 int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, u32 val);
 int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, u32 *val);
+void dw_handle_msi_irq(struct pcie_port *pp);
+void dw_pcie_msi_init(struct pcie_port *pp);
 int dw_pcie_link_up(struct pcie_port *pp);
 void dw_pcie_setup_rc(struct pcie_port *pp);
 int dw_pcie_host_init(struct pcie_port *pp);
index 2a47e82821dacff72dd227950a6c3de828755053..f8140164ec0b9bc8942c3b8a026490c1aec4c190 100644 (file)
@@ -338,7 +338,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
        acpi_handle chandle, handle;
        struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
 
-       flags &= OSC_SHPC_NATIVE_HP_CONTROL;
+       flags &= OSC_PCI_SHPC_NATIVE_HP_CONTROL;
        if (!flags) {
                err("Invalid flags %u specified!\n", flags);
                return -EINVAL;
index f4e0289246672c0a9157927303945f0934e26d31..26100f510b1087f45bbe39b79dcf9649acf38e9d 100644 (file)
 #include <linux/mutex.h>
 #include <linux/pci_hotplug.h>
 
-#define dbg(format, arg...)                                    \
-       do {                                                    \
-               if (acpiphp_debug)                              \
-                       printk(KERN_DEBUG "%s: " format,        \
-                               MY_NAME , ## arg);              \
-       } while (0)
-#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
-
 struct acpiphp_context;
 struct acpiphp_bridge;
 struct acpiphp_slot;
index bf2203ef1308bfa13f3e8b2744db6bd0b2adbcb8..8650d39db3922c74d36a01029068ca7b03c75935 100644 (file)
@@ -31,6 +31,8 @@
  *
  */
 
+#define pr_fmt(fmt) "acpiphp: " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/smp.h>
 #include "acpiphp.h"
 
-#define MY_NAME        "acpiphp"
-
 /* name size which is used for entries in pcihpfs */
 #define SLOT_NAME_SIZE  21              /* {_SUN} */
 
-bool acpiphp_debug;
 bool acpiphp_disabled;
 
 /* local variables */
@@ -61,9 +60,7 @@ static struct acpiphp_attention_info *attention_info;
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
 MODULE_PARM_DESC(disable, "disable acpiphp driver");
-module_param_named(debug, acpiphp_debug, bool, 0644);
 module_param_named(disable, acpiphp_disabled, bool, 0444);
 
 /* export the attention callback registration methods */
@@ -139,7 +136,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
 {
        struct slot *slot = hotplug_slot->private;
 
-       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
+       pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        /* enable the specified slot */
        return acpiphp_enable_slot(slot->acpi_slot);
@@ -156,7 +153,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
        struct slot *slot = hotplug_slot->private;
 
-       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
+       pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        /* disable the specified slot */
        return acpiphp_disable_and_eject_slot(slot->acpi_slot);
@@ -176,8 +173,9 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
  {
        int retval = -ENODEV;
 
-       dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot));
+       pr_debug("%s - physical_slot = %s\n", __func__,
+               hotplug_slot_name(hotplug_slot));
+
        if (attention_info && try_module_get(attention_info->owner)) {
                retval = attention_info->set_attn(hotplug_slot, status);
                module_put(attention_info->owner);
@@ -199,7 +197,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
 {
        struct slot *slot = hotplug_slot->private;
 
-       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
+       pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        *value = acpiphp_get_power_status(slot->acpi_slot);
 
@@ -221,7 +219,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
 {
        int retval = -EINVAL;
 
-       dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot));
+       pr_debug("%s - physical_slot = %s\n", __func__,
+               hotplug_slot_name(hotplug_slot));
 
        if (attention_info && try_module_get(attention_info->owner)) {
                retval = attention_info->get_attn(hotplug_slot, value);
@@ -244,7 +243,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
 {
        struct slot *slot = hotplug_slot->private;
 
-       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
+       pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        *value = acpiphp_get_latch_status(slot->acpi_slot);
 
@@ -264,7 +263,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
 {
        struct slot *slot = hotplug_slot->private;
 
-       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
+       pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        *value = acpiphp_get_adapter_status(slot->acpi_slot);
 
@@ -279,7 +278,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
 {
        struct slot *slot = hotplug_slot->private;
 
-       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
+       pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        kfree(slot->hotplug_slot);
        kfree(slot);
@@ -322,11 +321,11 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot,
        if (retval == -EBUSY)
                goto error_hpslot;
        if (retval) {
-               err("pci_hp_register failed with error %d\n", retval);
+               pr_err("pci_hp_register failed with error %d\n", retval);
                goto error_hpslot;
        }
 
-       info("Slot [%s] registered\n", slot_name(slot));
+       pr_info("Slot [%s] registered\n", slot_name(slot));
 
        return 0;
 error_hpslot:
@@ -343,17 +342,17 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
        struct slot *slot = acpiphp_slot->slot;
        int retval = 0;
 
-       info("Slot [%s] unregistered\n", slot_name(slot));
+       pr_info("Slot [%s] unregistered\n", slot_name(slot));
 
        retval = pci_hp_deregister(slot->hotplug_slot);
        if (retval)
-               err("pci_hp_deregister failed with error %d\n", retval);
+               pr_err("pci_hp_deregister failed with error %d\n", retval);
 }
 
 
 void __init acpiphp_init(void)
 {
-       info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n",
+       pr_info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n",
                acpiphp_disabled ? ", disabled by user; please report a bug"
                                 : "");
 }
index be12fbfcae1042e90c00d192bffe46c47821b6c4..9d066b86c72421aa82683a3a7ba31c05d7021869 100644 (file)
@@ -39,6 +39,8 @@
  *    bus. It loses the refcount when the the driver unloads.
  */
 
+#define pr_fmt(fmt) "acpiphp_glue: " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 
@@ -58,8 +60,6 @@ static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
 static DEFINE_MUTEX(acpiphp_context_lock);
 
-#define MY_NAME "acpiphp_glue"
-
 static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
@@ -335,7 +335,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
                if (ACPI_FAILURE(status))
                        sun = bridge->nr_slots;
 
-               dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n",
+               pr_debug("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n",
                    sun, pci_domain_nr(pbus), pbus->number, device);
 
                retval = acpiphp_register_hotplug_slot(slot, sun);
@@ -343,10 +343,10 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
                        slot->slot = NULL;
                        bridge->nr_slots--;
                        if (retval == -EBUSY)
-                               warn("Slot %llu already registered by another "
+                               pr_warn("Slot %llu already registered by another "
                                        "hotplug driver\n", sun);
                        else
-                               warn("acpiphp_register_hotplug_slot failed "
+                               pr_warn("acpiphp_register_hotplug_slot failed "
                                        "(err code = 0x%x)\n", retval);
                }
                /* Even if the slot registration fails, we can still use it. */
@@ -369,7 +369,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
                if (register_hotplug_dock_device(handle,
                        &acpiphp_dock_ops, context,
                        acpiphp_dock_init, acpiphp_dock_release))
-                       dbg("failed to register dock device\n");
+                       pr_debug("failed to register dock device\n");
        }
 
        /* install notify handler */
@@ -427,7 +427,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
                                                        ACPI_SYSTEM_NOTIFY,
                                                        handle_hotplug_event);
                                if (ACPI_FAILURE(status))
-                                       err("failed to remove notify handler\n");
+                                       pr_err("failed to remove notify handler\n");
                        }
                }
                if (slot->slot)
@@ -830,8 +830,9 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
                /* bus re-enumerate */
-               dbg("%s: Bus check notify on %s\n", __func__, objname);
-               dbg("%s: re-enumerating slots under %s\n", __func__, objname);
+               pr_debug("%s: Bus check notify on %s\n", __func__, objname);
+               pr_debug("%s: re-enumerating slots under %s\n",
+                        __func__, objname);
                if (bridge) {
                        acpiphp_check_bridge(bridge);
                } else {
@@ -845,7 +846,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
 
        case ACPI_NOTIFY_DEVICE_CHECK:
                /* device check */
-               dbg("%s: Device check notify on %s\n", __func__, objname);
+               pr_debug("%s: Device check notify on %s\n", __func__, objname);
                if (bridge) {
                        acpiphp_check_bridge(bridge);
                } else {
@@ -866,7 +867,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
 
        case ACPI_NOTIFY_EJECT_REQUEST:
                /* request device eject */
-               dbg("%s: Device eject notify on %s\n", __func__, objname);
+               pr_debug("%s: Device eject notify on %s\n", __func__, objname);
                acpiphp_disable_and_eject_slot(func->slot);
                break;
        }
index 2f5786c8522c2f170d8f57bc08c592e0ef78048a..0d64c414bf7876a74baf7acc4ebf6664c8bc7542 100644 (file)
@@ -25,6 +25,8 @@
  *
  */
 
+#define pr_fmt(fmt) "acpiphp_ibm: " fmt
+
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #define DRIVER_AUTHOR  "Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"
 #define DRIVER_DESC    "ACPI Hot Plug PCI Controller Driver IBM extension"
 
-static bool debug;
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRIVER_VERSION);
-module_param(debug, bool, 0644);
-MODULE_PARM_DESC(debug, " Debugging mode enabled or not");
-#define MY_NAME "acpiphp_ibm"
-
-#undef dbg
-#define dbg(format, arg...)                            \
-do {                                                   \
-       if (debug)                                      \
-               printk(KERN_DEBUG "%s: " format,        \
-                               MY_NAME , ## arg);      \
-} while (0)
 
 #define FOUND_APCI 0x61504349
 /* these are the names for the IBM ACPI pseudo-device */
@@ -189,7 +179,7 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
 
        ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot));
 
-       dbg("%s: set slot %d (%d) attention status to %d\n", __func__,
+       pr_debug("%s: set slot %d (%d) attention status to %d\n", __func__,
                        ibm_slot->slot.slot_num, ibm_slot->slot.slot_id,
                        (status ? 1 : 0));
 
@@ -202,10 +192,10 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
 
        stat = acpi_evaluate_integer(ibm_acpi_handle, "APLS", &params, &rc);
        if (ACPI_FAILURE(stat)) {
-               err("APLS evaluation failed:  0x%08x\n", stat);
+               pr_err("APLS evaluation failed:  0x%08x\n", stat);
                return -ENODEV;
        } else if (!rc) {
-               err("APLS method failed:  0x%08llx\n", rc);
+               pr_err("APLS method failed:  0x%08llx\n", rc);
                return -ERANGE;
        }
        return 0;
@@ -234,7 +224,7 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)
        else
                *status = 0;
 
-       dbg("%s: get slot %d (%d) attention status is %d\n", __func__,
+       pr_debug("%s: get slot %d (%d) attention status is %d\n", __func__,
                        ibm_slot->slot.slot_num, ibm_slot->slot.slot_id,
                        *status);
 
@@ -266,10 +256,10 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context)
        u8 subevent = event & 0xf0;
        struct notification *note = context;
 
-       dbg("%s: Received notification %02x\n", __func__, event);
+       pr_debug("%s: Received notification %02x\n", __func__, event);
 
        if (subevent == 0x80) {
-               dbg("%s: generationg bus event\n", __func__);
+               pr_debug("%s: generationg bus event\n", __func__);
                acpi_bus_generate_netlink_event(note->device->pnp.device_class,
                                                  dev_name(&note->device->dev),
                                                  note->event, detail);
@@ -301,7 +291,7 @@ static int ibm_get_table_from_acpi(char **bufp)
 
        status = acpi_evaluate_object(ibm_acpi_handle, "APCI", NULL, &buffer);
        if (ACPI_FAILURE(status)) {
-               err("%s:  APCI evaluation failed\n", __func__);
+               pr_err("%s:  APCI evaluation failed\n", __func__);
                return -ENODEV;
        }
 
@@ -309,13 +299,13 @@ static int ibm_get_table_from_acpi(char **bufp)
        if (!(package) ||
                        (package->type != ACPI_TYPE_PACKAGE) ||
                        !(package->package.elements)) {
-               err("%s:  Invalid APCI object\n", __func__);
+               pr_err("%s:  Invalid APCI object\n", __func__);
                goto read_table_done;
        }
 
        for(size = 0, i = 0; i < package->package.count; i++) {
                if (package->package.elements[i].type != ACPI_TYPE_BUFFER) {
-                       err("%s:  Invalid APCI element %d\n", __func__, i);
+                       pr_err("%s:  Invalid APCI element %d\n", __func__, i);
                        goto read_table_done;
                }
                size += package->package.elements[i].buffer.length;
@@ -325,7 +315,7 @@ static int ibm_get_table_from_acpi(char **bufp)
                goto read_table_done;
 
        lbuf = kzalloc(size, GFP_KERNEL);
-       dbg("%s: element count: %i, ASL table size: %i, &table = 0x%p\n",
+       pr_debug("%s: element count: %i, ASL table size: %i, &table = 0x%p\n",
                        __func__, package->package.count, size, lbuf);
 
        if (lbuf) {
@@ -370,8 +360,8 @@ static ssize_t ibm_read_apci_table(struct file *filp, struct kobject *kobj,
 {
        int bytes_read = -EINVAL;
        char *table = NULL;
-       
-       dbg("%s: pos = %d, size = %zd\n", __func__, (int)pos, size);
+
+       pr_debug("%s: pos = %d, size = %zd\n", __func__, (int)pos, size);
 
        if (pos == 0) {
                bytes_read = ibm_get_table_from_acpi(&table);
@@ -403,7 +393,7 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
 
        status = acpi_get_object_info(handle, &info);
        if (ACPI_FAILURE(status)) {
-               err("%s:  Failed to get device information status=0x%x\n",
+               pr_err("%s:  Failed to get device information status=0x%x\n",
                        __func__, status);
                return retval;
        }
@@ -411,7 +401,7 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
        if (info->current_status && (info->valid & ACPI_VALID_HID) &&
                        (!strcmp(info->hardware_id.string, IBM_HARDWARE_ID1) ||
                         !strcmp(info->hardware_id.string, IBM_HARDWARE_ID2))) {
-               dbg("found hardware: %s, handle: %p\n",
+               pr_debug("found hardware: %s, handle: %p\n",
                        info->hardware_id.string, handle);
                *phandle = handle;
                /* returning non-zero causes the search to stop
@@ -432,18 +422,18 @@ static int __init ibm_acpiphp_init(void)
        struct acpi_device *device;
        struct kobject *sysdir = &pci_slots_kset->kobj;
 
-       dbg("%s\n", __func__);
+       pr_debug("%s\n", __func__);
 
        if (acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                        ACPI_UINT32_MAX, ibm_find_acpi_device, NULL,
                        &ibm_acpi_handle, NULL) != FOUND_APCI) {
-               err("%s: acpi_walk_namespace failed\n", __func__);
+               pr_err("%s: acpi_walk_namespace failed\n", __func__);
                retval = -ENODEV;
                goto init_return;
        }
-       dbg("%s: found IBM aPCI device\n", __func__);
+       pr_debug("%s: found IBM aPCI device\n", __func__);
        if (acpi_bus_get_device(ibm_acpi_handle, &device)) {
-               err("%s: acpi_bus_get_device failed\n", __func__);
+               pr_err("%s: acpi_bus_get_device failed\n", __func__);
                retval = -ENODEV;
                goto init_return;
        }
@@ -457,7 +447,7 @@ static int __init ibm_acpiphp_init(void)
                        ACPI_DEVICE_NOTIFY, ibm_handle_events,
                        &ibm_note);
        if (ACPI_FAILURE(status)) {
-               err("%s: Failed to register notification handler\n",
+               pr_err("%s: Failed to register notification handler\n",
                                __func__);
                retval = -EBUSY;
                goto init_cleanup;
@@ -479,17 +469,17 @@ static void __exit ibm_acpiphp_exit(void)
        acpi_status status;
        struct kobject *sysdir = &pci_slots_kset->kobj;
 
-       dbg("%s\n", __func__);
+       pr_debug("%s\n", __func__);
 
        if (acpiphp_unregister_attention(&ibm_attention_info))
-               err("%s: attention info deregistration failed", __func__);
+               pr_err("%s: attention info deregistration failed", __func__);
 
        status = acpi_remove_notify_handler(
                           ibm_acpi_handle,
                           ACPI_DEVICE_NOTIFY,
                           ibm_handle_events);
        if (ACPI_FAILURE(status))
-               err("%s: Notification handler removal failed\n", __func__);
+               pr_err("%s: Notification handler removal failed\n", __func__);
        /* remove the /sys entries */
        sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr);
 }
index e260f207a90e2f22b3be53388e6cc5ab1b294920..d876e4b3c6a98d8412f154a4f63814ec5b27682c 100644 (file)
@@ -191,7 +191,7 @@ static inline const char *slot_name(struct slot *slot)
 #include <linux/pci-acpi.h>
 static inline int get_hp_hw_control_from_firmware(struct pci_dev *dev)
 {
-       u32 flags = OSC_SHPC_NATIVE_HP_CONTROL;
+       u32 flags = OSC_PCI_SHPC_NATIVE_HP_CONTROL;
        return acpi_get_hp_hw_control_from_firmware(dev, flags);
 }
 #else
index bdd64b1b4817f7223fa31db19a118db5a9caaaa5..2f2eedceda34c6c80e0f010fb56144e50a866e29 100644 (file)
@@ -2860,7 +2860,7 @@ void __weak pcibios_set_master(struct pci_dev *dev)
                lat = pcibios_max_latency;
        else
                return;
-       dev_printk(KERN_DEBUG, &dev->dev, "setting latency timer to %d\n", lat);
+
        pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
 }
 
index 7ef0f868b3e07bf48941075e269ef3976d3efcf1..5e14f5a51357cabd86d8e420e7684d3122b30006 100644 (file)
@@ -641,8 +641,7 @@ static void pci_set_bus_speed(struct pci_bus *bus)
                return;
        }
 
-       pos = pci_find_capability(bridge, PCI_CAP_ID_EXP);
-       if (pos) {
+       if (pci_is_pcie(bridge)) {
                u32 linkcap;
                u16 linksta;
 
@@ -984,7 +983,6 @@ void set_pcie_port_type(struct pci_dev *pdev)
        pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
        if (!pos)
                return;
-       pdev->is_pcie = 1;
        pdev->pcie_cap = pos;
        pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
        pdev->pcie_flags_reg = reg16;
index f6c31fabf3af0bbe24f20b949cc0b6373b11ab97..91490453c2296878f19ff8105e9dbbec4d4878b1 100644 (file)
@@ -2954,6 +2954,29 @@ static void disable_igfx_irq(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
 
+/*
+ * PCI devices which are on Intel chips can skip the 10ms delay
+ * before entering D3 mode.
+ */
+static void quirk_remove_d3_delay(struct pci_dev *dev)
+{
+       dev->d3_delay = 0;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c00, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0412, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c0c, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c31, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3a, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3d, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c2d, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c20, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c18, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c1c, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c26, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c4e, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c02, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c22, quirk_remove_d3_delay);
+
 /*
  * Some devices may pass our check in pci_intx_mask_supported if
  * PCI_COMMAND_INTX_DISABLE works though they actually do not properly
index bc26d7990cc3744512c717540565b7c0dfa557ad..4ce83b26ae9ef2dcbdf9e29c81d55751a9525a7e 100644 (file)
@@ -982,7 +982,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
        }
 
        min_align = calculate_mem_align(aligns, max_order);
-       min_align = max(min_align, window_alignment(bus, b_res->flags & mask));
+       min_align = max(min_align, window_alignment(bus, b_res->flags));
        size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
        if (children_add_size > add_size)
                add_size = children_add_size;
@@ -1136,7 +1136,7 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
        }
 
        /* The root bus? */
-       if (!bus->self)
+       if (pci_is_root_bus(bus))
                return;
 
        switch (bus->self->class >> 8) {
index f8ca7becacca15477dd04912acf4ccd11df948fc..7591fa4e28bb2be8ed6e6a64e972568429457f20 100644 (file)
@@ -766,49 +766,20 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
        bfad->pcidev = pdev;
 
        /* Adjust PCIe Maximum Read Request Size */
-       if (pcie_max_read_reqsz > 0) {
-               int pcie_cap_reg;
-               u16 pcie_dev_ctl;
-               u16 mask = 0xffff;
-
-               switch (pcie_max_read_reqsz) {
-               case 128:
-                       mask = 0x0;
-                       break;
-               case 256:
-                       mask = 0x1000;
-                       break;
-               case 512:
-                       mask = 0x2000;
-                       break;
-               case 1024:
-                       mask = 0x3000;
-                       break;
-               case 2048:
-                       mask = 0x4000;
-                       break;
-               case 4096:
-                       mask = 0x5000;
-                       break;
-               default:
-                       break;
-               }
-
-               pcie_cap_reg = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-               if (mask != 0xffff && pcie_cap_reg) {
-                       pcie_cap_reg += 0x08;
-                       pci_read_config_word(pdev, pcie_cap_reg, &pcie_dev_ctl);
-                       if ((pcie_dev_ctl & 0x7000) != mask) {
-                               printk(KERN_WARNING "BFA[%s]: "
+       if (pci_is_pcie(pdev) && pcie_max_read_reqsz) {
+               if (pcie_max_read_reqsz >= 128 &&
+                   pcie_max_read_reqsz <= 4096 &&
+                   is_power_of_2(pcie_max_read_reqsz)) {
+                       int max_rq = pcie_get_readrq(pdev);
+                       printk(KERN_WARNING "BFA[%s]: "
                                "pcie_max_read_request_size is %d, "
-                               "reset to %d\n", bfad->pci_name,
-                               (1 << ((pcie_dev_ctl & 0x7000) >> 12)) << 7,
+                               "reset to %d\n", bfad->pci_name, max_rq,
                                pcie_max_read_reqsz);
-
-                               pcie_dev_ctl &= ~0x7000;
-                               pci_write_config_word(pdev, pcie_cap_reg,
-                                               pcie_dev_ctl | mask);
-                       }
+                       pcie_set_readrq(pdev, pcie_max_read_reqsz);
+               } else {
+                       printk(KERN_WARNING "BFA[%s]: invalid "
+                              "pcie_max_read_request_size %d ignored\n",
+                              bfad->pci_name, pcie_max_read_reqsz);
                }
        }
 
index 0eb35b9b37843852e140e1bb3a601c5fa3e0f3a4..0eaec474895788a6437e12c9907e053c9f74b048 100644 (file)
@@ -852,22 +852,6 @@ csio_hw_get_flash_params(struct csio_hw *hw)
        return 0;
 }
 
-static void
-csio_set_pcie_completion_timeout(struct csio_hw *hw, u8 range)
-{
-       uint16_t val;
-       int pcie_cap;
-
-       if (!csio_pci_capability(hw->pdev, PCI_CAP_ID_EXP, &pcie_cap)) {
-               pci_read_config_word(hw->pdev,
-                                    pcie_cap + PCI_EXP_DEVCTL2, &val);
-               val &= 0xfff0;
-               val |= range ;
-               pci_write_config_word(hw->pdev,
-                                     pcie_cap + PCI_EXP_DEVCTL2, val);
-       }
-}
-
 /*****************************************************************************/
 /* HW State machine assists                                                  */
 /*****************************************************************************/
@@ -2069,8 +2053,10 @@ csio_hw_configure(struct csio_hw *hw)
                goto out;
        }
 
-       /* Set pci completion timeout value to 4 seconds. */
-       csio_set_pcie_completion_timeout(hw, 0xd);
+       /* Set PCIe completion timeout to 4 seconds */
+       if (pci_is_pcie(hw->pdev))
+               pcie_capability_clear_and_set_word(hw->pdev, PCI_EXP_DEVCTL2,
+                               PCI_EXP_DEVCTL2_COMP_TIMEOUT, 0xd);
 
        hw->chip_ops->chip_set_mem_win(hw, MEMWIN_CSIOSTOR);
 
index 62ee7131b20420a7d1d363682dde7192ed152758..30d20e74e48a393b3560a44bb354fb1fd058e60e 100644 (file)
@@ -507,7 +507,7 @@ qlafx00_pci_config(scsi_qla_host_t *vha)
        pci_write_config_word(ha->pdev, PCI_COMMAND, w);
 
        /* PCIe -- adjust Maximum Read Request Size (2048). */
-       if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP))
+       if (pci_is_pcie(ha->pdev))
                pcie_set_readrq(ha->pdev, 2048);
 
        ha->chip_revision = ha->pdev->revision;
@@ -660,10 +660,8 @@ char *
 qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str)
 {
        struct qla_hw_data *ha = vha->hw;
-       int pcie_reg;
 
-       pcie_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP);
-       if (pcie_reg) {
+       if (pci_is_pcie(ha->pdev)) {
                strcpy(str, "PCIe iSA");
                return str;
        }
index 9f01bbbf3a26c9138a9f457fa9af999fa6572b09..bcd57f699ebbcc7dad7d597044c7bc54da22cf52 100644 (file)
@@ -494,18 +494,14 @@ qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str)
        static char *pci_bus_modes[] = { "33", "66", "100", "133", };
        struct qla_hw_data *ha = vha->hw;
        uint32_t pci_bus;
-       int pcie_reg;
 
-       pcie_reg = pci_pcie_cap(ha->pdev);
-       if (pcie_reg) {
+       if (pci_is_pcie(ha->pdev)) {
                char lwstr[6];
-               uint16_t pcie_lstat, lspeed, lwidth;
+               uint32_t lstat, lspeed, lwidth;
 
-               pcie_reg += PCI_EXP_LNKCAP;
-               pci_read_config_word(ha->pdev, pcie_reg, &pcie_lstat);
-               lspeed = pcie_lstat & (BIT_0 | BIT_1 | BIT_2 | BIT_3);
-               lwidth = (pcie_lstat &
-                   (BIT_4 | BIT_5 | BIT_6 | BIT_7 | BIT_8 | BIT_9)) >> 4;
+               pcie_capability_read_dword(ha->pdev, PCI_EXP_LNKCAP, &lstat);
+               lspeed = lstat & PCI_EXP_LNKCAP_SLS;
+               lwidth = (lstat & PCI_EXP_LNKCAP_MLW) >> 4;
 
                strcpy(str, "PCIe (");
                switch (lspeed) {
index a5db4aeefa3642107e28b431c21a89c195569993..e2e52cf53224854e38e5534d3fa12824505b3f77 100644 (file)
@@ -294,58 +294,51 @@ void __init acpi_nvs_nosave_s3(void);
 #endif /* CONFIG_PM_SLEEP */
 
 struct acpi_osc_context {
-       char *uuid_str; /* uuid string */
+       char *uuid_str;                 /* UUID string */
        int rev;
-       struct acpi_buffer cap; /* arg2/arg3 */
-       struct acpi_buffer ret; /* free by caller if success */
+       struct acpi_buffer cap;         /* list of DWORD capabilities */
+       struct acpi_buffer ret;         /* free by caller if success */
 };
 
-#define OSC_QUERY_TYPE                 0
-#define OSC_SUPPORT_TYPE               1
-#define OSC_CONTROL_TYPE               2
-
-/* _OSC DW0 Definition */
-#define OSC_QUERY_ENABLE               1
-#define OSC_REQUEST_ERROR              2
-#define OSC_INVALID_UUID_ERROR         4
-#define OSC_INVALID_REVISION_ERROR     8
-#define OSC_CAPABILITIES_MASK_ERROR    16
-
 acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
 
-/* platform-wide _OSC bits */
-#define OSC_SB_PAD_SUPPORT             1
-#define OSC_SB_PPC_OST_SUPPORT         2
-#define OSC_SB_PR3_SUPPORT             4
-#define OSC_SB_HOTPLUG_OST_SUPPORT     8
-#define OSC_SB_APEI_SUPPORT            16
+/* Indexes into _OSC Capabilities Buffer (DWORDs 2 & 3 are device-specific) */
+#define OSC_QUERY_DWORD                                0       /* DWORD 1 */
+#define OSC_SUPPORT_DWORD                      1       /* DWORD 2 */
+#define OSC_CONTROL_DWORD                      2       /* DWORD 3 */
+
+/* _OSC Capabilities DWORD 1: Query/Control and Error Returns (generic) */
+#define OSC_QUERY_ENABLE                       0x00000001  /* input */
+#define OSC_REQUEST_ERROR                      0x00000002  /* return */
+#define OSC_INVALID_UUID_ERROR                 0x00000004  /* return */
+#define OSC_INVALID_REVISION_ERROR             0x00000008  /* return */
+#define OSC_CAPABILITIES_MASK_ERROR            0x00000010  /* return */
+
+/* Platform-Wide Capabilities _OSC: Capabilities DWORD 2: Support Field */
+#define OSC_SB_PAD_SUPPORT                     0x00000001
+#define OSC_SB_PPC_OST_SUPPORT                 0x00000002
+#define OSC_SB_PR3_SUPPORT                     0x00000004
+#define OSC_SB_HOTPLUG_OST_SUPPORT             0x00000008
+#define OSC_SB_APEI_SUPPORT                    0x00000010
+#define OSC_SB_CPC_SUPPORT                     0x00000020
 
 extern bool osc_sb_apei_support_acked;
 
-/* PCI defined _OSC bits */
-/* _OSC DW1 Definition (OS Support Fields) */
-#define OSC_EXT_PCI_CONFIG_SUPPORT             1
-#define OSC_ACTIVE_STATE_PWR_SUPPORT           2
-#define OSC_CLOCK_PWR_CAPABILITY_SUPPORT       4
-#define OSC_PCI_SEGMENT_GROUPS_SUPPORT         8
-#define OSC_MSI_SUPPORT                                16
-#define OSC_PCI_SUPPORT_MASKS                  0x1f
-
-/* _OSC DW1 Definition (OS Control Fields) */
-#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL      1
-#define OSC_SHPC_NATIVE_HP_CONTROL             2
-#define OSC_PCI_EXPRESS_PME_CONTROL            4
-#define OSC_PCI_EXPRESS_AER_CONTROL            8
-#define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL  16
-
-#define OSC_PCI_CONTROL_MASKS  (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |    \
-                               OSC_SHPC_NATIVE_HP_CONTROL |            \
-                               OSC_PCI_EXPRESS_PME_CONTROL |           \
-                               OSC_PCI_EXPRESS_AER_CONTROL |           \
-                               OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL)
-
-#define OSC_PCI_NATIVE_HOTPLUG (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |    \
-                               OSC_SHPC_NATIVE_HP_CONTROL)
+/* PCI Host Bridge _OSC: Capabilities DWORD 2: Support Field */
+#define OSC_PCI_EXT_CONFIG_SUPPORT             0x00000001
+#define OSC_PCI_ASPM_SUPPORT                   0x00000002
+#define OSC_PCI_CLOCK_PM_SUPPORT               0x00000004
+#define OSC_PCI_SEGMENT_GROUPS_SUPPORT         0x00000008
+#define OSC_PCI_MSI_SUPPORT                    0x00000010
+#define OSC_PCI_SUPPORT_MASKS                  0x0000001f
+
+/* PCI Host Bridge _OSC: Capabilities DWORD 3: Control Field */
+#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL      0x00000001
+#define OSC_PCI_SHPC_NATIVE_HP_CONTROL         0x00000002
+#define OSC_PCI_EXPRESS_PME_CONTROL            0x00000004
+#define OSC_PCI_EXPRESS_AER_CONTROL            0x00000008
+#define OSC_PCI_EXPRESS_CAPABILITY_CONTROL     0x00000010
+#define OSC_PCI_CONTROL_MASKS                  0x0000001f
 
 extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
                                             u32 *mask, u32 req);
index b6bdcd66c07d2e758ba677f9c9c1796ada542bc8..e00e9f362fd50641e3dbf79722e06cfa9a752fb5 100644 (file)
 
 #define IMX6Q_GPR5_L2_CLK_STOP                 BIT(8)
 
+#define IMX6Q_GPR8_TX_SWING_LOW                        (0x7f << 25)
+#define IMX6Q_GPR8_TX_SWING_FULL               (0x7f << 18)
+#define IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB          (0x3f << 12)
+#define IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB                (0x3f << 6)
+#define IMX6Q_GPR8_TX_DEEMPH_GEN1              (0x3f << 0)
+
 #define IMX6Q_GPR9_TZASC2_BYP                  BIT(1)
 #define IMX6Q_GPR9_TZASC1_BYP                  BIT(0)
 
 #define IMX6Q_GPR12_ARMP_AHB_CLK_EN            BIT(26)
 #define IMX6Q_GPR12_ARMP_ATB_CLK_EN            BIT(25)
 #define IMX6Q_GPR12_ARMP_APB_CLK_EN            BIT(24)
+#define IMX6Q_GPR12_DEVICE_TYPE                        (0xf << 12)
 #define IMX6Q_GPR12_PCIE_CTL_2                 BIT(10)
+#define IMX6Q_GPR12_LOS_LEVEL                  (0x1f << 4)
 
 #define IMX6Q_GPR13_SDMA_STOP_REQ              BIT(30)
 #define IMX6Q_GPR13_CAN2_STOP_REQ              BIT(29)
index da172f956ad6f0a6ff883d125ca70e9f97510612..d3a888ae4b2e3ad030bdb5f89354eea2f2567d0b 100644 (file)
@@ -330,8 +330,6 @@ struct pci_dev {
        unsigned int    msix_enabled:1;
        unsigned int    ari_enabled:1;  /* ARI forwarding */
        unsigned int    is_managed:1;
-       unsigned int    is_pcie:1;      /* Obsolete. Will be removed.
-                                          Use pci_is_pcie() instead */
        unsigned int    needs_freset:1; /* Dev requires fundamental reset */
        unsigned int    state_saved:1;
        unsigned int    is_physfn:1;
@@ -472,6 +470,10 @@ struct pci_bus {
 /*
  * Returns true if the pci bus is root (behind host-pci bridge),
  * false otherwise
+ *
+ * Some code assumes that "bus->self == NULL" means that bus is a root bus.
+ * This is incorrect because "virtual" buses added for SR-IOV (via
+ * virtfn_add_bus()) have "bus->self == NULL" but are not root buses.
  */
 static inline bool pci_is_root_bus(struct pci_bus *pbus)
 {
@@ -1749,11 +1751,11 @@ static inline int pci_pcie_cap(struct pci_dev *dev)
  * pci_is_pcie - check if the PCI device is PCI Express capable
  * @dev: PCI device
  *
- * Retrun true if the PCI device is PCI Express capable, false otherwise.
+ * Returns: true if the PCI device is PCI Express capable, false otherwise.
  */
 static inline bool pci_is_pcie(struct pci_dev *dev)
 {
-       return !!pci_pcie_cap(dev);
+       return pci_pcie_cap(dev);
 }
 
 /**
index baa7852468ef6eced239446f81b7b88b765e083e..0890556f779e489c16aa57490f3d4fef97e7e86e 100644 (file)
 #define PCI_MSIX_PBA           8       /* Pending Bit Array offset */
 #define  PCI_MSIX_PBA_BIR      0x00000007 /* BAR index */
 #define  PCI_MSIX_PBA_OFFSET   0xfffffff8 /* Offset into specified BAR */
-#define  PCI_MSIX_FLAGS_BIRMASK        (7 << 0)   /* deprecated */
 #define PCI_CAP_MSIX_SIZEOF    12      /* size of MSIX registers */
 
 /* MSI-X entry's format */
 #define  PCI_EXP_DEVCAP2_OBFF_MSG      0x00040000 /* New message signaling */
 #define  PCI_EXP_DEVCAP2_OBFF_WAKE     0x00080000 /* Re-use WAKE# for OBFF */
 #define PCI_EXP_DEVCTL2                40      /* Device Control 2 */
-#define  PCI_EXP_DEVCTL2_ARI           0x20    /* Alternative Routing-ID */
+#define  PCI_EXP_DEVCTL2_COMP_TIMEOUT  0x000f  /* Completion Timeout Value */
+#define  PCI_EXP_DEVCTL2_ARI           0x0020  /* Alternative Routing-ID */
 #define  PCI_EXP_DEVCTL2_IDO_REQ_EN    0x0100  /* Allow IDO for requests */
 #define  PCI_EXP_DEVCTL2_IDO_CMP_EN    0x0200  /* Allow IDO for completions */
 #define  PCI_EXP_DEVCTL2_LTR_EN                0x0400  /* Enable LTR mechanism */