@@ -8247,7 +8247,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
PCMCIA SUBSYSTEM
P: Linux PCMCIA Team
@@ -19,4 +19,4 @@ 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
new file mode 100644
@@ -0,0 +1,88 @@
+/*
+ * 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 */
+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;
+}
+
+/* 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;
+ 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(struct pcie_port *pp)
+{
+ struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+ return hisi_pcie->soc_ops->hisi_pcie_link_up(hisi_pcie);
+}
+
+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,
+};
@@ -21,124 +21,13 @@
#include <linux/regmap.h>
#include "pcie-designware.h"
+#include "pcie-hisi.h"
#define PCIE_LTSSM_LINKUP_STATE 0x11
#define PCIE_LTSSM_STATE_MASK 0x3F
#define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818
-#define PCIE_SYS_STATE4 0x31c
#define PCIE_HIP06_CTRL_OFF 0x1000
-
-#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;
- u32 port_id;
- struct pcie_port pp;
- 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;
-}
-
-/* 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;
- 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);
-}
-
-static int hisi_pcie_link_up_hip06(struct hisi_pcie *hisi_pcie)
-{
- u32 val;
-
- val = hisi_pcie_apb_readl(hisi_pcie, PCIE_HIP06_CTRL_OFF +
- 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,
-};
+#define PCIE_SYS_STATE4 0x31c
static int hisi_add_pcie_port(struct pcie_port *pp,
struct platform_device *pdev)
@@ -215,6 +104,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 = hisi_pcie_apb_readl(hisi_pcie, 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,44 @@
+/*
+ * 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_
+
+struct hisi_pcie {
+ struct regmap *subctrl;
+ void __iomem *reg_base;
+ u32 port_id;
+ struct pcie_port pp;
+ struct pcie_soc_ops *soc_ops;
+};
+
+struct pcie_soc_ops {
+ int (*hisi_pcie_link_up)(struct hisi_pcie *pcie);
+};
+
+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);
+}
+
+#define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp)
+
+extern struct pcie_host_ops hisi_pcie_host_ops;
+
+#endif /* PCIE_HISI_H_ */