summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: bc454df)
raw | patch | inline | side by side (parent: bc454df)
author | Murali Karicheri <m-karicheri2@ti.com> | |
Fri, 6 Sep 2013 15:39:12 +0000 (11:39 -0400) | ||
committer | Murali Karicheri <m-karicheri2@ti.com> | |
Wed, 3 Dec 2014 16:48:12 +0000 (11:48 -0500) |
serdes initialization and RC mode setting are specific to a
platform. This patch adds a K2 specific platform setup code
for PCIE and move the same to the driver folder. To support
PCI on another platform/device user may add a new match id string
and implement another platform setup code function for the
new device through this mechanism. If platform code is same,
the bindings for PCI can be same as in K2.
This patch also enable PCI link training based on DTS
attribute "enable-linktrain" to disable link training when
boot loader does the same.
Also add a Documentation for the PCIE bindings.
Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
platform. This patch adds a K2 specific platform setup code
for PCIE and move the same to the driver folder. To support
PCI on another platform/device user may add a new match id string
and implement another platform setup code function for the
new device through this mechanism. If platform code is same,
the bindings for PCI can be same as in K2.
This patch also enable PCI link training based on DTS
attribute "enable-linktrain" to disable link training when
boot loader does the same.
Also add a Documentation for the PCIE bindings.
Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Documentation/devicetree/bindings/pci/pcie-keystone.txt | [new file with mode: 0644] | patch | blob |
drivers/pci/host/Makefile | patch | blob | history | |
drivers/pci/host/k2-platform.c | [new file with mode: 0644] | patch | blob |
drivers/pci/host/pci-pdata.h | [new file with mode: 0644] | patch | blob |
drivers/pci/host/pcie-keystone.c | patch | blob | history |
diff --git a/Documentation/devicetree/bindings/pci/pcie-keystone.txt b/Documentation/devicetree/bindings/pci/pcie-keystone.txt
--- /dev/null
@@ -0,0 +1,37 @@
+Keystone PCIE Root complex device tree bindings
+-----------------------------------------------
+
+Sample bindings shown below:-
+
+ - Remove enable-linktrain if boot loader already does Link training and do EP
+ configuration.
+ - To Disable SERDES initialization during Linux boot up, remove the "Keystone2 serdes cfg"
+ reg values from the reg property.
+
+ pci-controller@21800000 {
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <2>;
+ compatible = "ti,keystone2-pci";
+ reg = <0x21800000 0x8000 /* pcie-regs */
+ 0x0262014c 4 /* device cfg */
+ 0x02320000 0x4000>; /* Keystone2 serdes cfg */
+
+ /* outbound pci resources */
+ ranges = <0x02000000 0 0x50000000 0x50000000 0 0x10000000
+ 0x01000000 0 0 0x24000000 0 0x4000>;
+
+ /* inbound dma range */
+ dma-ranges = <0x02000000 0 0x80000000 0x80000000 0 0x20000000>;
+
+ interrupt-parent = <&gic>;
+ interrupts = <0 26 0xf01 0 27 0xf01 0 28 0xf01 0 29 0xf01 /* 4 Legacy IRQs */
+ 0 30 0xf01 0 31 0xf01 0 32 0xf01 0 33 0xf01 /* 8 MSI IRQs */
+ 0 34 0xf01 0 35 0xf01 0 36 0xf01 0 37 0xf01
+ 0 38 0xf01>; /* Error IRQ */
+ clocks = <&clkpcie>;
+ clock-names = "pcie";
+ enable-linktrain; /* When the boot loader enables link train and configure ep
+ * remove this attribute */
+ };
index fd0e7607b807e9adf81681c30bbb7b408c78130a..09f3f63a46b205aafe97130289899903d27d5cfe 100644 (file)
# PCIe drivers
obj-$(CONFIG_TI_KEYSTONE_PCIE) += pcie-keystone.o
+obj-$(CONFIG_ARCH_KEYSTONE) += k2-platform.o
diff --git a/drivers/pci/host/k2-platform.c b/drivers/pci/host/k2-platform.c
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2013 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <asm/setup.h>
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "pci-pdata.h"
+
+#define reg_dump(addr, mask) \
+ pr_debug("reg %p has value %x\n", (void *)addr, \
+ (__raw_readl(addr) & ~mask))
+
+#define PCIE_RC_MODE (BIT(2))
+#define PCIE_MODE_MASK (BIT(1) | BIT(2))
+
+static inline void reg_rmw(void __iomem *addr, u32 mask, u32 val)
+{
+ u32 read_data, data;
+ read_data = __raw_readl(addr);
+ data = (val & ~mask) | (read_data & mask);
+ __raw_writel(data, addr);
+}
+
+struct serdes_config {
+ u32 reg;
+ u32 mask;
+ u32 val;
+};
+
+static struct serdes_config k2_pcie_serdes_cfg[] = {
+ { 0x000, 0xffff00ff, 0x00000800 },
+ { 0x060, 0xff000000, 0x00041c5c },
+ { 0x064, 0x000000ff, 0x0343c700 },
+ { 0x06c, 0xffffff00, 0x00000012 },
+ { 0x068, 0xff00ffff, 0x00070000 },
+ { 0x078, 0xffff00ff, 0x0000c000 },
+ { 0x200, 0xffffff00, 0x00000000 },
+ { 0x204, 0x00ffff00, 0x5e000080 },
+ { 0x208, 0xffffff00, 0x00000006 },
+ { 0x210, 0xffffff00, 0x00000023 },
+ { 0x214, 0x00ff0000, 0x2e003060 },
+ { 0x218, 0x00ffffff, 0x76000000 },
+ { 0x22c, 0xff00ff00, 0x00100002 },
+ { 0x2a0, 0x0000ffff, 0xffee0000 },
+ { 0x2a4, 0xffffff00, 0x0000000f },
+ { 0x204, 0x00ffffff, 0x5e000000 },
+ { 0x208, 0xffffff00, 0x00000006 },
+ { 0x278, 0xffff00ff, 0x00002000 },
+ { 0x280, 0xff00ff00, 0x00280028 },
+ { 0x284, 0x00000000, 0x2d0f0385 },
+ { 0x250, 0x00ffffff, 0xd0000000 },
+ { 0x284, 0xffffff00, 0x00000085 },
+ { 0x294, 0x00ffffff, 0x20000000 },
+
+ { 0x400, 0xffffff00, 0x00000000 },
+ { 0x404, 0x00ffff00, 0x5e000080 },
+ { 0x408, 0xffffff00, 0x00000006 },
+ { 0x410, 0xffffff00, 0x00000023 },
+ { 0x414, 0x00ff0000, 0x2e003060 },
+ { 0x418, 0x00ffffff, 0x76000000 },
+ { 0x42c, 0xff00ff00, 0x00100002 },
+ { 0x4a0, 0x0000ffff, 0xffee0000 },
+ { 0x4a4, 0xffffff00, 0x0000000f },
+ { 0x404, 0x00ffffff, 0x5e000000 },
+ { 0x408, 0xffffff00, 0x00000006 },
+ { 0x478, 0xffff00ff, 0x00002000 },
+ { 0x480, 0xff00ff00, 0x00280028 },
+ { 0x484, 0x00000000, 0x2d0f0385 },
+ { 0x450, 0x00ffffff, 0xd0000000 },
+ { 0x494, 0x00ffffff, 0x20000000 },
+
+ { 0x604, 0xffffff00, 0x00000080 },
+ { 0x600, 0xffffff00, 0x00000000 },
+ { 0x604, 0x00ffffff, 0x5e000000 },
+ { 0x608, 0xffffff00, 0x00000006 },
+ { 0x610, 0xffffff00, 0x00000023 },
+ { 0x614, 0x00ff0000, 0x2e003060 },
+ { 0x618, 0x00ffffff, 0x76000000 },
+ { 0x62c, 0xff00ff00, 0x00100002 },
+ { 0x6a0, 0x0000ffff, 0xffee0000 },
+ { 0x6a4, 0xffffff00, 0x0000000f },
+ { 0x604, 0x00ffffff, 0x5e000000 },
+ { 0x608, 0xffffff00, 0x00000006 },
+ { 0x678, 0xffff00ff, 0x00002000 },
+ { 0x680, 0xff00ff00, 0x00280028 },
+ { 0x684, 0x00000000, 0x2d0f0385 },
+ { 0x650, 0x00ffffff, 0xd0000000 },
+ { 0x694, 0x00ffffff, 0x20000000 },
+
+ { 0x800, 0xffffff00, 0x00000000 },
+ { 0x804, 0x00ffff00, 0x5e000080 },
+ { 0x808, 0xffffff00, 0x00000006 },
+ { 0x810, 0xffffff00, 0x00000023 },
+ { 0x814, 0x00ff0000, 0x2e003060 },
+ { 0x818, 0x00ffffff, 0x76000000 },
+ { 0x82c, 0xff00ff00, 0x00100002 },
+ { 0x8a0, 0x0000ffff, 0xffee0000 },
+ { 0x8a4, 0xffffff00, 0x0000000f },
+ { 0x804, 0x00ffffff, 0x5e000000 },
+ { 0x808, 0xffffff00, 0x00000006 },
+ { 0x878, 0xffff00ff, 0x00002000 },
+ { 0x880, 0xff00ff00, 0x00280028 },
+ { 0x884, 0x00000000, 0x2d0f0385 },
+ { 0x850, 0x00ffffff, 0xd0000000 },
+ { 0x894, 0x00ffffff, 0x20000000 },
+
+ { 0xa00, 0xffff00ff, 0x00000100 },
+ { 0xa08, 0xff000000, 0x00e12c08 },
+ { 0xa0c, 0xffffff00, 0x00000081 },
+ { 0xa18, 0xff00ffff, 0x00e80000 },
+ { 0xa30, 0x00ffff00, 0x002f2f00 },
+ { 0xa48, 0xff0000ff, 0x00e3ce00 },
+ { 0xa4c, 0x0000ffff, 0xac820000 },
+ { 0xa54, 0x00ffffff, 0xc0000000 },
+ { 0xa58, 0xffff0000, 0x00001441 },
+ { 0xa84, 0xffff0000, 0x00000301 },
+
+ { 0xa8c, 0x0000ffff, 0x81030000 },
+ { 0xa90, 0xffff0000, 0x00006001 },
+ { 0xa94, 0x00ffffff, 0x01000000 },
+ { 0xaa0, 0x00ffffff, 0x81000000 },
+ { 0xabc, 0x00ffffff, 0xff000000 },
+ { 0xac0, 0xffffff00, 0x0000008b },
+
+ { 0x000, 0xffffff00, 0x00000003 },
+ { 0xa00, 0xffffff00, 0x0000009f },
+};
+
+int k2_pcie_platform_setup(void *pdata, struct device_node *np)
+{
+ struct keystone_pcie_pdata *p_data = pdata;
+ void __iomem *reg_serdes_base, *devcfg;
+ u32 val;
+ int i;
+
+ devcfg = of_iomap(np, 1);
+ reg_serdes_base = of_iomap(np, 2);
+
+ pr_info("keystone2_pcie_serdes_setup\n");
+
+ if (!reg_serdes_base)
+ pr_info("Assuming SERDES initialized by boot loader\n");
+
+ if (!devcfg) {
+ pr_warn("pcie device cfg bindings missing\n");
+ return -EINVAL;
+ }
+
+ if (reg_serdes_base) {
+ for (i = 0; i < ARRAY_SIZE(k2_pcie_serdes_cfg); i++) {
+ reg_rmw((reg_serdes_base + k2_pcie_serdes_cfg[i].reg),
+ k2_pcie_serdes_cfg[i].mask,
+ k2_pcie_serdes_cfg[i].val);
+ reg_dump((reg_serdes_base + k2_pcie_serdes_cfg[i].reg),
+ k2_pcie_serdes_cfg[i].mask);
+ }
+ }
+
+ udelay(2000);
+
+ /* enable RC mode in devcfg */
+ val = __raw_readl(devcfg);
+ val &= ~PCIE_MODE_MASK;
+ val |= PCIE_RC_MODE;
+ __raw_writel(val, devcfg);
+
+ /* check if we need to enable link training */
+ p_data->en_link_train =
+ (of_get_property(np, "enable-linktrain", NULL) != NULL);
+
+ pr_info("keystone2_pcie_serdes_setup done, en_link_train = %d\n",
+ p_data->en_link_train);
+ return 0;
+}
diff --git a/drivers/pci/host/pci-pdata.h b/drivers/pci/host/pci-pdata.h
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* platform specific setup for k2 serdes */
+int k2_pcie_platform_setup(void *pdata, struct device_node *);
+
+/* keystone pcie pdata configurations */
+struct keystone_pcie_pdata {
+ int (*setup)(void *pdata, struct device_node *);
+ int en_link_train;
+};
+
index 91dc65c26195297043fa1e86440934319e2576e2..6a9dcb0e1127dddbb295a81db44dfe60d6a33597 100644 (file)
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <asm/irq.h>
+
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/types.h>
-
-#include <asm/irq.h>
#include <linux/signal.h>
#include <linux/pci.h>
+#include "pci-pdata.h"
+
#define DRIVER_NAME "keystone-pcie"
#define PCIE_REGS_INDEX 0
#define PCIE_NON_PREFETCH_INDEX 1
#define ENABLE_ERR_FATAL_IRQ BIT(1)
#define ERR_FATAL_IRQ BIT(1)
+static struct keystone_pcie_pdata keystone2_data = {
+ .setup = k2_pcie_platform_setup,
+};
+
struct keystone_pcie_info {
void __iomem *reg_cfg_virt;
/* PCIE resources */
int msi_virq_base;
struct irq_domain *msi_irqd;
int error_irq;
+ /* platform customization */
+ struct keystone_pcie_pdata *pdata;
};
/* abort reg reference */
u32 pci_space, temp;
const u32 *ranges;
-
err = of_address_to_resource(node, 0, &info->cfg_resource);
if (err < 0) {
pr_err(DRIVER_NAME ": Not found reg property\n");
struct keystone_pcie_info *info;
void __iomem *reg_virt;
int i, err;
+ u32 temp;
if (nr != 0)
return 0;
}
pci_add_resource(&sys->resources, &info->io_resource);
- /*
- * KeyStone devices do not support h/w autonomous
- * link up-training to GEN2 from GEN1 in either EP/RC modes.
- * The software needs to initiate speed change.
- */
- __raw_writel(DIR_SPD |
- __raw_readl(reg_virt + SPACE0_LOCAL_CFG_OFFSET + PL_GEN2),
+ if (info->pdata->en_link_train) {
+ /*
+ * KeyStone devices do not support h/w autonomous
+ * link up-training to GEN2 from GEN1 in either EP/RC modes.
+ * The software needs to initiate speed change.
+ */
+ temp = __raw_readl(
reg_virt + SPACE0_LOCAL_CFG_OFFSET + PL_GEN2);
- /*
- * Initiate Link Training. We will delay for L0 as specified by
- * standard, but will still proceed and return success irrespective of
- * L0 status as this will be handled by explicit L0 state checks during
- * enumeration.
- */
- __raw_writel(LTSSM_EN_VAL |
- __raw_readl(reg_virt + CMD_STATUS), reg_virt + CMD_STATUS);
+ __raw_writel(DIR_SPD | temp,
+ reg_virt + SPACE0_LOCAL_CFG_OFFSET + PL_GEN2);
+ /*
+ * Initiate Link Training. We will delay for L0 as specified by
+ * standard, but will still proceed and return success
+ * irrespective of L0 status as this will be handled by explicit
+ * L0 state checks during enumeration.
+ */
+ temp = __raw_readl(reg_virt + CMD_STATUS);
+ __raw_writel(LTSSM_EN_VAL | temp, reg_virt + CMD_STATUS);
- /* 100ms */
- msleep(100);
+ /* 100ms */
+ msleep(100);
+ }
/*
* Identify ourselves as 'Bridge' for enumeration purpose. This also
info->virqs[pin - 1] : -1;
}
-
static struct hw_pci keystone_pcie_hw = {
.nr_controllers = 1,
.setup = keystone_pcie_setup,
};
/* keystone pcie device tree match tables */
-const struct of_device_id keystone_pci_ids[] __initconst = {
- { .type = "pci", .compatible = "ti,keystone2-pci", },
+static const struct of_device_id keystone_pci_match_ids[] __initconst = {
+ {
+ .type = "pci",
+ .compatible = "ti,keystone2-pci",
+ .data = &keystone2_data,
+ },
{}
};
static int __init keystone_pcie_rc_init(void)
{
struct keystone_pcie_info *rc_info;
+ const struct of_device_id *of_id;
struct device_node *np;
int err = -EINVAL, i;
struct clk *pcie_clk;
return -ENOMEM;
}
- np = of_find_matching_node(NULL, keystone_pci_ids);
+ np = of_find_matching_node(NULL, keystone_pci_match_ids);
if (!np) {
pr_err(DRIVER_NAME ": Unable to find pcie device node\n");
goto err;
}
+ of_id = of_match_node(keystone_pci_match_ids, np);
+ if (of_id)
+ rc_info->pdata = (struct keystone_pcie_pdata *)of_id->data;
+
+ /* Setup platform specific initialization */
+ if (rc_info->pdata)
+ err = rc_info->pdata->setup(rc_info->pdata, np);
+
+ if (err < 0)
+ goto err;
+
/* Enable controller Power and Clock domains */
pcie_clk = of_clk_get(np, 0);
if (IS_ERR(pcie_clk)) {