diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-23 11:53:22 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-23 11:53:22 -0800 |
commit | 60e8d3e11645a1b9c4197d9786df3894332c1685 (patch) | |
tree | 00f2d71dfc8c9e6cf9fc1033eca3f169249a838e /drivers/pci/host/pcie-hisi.c | |
parent | 190c3ee06a0f0660839785b7ad8a830e832d9481 (diff) | |
parent | c4d052ce970ea98e9e1cc72461ba3b7a25397657 (diff) |
Merge tag 'pci-v4.11-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas:
- add ASPM L1 substate support
- enable PCIe Extended Tags when supported
- configure PCIe MPS settings on iProc, Versatile, X-Gene, and Xilinx
- increase VPD access timeout
- add ACS quirks for Intel Union Point, Qualcomm QDF2400 and QDF2432
- use new pci_irq_alloc_vectors() in more drivers
- fix MSI affinity memory leak
- remove unused MSI interfaces and update documentation
- remove unused AER .link_reset() callback
- avoid pci_lock / p->pi_lock deadlock seen with perf
- serialize sysfs enable/disable num_vfs operations
- move DesignWare IP from drivers/pci/host/ to drivers/pci/dwc/ and
refactor so we can support both hosts and endpoints
- add DT ECAM-like support for HiSilicon Hip06/Hip07 controllers
- add Rockchip system power management support
- add Thunder-X cn81xx and cn83xx support
- add Exynos 5440 PCIe PHY support
* tag 'pci-v4.11-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (93 commits)
PCI: dwc: Remove dependency of designware on CONFIG_PCI
PCI: dwc: Add CONFIG_PCIE_DW_HOST to enable PCI dwc host
PCI: dwc: Split pcie-designware.c into host and core files
PCI: dwc: designware: Fix style errors in pcie-designware.c
PCI: dwc: designware: Parse "num-lanes" property in dw_pcie_setup_rc()
PCI: dwc: all: Split struct pcie_port into host-only and core structures
PCI: dwc: designware: Get device pointer at the start of dw_pcie_host_init()
PCI: dwc: all: Rename cfg_read/cfg_write to read/write
PCI: dwc: all: Use platform_set_drvdata() to save private data
PCI: dwc: designware: Move register defines to designware header file
PCI: dwc: Use PTR_ERR_OR_ZERO to simplify code
PCI: dra7xx: Group PHY API invocations
PCI: dra7xx: Enable MSI and legacy interrupts simultaneously
PCI: dra7xx: Add support to force RC to work in GEN1 mode
PCI: dra7xx: Simplify probe code with devm_gpiod_get_optional()
PCI: Move DesignWare IP support to new drivers/pci/dwc/ directory
PCI: exynos: Support the PHY generic framework
Documentation: binding: Modify the exynos5440 PCIe binding
phy: phy-exynos-pcie: Add support for Exynos PCIe PHY
Documentation: samsung-phy: Add exynos-pcie-phy binding
...
Diffstat (limited to 'drivers/pci/host/pcie-hisi.c')
-rw-r--r-- | drivers/pci/host/pcie-hisi.c | 326 |
1 files changed, 0 insertions, 326 deletions
diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c deleted file mode 100644 index a301a7187b30..000000000000 --- a/drivers/pci/host/pcie-hisi.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * PCIe host controller driver for HiSilicon SoCs - * - * Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com - * - * Authors: Zhou Wang <wangzhou1@hisilicon.com> - * Dacai Zhu <zhudacai@hisilicon.com> - * Gabriele Paoloni <gabriele.paoloni@huawei.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/interrupt.h> -#include <linux/init.h> -#include <linux/mfd/syscon.h> -#include <linux/of_address.h> -#include <linux/of_pci.h> -#include <linux/platform_device.h> -#include <linux/of_device.h> -#include <linux/pci.h> -#include <linux/pci-acpi.h> -#include <linux/pci-ecam.h> -#include <linux/regmap.h> -#include "../pci.h" - -#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) - -static int hisi_pcie_acpi_rd_conf(struct pci_bus *bus, u32 devfn, int where, - int size, u32 *val) -{ - struct pci_config_window *cfg = bus->sysdata; - int dev = PCI_SLOT(devfn); - - if (bus->number == cfg->busr.start) { - /* access only one slot on each root port */ - if (dev > 0) - return PCIBIOS_DEVICE_NOT_FOUND; - else - return pci_generic_config_read32(bus, devfn, where, - size, val); - } - - return pci_generic_config_read(bus, devfn, where, size, val); -} - -static int hisi_pcie_acpi_wr_conf(struct pci_bus *bus, u32 devfn, - int where, int size, u32 val) -{ - struct pci_config_window *cfg = bus->sysdata; - int dev = PCI_SLOT(devfn); - - if (bus->number == cfg->busr.start) { - /* access only one slot on each root port */ - if (dev > 0) - return PCIBIOS_DEVICE_NOT_FOUND; - else - return pci_generic_config_write32(bus, devfn, where, - size, val); - } - - return pci_generic_config_write(bus, devfn, where, size, val); -} - -static void __iomem *hisi_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, - int where) -{ - struct pci_config_window *cfg = bus->sysdata; - void __iomem *reg_base = cfg->priv; - - if (bus->number == cfg->busr.start) - return reg_base + where; - else - return pci_ecam_map_bus(bus, devfn, where); -} - -static int hisi_pcie_init(struct pci_config_window *cfg) -{ - struct device *dev = cfg->parent; - struct acpi_device *adev = to_acpi_device(dev); - struct acpi_pci_root *root = acpi_driver_data(adev); - struct resource *res; - void __iomem *reg_base; - int ret; - - /* - * Retrieve RC base and size from a HISI0081 device with _UID - * matching our segment. - */ - res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL); - if (!res) - return -ENOMEM; - - ret = acpi_get_rc_resources(dev, "HISI0081", root->segment, res); - if (ret) { - dev_err(dev, "can't get rc base address\n"); - return -ENOMEM; - } - - reg_base = devm_ioremap(dev, res->start, resource_size(res)); - if (!reg_base) - return -ENOMEM; - - cfg->priv = reg_base; - return 0; -} - -struct pci_ecam_ops hisi_pcie_ops = { - .bus_shift = 20, - .init = hisi_pcie_init, - .pci_ops = { - .map_bus = hisi_pcie_map_bus, - .read = hisi_pcie_acpi_rd_conf, - .write = hisi_pcie_acpi_wr_conf, - } -}; - -#endif - -#ifdef CONFIG_PCI_HISI - -#include "pcie-designware.h" - -#define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818 -#define PCIE_HIP06_CTRL_OFF 0x1000 -#define PCIE_SYS_STATE4 (PCIE_HIP06_CTRL_OFF + 0x31c) -#define PCIE_LTSSM_LINKUP_STATE 0x11 -#define PCIE_LTSSM_STATE_MASK 0x3F - -#define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp) - -struct hisi_pcie; - -struct pcie_soc_ops { - int (*hisi_pcie_link_up)(struct hisi_pcie *hisi_pcie); -}; - -struct hisi_pcie { - struct pcie_port pp; /* pp.dbi_base is DT rc_dbi */ - struct regmap *subctrl; - u32 port_id; - struct pcie_soc_ops *soc_ops; -}; - -/* HipXX PCIe host only supports 32-bit config access */ -static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size, - u32 *val) -{ - u32 reg; - u32 reg_val; - void *walker = ®_val; - - walker += (where & 0x3); - reg = where & ~0x3; - reg_val = dw_pcie_readl_rc(pp, reg); - - if (size == 1) - *val = *(u8 __force *) walker; - else if (size == 2) - *val = *(u16 __force *) walker; - else if (size == 4) - *val = reg_val; - else - return PCIBIOS_BAD_REGISTER_NUMBER; - - return PCIBIOS_SUCCESSFUL; -} - -/* HipXX PCIe host only supports 32-bit config access */ -static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size, - u32 val) -{ - u32 reg_val; - u32 reg; - void *walker = ®_val; - - walker += (where & 0x3); - reg = where & ~0x3; - if (size == 4) - dw_pcie_writel_rc(pp, reg, val); - else if (size == 2) { - reg_val = dw_pcie_readl_rc(pp, reg); - *(u16 __force *) walker = val; - dw_pcie_writel_rc(pp, reg, reg_val); - } else if (size == 1) { - reg_val = dw_pcie_readl_rc(pp, reg); - *(u8 __force *) walker = val; - dw_pcie_writel_rc(pp, reg, reg_val); - } else - return PCIBIOS_BAD_REGISTER_NUMBER; - - return PCIBIOS_SUCCESSFUL; -} - -static int hisi_pcie_link_up_hip05(struct hisi_pcie *hisi_pcie) -{ - u32 val; - - regmap_read(hisi_pcie->subctrl, PCIE_SUBCTRL_SYS_STATE4_REG + - 0x100 * hisi_pcie->port_id, &val); - - return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE); -} - -static int hisi_pcie_link_up_hip06(struct hisi_pcie *hisi_pcie) -{ - struct pcie_port *pp = &hisi_pcie->pp; - u32 val; - - val = dw_pcie_readl_rc(pp, PCIE_SYS_STATE4); - - return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE); -} - -static int hisi_pcie_link_up(struct pcie_port *pp) -{ - struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp); - - return hisi_pcie->soc_ops->hisi_pcie_link_up(hisi_pcie); -} - -static struct pcie_host_ops hisi_pcie_host_ops = { - .rd_own_conf = hisi_pcie_cfg_read, - .wr_own_conf = hisi_pcie_cfg_write, - .link_up = hisi_pcie_link_up, -}; - -static int hisi_add_pcie_port(struct hisi_pcie *hisi_pcie, - struct platform_device *pdev) -{ - struct pcie_port *pp = &hisi_pcie->pp; - struct device *dev = pp->dev; - int ret; - u32 port_id; - - if (of_property_read_u32(dev->of_node, "port-id", &port_id)) { - dev_err(dev, "failed to read port-id\n"); - return -EINVAL; - } - if (port_id > 3) { - dev_err(dev, "Invalid port-id: %d\n", port_id); - return -EINVAL; - } - hisi_pcie->port_id = port_id; - - pp->ops = &hisi_pcie_host_ops; - - ret = dw_pcie_host_init(pp); - if (ret) { - dev_err(dev, "failed to initialize host\n"); - return ret; - } - - return 0; -} - -static int hisi_pcie_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct hisi_pcie *hisi_pcie; - struct pcie_port *pp; - const struct of_device_id *match; - struct resource *reg; - struct device_driver *driver; - int ret; - - hisi_pcie = devm_kzalloc(dev, sizeof(*hisi_pcie), GFP_KERNEL); - if (!hisi_pcie) - return -ENOMEM; - - pp = &hisi_pcie->pp; - pp->dev = dev; - driver = dev->driver; - - match = of_match_device(driver->of_match_table, dev); - hisi_pcie->soc_ops = (struct pcie_soc_ops *) match->data; - - hisi_pcie->subctrl = - syscon_regmap_lookup_by_compatible("hisilicon,pcie-sas-subctrl"); - if (IS_ERR(hisi_pcie->subctrl)) { - dev_err(dev, "cannot get subctrl base\n"); - return PTR_ERR(hisi_pcie->subctrl); - } - - reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi"); - pp->dbi_base = devm_ioremap_resource(dev, reg); - if (IS_ERR(pp->dbi_base)) - return PTR_ERR(pp->dbi_base); - - ret = hisi_add_pcie_port(hisi_pcie, pdev); - if (ret) - return ret; - - return 0; -} - -static struct pcie_soc_ops hip05_ops = { - &hisi_pcie_link_up_hip05 -}; - -static struct pcie_soc_ops hip06_ops = { - &hisi_pcie_link_up_hip06 -}; - -static const struct of_device_id hisi_pcie_of_match[] = { - { - .compatible = "hisilicon,hip05-pcie", - .data = (void *) &hip05_ops, - }, - { - .compatible = "hisilicon,hip06-pcie", - .data = (void *) &hip06_ops, - }, - {}, -}; - -static struct platform_driver hisi_pcie_driver = { - .probe = hisi_pcie_probe, - .driver = { - .name = "hisi-pcie", - .of_match_table = hisi_pcie_of_match, - }, -}; -builtin_platform_driver(hisi_pcie_driver); - -#endif |