[U-Boot] [PATCH 4/4] rapidio: add driver for TI KeyStone RapidIO
jacquiot.aurelien at gmail.com
jacquiot.aurelien at gmail.com
Tue Nov 10 13:13:53 CET 2015
From: Aurelien Jacquiot <a-jacquiot at ti.com>
This commit includes the KeyStone device driver for RapidIO
allowing to use the RapidIO boot functionality.
Today only K2HK devices have RapidIO support.
Signed-off-by: Aurelien Jacquiot <a-jacquiot at ti.com>
---
Makefile | 1 +
configs/k2hk_evm_defconfig | 2 +
drivers/Kconfig | 2 +
drivers/rapidio/Kconfig | 5 +
drivers/rapidio/Makefile | 8 +
drivers/rapidio/keystone_rio.c | 1374 ++++++++++++++++++++++++++++++++++++++++
drivers/rapidio/keystone_rio.h | 650 +++++++++++++++++++
7 files changed, 2042 insertions(+), 0 deletions(-)
create mode 100644 drivers/rapidio/Kconfig
create mode 100644 drivers/rapidio/Makefile
create mode 100644 drivers/rapidio/keystone_rio.c
create mode 100644 drivers/rapidio/keystone_rio.h
diff --git a/Makefile b/Makefile
index 3c21f8d..67e6b25 100644
--- a/Makefile
+++ b/Makefile
@@ -661,6 +661,7 @@ libs-y += drivers/usb/musb/
libs-y += drivers/usb/musb-new/
libs-y += drivers/usb/phy/
libs-y += drivers/usb/ulpi/
+libs-y += drivers/rapidio/
libs-y += common/
libs-$(CONFIG_API) += api/
libs-$(CONFIG_HAS_POST) += post/
diff --git a/configs/k2hk_evm_defconfig b/configs/k2hk_evm_defconfig
index d5a4ef2..e350ea4 100644
--- a/configs/k2hk_evm_defconfig
+++ b/configs/k2hk_evm_defconfig
@@ -11,3 +11,5 @@ CONFIG_SYS_PROMPT="K2HK EVM # "
CONFIG_OF_CONTROL=y
CONFIG_DM=y
CONFIG_SPI_FLASH=y
+CONFIG_CMD_RIO=y
+CONFIG_KEYSTONE_RIO=y
diff --git a/drivers/Kconfig b/drivers/Kconfig
index c481e93..37a37a6 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -70,6 +70,8 @@ source "drivers/video/Kconfig"
source "drivers/watchdog/Kconfig"
+source "drivers/rapidio/Kconfig"
+
config PHYS_TO_BUS
bool "Custom physical to bus address mapping"
help
diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig
new file mode 100644
index 0000000..2560957
--- /dev/null
+++ b/drivers/rapidio/Kconfig
@@ -0,0 +1,5 @@
+config KEYSTONE_RIO
+ bool "Support for TI KeyStone RapidIO"
+ depends on TARGET_K2HK_EVM
+ ---help---
+ Say Y here if you want to use RapidIO to boot your board.
diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile
new file mode 100644
index 0000000..bd7ec50
--- /dev/null
+++ b/drivers/rapidio/Makefile
@@ -0,0 +1,8 @@
+#
+# (C) Copyright 2015
+# Texas Instruments Incorporated, <www.ti.com>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-$(CONFIG_KEYSTONE_RIO) += keystone_rio.o
diff --git a/drivers/rapidio/keystone_rio.c b/drivers/rapidio/keystone_rio.c
new file mode 100644
index 0000000..9fe93c3
--- /dev/null
+++ b/drivers/rapidio/keystone_rio.c
@@ -0,0 +1,1374 @@
+/*
+ * (C) Copyright 2015
+ * Texas Instruments Incorporated, <www.ti.com>
+ * Authors: Aurelien Jacquiot <a-jacquiot at ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <asm/dma-mapping.h>
+#include <asm/io.h>
+#include <asm/arch/psc_defs.h>
+#include <rio.h>
+
+#include "keystone_rio.h"
+
+#define DRIVER_VER "v1.1"
+
+#ifdef CONFIG_SOC_K2HK
+#define KEYSTONE_RIO_IS_K2 1
+#else
+#define KEYSTONE_RIO_IS_K2 0
+#endif
+
+#define K2_SERDES(p) ((p)->board_rio_cfg.keystone2_serdes)
+
+static unsigned int rio_dbg;
+
+#define debug_rio(fmt, args...) if (rio_dbg) printf(fmt, ##args)
+
+/*
+ * Main KeyStone RapidIO driver data
+ */
+struct keystone_rio_data {
+ int riohdid;
+ u32 rio_pe_feat;
+
+ u32 ports_registering;
+ u32 port_chk_cnt;
+
+ u32 *jtagid_reg;
+ u32 *serdes_sts_reg;
+ struct keystone_srio_serdes_regs *serdes_regs;
+ struct keystone_rio_regs *regs;
+
+ struct keystone_rio_car_csr_regs *car_csr_regs;
+ struct keystone_rio_serial_port_regs *serial_port_regs;
+ struct keystone_rio_err_mgmt_regs *err_mgmt_regs;
+ struct keystone_rio_phy_layer_regs *phy_regs;
+ struct keystone_rio_transport_layer_regs *transport_regs;
+ struct keystone_rio_pkt_buf_regs *pkt_buf_regs;
+ struct keystone_rio_evt_mgmt_regs *evt_mgmt_regs;
+ struct keystone_rio_port_write_regs *port_write_regs;
+ struct keystone_rio_link_layer_regs *link_regs;
+ struct keystone_rio_fabric_regs *fabric_regs;
+ u32 car_csr_regs_base;
+
+ struct keystone_rio_board_controller_info board_rio_cfg;
+} __krio_priv;
+
+/*--------------------- Maintenance Request Management ---------------------*/
+
+static u32 keystone_rio_dio_get_lsu_cc(u32 lsu_id, u8 ltid, u8 *lcb,
+ struct keystone_rio_data *krio_priv)
+{
+ u32 idx;
+ u32 shift;
+ u32 value;
+ u32 cc;
+ /* lSU shadow register status mapping */
+ u32 lsu_index[8] = { 0, 9, 15, 20, 24, 33, 39, 44 };
+
+ /* Compute LSU stat index from LSU id and LTID */
+ idx = (lsu_index[lsu_id] + ltid) >> 3;
+ shift = ((lsu_index[lsu_id] + ltid) & 0x7) << 2;
+
+ /* Get completion code and context */
+ value = readl(&(krio_priv->regs->lsu_stat_reg[idx]));
+ cc = (value >> (shift + 1)) & 0x7;
+ *lcb = (value >> shift) & 0x1;
+
+ return cc;
+}
+
+/**
+ * maint_request - Perform a maintenance request
+ * @port_id: output port ID of transaction
+ * @dest_id: destination ID of target device
+ * @hopcount: hopcount for this request
+ * @offset: offset in the RapidIO configuration space
+ * @buff: dma address of the data on the host
+ * @buff_len: length of the data
+ * @size: 1 for 16bit, 0 for 8bit ID size
+ * @type: packet type
+ *
+ * Returns %0 on success or %-1 on failure.
+ */
+static inline int keystone_rio_maint_request(
+ int port_id,
+ u32 dest_id,
+ u8 hopcount,
+ u32 offset,
+ dma_addr_t buff,
+ int buff_len,
+ u16 size,
+ u16 type,
+ struct keystone_rio_data *krio_priv)
+{
+ unsigned int count;
+ unsigned int status = 0;
+ unsigned int res = 0;
+ u8 context;
+ u8 ltid;
+
+ /* Check is there is space in the LSU shadow reg and that it is free */
+ count = 0;
+ while (1) {
+ status = readl(&(krio_priv->regs->lsu_reg[0].busy_full));
+ if (((status & KEYSTONE_RIO_LSU_FULL_MASK) == 0x0) &&
+ ((status & KEYSTONE_RIO_LSU_BUSY_MASK) == 0x0))
+ break;
+ count++;
+
+ if (count >= KEYSTONE_RIO_TIMEOUT_CNT) {
+ debug_rio("RIO: no LSU available, status = 0x%x\n",
+ status);
+ res = -1;
+ goto out;
+ }
+ udelay(1);
+ }
+
+ /* Get LCB and LTID, LSU reg 6 is already read */
+ context = (status >> 4) & 0x1;
+ ltid = status & 0xf;
+
+ /* LSU Reg 0 - MSB of RapidIO address */
+ writel(0, &(krio_priv->regs->lsu_reg[0].addr_msb));
+
+ /* LSU Reg 1 - LSB of destination */
+ writel(offset, &(krio_priv->regs->lsu_reg[0].addr_lsb_cfg_ofs));
+
+ /* LSU Reg 2 - source address */
+ writel(buff, &(krio_priv->regs->lsu_reg[0].dsp_addr));
+
+ /* LSU Reg 3 - byte count */
+ writel(buff_len,
+ &(krio_priv->regs->lsu_reg[0].dbell_val_byte_cnt));
+
+ /* LSU Reg 4 - */
+ writel(((port_id << 8)
+ | (KEYSTONE_RIO_LSU_PRIO << 4)
+ | (size ? (1 << 10) : 0)
+ | ((u32) dest_id << 16)),
+ &(krio_priv->regs->lsu_reg[0].destid));
+
+ /* LSU Reg 5 */
+ writel(((hopcount & 0xff) << 8) | (type & 0xff),
+ &(krio_priv->regs->lsu_reg[0].dbell_info_fttype));
+
+ /* Retrieve our completion code */
+ count = 0;
+ res = 0;
+ while (1) {
+ u8 lcb;
+
+ status = keystone_rio_dio_get_lsu_cc(0, ltid, &lcb, krio_priv);
+ if (lcb == context)
+ break;
+ count++;
+ if (count >= KEYSTONE_RIO_TIMEOUT_CNT) {
+ debug_rio(
+ "RIO: timeout %d, ltid = %d, context = %d, lcb = %d, cc = %d\n",
+ count, ltid, context, lcb, status);
+ res = -2;
+ break;
+ }
+ udelay(1);
+ }
+out:
+ if (res)
+ return res;
+
+ if (status)
+ debug_rio("RIO: transfer error = 0x%x\n", status);
+
+ switch (status) {
+ case KEYSTONE_RIO_LSU_CC_TIMEOUT:
+ case KEYSTONE_RIO_LSU_CC_XOFF:
+ case KEYSTONE_RIO_LSU_CC_ERROR:
+ case KEYSTONE_RIO_LSU_CC_INVALID:
+ case KEYSTONE_RIO_LSU_CC_DMA:
+ return -3;
+ break;
+ case KEYSTONE_RIO_LSU_CC_RETRY:
+ return -4;
+ break;
+ case KEYSTONE_RIO_LSU_CC_CANCELED:
+ return -5;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * rio_config_read - Generate a RIO read maintenance transaction
+ * @portid: Output port ID of transaction
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @val: Location to be read into
+ *
+ * Returns %0 on success or %-1 on failure.
+ */
+int rio_config_read(int portid,
+ u16 destid,
+ u8 hopcount,
+ u32 offset,
+ int len,
+ u32 *val)
+{
+ struct keystone_rio_data *krio_priv = &__krio_priv;
+ u32 *tbuf;
+ int res;
+ dma_addr_t dma;
+
+ tbuf = malloc(len);
+ if (!tbuf)
+ return -1;
+
+ memset(tbuf, 0, len);
+
+ dma = dma_map_single(tbuf, len, DMA_FROM_DEVICE);
+
+ res = keystone_rio_maint_request(portid, destid, hopcount, offset, dma,
+ len, krio_priv->board_rio_cfg.size,
+ KEYSTONE_RIO_PACKET_TYPE_MAINT_R,
+ krio_priv);
+
+ dma_unmap_single((void *)tbuf, len, dma);
+
+ /* Taking care of byteswap */
+ switch (len) {
+ case 1:
+ *val = *((u8 *)tbuf);
+ break;
+ case 2:
+ *val = ntohs(*((u16 *)tbuf));
+ break;
+ default:
+ *val = ntohl(*((u32 *)tbuf));
+ break;
+ }
+
+ free(tbuf);
+
+ debug_rio(
+ "RIO: %s portid %d destid %d hopcount %d offset 0x%x len %d val 0x%x res %d\n",
+ __func__, portid, destid, hopcount, offset, len, *val,
+ res);
+
+ return res;
+}
+
+/**
+ * rio_config_write - Generate a RIO write maintenance transaction
+ * @portid: Output port ID of transaction
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @val: Value to be written
+ *
+ * Returns %0 on success or %-1 on failure.
+ */
+int rio_config_write(int portid,
+ u16 destid,
+ u8 hopcount,
+ u32 offset,
+ int len,
+ u32 val)
+{
+ struct keystone_rio_data *krio_priv = &__krio_priv;
+ u32 *tbuf;
+ int res;
+ dma_addr_t dma;
+
+ tbuf = malloc(len);
+ if (!tbuf)
+ return -1;
+
+ memset(tbuf, 0, len);
+
+ /* Taking care of byteswap */
+ switch (len) {
+ case 1:
+ *tbuf = ((u8) val);
+ break;
+ case 2:
+ *tbuf = htons((u16) val);
+ break;
+ default:
+ *tbuf = htonl((u32) val);
+ break;
+ }
+
+ dma = dma_map_single(tbuf, len, DMA_TO_DEVICE);
+
+ res = keystone_rio_maint_request(portid, destid, hopcount, offset, dma,
+ len, krio_priv->board_rio_cfg.size,
+ KEYSTONE_RIO_PACKET_TYPE_MAINT_W,
+ krio_priv);
+
+ dma_unmap_single((void *)tbuf, len, dma);
+
+ debug_rio(
+ "RIO: %s portid %d destid %d hopcount %d offset 0x%x len %d val 0x%x res %d\n",
+ __func__, portid, destid, hopcount, offset, len, val,
+ res);
+
+ free(tbuf);
+
+ return res;
+}
+
+/**
+ * rio_local_config_read - RIO local config space read
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Value to be read into
+ *
+ * Returns %0 on success or %-1 on failure.
+ */
+int rio_local_config_read(u32 offset, int len, u32 *data)
+{
+ struct keystone_rio_data *krio_priv = &__krio_priv;
+
+ *data = readl((void *)(krio_priv->car_csr_regs_base + offset));
+
+ debug_rio("RIO: %s offset 0x%x data 0x%x\n",
+ __func__, offset, *data);
+
+ return 0;
+}
+
+/**
+ * rio_local_config_write - RIO local config space write
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Value to be written
+ *
+ * Returns %0 on success or %-1 on failure.
+ */
+int rio_local_config_write(u32 offset, int len, u32 data)
+{
+ struct keystone_rio_data *krio_priv = &__krio_priv;
+
+ debug_rio("RIO: %s offset 0x%x data 0x%x\n",
+ __func__, offset, data);
+
+ writel(data, (void *)(krio_priv->car_csr_regs_base + offset));
+
+ return 0;
+}
+
+/*------------------------- RapidIO hw controller setup ---------------------*/
+
+struct keystone_lane_config {
+ int start; /* lane start number of the port */
+ int end; /* lane end number of the port */
+};
+
+/*
+ * Table with the various lanes per port configuration modes:
+ * path mode 0: 4 ports in 1x
+ * path mode 1: 3 ports in 2x/1x
+ * path mode 2: 3 ports in 1x/2x
+ * path mode 3: 2 ports in 2x
+ * path mode 4: 1 ports in 4x
+ */
+static struct keystone_lane_config keystone_lane_configs[5][4] = {
+ { {0, 1}, {1, 2}, {2, 3}, {3, 4} },
+ { {0, 2}, {-1, -1}, {2, 3}, {3, 4} },
+ { {0, 1}, {1, 2}, {2, 4}, {-1, -1} },
+ { {0, 2}, {-1, -1}, {2, 4}, {-1, -1} },
+ { {0, 4}, {-1, -1}, {-1, -1}, {-1, -1} },
+};
+
+/* Retrieve the corresponding lanes bitmask from ports bitmask and path_mode */
+static int keystone_rio_get_lane_config(u32 ports, u32 path_mode)
+{
+ u32 lanes = 0;
+
+ while (ports) {
+ u32 lane;
+ u32 port = ffs(ports) - 1;
+ ports &= ~(1 << port);
+
+ if (keystone_lane_configs[path_mode][port].start == -1)
+ return -1;
+
+ for (lane = keystone_lane_configs[path_mode][port].start;
+ lane < keystone_lane_configs[path_mode][port].end;
+ lane++) {
+ lanes |= (1 << lane);
+ }
+ }
+ return (int) lanes;
+}
+
+#define reg_fmkr(msb, lsb, val) \
+ (((val) & ((1 << ((msb) - (lsb) + 1)) - 1)) << (lsb))
+
+#define reg_finsr(addr, msb, lsb, val) \
+ writel(((readl(addr) \
+ & ~(((1 << ((msb) - (lsb) + 1)) - 1) << (lsb))) \
+ | reg_fmkr(msb, lsb, val)), (addr))
+
+static void k2_rio_serdes_init_3g(u32 lanes,
+ struct keystone_rio_data *krio_priv)
+{
+ void __iomem *reg = (void __iomem *)krio_priv->serdes_regs;
+
+ /* Uses 6G half rate configuration */
+ reg_finsr((reg + 0x0000), 31, 24, 0x00);
+ reg_finsr((reg + 0x0014), 7, 0, 0x82);
+ reg_finsr((reg + 0x0014), 15, 8, 0x82);
+ reg_finsr((reg + 0x0060), 7, 0, 0x48);
+ reg_finsr((reg + 0x0060), 15, 8, 0x2c);
+ reg_finsr((reg + 0x0060), 23, 16, 0x13);
+ reg_finsr((reg + 0x0064), 15, 8, 0xc7);
+ reg_finsr((reg + 0x0064), 23, 16, 0xc3);
+ reg_finsr((reg + 0x0078), 15, 8, 0xc0);
+
+ /* Setting lane 0 SerDes to 3GHz */
+ reg_finsr((reg + 0x0204), 7, 0, 0x80);
+ reg_finsr((reg + 0x0204), 31, 24, 0x78);
+ reg_finsr((reg + 0x0208), 7, 0, 0x24);
+ reg_finsr((reg + 0x020c), 31, 24, 0x02);
+ reg_finsr((reg + 0x0210), 31, 24, 0x1b);
+ reg_finsr((reg + 0x0214), 7, 0, 0x7c);
+ reg_finsr((reg + 0x0214), 15, 8, 0x6e);
+ reg_finsr((reg + 0x0218), 7, 0, 0xe4);
+ reg_finsr((reg + 0x0218), 23, 16, 0x80);
+ reg_finsr((reg + 0x0218), 31, 24, 0x75);
+ reg_finsr((reg + 0x022c), 15, 8, 0x08);
+ reg_finsr((reg + 0x022c), 23, 16, 0x20);
+ reg_finsr((reg + 0x0280), 7, 0, 0x70);
+ reg_finsr((reg + 0x0280), 23, 16, 0x70);
+ reg_finsr((reg + 0x0284), 7, 0, 0x85);
+ reg_finsr((reg + 0x0284), 23, 16, 0x0f);
+ reg_finsr((reg + 0x0284), 31, 24, 0x1d);
+ reg_finsr((reg + 0x028c), 15, 8, 0x3b);
+
+ /* Setting lane 1 SerDes to 3GHz */
+ reg_finsr((reg + 0x0404), 7, 0, 0x80);
+ reg_finsr((reg + 0x0404), 31, 24, 0x78);
+ reg_finsr((reg + 0x0408), 7, 0, 0x24);
+ reg_finsr((reg + 0x040c), 31, 24, 0x02);
+ reg_finsr((reg + 0x0410), 31, 24, 0x1b);
+ reg_finsr((reg + 0x0414), 7, 0, 0x7c);
+ reg_finsr((reg + 0x0414), 15, 8, 0x6e);
+ reg_finsr((reg + 0x0418), 7, 0, 0xe4);
+ reg_finsr((reg + 0x0418), 23, 16, 0x80);
+ reg_finsr((reg + 0x0418), 31, 24, 0x75);
+ reg_finsr((reg + 0x042c), 15, 8, 0x08);
+ reg_finsr((reg + 0x042c), 23, 16, 0x20);
+ reg_finsr((reg + 0x0480), 7, 0, 0x70);
+ reg_finsr((reg + 0x0480), 23, 16, 0x70);
+ reg_finsr((reg + 0x0484), 7, 0, 0x85);
+ reg_finsr((reg + 0x0484), 23, 16, 0x0f);
+ reg_finsr((reg + 0x0484), 31, 24, 0x1d);
+ reg_finsr((reg + 0x048c), 15, 8, 0x3b);
+
+ /* Setting lane 2 SerDes to 3GHz */
+ reg_finsr((reg + 0x0604), 7, 0, 0x80);
+ reg_finsr((reg + 0x0604), 31, 24, 0x78);
+ reg_finsr((reg + 0x0608), 7, 0, 0x24);
+ reg_finsr((reg + 0x060c), 31, 24, 0x02);
+ reg_finsr((reg + 0x0610), 31, 24, 0x1b);
+ reg_finsr((reg + 0x0614), 7, 0, 0x7c);
+ reg_finsr((reg + 0x0614), 15, 8, 0x6e);
+ reg_finsr((reg + 0x0618), 7, 0, 0xe4);
+ reg_finsr((reg + 0x0618), 23, 16, 0x80);
+ reg_finsr((reg + 0x0618), 31, 24, 0x75);
+ reg_finsr((reg + 0x062c), 15, 8, 0x08);
+ reg_finsr((reg + 0x062c), 23, 16, 0x20);
+ reg_finsr((reg + 0x0680), 7, 0, 0x70);
+ reg_finsr((reg + 0x0680), 23, 16, 0x70);
+ reg_finsr((reg + 0x0684), 7, 0, 0x85);
+ reg_finsr((reg + 0x0684), 23, 16, 0x0f);
+ reg_finsr((reg + 0x0684), 31, 24, 0x1d);
+ reg_finsr((reg + 0x068c), 15, 8, 0x3b);
+
+ /* Setting lane 3 SerDes to 3GHz */
+ reg_finsr((reg + 0x0804), 7, 0, 0x80);
+ reg_finsr((reg + 0x0804), 31, 24, 0x78);
+ reg_finsr((reg + 0x0808), 7, 0, 0x24);
+ reg_finsr((reg + 0x080c), 31, 24, 0x02);
+ reg_finsr((reg + 0x0810), 31, 24, 0x1b);
+ reg_finsr((reg + 0x0814), 7, 0, 0x7c);
+ reg_finsr((reg + 0x0814), 15, 8, 0x6e);
+ reg_finsr((reg + 0x0818), 7, 0, 0xe4);
+ reg_finsr((reg + 0x0818), 23, 16, 0x80);
+ reg_finsr((reg + 0x0818), 31, 24, 0x75);
+ reg_finsr((reg + 0x082c), 15, 8, 0x08);
+ reg_finsr((reg + 0x082c), 23, 16, 0x20);
+ reg_finsr((reg + 0x0880), 7, 0, 0x70);
+ reg_finsr((reg + 0x0880), 23, 16, 0x70);
+ reg_finsr((reg + 0x0884), 7, 0, 0x85);
+ reg_finsr((reg + 0x0884), 23, 16, 0x0f);
+ reg_finsr((reg + 0x0884), 31, 24, 0x1d);
+ reg_finsr((reg + 0x088c), 15, 8, 0x3b);
+
+ reg_finsr((reg + 0x0a00), 15, 8, 0x08);
+ reg_finsr((reg + 0x0a08), 23, 16, 0x72);
+ reg_finsr((reg + 0x0a08), 31, 24, 0x37);
+ reg_finsr((reg + 0x0a30), 15, 8, 0x77);
+ reg_finsr((reg + 0x0a30), 23, 16, 0x77);
+ reg_finsr((reg + 0x0a84), 15, 8, 0x06);
+ reg_finsr((reg + 0x0a94), 31, 24, 0x10);
+ reg_finsr((reg + 0x0aa0), 31, 24, 0x81);
+ reg_finsr((reg + 0x0abc), 31, 24, 0xff);
+ reg_finsr((reg + 0x0ac0), 7, 0, 0x8b);
+ reg_finsr((reg + 0x0a48), 15, 8, 0x8c);
+ reg_finsr((reg + 0x0a48), 23, 16, 0xfd);
+ reg_finsr((reg + 0x0a54), 7, 0, 0x72);
+ reg_finsr((reg + 0x0a54), 15, 8, 0xec);
+ reg_finsr((reg + 0x0a54), 23, 16, 0x2f);
+ reg_finsr((reg + 0x0a58), 15, 8, 0x21);
+ reg_finsr((reg + 0x0a58), 23, 16, 0xf9);
+ reg_finsr((reg + 0x0a58), 31, 24, 0x00);
+ reg_finsr((reg + 0x0a5c), 7, 0, 0x60);
+ reg_finsr((reg + 0x0a5c), 15, 8, 0x00);
+ reg_finsr((reg + 0x0a5c), 23, 16, 0x04);
+ reg_finsr((reg + 0x0a5c), 31, 24, 0x00);
+ reg_finsr((reg + 0x0a60), 7, 0, 0x00);
+ reg_finsr((reg + 0x0a60), 15, 8, 0x80);
+ reg_finsr((reg + 0x0a60), 23, 16, 0x00);
+ reg_finsr((reg + 0x0a60), 31, 24, 0x00);
+ reg_finsr((reg + 0x0a64), 7, 0, 0x20);
+ reg_finsr((reg + 0x0a64), 15, 8, 0x12);
+ reg_finsr((reg + 0x0a64), 23, 16, 0x58);
+ reg_finsr((reg + 0x0a64), 31, 24, 0x0c);
+ reg_finsr((reg + 0x0a68), 7, 0, 0x02);
+ reg_finsr((reg + 0x0a68), 15, 8, 0x06);
+ reg_finsr((reg + 0x0a68), 23, 16, 0x3b);
+ reg_finsr((reg + 0x0a68), 31, 24, 0xe1);
+ reg_finsr((reg + 0x0a6c), 7, 0, 0xc1);
+ reg_finsr((reg + 0x0a6c), 15, 8, 0x4c);
+ reg_finsr((reg + 0x0a6c), 23, 16, 0x07);
+ reg_finsr((reg + 0x0a6c), 31, 24, 0xb8);
+ reg_finsr((reg + 0x0a70), 7, 0, 0x89);
+ reg_finsr((reg + 0x0a70), 15, 8, 0xe9);
+ reg_finsr((reg + 0x0a70), 23, 16, 0x02);
+ reg_finsr((reg + 0x0a70), 31, 24, 0x3f);
+ reg_finsr((reg + 0x0a74), 7, 0, 0x01);
+ reg_finsr((reg + 0x0b20), 23, 16, 0x37);
+ reg_finsr((reg + 0x0b1c), 31, 24, 0x37);
+ reg_finsr((reg + 0x0b20), 7, 0, 0x5d);
+ reg_finsr((reg + 0x0000), 7, 0, 0x03);
+ reg_finsr((reg + 0x0a00), 7, 0, 0x5f);
+}
+
+static void k2_rio_serdes_init_5g(u32 lanes,
+ struct keystone_rio_data *krio_priv)
+{
+ void __iomem *reg = (void __iomem *)krio_priv->serdes_regs;
+
+ /* Uses 5Gbps full rate configuration by default */
+ reg_finsr((reg + 0x0000), 31, 24, 0x00);
+ reg_finsr((reg + 0x0014), 7, 0, 0x82);
+ reg_finsr((reg + 0x0014), 15, 8, 0x82);
+ reg_finsr((reg + 0x0060), 7, 0, 0x38);
+ reg_finsr((reg + 0x0060), 15, 8, 0x24);
+ reg_finsr((reg + 0x0060), 23, 16, 0x14);
+ reg_finsr((reg + 0x0064), 15, 8, 0xc7);
+ reg_finsr((reg + 0x0064), 23, 16, 0xc3);
+ reg_finsr((reg + 0x0078), 15, 8, 0xc0);
+
+ /* Setting lane 0 SerDes to 5GHz */
+ reg_finsr((reg + 0x0204), 7, 0, 0x80);
+ reg_finsr((reg + 0x0204), 31, 24, 0x78);
+ reg_finsr((reg + 0x0208), 7, 0, 0x26);
+ reg_finsr((reg + 0x020c), 31, 24, 0x02);
+ reg_finsr((reg + 0x0214), 7, 0, 0x38);
+ reg_finsr((reg + 0x0214), 15, 8, 0x6f);
+ reg_finsr((reg + 0x0218), 7, 0, 0xe4);
+ reg_finsr((reg + 0x0218), 23, 16, 0x80);
+ reg_finsr((reg + 0x0218), 31, 24, 0x75);
+ reg_finsr((reg + 0x022c), 15, 8, 0x08);
+ reg_finsr((reg + 0x022c), 23, 16, 0x20);
+ reg_finsr((reg + 0x0280), 7, 0, 0x86);
+ reg_finsr((reg + 0x0280), 23, 16, 0x86);
+ reg_finsr((reg + 0x0284), 7, 0, 0x85);
+ reg_finsr((reg + 0x0284), 23, 16, 0x0f);
+ reg_finsr((reg + 0x0284), 31, 24, 0x1d);
+ reg_finsr((reg + 0x028c), 15, 8, 0x2c);
+
+ /* Setting lane 1 SerDes to 5GHz */
+ reg_finsr((reg + 0x0404), 7, 0, 0x80);
+ reg_finsr((reg + 0x0404), 31, 24, 0x78);
+ reg_finsr((reg + 0x0408), 7, 0, 0x26);
+ reg_finsr((reg + 0x040c), 31, 24, 0x02);
+ reg_finsr((reg + 0x0414), 7, 0, 0x38);
+ reg_finsr((reg + 0x0414), 15, 8, 0x6f);
+ reg_finsr((reg + 0x0418), 7, 0, 0xe4);
+ reg_finsr((reg + 0x0418), 23, 16, 0x80);
+ reg_finsr((reg + 0x0418), 31, 24, 0x75);
+ reg_finsr((reg + 0x042c), 15, 8, 0x08);
+ reg_finsr((reg + 0x042c), 23, 16, 0x20);
+ reg_finsr((reg + 0x0480), 7, 0, 0x86);
+ reg_finsr((reg + 0x0480), 23, 16, 0x86);
+ reg_finsr((reg + 0x0484), 7, 0, 0x85);
+ reg_finsr((reg + 0x0484), 23, 16, 0x0f);
+ reg_finsr((reg + 0x0484), 31, 24, 0x1d);
+ reg_finsr((reg + 0x048c), 15, 8, 0x2c);
+
+ /* Setting lane 2 SerDes to 5GHz */
+ reg_finsr((reg + 0x0604), 7, 0, 0x80);
+ reg_finsr((reg + 0x0604), 31, 24, 0x78);
+ reg_finsr((reg + 0x0608), 7, 0, 0x26);
+ reg_finsr((reg + 0x060c), 31, 24, 0x02);
+ reg_finsr((reg + 0x0614), 7, 0, 0x38);
+ reg_finsr((reg + 0x0614), 15, 8, 0x6f);
+ reg_finsr((reg + 0x0618), 7, 0, 0xe4);
+ reg_finsr((reg + 0x0618), 23, 16, 0x80);
+ reg_finsr((reg + 0x0618), 31, 24, 0x75);
+ reg_finsr((reg + 0x062c), 15, 8, 0x08);
+ reg_finsr((reg + 0x062c), 23, 16, 0x20);
+ reg_finsr((reg + 0x0680), 7, 0, 0x86);
+ reg_finsr((reg + 0x0680), 23, 16, 0x86);
+ reg_finsr((reg + 0x0684), 7, 0, 0x85);
+ reg_finsr((reg + 0x0684), 23, 16, 0x0f);
+ reg_finsr((reg + 0x0684), 31, 24, 0x1d);
+ reg_finsr((reg + 0x068c), 15, 8, 0x2c);
+
+ /* Setting lane 3 SerDes to 5GHz */
+ reg_finsr((reg + 0x0804), 7, 0, 0x80);
+ reg_finsr((reg + 0x0804), 31, 24, 0x78);
+ reg_finsr((reg + 0x0808), 7, 0, 0x26);
+ reg_finsr((reg + 0x080c), 31, 24, 0x02);
+ reg_finsr((reg + 0x0814), 7, 0, 0x38);
+ reg_finsr((reg + 0x0814), 15, 8, 0x6f);
+ reg_finsr((reg + 0x0818), 7, 0, 0xe4);
+ reg_finsr((reg + 0x0818), 23, 16, 0x80);
+ reg_finsr((reg + 0x0818), 31, 24, 0x75);
+ reg_finsr((reg + 0x082c), 15, 8, 0x08);
+ reg_finsr((reg + 0x082c), 23, 16, 0x20);
+ reg_finsr((reg + 0x0880), 7, 0, 0x86);
+ reg_finsr((reg + 0x0880), 23, 16, 0x86);
+ reg_finsr((reg + 0x0884), 7, 0, 0x85);
+ reg_finsr((reg + 0x0884), 23, 16, 0x0f);
+ reg_finsr((reg + 0x0884), 31, 24, 0x1d);
+ reg_finsr((reg + 0x088c), 15, 8, 0x2c);
+
+ reg_finsr((reg + 0x0a00), 15, 8, 0x80);
+ reg_finsr((reg + 0x0a08), 23, 16, 0xd2);
+ reg_finsr((reg + 0x0a08), 31, 24, 0x38);
+ reg_finsr((reg + 0x0a30), 15, 8, 0x8d);
+ reg_finsr((reg + 0x0a30), 23, 16, 0x8d);
+ reg_finsr((reg + 0x0a84), 15, 8, 0x06);
+ reg_finsr((reg + 0x0a94), 31, 24, 0x10);
+ reg_finsr((reg + 0x0aa0), 31, 24, 0x81);
+ reg_finsr((reg + 0x0abc), 31, 24, 0xff);
+ reg_finsr((reg + 0x0ac0), 7, 0, 0x8b);
+ reg_finsr((reg + 0x0a48), 15, 8, 0x8c);
+ reg_finsr((reg + 0x0a48), 23, 16, 0xfd);
+ reg_finsr((reg + 0x0a54), 7, 0, 0x72);
+ reg_finsr((reg + 0x0a54), 15, 8, 0xec);
+ reg_finsr((reg + 0x0a54), 23, 16, 0x2f);
+ reg_finsr((reg + 0x0a58), 15, 8, 0x21);
+ reg_finsr((reg + 0x0a58), 23, 16, 0xf9);
+ reg_finsr((reg + 0x0a58), 31, 24, 0x00);
+ reg_finsr((reg + 0x0a5c), 7, 0, 0x60);
+ reg_finsr((reg + 0x0a5c), 15, 8, 0x00);
+ reg_finsr((reg + 0x0a5c), 23, 16, 0x04);
+ reg_finsr((reg + 0x0a5c), 31, 24, 0x00);
+ reg_finsr((reg + 0x0a60), 7, 0, 0x00);
+ reg_finsr((reg + 0x0a60), 15, 8, 0x80);
+ reg_finsr((reg + 0x0a60), 23, 16, 0x00);
+ reg_finsr((reg + 0x0a60), 31, 24, 0x00);
+ reg_finsr((reg + 0x0a64), 7, 0, 0x20);
+ reg_finsr((reg + 0x0a64), 15, 8, 0x12);
+ reg_finsr((reg + 0x0a64), 23, 16, 0x58);
+ reg_finsr((reg + 0x0a64), 31, 24, 0x0c);
+ reg_finsr((reg + 0x0a68), 7, 0, 0x02);
+ reg_finsr((reg + 0x0a68), 15, 8, 0x06);
+ reg_finsr((reg + 0x0a68), 23, 16, 0x3b);
+ reg_finsr((reg + 0x0a68), 31, 24, 0xe1);
+ reg_finsr((reg + 0x0a6c), 7, 0, 0xc1);
+ reg_finsr((reg + 0x0a6c), 15, 8, 0x4c);
+ reg_finsr((reg + 0x0a6c), 23, 16, 0x07);
+ reg_finsr((reg + 0x0a6c), 31, 24, 0xb8);
+ reg_finsr((reg + 0x0a70), 7, 0, 0x89);
+ reg_finsr((reg + 0x0a70), 15, 8, 0xe9);
+ reg_finsr((reg + 0x0a70), 23, 16, 0x02);
+ reg_finsr((reg + 0x0a70), 31, 24, 0x3f);
+ reg_finsr((reg + 0x0a74), 7, 0, 0x01);
+ reg_finsr((reg + 0x0b20), 23, 16, 0x37);
+ reg_finsr((reg + 0x0b1c), 31, 24, 0x37);
+ reg_finsr((reg + 0x0b20), 7, 0, 0x5d);
+ reg_finsr((reg + 0x0000), 7, 0, 0x03);
+ reg_finsr((reg + 0x0a00), 7, 0, 0x5f);
+}
+
+static void k2_rio_serdes_lane_enable(u32 lane, u32 rate,
+ struct keystone_rio_data *krio_priv)
+{
+ void *regs = (void *)krio_priv->serdes_regs;
+ u32 val;
+
+ /* Bit 28 Toggled. Bring it out of Reset TX PLL for all lanes */
+ val = readl(regs + 0x200 * (lane + 1) + 0x28);
+ val &= ~BIT(29);
+ writel(val, regs + 0x200 * (lane + 1) + 0x28);
+
+ /* Set Lane Control Rate */
+ switch (rate) {
+ case KEYSTONE_RIO_FULL_RATE:
+ writel(0xF0C0F0F0, regs + 0x1fe0 + 4 * lane);
+ break;
+ case KEYSTONE_RIO_HALF_RATE:
+ writel(0xF4C0F4F0, regs + 0x1fe0 + 4 * lane);
+ break;
+ case KEYSTONE_RIO_QUARTER_RATE:
+ writel(0xF8C0F8F0, regs + 0x1fe0 + 4 * lane);
+ break;
+ default:
+ return;
+ }
+}
+
+static int k2_rio_serdes_config(u32 lanes, u32 baud,
+ struct keystone_rio_data *krio_priv)
+{
+ void *regs = (void *)krio_priv->serdes_regs;
+ u32 rate;
+ u32 val;
+
+ /* Disable pll before configuring the SerDes registers */
+ writel(0x00000000, regs + 0x1ff4);
+
+ switch (baud) {
+ case KEYSTONE_RIO_BAUD_1_250:
+ rate = KEYSTONE_RIO_QUARTER_RATE;
+ k2_rio_serdes_init_5g(lanes, krio_priv);
+ break;
+ case KEYSTONE_RIO_BAUD_2_500:
+ rate = KEYSTONE_RIO_HALF_RATE;
+ k2_rio_serdes_init_5g(lanes, krio_priv);
+ break;
+ case KEYSTONE_RIO_BAUD_5_000:
+ rate = KEYSTONE_RIO_FULL_RATE;
+ k2_rio_serdes_init_5g(lanes, krio_priv);
+ break;
+ case KEYSTONE_RIO_BAUD_3_125:
+ rate = KEYSTONE_RIO_HALF_RATE;
+ k2_rio_serdes_init_3g(lanes, krio_priv);
+ break;
+ default:
+ printf("RIO: unsupported baud rate %d\n", baud);
+ return -1;
+ }
+
+ /* Enable serdes for requested lanes */
+ while (lanes) {
+ u32 lane = ffs(lanes) - 1;
+ lanes &= ~(1 << lane);
+
+ if (lane >= KEYSTONE_RIO_MAX_PORT)
+ return -1;
+
+ k2_rio_serdes_lane_enable(lane, rate, krio_priv);
+ }
+
+ /* Enable pll via the pll_ctrl 0x0014 */
+ writel(0xe0000000, regs + 0x1ff4);
+
+ /* Wait until CMU_OK bit is set */
+ do {
+ val = readl(regs + 0xbf8);
+ } while (!(val & BIT(16)));
+
+ return 0;
+}
+
+static int k2_rio_serdes_wait_lock(struct keystone_rio_data *krio_priv,
+ u32 lanes)
+{
+ u32 loop;
+ u32 val;
+ u32 val_mask;
+ void *regs = (void *)krio_priv->serdes_regs;
+
+ val_mask = lanes | (lanes << 8);
+
+ /* Wait for the SerDes PLL lock */
+ for (loop = 0; loop < 100000; loop++) {
+ /* read PLL_CTRL */
+ val = readl(regs + 0x1ff4);
+ if ((val & val_mask) == val_mask)
+ break;
+ udelay(10);
+ }
+
+ if (loop == 100000)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * keystone_rio_hw_init - Configure a RapidIO controller
+ * @mode: serdes configuration
+ * @hostid: device id of the host
+ */
+static void keystone_rio_hw_init(u32 mode, u32 baud,
+ struct keystone_rio_data *krio_priv)
+{
+ u32 val;
+ u32 block;
+ struct keystone_serdes_config *serdes_config
+ = &(krio_priv->board_rio_cfg.serdes_config[mode]);
+
+ /* Set sRIO out of reset */
+ writel(0x00000011, &krio_priv->regs->pcr);
+
+ /* Clear BOOT_COMPLETE bit (allowing write) */
+ writel(0x00000000, &krio_priv->regs->per_set_cntl);
+
+ /* Enable blocks */
+ writel(1, &krio_priv->regs->gbl_en);
+ for (block = 0; block <= KEYSTONE_RIO_BLK_NUM; block++)
+ writel(1, &(krio_priv->regs->blk[block].enable));
+
+ /* Set control register 1 configuration */
+ writel(0x00000000, &krio_priv->regs->per_set_cntl1);
+
+ /* Set Control register */
+ writel(serdes_config->cfg_cntl, &krio_priv->regs->per_set_cntl);
+
+ if (K2_SERDES(krio_priv)) {
+ u32 path_mode = krio_priv->board_rio_cfg.path_mode;
+ u32 ports = krio_priv->board_rio_cfg.ports;
+ int res;
+
+ /* K2 SerDes main configuration */
+ res = keystone_rio_get_lane_config(ports, path_mode);
+ if (res > 0) {
+ u32 lanes = (u32) res;
+ res = k2_rio_serdes_config(lanes, baud, krio_priv);
+ }
+ } else {
+ u32 port;
+
+ /* K1 SerDes main configuration */
+ writel(serdes_config->serdes_cfg_pll,
+ &krio_priv->serdes_regs->pll);
+
+ /* Per-port SerDes configuration */
+ for (port = 0; port < KEYSTONE_RIO_MAX_PORT; port++) {
+ writel(serdes_config->rx_chan_config[port],
+ &krio_priv->serdes_regs->channel[port].rx);
+ writel(serdes_config->tx_chan_config[port],
+ &krio_priv->serdes_regs->channel[port].tx);
+ }
+
+ /* Check for RIO SerDes PLL lock */
+ do {
+ val = readl(krio_priv->serdes_sts_reg);
+ } while ((val & 0x1) != 0x1);
+ }
+
+ /* Set prescalar for ip_clk */
+ writel(serdes_config->prescalar_srv_clk,
+ &krio_priv->link_regs->prescalar_srv_clk);
+
+ /* Peripheral-specific configuration and capabilities */
+ writel(KEYSTONE_RIO_DEV_ID_VAL,
+ &krio_priv->car_csr_regs->dev_id);
+ writel(KEYSTONE_RIO_DEV_INFO_VAL,
+ &krio_priv->car_csr_regs->dev_info);
+ writel(KEYSTONE_RIO_ID_TI,
+ &krio_priv->car_csr_regs->assembly_id);
+ writel(KEYSTONE_RIO_EXT_FEAT_PTR,
+ &krio_priv->car_csr_regs->assembly_info);
+
+ /* Set host device id */
+ writel((krio_priv->riohdid & 0xffff)
+ | ((krio_priv->riohdid & 0xff) << 16),
+ &krio_priv->car_csr_regs->base_dev_id);
+
+ krio_priv->rio_pe_feat = RIO_PEF_PROCESSOR
+ | RIO_PEF_CTLS
+ | KEYSTONE_RIO_PEF_FLOW_CONTROL
+ | RIO_PEF_EXT_FEATURES
+ | RIO_PEF_ADDR_34
+ | RIO_PEF_STD_RT
+ | RIO_PEF_INB_DOORBELL
+ | RIO_PEF_INB_MBOX;
+
+ writel(krio_priv->rio_pe_feat,
+ &krio_priv->car_csr_regs->pe_feature);
+
+ writel(KEYSTONE_RIO_MAX_PORT << 8,
+ &krio_priv->car_csr_regs->sw_port);
+
+ writel((RIO_SRC_OPS_READ
+ | RIO_SRC_OPS_WRITE
+ | RIO_SRC_OPS_STREAM_WRITE
+ | RIO_SRC_OPS_WRITE_RESPONSE
+ | RIO_SRC_OPS_DATA_MSG
+ | RIO_SRC_OPS_DOORBELL
+ | RIO_SRC_OPS_ATOMIC_TST_SWP
+ | RIO_SRC_OPS_ATOMIC_INC
+ | RIO_SRC_OPS_ATOMIC_DEC
+ | RIO_SRC_OPS_ATOMIC_SET
+ | RIO_SRC_OPS_ATOMIC_CLR
+ | RIO_SRC_OPS_PORT_WRITE),
+ &krio_priv->car_csr_regs->src_op);
+
+ writel((RIO_DST_OPS_READ
+ | RIO_DST_OPS_WRITE
+ | RIO_DST_OPS_STREAM_WRITE
+ | RIO_DST_OPS_WRITE_RESPONSE
+ | RIO_DST_OPS_DATA_MSG
+ | RIO_DST_OPS_DOORBELL
+ | RIO_DST_OPS_PORT_WRITE),
+ &krio_priv->car_csr_regs->dest_op);
+
+ writel(RIO_PELL_ADDR_34,
+ &krio_priv->car_csr_regs->pe_logical_ctl);
+
+ val = (((KEYSTONE_RIO_SP_HDR_NEXT_BLK_PTR & 0xffff) << 16) |
+ KEYSTONE_RIO_SP_HDR_EP_REC_ID);
+ writel(val, &krio_priv->serial_port_regs->sp_maint_blk_hdr);
+
+ /* clear high bits of local config space base addr */
+ writel(0x00000000, &krio_priv->car_csr_regs->local_cfg_hbar);
+
+ /* set local config space base addr */
+ writel(0x00520000, &krio_priv->car_csr_regs->local_cfg_bar);
+
+ /* Enable HOST & MASTER_ENABLE bits */
+ writel(0xe0000000, &krio_priv->serial_port_regs->sp_gen_ctl);
+
+ /* set link timeout value */
+ writel(0x000FFF00,
+ &krio_priv->serial_port_regs->sp_link_timeout_ctl);
+
+ /* set response timeout value */
+ writel(0x000FFF00,
+ &krio_priv->serial_port_regs->sp_rsp_timeout_ctl);
+
+ /* allows SELF_RESET and PWDN_PORT resets to clear sticky reg bits */
+ writel(0x00000001, &krio_priv->link_regs->reg_rst_ctl);
+
+ /* Set error detection mode */
+ /* clear all errors */
+ writel(0x00000000, &krio_priv->err_mgmt_regs->err_det);
+
+ /* enable all error detection */
+ writel(0x00000000, &krio_priv->err_mgmt_regs->err_en);
+
+ /* set err det block header */
+ val = (((KEYSTONE_RIO_ERR_HDR_NEXT_BLK_PTR & 0xffff) << 16) |
+ KEYSTONE_RIO_ERR_EXT_FEAT_ID);
+ writel(val, &krio_priv->err_mgmt_regs->err_report_blk_hdr);
+
+ /* clear msb of err catptured addr reg */
+ writel(0x00000000, &krio_priv->err_mgmt_regs->h_addr_capt);
+
+ /* clear lsb of err catptured addr reg */
+ writel(0x00000000, &krio_priv->err_mgmt_regs->addr_capt);
+
+ /* clear err catptured source and dest devID reg */
+ writel(0x00000000, &krio_priv->err_mgmt_regs->id_capt);
+
+ /* clear err catptured packet info */
+ writel(0x00000000, &krio_priv->err_mgmt_regs->ctrl_capt);
+
+ /* Force all writes to finish */
+ val = readl(&krio_priv->err_mgmt_regs->ctrl_capt);
+}
+
+/**
+ * keystone_rio_start - Start RapidIO controller
+ */
+static void keystone_rio_start(struct keystone_rio_data *krio_priv)
+{
+ u32 val;
+
+ /* set PEREN bit to enable logical layer data flow */
+ val = (KEYSTONE_RIO_PER_EN | KEYSTONE_RIO_PER_FREE);
+ writel(val, &krio_priv->regs->pcr);
+
+ /* set BOOT_COMPLETE bit */
+ val = readl(&krio_priv->regs->per_set_cntl);
+ writel(val | KEYSTONE_RIO_BOOT_COMPLETE,
+ &krio_priv->regs->per_set_cntl);
+}
+
+/**
+ * keystone_rio_port_status - Return if the port is OK or not
+ * @port: index of the port
+ *
+ * Return %0 if the port is ready or %-EIO on failure.
+ */
+static int keystone_rio_port_status(int port,
+ struct keystone_rio_data *krio_priv)
+{
+ unsigned int count, value;
+ int solid_ok = 0;
+
+ if (port >= KEYSTONE_RIO_MAX_PORT)
+ return -1;
+
+ /* Check port status */
+ for (count = 0; count < 300; count++) {
+ value = readl(
+ &(krio_priv->serial_port_regs->sp[port].err_stat));
+
+ if (value & RIO_PORT_N_ERR_STS_PORT_OK) {
+ solid_ok++;
+ if (solid_ok == 100)
+ break;
+ } else {
+ if (solid_ok) {
+ debug_rio(
+ "RIO: unstable port %d (solid_ok = %d)\n",
+ port, solid_ok);
+ return -2;
+ }
+ solid_ok = 0;
+ }
+ udelay(20);
+ }
+
+ return 0;
+}
+
+/**
+ * keystone_rio_port_disable - Disable a RapidIO port
+ * @port: index of the port to configure
+ */
+static void keystone_rio_port_disable(u32 port,
+ struct keystone_rio_data *krio_priv)
+{
+ /* Disable port */
+ writel(0x800000, &(krio_priv->serial_port_regs->sp[port].ctl));
+}
+
+/**
+ * keystone_rio_port_init - Configure a RapidIO port
+ * @port: index of the port to configure
+ * @mode: serdes configuration
+ */
+static int keystone_rio_port_init(u32 port, u32 path_mode,
+ struct keystone_rio_data *krio_priv)
+{
+ if (port >= KEYSTONE_RIO_MAX_PORT)
+ return -1;
+
+ /* Disable packet forwarding */
+ writel(0xffffffff, &(krio_priv->regs->pkt_fwd_cntl[port].pf_16b));
+ writel(0x0003ffff, &(krio_priv->regs->pkt_fwd_cntl[port].pf_8b));
+
+ /* Silence and discovery timers */
+ if ((port == 0) || (port == 2)) {
+ writel(0x20000000,
+ &(krio_priv->phy_regs->phy_sp[port].silence_timer));
+ writel(0x20000000,
+ &(krio_priv->phy_regs->phy_sp[port].discovery_timer));
+ }
+
+ /* Enable port in input and output */
+ writel(0x600000, &(krio_priv->serial_port_regs->sp[port].ctl));
+
+ /* Program channel allocation to ports (1x, 2x or 4x) */
+ writel(path_mode, &(krio_priv->phy_regs->phy_sp[port].path_ctl));
+
+ return 0;
+}
+
+/**
+ * keystone_rio_port_activate - Start using a RapidIO port
+ * @port: index of the port to configure
+ */
+static int keystone_rio_port_activate(u32 port,
+ struct keystone_rio_data *krio_priv)
+{
+ /* Cleanup port error status */
+ writel(KEYSTONE_RIO_PORT_ERROR_MASK,
+ &(krio_priv->serial_port_regs->sp[port].err_stat));
+ writel(0, &(krio_priv->err_mgmt_regs->sp_err[port].det));
+
+ /* Enable promiscuous */
+ writel(0x00309000,
+ &(krio_priv->transport_regs->transport_sp[port].control));
+
+ return 0;
+}
+
+/*------------------------ Main driver functions -----------------------*/
+
+static void keystone_rio_get_controller_defaults(
+ struct keystone_rio_data *krio_priv,
+ int riosize,
+ u32 rioports,
+ int riopmode,
+ int riobaudrate)
+{
+ struct keystone_rio_board_controller_info *c
+ = &krio_priv->board_rio_cfg;
+ int i;
+
+ c->keystone2_serdes = KEYSTONE_RIO_IS_K2;
+
+ if (K2_SERDES(krio_priv)) {
+ /* K2 configuration */
+ c->rio_regs_base = 0x2900000;
+ c->rio_regs_size = 0x40000;
+ c->boot_cfg_regs_base = 0x2620000;
+ c->boot_cfg_regs_size = 0x1000;
+ c->serdes_cfg_regs_base = 0x232c000;
+ c->serdes_cfg_regs_size = 0x1000;
+ } else {
+ /* K1 configuration */
+ c->rio_regs_base = 0x2900000;
+ c->rio_regs_size = 0x21000;
+ c->boot_cfg_regs_base = 0x2620000;
+ c->boot_cfg_regs_size = 0x3b0;
+ c->serdes_cfg_regs_base = 0x2900360;
+ c->serdes_cfg_regs_size = 0x1000;
+ }
+
+ /* dev-id-size */
+ c->size = riosize;
+
+ /* ports to use */
+ c->ports = rioports;
+
+ /* SerDes config */
+ c->serdes_config_num = 1; /* total number of serdes_config[] entries */
+ c->mode = 0; /* default serdes_config[] entry to use */
+ c->path_mode = riopmode;
+
+ if (K2_SERDES(krio_priv)) {
+ /*
+ * K2 sRIO config 0
+ */
+ c->serdes_config[0].prescalar_srv_clk = 0x001f;
+ c->serdes_baudrate = riobaudrate;
+ } else {
+ /*
+ * K1 sRIO config 0: MPY = 5x, div rate = half,
+ * link rate = 3.125 Gbps, mode 1x
+ */
+
+ /* setting control register config */
+ c->serdes_config[0].cfg_cntl = 0x0c053860;
+
+ /* SerDes PLL configuration */
+ c->serdes_config[0].serdes_cfg_pll = 0x0229;
+
+ /* prescalar_srv_clk */
+ c->serdes_config[0].prescalar_srv_clk = 0x001e;
+
+ /* serdes rx_chan_config */
+ for (i = 0; i < KEYSTONE_RIO_MAX_PORT; i++)
+ c->serdes_config[0].rx_chan_config[i] = 0x00440495;
+
+ /* serdes tx_chan_config */
+ for (i = 0; i < KEYSTONE_RIO_MAX_PORT; i++)
+ c->serdes_config[0].tx_chan_config[i] = 0x00180795;
+ }
+}
+
+/*
+ * Platform configuration setup
+ */
+static int keystone_rio_setup_controller(struct keystone_rio_data *krio_priv)
+{
+ u32 ports;
+ u32 p;
+ u32 mode;
+ u32 baud;
+ u32 path_mode;
+ u32 size = 0;
+ int res = 0;
+ char str[8];
+
+ size = krio_priv->board_rio_cfg.size;
+ ports = krio_priv->board_rio_cfg.ports;
+ mode = krio_priv->board_rio_cfg.mode;
+ baud = krio_priv->board_rio_cfg.serdes_baudrate;
+ path_mode = krio_priv->board_rio_cfg.path_mode;
+
+ debug_rio(
+ "RIO: size = %d, ports = 0x%x, mode = %d, baud = %d, path_mode = %d\n",
+ size, ports, mode, baud, path_mode);
+
+ if (mode >= krio_priv->board_rio_cfg.serdes_config_num) {
+ mode = 0;
+ printf("RIO: invalid port mode, forcing it to %d\n", mode);
+ }
+
+ if (baud > KEYSTONE_RIO_BAUD_5_000) {
+ baud = KEYSTONE_RIO_BAUD_5_000;
+ printf("RIO: invalid baud rate, forcing it to 5Gbps\n");
+ }
+
+ switch (baud) {
+ case KEYSTONE_RIO_BAUD_1_250:
+ snprintf(str, sizeof(str), "1.25");
+ break;
+ case KEYSTONE_RIO_BAUD_2_500:
+ snprintf(str, sizeof(str), "2.50");
+ break;
+ case KEYSTONE_RIO_BAUD_3_125:
+ snprintf(str, sizeof(str), "3.125");
+ break;
+ case KEYSTONE_RIO_BAUD_5_000:
+ snprintf(str, sizeof(str), "5.00");
+ break;
+ default:
+ return -1;
+ }
+
+ printf("RIO: initializing %s Gbps interface with port configuration %d\n",
+ str, path_mode);
+
+ /* Hardware set up of the controller */
+ keystone_rio_hw_init(mode, baud, krio_priv);
+
+ /* Disable all ports */
+ for (p = 0; p < KEYSTONE_RIO_MAX_PORT; p++)
+ keystone_rio_port_disable(p, krio_priv);
+
+ /* Start the controller */
+ keystone_rio_start(krio_priv);
+
+ /* Try to lock K2 SerDes*/
+ if (K2_SERDES(krio_priv)) {
+ int lanes = keystone_rio_get_lane_config(ports, path_mode);
+ if (lanes > 0) {
+ res = k2_rio_serdes_wait_lock(krio_priv, (u32) lanes);
+ if (res < 0)
+ debug_rio(
+ "SerDes for lane mask 0x%x on %s Gbps not locked\n",
+ lanes, str);
+ }
+ }
+
+ /* Use and check ports status (but only the requested ones) */
+ krio_priv->ports_registering = ports;
+ while (ports) {
+ int status;
+ u32 port = ffs(ports) - 1;
+ if (port > 32)
+ return 0;
+ ports &= ~(1 << port);
+
+ res = keystone_rio_port_init(port, path_mode, krio_priv);
+ if (res < 0) {
+ printf("RIO: initialization of port %d failed\n", p);
+ return res;
+ }
+
+ /* Start the port */
+ keystone_rio_port_activate(port, krio_priv);
+
+ /* Check the port status */
+ status = keystone_rio_port_status(port, krio_priv);
+ if (status == 0) {
+ krio_priv->ports_registering &= ~(1 << port);
+ printf("RIO: port RIO%d ready\n", port);
+ } else {
+ printf("RIO: port %d not ready (status %d)\n",
+ port, status);
+ }
+ }
+
+ if (krio_priv->ports_registering != 0)
+ return -1;
+
+ return res;
+}
+
+/**
+ * rio_init - Initialize RapidIO subsystem
+ * @riohdid: RapidIO host device ID
+ * @riosize: RapidIO device ID size
+ * @rioports: bitmask of ports to configure
+ * @riopmode: path mode (lanes to ports mapping)
+ * @riobaudrate: link baudrate
+ *
+ * Returns riohandle on success or %NULL on failure.
+ */
+void *rio_init(int riohdid,
+ int riosize,
+ u32 rioports,
+ int riopmode,
+ int riobaudrate)
+{
+ struct keystone_rio_data *krio_priv = &__krio_priv;
+ int res = 0;
+ void *regs;
+
+ keystone_rio_get_controller_defaults(krio_priv,
+ riosize,
+ rioports,
+ riopmode,
+ riobaudrate);
+
+ regs = (void *)krio_priv->board_rio_cfg.boot_cfg_regs_base;
+ krio_priv->jtagid_reg = regs + 0x0018;
+ krio_priv->serdes_sts_reg = regs + 0x0154;
+
+ regs = (void *)krio_priv->board_rio_cfg.serdes_cfg_regs_base;
+ krio_priv->serdes_regs = regs;
+
+ regs = (void *)krio_priv->board_rio_cfg.rio_regs_base;
+ krio_priv->regs = regs;
+ krio_priv->car_csr_regs = regs + 0x0b000;
+ krio_priv->serial_port_regs = regs + 0x0b100;
+ krio_priv->err_mgmt_regs = regs + 0x0c000;
+ krio_priv->phy_regs = regs + 0x1b000;
+ krio_priv->transport_regs = regs + 0x1b300;
+ krio_priv->pkt_buf_regs = regs + 0x1b600;
+ krio_priv->evt_mgmt_regs = regs + 0x1b900;
+ krio_priv->port_write_regs = regs + 0x1ba00;
+ krio_priv->link_regs = regs + 0x1bd00;
+ krio_priv->fabric_regs = regs + 0x1be00;
+ krio_priv->car_csr_regs_base = (u32) regs + 0xb000;
+
+ krio_priv->riohdid = riohdid;
+
+ /* Enable srio clock */
+ psc_enable_module(KS2_LPSC_SRIO);
+
+ printf("KeyStone RapidIO driver %s, hdid=%d\n", DRIVER_VER, riohdid);
+
+ /* Setup the sRIO controller */
+ res = keystone_rio_setup_controller(krio_priv);
+ if (res < 0)
+ return NULL;
+
+ return (void *)krio_priv;
+}
+
+/**
+ * rio_shutdown - Shutdown RapidIO subsystem
+ * @riohandle: RapidIO handle (returned by rio_init)
+ *
+ * Returns %0 on success or %-1 on failure.
+ */
+int rio_shutdown(void *riohandle)
+{
+ if (riohandle != &__krio_priv)
+ return -1;
+
+ /* Power off */
+ psc_disable_module(KS2_LPSC_SRIO);
+
+ return 0;
+}
diff --git a/drivers/rapidio/keystone_rio.h b/drivers/rapidio/keystone_rio.h
new file mode 100644
index 0000000..92547ae
--- /dev/null
+++ b/drivers/rapidio/keystone_rio.h
@@ -0,0 +1,650 @@
+/*
+ * (C) Copyright 2015
+ * Texas Instruments Incorporated, <www.ti.com>
+ * Authors: Aurelien Jacquiot <a-jacquiot at ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef KEYSTONE_RIO_H
+#define KEYSTONE_RIO_H
+
+#include <asm/setup.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+#define BIT(x) (1 << (x))
+
+#define KEYSTONE_RIO_MAP_FLAG_SEGMENT BIT(0)
+#define KEYSTONE_RIO_MAP_FLAG_SRC_PROMISC BIT(1)
+#define KEYSTONE_RIO_MAP_FLAG_TT_16 BIT(13)
+#define KEYSTONE_RIO_MAP_FLAG_DST_PROMISC BIT(15)
+#define KEYSTONE_RIO_DESC_FLAG_TT_16 BIT(9)
+
+#define KEYSTONE_RIO_BOOT_COMPLETE BIT(24)
+#define KEYSTONE_RIO_PER_EN BIT(2)
+#define KEYSTONE_RIO_PER_FREE BIT(0)
+#define KEYSTONE_RIO_PEF_FLOW_CONTROL BIT(7)
+
+/*
+ * Packet types
+ */
+#define KEYSTONE_RIO_PACKET_TYPE_NREAD 0x24
+#define KEYSTONE_RIO_PACKET_TYPE_NWRITE 0x54
+#define KEYSTONE_RIO_PACKET_TYPE_NWRITE_R 0x55
+#define KEYSTONE_RIO_PACKET_TYPE_SWRITE 0x60
+#define KEYSTONE_RIO_PACKET_TYPE_DBELL 0xa0
+#define KEYSTONE_RIO_PACKET_TYPE_MAINT_R 0x80
+#define KEYSTONE_RIO_PACKET_TYPE_MAINT_W 0x81
+#define KEYSTONE_RIO_PACKET_TYPE_MAINT_RR 0x82
+#define KEYSTONE_RIO_PACKET_TYPE_MAINT_WR 0x83
+#define KEYSTONE_RIO_PACKET_TYPE_MAINT_PW 0x84
+
+/*
+ * LSU defines
+ */
+#define KEYSTONE_RIO_LSU_PRIO 0
+
+#define KEYSTONE_RIO_LSU_BUSY_MASK BIT(31)
+#define KEYSTONE_RIO_LSU_FULL_MASK BIT(30)
+
+#define KEYSTONE_RIO_LSU_CC_MASK 0x0f
+#define KEYSTONE_RIO_LSU_CC_TIMEOUT 0x01
+#define KEYSTONE_RIO_LSU_CC_XOFF 0x02
+#define KEYSTONE_RIO_LSU_CC_ERROR 0x03
+#define KEYSTONE_RIO_LSU_CC_INVALID 0x04
+#define KEYSTONE_RIO_LSU_CC_DMA 0x05
+#define KEYSTONE_RIO_LSU_CC_RETRY 0x06
+#define KEYSTONE_RIO_LSU_CC_CANCELED 0x07
+
+/* Mask for receiving both error and good completion LSU interrupts */
+#define KEYSTONE_RIO_ICSR_LSU0(src_id) ((0x10001) << (src_id))
+
+/* Keystone2 supported baud rates */
+#define KEYSTONE_RIO_BAUD_1_250 0
+#define KEYSTONE_RIO_BAUD_2_500 1
+#define KEYSTONE_RIO_BAUD_3_125 2
+#define KEYSTONE_RIO_BAUD_5_000 3
+
+#define KEYSTONE_RIO_FULL_RATE 0
+#define KEYSTONE_RIO_HALF_RATE 1
+#define KEYSTONE_RIO_QUARTER_RATE 2
+
+/* Max ports configuration per path modes */
+#define KEYSTONE_MAX_PORTS_PATH_MODE_0 0xf /* 4 ports */
+#define KEYSTONE_MAX_PORTS_PATH_MODE_1 0xd /* 3 ports */
+#define KEYSTONE_MAX_PORTS_PATH_MODE_2 0x7 /* 3 ports */
+#define KEYSTONE_MAX_PORTS_PATH_MODE_3 0x5 /* 2 ports */
+#define KEYSTONE_MAX_PORTS_PATH_MODE_4 0x1 /* 1 ports */
+
+#define SERDES_LANE(lane_num) (0x01 << lane_num)
+#define IS_SERDES_LANE_USED(lanes, lane_num) (lanes & SERDES_LANE(lane_num))
+
+/*
+ * Various RIO defines
+ */
+#define KEYSTONE_RIO_TIMEOUT_CNT 1000
+
+/*
+ * RIO error, reset and special event interrupt defines
+ */
+#define KEYSTONE_RIO_PORT_ERROR_OUT_PKT_DROP BIT(26)
+#define KEYSTONE_RIO_PORT_ERROR_OUT_FAILED BIT(25)
+#define KEYSTONE_RIO_PORT_ERROR_OUT_DEGRADED BIT(24)
+#define KEYSTONE_RIO_PORT_ERROR_OUT_RETRY BIT(20)
+#define KEYSTONE_RIO_PORT_ERROR_OUT_ERROR BIT(17)
+#define KEYSTONE_RIO_PORT_ERROR_IN_ERROR BIT(9)
+#define KEYSTONE_RIO_PORT_ERROR_PW_PENDING BIT(4)
+#define KEYSTONE_RIO_PORT_ERROR_PORT_ERR BIT(2)
+
+#define KEYSTONE_RIO_PORT_ERROR_MASK \
+ (KEYSTONE_RIO_PORT_ERROR_OUT_PKT_DROP |\
+ KEYSTONE_RIO_PORT_ERROR_OUT_FAILED |\
+ KEYSTONE_RIO_PORT_ERROR_OUT_DEGRADED |\
+ KEYSTONE_RIO_PORT_ERROR_OUT_RETRY |\
+ KEYSTONE_RIO_PORT_ERROR_OUT_ERROR |\
+ KEYSTONE_RIO_PORT_ERROR_IN_ERROR |\
+ KEYSTONE_RIO_PORT_ERROR_PW_PENDING |\
+ KEYSTONE_RIO_PORT_ERROR_PORT_ERR)
+
+
+#define KEYSTONE_RIO_SP_HDR_NEXT_BLK_PTR 0x1000
+#define KEYSTONE_RIO_SP_HDR_EP_REC_ID 0x0002
+#define KEYSTONE_RIO_ERR_HDR_NEXT_BLK_PTR 0x3000
+#define KEYSTONE_RIO_ERR_EXT_FEAT_ID 0x0007
+
+/*
+ * RapidIO global definitions
+ */
+#define KEYSTONE_RIO_MAX_PORT 4
+#define KEYSTONE_RIO_BLK_NUM 9
+#define KEYSTONE_RIO_MAINT_BUF_SIZE 64
+
+/*
+ * Dev Id and dev revision
+ */
+#define KEYSTONE_RIO_DEV_ID_VAL \
+ ((((__raw_readl(krio_priv->jtagid_reg)) << 4) & 0xffff0000) | 0x30)
+
+#define KEYSTONE_RIO_DEV_INFO_VAL \
+ (((__raw_readl(krio_priv->jtagid_reg)) >> 28) & 0xf)
+
+#define KEYSTONE_RIO_ID_TI (0x00000030)
+#define KEYSTONE_RIO_EXT_FEAT_PTR (0x00000100)
+
+/*
+ * SerDes configurations
+ */
+struct keystone_serdes_config {
+ u32 cfg_cntl; /* setting control register config */
+ u16 serdes_cfg_pll; /* SerDes PLL configuration */
+ u16 prescalar_srv_clk; /* prescalar fo ip_clk */
+
+ /* SerDes receive channel configuration (per-port) */
+ u32 rx_chan_config[KEYSTONE_RIO_MAX_PORT];
+
+ /* SerDes transmit channel configuration (per-port) */
+ u32 tx_chan_config[KEYSTONE_RIO_MAX_PORT];
+};
+
+/*
+ * Per board RIO devices controller configuration
+ */
+struct keystone_rio_board_controller_info {
+ u32 rio_regs_base;
+ u32 rio_regs_size;
+
+ u32 boot_cfg_regs_base;
+ u32 boot_cfg_regs_size;
+
+ u32 serdes_cfg_regs_base;
+ u32 serdes_cfg_regs_size;
+
+ u16 ports; /* bitfield of port(s) to probe on this controller */
+ u16 mode; /* hw mode (default serdes config).
+ index into serdes_config[] */
+ u16 id; /* host id */
+ u16 size; /* RapidIO common transport system size.
+ * 0 - Small size. 256 devices.
+ * 1 - Large size, 65536 devices. */
+ u16 keystone2_serdes;
+ u16 serdes_config_num;
+ u32 serdes_baudrate;
+ u32 path_mode;
+
+ struct keystone_serdes_config serdes_config[4];
+};
+
+struct keystone_rio_data;
+
+/*
+ * RapidIO Registers
+ */
+
+struct keystone_srio_serdes_regs {
+ u32 pll;
+
+ struct {
+ u32 rx;
+ u32 tx;
+ } channel[4];
+};
+
+/* RIO Registers 0000 - 2fff */
+struct keystone_rio_regs {
+/* Required Peripheral Registers */
+ u32 pid; /* 0000 */
+ u32 pcr; /* 0004 */
+ u32 __rsvd0[3]; /* 0008 - 0010 */
+
+/* Peripheral Settting Control Registers */
+ u32 per_set_cntl; /* 0014 */
+ u32 per_set_cntl1; /* 0018 */
+
+ u32 __rsvd1[2]; /* 001c - 0020 */
+
+ u32 gbl_en; /* 0024 */
+ u32 gbl_en_stat; /* 0028 */
+
+ struct {
+ u32 enable; /* 002c */
+ u32 status; /* 0030 */
+ } blk[10]; /* 002c - 0078 */
+
+ /* ID Registers */
+ u32 __rsvd2[17]; /* 007c - 00bc */
+ u32 multiid_reg[8]; /* 00c0 - 00dc */
+
+/* Hardware Packet Forwarding Registers */
+ struct {
+ u32 pf_16b;
+ u32 pf_8b;
+ } pkt_fwd_cntl[8]; /* 00e0 - 011c */
+
+ u32 __rsvd3[24]; /* 0120 - 017c */
+
+/* Interrupt Registers */
+ struct {
+ u32 status;
+ u32 __rsvd0;
+ u32 clear;
+ u32 __rsvd1;
+ } doorbell_int[4]; /* 0180 - 01bc */
+
+ struct {
+ u32 status;
+ u32 __rsvd0;
+ u32 clear;
+ u32 __rsvd1;
+ } lsu_int[2]; /* 01c0 - 01dc */
+
+ u32 err_rst_evnt_int_stat; /* 01e0 */
+ u32 __rsvd4;
+ u32 err_rst_evnt_int_clear; /* 01e8 */
+ u32 __rsvd5;
+
+ u32 __rsvd6[4]; /* 01f0 - 01fc */
+
+ struct {
+ u32 route; /* 0200 */
+ u32 route2; /* 0204 */
+ u32 __rsvd; /* 0208 */
+ } doorbell_int_route[4]; /* 0200 - 022c */
+
+ u32 lsu0_int_route[4]; /* 0230 - 023c */
+ u32 lsu1_int_route1; /* 0240 */
+
+ u32 __rsvd7[3]; /* 0244 - 024c */
+
+ u32 err_rst_evnt_int_route[3]; /* 0250 - 0258 */
+
+ u32 __rsvd8[2]; /* 025c - 0260 */
+
+ u32 interupt_ctl; /* 0264 */
+
+ u32 __rsvd9[26]; /* 0268, 026c, 0270 - 02cc */
+
+ u32 intdst_rate_cntl[16]; /* 02d0 - 030c */
+ u32 intdst_rate_disable; /* 0310 */
+
+ u32 __rsvd10[59]; /* 0314 - 03fc */
+
+/* RXU Registers */
+ struct {
+ u32 ltr_mbox_src;
+ u32 dest_prom_seg;
+ u32 flow_qid;
+ } rxu_map[64]; /* 0400 - 06fc */
+
+ struct {
+ u32 cos_src;
+ u32 dest_prom;
+ u32 stream;
+ } rxu_type9_map[64]; /* 0700 - 09fc */
+
+ u32 __rsvd11[192]; /* 0a00 - 0cfc */
+
+/* LSU/MAU Registers */
+ struct {
+ u32 addr_msb; /* 0d00 */
+ u32 addr_lsb_cfg_ofs; /* 0d04 */
+ u32 dsp_addr; /* 0d08 */
+ u32 dbell_val_byte_cnt; /* 0d0c */
+ u32 destid; /* 0d10 */
+ u32 dbell_info_fttype; /* 0d14 */
+ u32 busy_full; /* 0d18 */
+ } lsu_reg[8]; /* 0d00 - 0ddc */
+
+ u32 lsu_setup_reg[2]; /* 0de0 - 0de4 */
+ u32 lsu_stat_reg[6]; /* 0de8 - 0dfc */
+ u32 lsu_flow_masks[4]; /* 0e00 - 0e0c */
+
+ u32 __rsvd12[16]; /* 0e10 - 0e4c */
+
+/* Flow Control Registers */
+ u32 flow_cntl[16]; /* 0e50 - 0e8c */
+ u32 __rsvd13[8]; /* 0e90 - 0eac */
+
+/* TXU Registers 0eb0 - 0efc */
+ u32 tx_cppi_flow_masks[8]; /* 0eb0 - 0ecc */
+ u32 tx_queue_sch_info[4]; /* 0ed0 - 0edc */
+ u32 garbage_coll_qid[3]; /* 0ee0 - 0ee8 */
+
+ u32 __rsvd14[69]; /* 0eec, 0ef0 - 0ffc */
+
+};
+
+/* CDMAHP Registers 1000 - 2ffc */
+struct keystone_rio_pktdma_regs {
+ u32 __rsvd[2048]; /* 1000 - 2ffc */
+};
+
+/* CSR/CAR Registers b000+ */
+struct keystone_rio_car_csr_regs {
+ u32 dev_id; /* b000 */
+ u32 dev_info; /* b004 */
+ u32 assembly_id; /* b008 */
+ u32 assembly_info; /* b00c */
+ u32 pe_feature; /* b010 */
+
+ u32 sw_port; /* b014 */
+
+ u32 src_op; /* b018 */
+ u32 dest_op; /* b01c */
+
+ u32 __rsvd1[7]; /* b020 - b038 */
+
+ u32 data_stm_info; /* b03c */
+
+ u32 __rsvd2[2]; /* b040 - b044 */
+
+ u32 data_stm_logical_ctl; /* b048 */
+ u32 pe_logical_ctl; /* b04c */
+
+ u32 __rsvd3[2]; /* b050 - b054 */
+
+ u32 local_cfg_hbar; /* b058 */
+ u32 local_cfg_bar; /* b05c */
+
+ u32 base_dev_id; /* b060 */
+ u32 __rsvd4;
+ u32 host_base_id_lock; /* b068 */
+ u32 component_tag; /* b06c */
+ /* b070 - b0fc */
+};
+
+struct keystone_rio_serial_port_regs {
+ u32 sp_maint_blk_hdr; /* b100 */
+ u32 __rsvd6[7]; /* b104 - b11c */
+
+ u32 sp_link_timeout_ctl; /* b120 */
+ u32 sp_rsp_timeout_ctl; /* b124 */
+ u32 __rsvd7[5]; /* b128 - b138 */
+ u32 sp_gen_ctl; /* b13c */
+
+ struct {
+ u32 link_maint_req; /* b140 */
+ u32 link_maint_resp;/* b144 */
+ u32 ackid_stat; /* b148 */
+ u32 __rsvd[2]; /* b14c - b150 */
+ u32 ctl2; /* b154 */
+ u32 err_stat; /* b158 */
+ u32 ctl; /* b15c */
+ } sp[4]; /* b140 - b1bc */
+
+ /* b1c0 - bffc */
+};
+
+struct keystone_rio_err_mgmt_regs {
+ u32 err_report_blk_hdr; /* c000 */
+ u32 __rsvd9;
+ u32 err_det; /* c008 */
+ u32 err_en; /* c00c */
+ u32 h_addr_capt; /* c010 */
+ u32 addr_capt; /* c014 */
+ u32 id_capt; /* c018 */
+ u32 ctrl_capt; /* c01c */
+ u32 __rsvd10[2]; /* c020 - c024 */
+ u32 port_write_tgt_id; /* c028 */
+ u32 __rsvd11[5]; /* c02c - c03c */
+
+ struct {
+ u32 det; /* c040 */
+ u32 rate_en; /* c044 */
+ u32 attr_capt_dbg0; /* c048 */
+ u32 capt_0_dbg1; /* c04c */
+ u32 capt_1_dbg2; /* c050 */
+ u32 capt_2_dbg3; /* c054 */
+ u32 capt_3_dbg4; /* c058 */
+ u32 __rsvd0[3]; /* c05c - c064 */
+ u32 rate; /* c068 */
+ u32 thresh; /* c06c */
+ u32 __rsvd1[4]; /* c070 - c07c */
+ } sp_err[4]; /* c040 - c13c */
+
+ u32 __rsvd12[1972]; /* c140 - e00c */
+
+ struct {
+ u32 stat0; /* e010 */
+ u32 stat1; /* e014 */
+ u32 __rsvd[6]; /* e018 - e02c */
+ } lane_stat[4]; /* e010 - e08c */
+
+ /* e090 - 1affc */
+};
+
+struct keystone_rio_phy_layer_regs {
+ u32 phy_blk_hdr; /* 1b000 */
+ u32 __rsvd14[31]; /* 1b004 - 1b07c */
+ struct {
+ u32 imp_spec_ctl; /* 1b080 */
+ u32 pwdn_ctl; /* 1b084 */
+ u32 __rsvd0[2];
+
+ u32 status; /* 1b090 */
+ u32 int_enable; /* 1b094 */
+ u32 port_wr_enable; /* 1b098 */
+ u32 event_gen; /* 1b09c */
+
+ u32 all_int_en; /* 1b0a0 */
+ u32 all_port_wr_en; /* 1b0a4 */
+ u32 __rsvd1[2];
+
+ u32 path_ctl; /* 1b0b0 */
+ u32 discovery_timer;/* 1b0b4 */
+ u32 silence_timer; /* 1b0b8 */
+ u32 vmin_exp; /* 1b0bc */
+
+ u32 pol_ctl; /* 1b0c0 */
+ u32 __rsvd2;
+ u32 denial_ctl; /* 1b0c8 */
+ u32 __rsvd3;
+
+ u32 rcvd_mecs; /* 1b0d0 */
+ u32 __rsvd4;
+ u32 mecs_fwd; /* 1b0d8 */
+ u32 __rsvd5;
+
+ u32 long_cs_tx1; /* 1b0e0 */
+ u32 long_cs_tx2; /* 1b0e4 */
+ u32 __rsvd[6]; /* 1b0e8, 1b0ec, 1b0f0 - 1b0fc */
+ } phy_sp[4]; /* 1b080 - 1b27c */
+
+ /* 1b280 - 1b2fc */
+};
+
+struct keystone_rio_transport_layer_regs {
+ u32 transport_blk_hdr; /* 1b300 */
+ u32 __rsvd16[31]; /* 1b304 - 1b37c */
+
+ struct {
+ u32 control; /*1b380 */
+ u32 __rsvd0[3];
+
+ u32 status; /* 1b390 */
+ u32 int_enable; /* 1b394 */
+ u32 port_wr_enable; /* 1b398 */
+ u32 event_gen; /* 1b39c */
+
+ struct {
+ u32 ctl; /* 1b3a0 */
+ u32 pattern_match; /* 1b3a4 */
+ u32 __rsvd[2]; /* 1b3a8 - 1b3ac */
+ } base_route[4]; /* 1b3a0 - 1b3dc */
+
+ u32 __rsvd1[8]; /* 1b3e0 - 1b3fc */
+
+ } transport_sp[4]; /* 1b380 - 1b57c */
+
+ /* 1b580 - 1b5fc */
+};
+
+struct keystone_rio_pkt_buf_regs {
+ u32 pkt_buf_blk_hdr; /* 1b600 */
+ u32 __rsvd18[31]; /* 1b604 - 1b67c */
+
+ struct {
+ u32 control; /* 1b680 */
+ u32 __rsvd0[3];
+
+ u32 status; /* 1b690 */
+ u32 int_enable; /* 1b694 */
+ u32 port_wr_enable; /* 1b698 */
+ u32 event_gen; /* 1b69c */
+
+ u32 ingress_rsc; /* 1b6a0 */
+ u32 egress_rsc; /* 1b6a4 */
+ u32 __rsvd1[2];
+
+ u32 ingress_watermark[4]; /* 1b6b0 - 1b6bc */
+ u32 __rsvd2[16]; /* 1b6c0 - 1b6fc */
+
+ } pkt_buf_sp[4]; /* 1b680 - 1b87c */
+
+ /* 1b880 - 1b8fc */
+};
+
+struct keystone_rio_evt_mgmt_regs {
+ u32 evt_mgmt_blk_hdr; /* 1b900 */
+ u32 __rsvd20[3];
+
+ u32 evt_mgmt_int_stat; /* 1b910 */
+ u32 evt_mgmt_int_enable; /* 1b914 */
+ u32 evt_mgmt_int_port_stat; /* 1b918 */
+ u32 __rsvd21;
+
+ u32 evt_mgmt_port_wr_stat; /* 1b920 */
+ u32 evt_mgmt_port_wr_enable;/* 1b924 */
+ u32 evt_mgmt_port_wr_port_stat; /* 1b928 */
+ u32 __rsvd22;
+
+ u32 evt_mgmt_dev_int_en; /* 1b930 */
+ u32 evt_mgmt_dev_port_wr_en; /* 1b934 */
+ u32 __rsvd23;
+ u32 evt_mgmt_mecs_stat; /* 1b93c */
+
+ u32 evt_mgmt_mecs_int_en; /* 1b940 */
+ u32 evt_mgmt_mecs_cap_en; /* 1b944 */
+ u32 evt_mgmt_mecs_trig_en; /* 1b948 */
+ u32 evt_mgmt_mecs_req; /* 1b94c */
+
+ u32 evt_mgmt_mecs_port_stat;/* 1b950 */
+ u32 __rsvd24[2];
+ u32 evt_mgmt_mecs_event_gen;/* 1b95c */
+
+ u32 evt_mgmt_rst_port_stat; /* 1b960 */
+ u32 __rsvd25;
+ u32 evt_mgmt_rst_int_en; /* 1b968 */
+ u32 __rsvd26;
+
+ u32 evt_mgmt_rst_port_wr_en;/* 1b970 */
+ /* 1b974 - 1b9fc */
+};
+
+struct keystone_rio_port_write_regs {
+ u32 port_wr_blk_hdr; /* 1ba00 */
+ u32 port_wr_ctl; /* 1ba04 */
+ u32 port_wr_route; /* 1ba08 */
+ u32 __rsvd28;
+
+ u32 port_wr_rx_stat; /* 1ba10 */
+ u32 port_wr_rx_event_gen; /* 1ba14 */
+ u32 __rsvd29[2];
+
+ u32 port_wr_rx_capt[4]; /* 1ba20 - 1ba2c */
+ /* 1ba30 - 1bcfc */
+};
+
+struct keystone_rio_link_layer_regs {
+ u32 link_blk_hdr; /* 1bd00 */
+ u32 __rsvd31[8]; /* 1bd04 - 1bd20 */
+ u32 whiteboard; /* 1bd24 */
+ u32 port_number; /* 1bd28 */
+
+ u32 __rsvd32; /* 1bd2c */
+
+ u32 prescalar_srv_clk; /* 1bd30 */
+ u32 reg_rst_ctl; /* 1bd34 */
+ u32 __rsvd33[4]; /* 1bd38, 1bd3c, 1bd40, 1bd44 */
+ u32 local_err_det; /* 1bd48 */
+ u32 local_err_en; /* 1bd4c */
+
+ u32 local_h_addr_capt; /* 1bd50 */
+ u32 local_addr_capt; /* 1bd54 */
+ u32 local_id_capt; /* 1bd58 */
+ u32 local_ctrl_capt; /* 1bd5c */
+
+ /* 1bd60 - 1bdfc */
+};
+
+struct keystone_rio_fabric_regs {
+ u32 fabric_hdr; /* 1be00 */
+ u32 __rsvd35[3]; /* 1be04 - 1be0c */
+
+ u32 fabric_csr; /* 1be10 */
+ u32 __rsvd36[11]; /* 1be14 - 1be3c */
+
+ u32 sp_fabric_status[4]; /* 1be40 - 1be4c */
+};
+
+/**
+ * keystone_rio_config_read - Generate a KeyStone read maintenance transaction
+ * @portid: Output port ID of transaction
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @val: Location to be read into
+ *
+ * Generates a KeyStone read maintenance transaction. Returns %0 on
+ * success or %-1 on failure.
+ */
+int keystone_rio_config_read(int portid,
+ u16 destid,
+ u8 hopcount,
+ u32 offset,
+ int len,
+ u32 *val);
+
+/**
+ * keystone_rio_config_write - Generate a KeyStone write maintenance transaction
+ * @portid: Output port ID of transaction
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @val: Value to be written
+ *
+ * Generates an KeyStone write maintenance transaction. Returns %0 on
+ * success or %-1 on failure.
+ */
+int keystone_rio_config_write(int portid,
+ u16 destid,
+ u8 hopcount,
+ u32 offset,
+ int len,
+ u32 val);
+
+/**
+ * keystone_local_config_read - Generate a KeyStone local config space read
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Value to be read into
+ *
+ * Generates a KeyStone local configuration space read. Returns %0 on
+ * success or %-1 on failure.
+ */
+int keystone_local_config_read(u32 offset, int len, u32 *data);
+
+/**
+ * keystone_local_config_write - Generate a KeyStone local config space write
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Value to be written
+ *
+ * Generates a KeyStone local configuration space write. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+int keystone_local_config_write(u32 offset, int len, u32 data);
+
+#endif /* KEYSTONE_RIO_H */
--
1.6.2.1
More information about the U-Boot
mailing list