@@ -8409,7 +8409,9 @@ M: Gabriele Paoloni <gabriele.paoloni@huawei.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
+F: drivers/pci/host/pcie-hisi.h
F: drivers/pci/host/pcie-hisi.c
+F: drivers/pci/host/pcie-hisi-common.c
PCIE DRIVER FOR QUALCOMM MSM
M: Stanimir Varbanov <svarbanov@mm-sol.com>
@@ -20,5 +20,5 @@ obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
-obj-$(CONFIG_PCI_HISI) += pcie-hisi.o
+obj-$(CONFIG_PCI_HISI) += pcie-hisi.o pcie-hisi-common.o
obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
new file mode 100644
@@ -0,0 +1,73 @@
+/*
+ * PCIe host controller common functions for HiSilicon SoCs
+ *
+ * Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com
+ *
+ * Author: 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/acpi.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_pci.h>
+#include <linux/regmap.h>
+
+#include "pcie-designware.h"
+#include "pcie-hisi.h"
+
+/* HipXX PCIe host only supports 32-bit config access */
+int hisi_pcie_common_cfg_read(void __iomem *reg_base, int where, int size,
+ u32 *val)
+{
+ u32 reg;
+ u32 reg_val;
+ void *walker = ®_val;
+
+ walker += (where & 0x3);
+ reg = where & ~0x3;
+ reg_val = readl(reg_base + 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 */
+int hisi_pcie_common_cfg_write(void __iomem *reg_base, int where, int size,
+ u32 val)
+{
+ u32 reg_val;
+ u32 reg;
+ void *walker = ®_val;
+
+ walker += (where & 0x3);
+ reg = where & ~0x3;
+ if (size == 4)
+ writel(val, reg_base + reg);
+ else if (size == 2) {
+ reg_val = readl(reg_base + reg);
+ *(u16 __force *) walker = val;
+ writel(val, reg_base + reg);
+ } else if (size == 1) {
+ reg_val = readl(reg_base + reg);
+ *(u8 __force *) walker = val;
+ writel(val, reg_base + reg);
+ } else
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ return PCIBIOS_SUCCESSFUL;
+}
@@ -21,6 +21,7 @@
#include <linux/regmap.h>
#include "pcie-designware.h"
+#include "pcie-hisi.h"
#define PCIE_LTSSM_LINKUP_STATE 0x11
#define PCIE_LTSSM_STATE_MASK 0x3F
@@ -30,12 +31,6 @@
#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 *pcie);
-};
-
struct hisi_pcie {
struct regmap *subctrl;
void __iomem *reg_base;
@@ -44,87 +39,24 @@ struct hisi_pcie {
struct pcie_soc_ops *soc_ops;
};
-static inline void hisi_pcie_apb_writel(struct hisi_pcie *pcie,
- u32 val, u32 reg)
-{
- writel(val, pcie->reg_base + reg);
-}
-
-static inline u32 hisi_pcie_apb_readl(struct hisi_pcie *pcie, u32 reg)
-{
- return readl(pcie->reg_base + reg);
-}
-
-/* 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;
- struct hisi_pcie *pcie = to_hisi_pcie(pp);
- void *walker = ®_val;
-
- walker += (where & 0x3);
- reg = where & ~0x3;
- reg_val = hisi_pcie_apb_readl(pcie, 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;
-}
+struct pcie_soc_ops {
+ int (*hisi_pcie_link_up)(struct hisi_pcie *pcie);
+};
-/* 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)
+static inline int hisi_pcie_cfg_read(struct pcie_port *pp, int where,
+ int size, u32 *val)
{
- u32 reg_val;
- u32 reg;
struct hisi_pcie *pcie = to_hisi_pcie(pp);
- void *walker = ®_val;
-
- walker += (where & 0x3);
- reg = where & ~0x3;
- if (size == 4)
- hisi_pcie_apb_writel(pcie, val, reg);
- else if (size == 2) {
- reg_val = hisi_pcie_apb_readl(pcie, reg);
- *(u16 __force *) walker = val;
- hisi_pcie_apb_writel(pcie, reg_val, reg);
- } else if (size == 1) {
- reg_val = hisi_pcie_apb_readl(pcie, reg);
- *(u8 __force *) walker = val;
- hisi_pcie_apb_writel(pcie, reg_val, reg);
- } 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);
+ return hisi_pcie_common_cfg_read(pcie->reg_base, where, size, val);
}
-static int hisi_pcie_link_up_hip06(struct hisi_pcie *hisi_pcie)
+static inline int hisi_pcie_cfg_write(struct pcie_port *pp, int where,
+ int size, u32 val)
{
- u32 val;
-
- val = hisi_pcie_apb_readl(hisi_pcie, PCIE_HIP06_CTRL_OFF +
- PCIE_SYS_STATE4);
+ struct hisi_pcie *pcie = to_hisi_pcie(pp);
- return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
+ return hisi_pcie_common_cfg_write(pcie->reg_base, where, size, val);
}
static int hisi_pcie_link_up(struct pcie_port *pp)
@@ -134,12 +66,13 @@ static int hisi_pcie_link_up(struct pcie_port *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,
+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 pcie_port *pp,
struct platform_device *pdev)
{
@@ -215,6 +148,26 @@ static int hisi_pcie_probe(struct platform_device *pdev)
return 0;
}
+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)
+{
+ u32 val;
+
+ val = readl(hisi_pcie->reg_base + PCIE_HIP06_CTRL_OFF +
+ PCIE_SYS_STATE4);
+
+ return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
+}
+
static struct pcie_soc_ops hip05_ops = {
&hisi_pcie_link_up_hip05
};
new file mode 100644
@@ -0,0 +1,23 @@
+/*
+ * PCIe host controller driver for HiSilicon SoCs
+ *
+ * Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com
+ *
+ * Author: 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.
+ */
+#ifndef PCIE_HISI_H_
+#define PCIE_HISI_H_
+
+
+int hisi_pcie_common_cfg_read(void __iomem *reg_base, int where, int size,
+ u32 *val);
+int hisi_pcie_common_cfg_write(void __iomem *reg_base, int where, int size,
+ u32 val);
+
+#endif /* PCIE_HISI_H_ */