From patchwork Tue Nov 10 12:13:53 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: jacquiot.aurelien@gmail.com X-Patchwork-Id: 56302 Delivered-To: patch@linaro.org Received: by 10.112.155.196 with SMTP id vy4csp762859lbb; Tue, 10 Nov 2015 05:14:05 -0800 (PST) X-Received: by 10.28.174.144 with SMTP id x138mr33416939wme.28.1447161240707; Tue, 10 Nov 2015 05:14:00 -0800 (PST) Return-Path: Received: from theia.denx.de (theia.denx.de. [85.214.87.163]) by mx.google.com with ESMTP id q6si23742441wmg.4.2015.11.10.05.14.00; Tue, 10 Nov 2015 05:14:00 -0800 (PST) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.87.163 as permitted sender) client-ip=85.214.87.163; Authentication-Results: mx.google.com; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.87.163 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE dis=NONE) header.from=gmail.com Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id CC3A54B89C; Tue, 10 Nov 2015 14:13:51 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id xPXWs2KTqCkg; Tue, 10 Nov 2015 14:13:51 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9F8E24B903; Tue, 10 Nov 2015 14:12:52 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4EF134B8BD for ; Tue, 10 Nov 2015 13:14:02 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id xZx766Pm0D1Z for ; Tue, 10 Nov 2015 13:14:02 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from bear.ext.ti.com (bear.ext.ti.com [192.94.94.41]) by theia.denx.de (Postfix) with ESMTPS id 170014B8BC for ; Tue, 10 Nov 2015 13:13:57 +0100 (CET) Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id tAACDswZ006827; Tue, 10 Nov 2015 06:13:54 -0600 Received: from DFLE72.ent.ti.com (dfle72.ent.ti.com [128.247.5.109]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id tAACDsOv009817; Tue, 10 Nov 2015 06:13:54 -0600 Received: from dlep32.itg.ti.com (157.170.170.100) by DFLE72.ent.ti.com (128.247.5.109) with Microsoft SMTP Server id 14.3.224.2; Tue, 10 Nov 2015 06:13:54 -0600 Received: from svrmail.tif.ti.com (svrmail.tif.ti.com [137.167.140.111]) by dlep32.itg.ti.com (8.14.3/8.13.8) with ESMTP id tAACDrnL005162; Tue, 10 Nov 2015 06:13:54 -0600 Received: from vmuna0919873.tif.ti.com (vmuna0919873.tif.ti.com [137.167.140.82]) by svrmail.tif.ti.com (Postfix) with ESMTP id 6AA4527DFCF; Tue, 10 Nov 2015 13:13:53 +0100 (CET) Received: (from a0919873@localhost) by vmuna0919873.tif.ti.com (8.14.4/8.14.4/Submit) id tAACDrDo003789; Tue, 10 Nov 2015 13:13:53 +0100 From: To: Date: Tue, 10 Nov 2015 13:13:53 +0100 Message-ID: <1447157633-3757-1-git-send-email-jacquiot.aurelien@gmail.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-Mailman-Approved-At: Tue, 10 Nov 2015 14:10:54 +0100 Cc: trini@konsulko.com Subject: [U-Boot] [PATCH 4/4] rapidio: add driver for TI KeyStone RapidIO X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Aurelien Jacquiot 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 --- 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 -- 1.6.2.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot 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, +# +# 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, + * Authors: Aurelien Jacquiot + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +#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, + * Authors: Aurelien Jacquiot + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef KEYSTONE_RIO_H +#define KEYSTONE_RIO_H + +#include +#include +#include + +#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 */