Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp3708226yba; Tue, 9 Apr 2019 03:09:22 -0700 (PDT) X-Google-Smtp-Source: APXvYqxZ9hlcCOF/ccOfF9ExUiUlkDRxPE4mHK/8ZNVDYztVhHVVVFinywvbKcmJh6CSm3yFYey3 X-Received: by 2002:a65:64c8:: with SMTP id t8mr33381477pgv.248.1554804562192; Tue, 09 Apr 2019 03:09:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554804562; cv=none; d=google.com; s=arc-20160816; b=kApEXyjXCe6Fo1YNBGOPDmCPr+ATXwdhnSDgQ3PPvPbt+4DksFdZAT7+3FcK4HfSD/ kNSx8Zr4REoWc0OChXv8EqE4XRy0byhhET4op4NJJ+mh4OzHODupnhOw3npgFF1OoAjp pIZhgauPxlnV+hcbJk09Ckw/LIyp9vj9SBcNZzuiGfLPCna/LDFLk6Y/xENExq1hkazi bATyoCfEWDtNDmd3tJvpqGj9sDwZ05hy4DC3U7uBh9TtuXySrSdIXJEb0DhhDjQHDWgc G9ZRkqtcCfajmzDzSwGirUEY8qoZeraAKHEArJMFqKYD4Ga4z/7VU9Pl671Lz6qJIhHY UAbQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:envelope-to:dkim-signature; bh=9oOIT2dKtlzwhaRB8nqcG8StpzRfuoPMv5SlKdkhCpw=; b=ByJYXsNZ57om91k3WJDBS9lqKXK9DFsSo8SEi4xAOGaFahRUFTBOWlY1W4Po0WRIT2 jLcMmTRGcr2508rIZBkM1g4jkOZh3ILGFq9y33FVbYyaZ/9dMQH/6l5emzdY7z4zwEj7 qFcY5S4x22zmMgTgbyvQi+220/Ok32IR2Zlr4h7Dmp9gzXRaTUnAdK6Fh+pt3k2MLI+F 3TjSxXNDyKKqtLVodlOmix/2LnikAlQ1e7RSbiUyapPXEwS7hQzQPShwrvCfq3aS5XnK 9Oi/ABCp14UTzUNolpM8bxCRr3LmIhq7icPxqiMHLVoS8hRBGdvcWayxGJkMpGH4GQVU BzZg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@xilinx.onmicrosoft.com header.s=selector1-xilinx-com header.b=n33ZxbDq; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x14si28651956pfm.179.2019.04.09.03.09.05; Tue, 09 Apr 2019 03:09:22 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@xilinx.onmicrosoft.com header.s=selector1-xilinx-com header.b=n33ZxbDq; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726936AbfDIKHV (ORCPT + 99 others); Tue, 9 Apr 2019 06:07:21 -0400 Received: from mail-eopbgr750043.outbound.protection.outlook.com ([40.107.75.43]:51474 "EHLO NAM02-BL2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726236AbfDIKHT (ORCPT ); Tue, 9 Apr 2019 06:07:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector1-xilinx-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=9oOIT2dKtlzwhaRB8nqcG8StpzRfuoPMv5SlKdkhCpw=; b=n33ZxbDqoWblAsTGeIGa6jZvOe5Yn5L8jf4nXGsRAaXrxIQRvWAXAz5vjI5CywBZOEGlUi+TotDDSQva58/AfQqJc3lbiiEVrzHYtSzXzGuxJ/T0B77I1LL+7YVDmIma970bG9RyNYmL+qBSo5TAa4XXh158cL2zQIG8b9oAABc= Received: from BYAPR02CA0009.namprd02.prod.outlook.com (2603:10b6:a02:ee::22) by SN1PR02MB3839.namprd02.prod.outlook.com (2603:10b6:802:24::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1771.16; Tue, 9 Apr 2019 10:07:13 +0000 Received: from BL2NAM02FT055.eop-nam02.prod.protection.outlook.com (2a01:111:f400:7e46::206) by BYAPR02CA0009.outlook.office365.com (2603:10b6:a02:ee::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.1792.14 via Frontend Transport; Tue, 9 Apr 2019 10:07:12 +0000 Authentication-Results: spf=pass (sender IP is 149.199.80.198) smtp.mailfrom=xilinx.com; arndb.de; dkim=none (message not signed) header.d=none;arndb.de; dmarc=bestguesspass action=none header.from=xilinx.com; Received-SPF: Pass (protection.outlook.com: domain of xilinx.com designates 149.199.80.198 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.80.198; helo=xir-pvapexch01.xlnx.xilinx.com; Received: from xir-pvapexch01.xlnx.xilinx.com (149.199.80.198) by BL2NAM02FT055.mail.protection.outlook.com (10.152.77.126) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.20.1771.16 via Frontend Transport; Tue, 9 Apr 2019 10:07:12 +0000 Received: from xir-pvapexch01.xlnx.xilinx.com (172.21.17.15) by xir-pvapexch01.xlnx.xilinx.com (172.21.17.15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1531.3; Tue, 9 Apr 2019 11:07:04 +0100 Received: from smtp.xilinx.com (172.21.105.197) by xir-pvapexch01.xlnx.xilinx.com (172.21.17.15) with Microsoft SMTP Server id 15.1.1531.3 via Frontend Transport; Tue, 9 Apr 2019 11:07:04 +0100 Envelope-to: arnd@arndb.de, gregkh@linuxfoundation.org, michal.simek@xilinx.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, dragan.cvetic@xilinx.com, derek.kiernan@xilinx.com Received: from [149.199.110.15] (port=57788 helo=xirdraganc40.xilinx.com) by smtp.xilinx.com with esmtp (Exim 4.90) (envelope-from ) id 1hDnei-0007SJ-KU; Tue, 09 Apr 2019 11:07:04 +0100 From: Dragan Cvetic To: , , , CC: , Dragan Cvetic , Derek Kiernan Subject: [PATCH V2 05/12] misc: xilinx_sdfec: Store driver config and state Date: Tue, 9 Apr 2019 11:06:47 +0100 Message-ID: <1554804414-206099-6-git-send-email-dragan.cvetic@xilinx.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1554804414-206099-1-git-send-email-dragan.cvetic@xilinx.com> References: <1554804414-206099-1-git-send-email-dragan.cvetic@xilinx.com> MIME-Version: 1.0 Content-Type: text/plain X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:149.199.80.198;IPV:CAL;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(39860400002)(136003)(346002)(396003)(376002)(2980300002)(189003)(199004)(47776003)(26005)(26826003)(44832011)(30864003)(8676002)(476003)(9786002)(478600001)(106466001)(7636002)(2906002)(71366001)(50466002)(186003)(486006)(93146003)(14444005)(336012)(2616005)(446003)(956004)(8936002)(48376002)(76130400001)(426003)(11346002)(28376004)(60926002)(246002)(50226002)(106002)(316002)(110136005)(16586007)(51416003)(126002)(76176011)(107886003)(5660300002)(54906003)(36756003)(7696005)(36906005)(2201001)(305945005)(4326008)(356004)(6666004)(102446001)(461764006);DIR:OUT;SFP:1101;SCL:1;SRVR:SN1PR02MB3839;H:xir-pvapexch01.xlnx.xilinx.com;FPR:;SPF:Pass;LANG:en;PTR:unknown-80-198.xilinx.com;MX:1;A:1; X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: cfae94ff-6adb-415e-7c86-08d6bcd322c7 X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600139)(711020)(4605104)(4709054)(2017052603328);SRVR:SN1PR02MB3839; X-MS-TrafficTypeDiagnostic: SN1PR02MB3839: X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Microsoft-Antispam-PRVS: X-Forefront-PRVS: 000227DA0C X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Message-Info: K3zJUxaiYoTuxsgHX2O6bIgNDFgIco/XEBtnpfJGty0bTbtk6yBV1ik+nRZETwruYUUE2iOi/BUqk8YnW4bUYDKEAbjdQKe5bK+iJ3d7BPSDFRfht+a2vSVwo5ypL/QNJAwmXbGAMuSCVaprXzR3GHmdbPJJZyTHpHc3Mi9Cu9+JzMDi1heMFZQNSEEsNQnBeuM/ov71iVxqs+b4NfCBQOSadWt9CsAOWnLtQd87nDHjQ5XNTjS7mACnCvZ2RyaOhJO7bRSS1rgV1IEbvruK/7JBRwmVsA7HMa46BkhBvnySDeNLKDke4DwEHY47IpFIxjq8nITW72H90luHTy1DJYC5tdDM9I5PqAncu80CrZn9vghP1BCFFrhfUA2VO4x6xJA7Yj9XLALCE7aHGzOz6uaabHIAWfTs0Q8rGUBL/Ic= X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Apr 2019 10:07:12.5522 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: cfae94ff-6adb-415e-7c86-08d6bcd322c7 X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c;Ip=[149.199.80.198];Helo=[xir-pvapexch01.xlnx.xilinx.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR02MB3839 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Stores configuration based on parameters from the DT node and values from the SD-FEC core plus reads the default state from the SD-FEC core. To obtain values from the core register read, write capabilities have been added plus related register map details. Tested-by: Dragan Cvetic Signed-off-by: Derek Kiernan Signed-off-by: Dragan Cvetic --- drivers/misc/xilinx_sdfec.c | 307 +++++++++++++++++++++++++++++++++++++++ include/uapi/misc/xilinx_sdfec.h | 94 ++++++++++++ 2 files changed, 401 insertions(+) diff --git a/drivers/misc/xilinx_sdfec.c b/drivers/misc/xilinx_sdfec.c index 30879ae..77ee62d 100644 --- a/drivers/misc/xilinx_sdfec.c +++ b/drivers/misc/xilinx_sdfec.c @@ -37,6 +37,85 @@ static struct class *xsdfec_class; static atomic_t xsdfec_ndevs = ATOMIC_INIT(0); static dev_t xsdfec_devt; +/* Xilinx SDFEC Register Map */ +/* CODE_WRI_PROTECT Register */ +#define XSDFEC_CODE_WR_PROTECT_ADDR (0x4) + +/* ACTIVE Register */ +#define XSDFEC_ACTIVE_ADDR (0x8) +#define XSDFEC_IS_ACTIVITY_SET (0x1) + +/* AXIS_WIDTH Register */ +#define XSDFEC_AXIS_WIDTH_ADDR (0xC) +#define XSDFEC_AXIS_DOUT_WORDS_LSB (5) +#define XSDFEC_AXIS_DOUT_WIDTH_LSB (3) +#define XSDFEC_AXIS_DIN_WORDS_LSB (2) +#define XSDFEC_AXIS_DIN_WIDTH_LSB (0) + +/* AXIS_ENABLE Register */ +#define XSDFEC_AXIS_ENABLE_ADDR (0x10) +#define XSDFEC_AXIS_OUT_ENABLE_MASK (0x38) +#define XSDFEC_AXIS_IN_ENABLE_MASK (0x7) +#define XSDFEC_AXIS_ENABLE_MASK \ + (XSDFEC_AXIS_OUT_ENABLE_MASK | XSDFEC_AXIS_IN_ENABLE_MASK) + +/* FEC_CODE Register */ +#define XSDFEC_FEC_CODE_ADDR (0x14) + +/* ORDER Register Map */ +#define XSDFEC_ORDER_ADDR (0x18) + +/* Interrupt Status Register */ +#define XSDFEC_ISR_ADDR (0x1C) +/* Interrupt Status Register Bit Mask */ +#define XSDFEC_ISR_MASK (0x3F) + +/* Write Only - Interrupt Enable Register */ +#define XSDFEC_IER_ADDR (0x20) +/* Write Only - Interrupt Disable Register */ +#define XSDFEC_IDR_ADDR (0x24) +/* Read Only - Interrupt Mask Register */ +#define XSDFEC_IMR_ADDR (0x28) + +/* ECC Interrupt Status Register */ +#define XSDFEC_ECC_ISR_ADDR (0x2C) +/* Single Bit Errors */ +#define XSDFEC_ECC_ISR_SBE_MASK (0x7FF) +/* PL Initialize Single Bit Errors */ +#define XSDFEC_PL_INIT_ECC_ISR_SBE_MASK (0x3C00000) +/* Multi Bit Errors */ +#define XSDFEC_ECC_ISR_MBE_MASK (0x3FF800) +/* PL Initialize Multi Bit Errors */ +#define XSDFEC_PL_INIT_ECC_ISR_MBE_MASK (0x3C000000) +/* Multi Bit Error to Event Shift */ +#define XSDFEC_ECC_ISR_MBE_TO_EVENT_SHIFT (11) +/* PL Initialize Multi Bit Error to Event Shift */ +#define XSDFEC_PL_INIT_ECC_ISR_MBE_TO_EVENT_SHIFT (4) +/* ECC Interrupt Status Bit Mask */ +#define XSDFEC_ECC_ISR_MASK (XSDFEC_ECC_ISR_SBE_MASK | XSDFEC_ECC_ISR_MBE_MASK) +/* ECC Interrupt Status PL Initialize Bit Mask */ +#define XSDFEC_PL_INIT_ECC_ISR_MASK \ + (XSDFEC_PL_INIT_ECC_ISR_SBE_MASK | XSDFEC_PL_INIT_ECC_ISR_MBE_MASK) +/* ECC Interrupt Status All Bit Mask */ +#define XSDFEC_ALL_ECC_ISR_MASK \ + (XSDFEC_ECC_ISR_MASK | XSDFEC_PL_INIT_ECC_ISR_MASK) +/* ECC Interrupt Status Single Bit Errors Mask */ +#define XSDFEC_ALL_ECC_ISR_SBE_MASK \ + (XSDFEC_ECC_ISR_SBE_MASK | XSDFEC_PL_INIT_ECC_ISR_SBE_MASK) +/* ECC Interrupt Status Multi Bit Errors Mask */ +#define XSDFEC_ALL_ECC_ISR_MBE_MASK \ + (XSDFEC_ECC_ISR_MBE_MASK | XSDFEC_PL_INIT_ECC_ISR_MBE_MASK) + +/* Write Only - ECC Interrupt Enable Register */ +#define XSDFEC_ECC_IER_ADDR (0x30) +/* Write Only - ECC Interrupt Disable Register */ +#define XSDFEC_ECC_IDR_ADDR (0x34) +/* Read Only - ECC Interrupt Mask Register */ +#define XSDFEC_ECC_IMR_ADDR (0x38) + +/* BYPASS Register */ +#define XSDFEC_BYPASS_ADDR (0x3C) + /** * struct xsdfec_clks - For managing SD-FEC clocks * @core_clk: Main processing clock for core @@ -63,6 +142,7 @@ struct xsdfec_clks { * struct xsdfec_dev - Driver data for SDFEC * @regs: device physical base address * @dev: pointer to device struct + * @state: State of the SDFEC device * @config: Configuration of the SDFEC device * @open_count: Count of char device being opened * @xsdfec_cdev: Character device handle @@ -74,6 +154,7 @@ struct xsdfec_clks { struct xsdfec_dev { void __iomem *regs; struct device *dev; + enum xsdfec_state state; struct xsdfec_config config; atomic_t open_count; struct cdev xsdfec_cdev; @@ -82,6 +163,65 @@ struct xsdfec_dev { struct xsdfec_clks clks; }; +static inline void xsdfec_regwrite(struct xsdfec_dev *xsdfec, u32 addr, + u32 value) +{ + dev_dbg(xsdfec->dev, "Writing 0x%x to offset 0x%x", value, addr); + iowrite32(value, xsdfec->regs + addr); +} + +static inline u32 xsdfec_regread(struct xsdfec_dev *xsdfec, u32 addr) +{ + u32 rval; + + rval = ioread32(xsdfec->regs + addr); + dev_dbg(xsdfec->dev, "Read value = 0x%x from offset 0x%x", rval, addr); + return rval; +} + +static void update_bool_config_from_reg(struct xsdfec_dev *xsdfec, + u32 reg_offset, u32 bit_num, + char *config_value) +{ + u32 reg_val; + u32 bit_mask = 1 << bit_num; + + reg_val = xsdfec_regread(xsdfec, reg_offset); + *config_value = (reg_val & bit_mask) > 0; +} + +static void update_config_from_hw(struct xsdfec_dev *xsdfec) +{ + u32 reg_value; + bool sdfec_started; + + /* Update the Order */ + reg_value = xsdfec_regread(xsdfec, XSDFEC_ORDER_ADDR); + xsdfec->config.order = reg_value; + + update_bool_config_from_reg(xsdfec, XSDFEC_BYPASS_ADDR, + 0, /* Bit Number, maybe change to mask */ + &xsdfec->config.bypass); + + update_bool_config_from_reg(xsdfec, XSDFEC_CODE_WR_PROTECT_ADDR, + 0, /* Bit Number */ + &xsdfec->config.code_wr_protect); + + reg_value = xsdfec_regread(xsdfec, XSDFEC_IMR_ADDR); + xsdfec->config.irq.enable_isr = (reg_value & XSDFEC_ISR_MASK) > 0; + + reg_value = xsdfec_regread(xsdfec, XSDFEC_ECC_IMR_ADDR); + xsdfec->config.irq.enable_ecc_isr = + (reg_value & XSDFEC_ECC_ISR_MASK) > 0; + + reg_value = xsdfec_regread(xsdfec, XSDFEC_AXIS_ENABLE_ADDR); + sdfec_started = (reg_value & XSDFEC_AXIS_IN_ENABLE_MASK) > 0; + if (sdfec_started) + xsdfec->state = XSDFEC_STARTED; + else + xsdfec->state = XSDFEC_STOPPED; +} + static int xsdfec_dev_open(struct inode *iptr, struct file *fptr) { struct xsdfec_dev *xsdfec; @@ -107,6 +247,69 @@ static int xsdfec_dev_release(struct inode *iptr, struct file *fptr) return 0; } +static u32 +xsdfec_translate_axis_width_cfg_val(enum xsdfec_axis_width axis_width_cfg) +{ + u32 axis_width_field = 0; + + switch (axis_width_cfg) { + case XSDFEC_1x128b: + axis_width_field = 0; + break; + case XSDFEC_2x128b: + axis_width_field = 1; + break; + case XSDFEC_4x128b: + axis_width_field = 2; + break; + } + + return axis_width_field; +} + +static u32 xsdfec_translate_axis_words_cfg_val(enum xsdfec_axis_word_include + axis_word_inc_cfg) +{ + u32 axis_words_field = 0; + + if (axis_word_inc_cfg == XSDFEC_FIXED_VALUE || + axis_word_inc_cfg == XSDFEC_IN_BLOCK) + axis_words_field = 0; + else if (axis_word_inc_cfg == XSDFEC_PER_AXI_TRANSACTION) + axis_words_field = 1; + + return axis_words_field; +} + +static int xsdfec_cfg_axi_streams(struct xsdfec_dev *xsdfec) +{ + u32 reg_value; + u32 dout_words_field; + u32 dout_width_field; + u32 din_words_field; + u32 din_width_field; + struct xsdfec_config *config = &xsdfec->config; + + /* translate config info to register values */ + dout_words_field = + xsdfec_translate_axis_words_cfg_val(config->dout_word_include); + dout_width_field = + xsdfec_translate_axis_width_cfg_val(config->dout_width); + din_words_field = + xsdfec_translate_axis_words_cfg_val(config->din_word_include); + din_width_field = + xsdfec_translate_axis_width_cfg_val(config->din_width); + + reg_value = dout_words_field << XSDFEC_AXIS_DOUT_WORDS_LSB; + reg_value |= dout_width_field << XSDFEC_AXIS_DOUT_WIDTH_LSB; + reg_value |= din_words_field << XSDFEC_AXIS_DIN_WORDS_LSB; + reg_value |= din_width_field << XSDFEC_AXIS_DIN_WIDTH_LSB; + + xsdfec_regwrite(xsdfec, XSDFEC_AXIS_WIDTH_ADDR, reg_value); + + return 0; +} + static long xsdfec_dev_ioctl(struct file *fptr, unsigned int cmd, unsigned long data) { @@ -163,6 +366,104 @@ static const struct file_operations xsdfec_fops = { #endif }; +static int xsdfec_parse_of(struct xsdfec_dev *xsdfec) +{ + struct device *dev = xsdfec->dev; + struct device_node *node = dev->of_node; + int rval; + const char *fec_code; + u32 din_width; + u32 din_word_include; + u32 dout_width; + u32 dout_word_include; + + rval = of_property_read_string(node, "xlnx,sdfec-code", &fec_code); + if (rval < 0) { + dev_err(dev, "xlnx,sdfec-code not in DT"); + return rval; + } + + if (!strcasecmp(fec_code, "ldpc")) { + xsdfec->config.code = XSDFEC_LDPC_CODE; + } else if (!strcasecmp(fec_code, "turbo")) { + xsdfec->config.code = XSDFEC_TURBO_CODE; + } else { + dev_err(xsdfec->dev, "Invalid Code in DT"); + return -EINVAL; + } + + rval = of_property_read_u32(node, "xlnx,sdfec-din-words", + &din_word_include); + if (rval < 0) { + dev_err(dev, "xlnx,sdfec-din-words not in DT"); + return rval; + } + + if (din_word_include < XSDFEC_AXIS_WORDS_INCLUDE_MAX) { + xsdfec->config.din_word_include = din_word_include; + } else { + dev_err(xsdfec->dev, "Invalid DIN Words in DT"); + return -EINVAL; + } + + rval = of_property_read_u32(node, "xlnx,sdfec-din-width", &din_width); + if (rval < 0) { + dev_err(dev, "xlnx,sdfec-din-width not in DT"); + return rval; + } + + switch (din_width) { + /* Fall through and set for valid values */ + case XSDFEC_1x128b: + case XSDFEC_2x128b: + case XSDFEC_4x128b: + xsdfec->config.din_width = din_width; + break; + default: + dev_err(xsdfec->dev, "Invalid DIN Width in DT"); + return -EINVAL; + } + + rval = of_property_read_u32(node, "xlnx,sdfec-dout-words", + &dout_word_include); + if (rval < 0) { + dev_err(dev, "xlnx,sdfec-dout-words not in DT"); + return rval; + } + + if (dout_word_include < XSDFEC_AXIS_WORDS_INCLUDE_MAX) { + xsdfec->config.dout_word_include = dout_word_include; + } else { + dev_err(xsdfec->dev, "Invalid DOUT Words in DT"); + return -EINVAL; + } + + rval = of_property_read_u32(node, "xlnx,sdfec-dout-width", &dout_width); + if (rval < 0) { + dev_err(dev, "xlnx,sdfec-dout-width not in DT"); + return rval; + } + + switch (dout_width) { + /* Fall through and set for valid values */ + case XSDFEC_1x128b: + case XSDFEC_2x128b: + case XSDFEC_4x128b: + xsdfec->config.dout_width = dout_width; + break; + default: + dev_err(xsdfec->dev, "Invalid DOUT Width in DT"); + return -EINVAL; + } + + /* Write LDPC to CODE Register */ + xsdfec_regwrite(xsdfec, XSDFEC_FEC_CODE_ADDR, xsdfec->config.code); + + xsdfec_cfg_axi_streams(xsdfec); + + return 0; +} + static int xsdfec_clk_init(struct platform_device *pdev, struct xsdfec_clks *clks) { @@ -315,6 +616,12 @@ static int xsdfec_probe(struct platform_device *pdev) goto err_xsdfec_dev; } + err = xsdfec_parse_of(xsdfec); + if (err < 0) + goto err_xsdfec_dev; + + update_config_from_hw(xsdfec); + /* Save driver private data */ platform_set_drvdata(pdev, xsdfec); diff --git a/include/uapi/misc/xilinx_sdfec.h b/include/uapi/misc/xilinx_sdfec.h index 5de0add..0497b66 100644 --- a/include/uapi/misc/xilinx_sdfec.h +++ b/include/uapi/misc/xilinx_sdfec.h @@ -12,6 +12,33 @@ #define __XILINX_SDFEC_H__ /** + * enum xsdfec_code - Code Type. + * @XSDFEC_TURBO_CODE: Driver is configured for Turbo mode. + * @XSDFEC_LDPC_CODE: Driver is configured for LDPC mode. + * + * This enum is used to indicate the mode of the driver. The mode is determined + * by checking which codes are set in the driver. Note that the mode cannot be + * changed by the driver. + */ +enum xsdfec_code { + XSDFEC_TURBO_CODE = 0, + XSDFEC_LDPC_CODE, +}; + +/** + * enum xsdfec_order - Order + * @XSDFEC_MAINTAIN_ORDER: Maintain order execution of blocks. + * @XSDFEC_OUT_OF_ORDER: Out-of-order execution of blocks. + * + * This enum is used to indicate whether the order of blocks can change from + * input to output. + */ +enum xsdfec_order { + XSDFEC_MAINTAIN_ORDER = 0, + XSDFEC_OUT_OF_ORDER, +}; + +/** * enum xsdfec_state - State. * @XSDFEC_INIT: Driver is initialized. * @XSDFEC_STARTED: Driver is started. @@ -30,13 +57,80 @@ enum xsdfec_state { }; /** + * enum xsdfec_axis_width - AXIS_WIDTH.DIN Setting for 128-bit width. + * @XSDFEC_1x128b: DIN data input stream consists of a 128-bit lane + * @XSDFEC_2x128b: DIN data input stream consists of two 128-bit lanes + * @XSDFEC_4x128b: DIN data input stream consists of four 128-bit lanes + * + * This enum is used to indicate the AXIS_WIDTH.DIN setting for 128-bit width. + * The number of lanes of the DIN data input stream depends upon the + * AXIS_WIDTH.DIN parameter. + */ +enum xsdfec_axis_width { + XSDFEC_1x128b = 1, + XSDFEC_2x128b = 2, + XSDFEC_4x128b = 4, +}; + +/** + * enum xsdfec_axis_word_include - Words Configuration. + * @XSDFEC_FIXED_VALUE: Fixed, the DIN_WORDS AXI4-Stream interface is removed + * from the IP instance and is driven with the specified + * number of words. + * @XSDFEC_IN_BLOCK: In Block, configures the IP instance to expect a single + * DIN_WORDS value per input code block. The DIN_WORDS + * interface is present. + * @XSDFEC_PER_AXI_TRANSACTION: Per Transaction, configures the IP instance to + * expect one DIN_WORDS value per input transaction on the DIN interface. The + * DIN_WORDS interface is present. + * @XSDFEC_AXIS_WORDS_INCLUDE_MAX: Used to indicate out of bound Words + * Configurations. + * + * This enum is used to specify the DIN_WORDS configuration. + */ +enum xsdfec_axis_word_include { + XSDFEC_FIXED_VALUE = 0, + XSDFEC_IN_BLOCK, + XSDFEC_PER_AXI_TRANSACTION, + XSDFEC_AXIS_WORDS_INCLUDE_MAX, +}; + +/** + * struct xsdfec_irq - Enabling or Disabling Interrupts. + * @enable_isr: If true enables the ISR + * @enable_ecc_isr: If true enables the ECC ISR + */ +struct xsdfec_irq { + char enable_isr; + char enable_ecc_isr; +}; + +/** * struct xsdfec_config - Configuration of SD-FEC core. * @fec_id: ID of SD-FEC instance. ID is limited to the number of active * SD-FEC's in the FPGA and is related to the driver instance * Minor number. + * @code: The codes being used by the SD-FEC instance + * @order: Order of Operation + * @bypass: Is the core being bypassed + * @code_wr_protect: Is write protection of LDPC codes enabled + * @din_width: Width of the DIN AXI4-Stream + * @din_word_include: How DIN_WORDS are inputted + * @dout_width: Width of the DOUT AXI4-Stream + * @dout_word_include: HOW DOUT_WORDS are outputted + * @irq: Enabling or disabling interrupts */ struct xsdfec_config { s32 fec_id; + enum xsdfec_code code; + enum xsdfec_order order; + char bypass; + char code_wr_protect; + enum xsdfec_axis_width din_width; + enum xsdfec_axis_word_include din_word_include; + enum xsdfec_axis_width dout_width; + enum xsdfec_axis_word_include dout_word_include; + struct xsdfec_irq irq; }; /* -- 2.7.4