From patchwork Thu Oct 4 07:00:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978678 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkSs1pBSz9s7h for ; Thu, 4 Oct 2018 17:06:21 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id E61D6C221D0; Thu, 4 Oct 2018 07:03:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 01AC4C221BA; Thu, 4 Oct 2018 07:01:38 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 146CFC21F9B; Thu, 4 Oct 2018 07:01:25 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id 7E28DC2213B for ; Thu, 4 Oct 2018 07:01:25 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdU-0005pi-4Y; Thu, 04 Oct 2018 09:01:24 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:40 +0200 Message-Id: <20181004070055.1669-1-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 01/16] test: regmap: Increase size of syscon0 memory X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The upcoming changes to the regmap interface will contain a proper check for plausibility when reading/writing from/to a register map. To still have the current tests pass, increase the size of the memory region for the syscon0 device, since one of the tests reads and writes beyond this range. Reviewed-by: Anatolij Gustschin Reviewed-by: Simon Glass Signed-off-by: Mario Six --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: * Fix the test that checks the changed size v4 -> v5: No changes v3 -> v4: No changes v2 -> v3: New in v3 --- arch/sandbox/dts/test.dts | 2 +- test/dm/regmap.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) -- 2.11.0 diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 491f889f3b..a14ddea54c 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -474,7 +474,7 @@ syscon@0 { compatible = "sandbox,syscon0"; - reg = <0x10 4>; + reg = <0x10 16>; }; syscon@1 { diff --git a/test/dm/regmap.c b/test/dm/regmap.c index d4b86b3b03..b28d6a6cd1 100644 --- a/test/dm/regmap.c +++ b/test/dm/regmap.c @@ -25,7 +25,7 @@ static int dm_test_regmap_base(struct unit_test_state *uts) ut_assertok_ptr(map); ut_asserteq(1, map->range_count); ut_asserteq(0x10, map->ranges[0].start); - ut_asserteq(4, map->ranges[0].size); + ut_asserteq(16, map->ranges[0].size); ut_asserteq(0x10, map_to_sysmem(regmap_get_range(map, 0))); ut_assertok(uclass_get_device(UCLASS_SYSCON, 1, &dev)); From patchwork Thu Oct 4 07:00:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978680 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkWM1tVCz9s55 for ; Thu, 4 Oct 2018 17:08:31 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id E44EFC2200C; Thu, 4 Oct 2018 07:06:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id EDBF4C221FD; Thu, 4 Oct 2018 07:01:47 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id E5CEAC21F9B; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id 38EFAC22184 for ; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdU-0005pi-8L; Thu, 04 Oct 2018 09:01:24 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:41 +0200 Message-Id: <20181004070055.1669-2-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 02/16] regmap: Fix documentation X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The documentation in regmap.h is not in kernel-doc format. Correct this. Reviewed-by: Anatolij Gustschin Reviewed-by: Simon Glass Signed-off-by: Mario Six --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: No changes v4 -> v5: No changes v3 -> v4: No changes v2 -> v3: New in v3 --- include/regmap.h | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) -- 2.11.0 diff --git a/include/regmap.h b/include/regmap.h index 6a574eaa41..32f75e06f5 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -21,8 +21,8 @@ struct regmap_range { /** * struct regmap - a way of accessing hardware/bus registers * - * @range_count: Number of ranges available within the map - * @ranges: Array of ranges + * @range_count: Number of ranges available within the map + * @ranges: Array of ranges */ struct regmap { int range_count; @@ -33,7 +33,28 @@ struct regmap { * Interface to provide access to registers either through a direct memory * bus or through a peripheral bus like I2C, SPI. */ + +/** + * regmap_write() - Write a 32-bit value to a regmap + * + * @map: Regmap to write to + * @offset: Offset in the regmap to write to + * @val: Data to write to the regmap at the specified offset + * + * Return: 0 if OK, -ve on error + */ int regmap_write(struct regmap *map, uint offset, uint val); + +/** + * regmap_read() - Read a 32-bit value from a regmap + * + * @map: Regmap to read from + * @offset: Offset in the regmap to read from + * @valp: Pointer to the buffer to receive the data read from the regmap + * at the specified offset + * + * Return: 0 if OK, -ve on error + */ int regmap_read(struct regmap *map, uint offset, uint *valp); #define regmap_write32(map, ptr, member, val) \ @@ -49,31 +70,36 @@ int regmap_read(struct regmap *map, uint offset, uint *valp); * @offset: Offset of the memory * @mask: Mask to apply to the read value * @val: Value to apply to the value to write + * Return: 0 if OK, -ve on error */ int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val); /** * regmap_init_mem() - Set up a new register map that uses memory access * - * Use regmap_uninit() to free it. - * * @node: Device node that uses this map * @mapp: Returns allocated map + * Return: 0 if OK, -ve on error + * + * Use regmap_uninit() to free it. */ int regmap_init_mem(ofnode node, struct regmap **mapp); /** - * regmap_init_mem_platdata() - Set up a new memory register map for of-platdata + * regmap_init_mem_platdata() - Set up a new memory register map for + * of-platdata + * + * @dev: Device that uses this map + * @reg: List of address, size pairs + * @count: Number of pairs (e.g. 1 if the regmap has a single entry) + * @mapp: Returns allocated map + * Return: 0 if OK, -ve on error * * This creates a new regmap with a list of regions passed in, rather than * using the device tree. It only supports 32-bit machines. * * Use regmap_uninit() to free it. * - * @dev: Device that uses this map - * @reg: List of address, size pairs - * @count: Number of pairs (e.g. 1 if the regmap has a single entry) - * @mapp: Returns allocated map */ int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count, struct regmap **mapp); @@ -83,11 +109,15 @@ int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count, * * @map: Regmap to query * @range_num: Range to look up + * Return: Pointer to the range in question if OK, NULL on error */ void *regmap_get_range(struct regmap *map, unsigned int range_num); /** * regmap_uninit() - free a previously inited regmap + * + * @map: Regmap to free + * Return: 0 if OK, -ve on error */ int regmap_uninit(struct regmap *map); From patchwork Thu Oct 4 07:00:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978683 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkYy3Hp3z9s7h for ; Thu, 4 Oct 2018 17:10:46 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 21DB1C221B2; Thu, 4 Oct 2018 07:06:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 2A70AC2220C; Thu, 4 Oct 2018 07:01:47 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id C5704C22143; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id BE5DDC221A6 for ; Thu, 4 Oct 2018 07:01:25 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdU-0005pi-CB; Thu, 04 Oct 2018 09:01:24 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:42 +0200 Message-Id: <20181004070055.1669-3-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 03/16] regmap: Add documentation X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Document the regmap_alloc() function. Reviewed-by: Anatolij Gustschin Reviewed-by: Simon Glass Signed-off-by: Mario Six --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: No changes v4 -> v5: No changes v3 -> v4: No changes v2 -> v3: New in v3 --- drivers/core/regmap.c | 6 ++++++ 1 file changed, 6 insertions(+) -- 2.11.0 diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index 8e5c3bcf61..77f6f520a0 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -17,6 +17,12 @@ DECLARE_GLOBAL_DATA_PTR; +/** + * regmap_alloc() - Allocate a regmap with a given number of ranges. + * + * @count: Number of ranges to be allocated for the regmap. + * Return: A pointer to the newly allocated regmap, or NULL on error. + */ static struct regmap *regmap_alloc(int count) { struct regmap *map; From patchwork Thu Oct 4 07:00:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978686 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkcJ66QXz9s55 for ; Thu, 4 Oct 2018 17:12:48 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 7E156C221E7; Thu, 4 Oct 2018 07:04:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 9023BC221FC; Thu, 4 Oct 2018 07:01:44 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 874F3C22159; Thu, 4 Oct 2018 07:01:25 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id 16FFAC221B2 for ; Thu, 4 Oct 2018 07:01:25 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdU-0005pi-HE; Thu, 04 Oct 2018 09:01:24 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:43 +0200 Message-Id: <20181004070055.1669-4-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 04/16] regmap: Improve error handling X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" ofnode_read_simple_addr_cells may fail and return a negative error code. Check for this when initializing regmaps. Also check if both_len is zero, since this is perfectly possible, and would lead to a division-by-zero further down the line. Reviewed-by: Anatolij Gustschin Reviewed-by: Simon Glass Signed-off-by: Mario Six --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: No changes v4 -> v5: No changes v3 -> v4: No changes v2 -> v3: New in v3 --- drivers/core/regmap.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) -- 2.11.0 diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index 77f6f520a0..4ebab23349 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -67,8 +67,25 @@ int regmap_init_mem(ofnode node, struct regmap **mapp) struct resource r; addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node)); + if (addr_len < 0) { + debug("%s: Error while reading the addr length (ret = %d)\n", + ofnode_get_name(node), addr_len); + return addr_len; + } + size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node)); + if (size_len < 0) { + debug("%s: Error while reading the size length: (ret = %d)\n", + ofnode_get_name(node), size_len); + return size_len; + } + both_len = addr_len + size_len; + if (!both_len) { + debug("%s: Both addr and size length are zero\n", + ofnode_get_name(node)); + return -EINVAL; + } len = ofnode_read_size(node, "reg"); if (len < 0) From patchwork Thu Oct 4 07:00:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978688 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42Qkd45FgMz9s55 for ; Thu, 4 Oct 2018 17:13:28 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 65A6CC221A6; Thu, 4 Oct 2018 07:05:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 7C435C21F9B; Thu, 4 Oct 2018 07:01:45 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 9B564C21F9B; Thu, 4 Oct 2018 07:01:25 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id 46BE9C22184 for ; Thu, 4 Oct 2018 07:01:25 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdU-0005pi-L8; Thu, 04 Oct 2018 09:01:24 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:44 +0200 Message-Id: <20181004070055.1669-5-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 05/16] regmap: Introduce init_range X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Both fdtdec_get_addr_size_fixed and of_address_to_resource can fail with an error, which is not currently checked during regmap initialization. Since the indentation depth is already quite deep, extract a new 'init_range' method to do the initialization. Reviewed-by: Anatolij Gustschin Reviewed-by: Simon Glass Signed-off-by: Mario Six --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: No changes v4 -> v5: No changes v3 -> v4: * Introduced else clause in of_live_active() if statement to make the distinction between live and non-live cases clearer v2 -> v3: New in v3 --- drivers/core/regmap.c | 68 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 12 deletions(-) -- 2.11.0 diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index 4ebab23349..25c1ae5d7d 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -56,6 +56,58 @@ int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count, return 0; } #else +/** + * init_range() - Initialize a single range of a regmap + * @node: Device node that will use the map in question + * @range: Pointer to a regmap_range structure that will be initialized + * @addr_len: The length of the addr parts of the reg property + * @size_len: The length of the size parts of the reg property + * @index: The index of the range to initialize + * + * This function will read the necessary 'reg' information from the device tree + * (the 'addr' part, and the 'length' part), and initialize the range in + * quesion. + * + * Return: 0 if OK, -ve on error + */ +static int init_range(ofnode node, struct regmap_range *range, int addr_len, + int size_len, int index) +{ + fdt_size_t sz; + struct resource r; + + if (of_live_active()) { + int ret; + + ret = of_address_to_resource(ofnode_to_np(node), + index, &r); + if (ret) { + debug("%s: Could not read resource of range %d (ret = %d)\n", + ofnode_get_name(node), index, ret); + return ret; + } + + range->start = r.start; + range->size = r.end - r.start + 1; + } else { + int offset = ofnode_to_offset(node); + + range->start = fdtdec_get_addr_size_fixed(gd->fdt_blob, offset, + "reg", index, + addr_len, size_len, + &sz, true); + if (range->start == FDT_ADDR_T_NONE) { + debug("%s: Could not read start of range %d\n", + ofnode_get_name(node), index); + return -EINVAL; + } + + range->size = sz; + } + + return 0; +} + int regmap_init_mem(ofnode node, struct regmap **mapp) { struct regmap_range *range; @@ -64,7 +116,6 @@ int regmap_init_mem(ofnode node, struct regmap **mapp) int addr_len, size_len, both_len; int len; int index; - struct resource r; addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node)); if (addr_len < 0) { @@ -101,17 +152,10 @@ int regmap_init_mem(ofnode node, struct regmap **mapp) for (range = map->ranges, index = 0; count > 0; count--, range++, index++) { - fdt_size_t sz; - if (of_live_active()) { - of_address_to_resource(ofnode_to_np(node), index, &r); - range->start = r.start; - range->size = r.end - r.start + 1; - } else { - range->start = fdtdec_get_addr_size_fixed(gd->fdt_blob, - ofnode_to_offset(node), "reg", index, - addr_len, size_len, &sz, true); - range->size = sz; - } + int ret = init_range(node, range, addr_len, size_len, index); + + if (ret) + return ret; } *mapp = map; From patchwork Thu Oct 4 07:00:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978687 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42Qkcw4b7hz9s55 for ; Thu, 4 Oct 2018 17:13:20 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 40093C221B5; Thu, 4 Oct 2018 07:04:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 98C97C221E2; Thu, 4 Oct 2018 07:01:43 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 7B02FC2201E; Thu, 4 Oct 2018 07:01:25 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id 6F0C0C21F9B for ; Thu, 4 Oct 2018 07:01:25 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdU-0005pi-P3; Thu, 04 Oct 2018 09:01:24 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:45 +0200 Message-Id: <20181004070055.1669-6-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 06/16] regmap: Add error output X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add some debug output in cases where the initialization of a regmap fails. Reviewed-by: Anatolij Gustschin Reviewed-by: Simon Glass Signed-off-by: Mario Six --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: No changes v4 -> v5: No changes v3 -> v4: No changes v2 -> v3: New in v3 --- drivers/core/regmap.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) -- 2.11.0 diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index 25c1ae5d7d..154426269d 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -139,12 +139,18 @@ int regmap_init_mem(ofnode node, struct regmap **mapp) } len = ofnode_read_size(node, "reg"); - if (len < 0) + if (len < 0) { + debug("%s: Error while reading reg size (ret = %d)\n", + ofnode_get_name(node), len); return len; + } len /= sizeof(fdt32_t); count = len / both_len; - if (!count) + if (!count) { + debug("%s: Not enough data in reg property\n", + ofnode_get_name(node)); return -EINVAL; + } map = regmap_alloc(count); if (!map) From patchwork Thu Oct 4 07:00:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978674 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkPf1DvNz9s55 for ; Thu, 4 Oct 2018 17:03:33 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 96019C22159; Thu, 4 Oct 2018 07:02:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id DC3ACC221C0; Thu, 4 Oct 2018 07:01:35 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D71BDC22159; Thu, 4 Oct 2018 07:01:25 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id A8274C2201E for ; Thu, 4 Oct 2018 07:01:25 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdU-0005pi-UG; Thu, 04 Oct 2018 09:01:24 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:46 +0200 Message-Id: <20181004070055.1669-7-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 07/16] mips: Implement {in, out}_{le, be}_{16, 32, 64} and {in, out}_8 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" MIPS is the only architecture currently supported by U-Boot that does not implement any of the in/out register access functions. To have a interface that is useable across architectures, add the functions to the MIPS architecture (implemented using the __raw_write and __raw_read functions). Reviewed-by: Simon Glass Signed-off-by: Mario Six Reviewed-by: Stefan Roese Reviewed-by: Daniel Schwierzeck --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: New in v6 --- arch/mips/include/asm/io.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) -- 2.11.0 diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 957442effd..7c40e415c7 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -547,6 +547,28 @@ __BUILD_CLRSETBITS(bwlq, sfx, end, type) #define __to_cpu(v) (v) #define cpu_to__(v) (v) +#define out_arch(type, endian, a, v) __raw_write##type(cpu_to_##endian(v),a) +#define in_arch(type, endian, a) endian##_to_cpu(__raw_read##type(a)) + +#define out_le64(a, v) out_arch(q, le64, a, v) +#define out_le32(a, v) out_arch(l, le32, a, v) +#define out_le16(a, v) out_arch(w, le16, a, v) + +#define in_le64(a) in_arch(q, le64, a) +#define in_le32(a) in_arch(l, le32, a) +#define in_le16(a) in_arch(w, le16, a) + +#define out_be64(a, v) out_arch(q, be64, a, v) +#define out_be32(a, v) out_arch(l, be32, a, v) +#define out_be16(a, v) out_arch(w, be16, a, v) + +#define in_be64(a) in_arch(q, be64, a) +#define in_be32(a) in_arch(l, be32, a) +#define in_be16(a) in_arch(w, be16, a) + +#define out_8(a, v) __raw_writeb(v, a) +#define in_8(a) __raw_readb(a) + BUILD_CLRSETBITS(b, 8, _, u8) BUILD_CLRSETBITS(w, le16, le16, u16) BUILD_CLRSETBITS(w, be16, be16, u16) From patchwork Thu Oct 4 07:00:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978685 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkbK4VnTz9s55 for ; Thu, 4 Oct 2018 17:11:53 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 31B09C221C0; Thu, 4 Oct 2018 07:03:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 1EE11C221C9; Thu, 4 Oct 2018 07:01:39 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 2687EC22143; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id 2D526C22143 for ; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdV-0005pi-1v; Thu, 04 Oct 2018 09:01:25 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:47 +0200 Message-Id: <20181004070055.1669-8-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 08/16] regmap: Add raw read/write functions X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The regmap functions currently assume that all register map accesses have a data width of 32 bits, but there are maps that have different widths. To rectify this, implement the regmap_raw_read and regmap_raw_write functions from the Linux kernel API that specify the width of a desired read or write operation on a regmap. Implement the regmap_read and regmap_write functions using these raw functions in a backwards-compatible manner. Reviewed-by: Anatolij Gustschin Signed-off-by: Mario Six --- v9 -> v10: * Switched to the read{b,w,l,q} and write{b,w,l,q} functions for register map access v8 -> v9: * Removed forgotten "fpgamap" in documentation v7 -> v8: No changes v6 -> v7: * Fixed wrong variable type in 64-bit read (u32 -> u64) * Added 64-bit case in write function v5 -> v6: * Corrected format specifier * Added support for 64-bit reads/writes v4 -> v5: No changes v3 -> v4: * Switched 'ranges[0] + offset' to 'ranges[0].start + offset' * Explained the difference between the raw and non-raw read/write functions better in the docs v2 -> v3: * Implement the "raw" functions from Linux instead of adding a size parameter to the regmap_{read,write} functions * Fixed style violation * Improved error handling v1 -> v2: New in v2 --- drivers/core/regmap.c | 64 +++++++++++++++++++++++++++++++++++++++++++++------ include/regmap.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 7 deletions(-) -- 2.11.0 diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index 154426269d..916d9272ea 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -188,22 +188,72 @@ int regmap_uninit(struct regmap *map) return 0; } +int regmap_raw_read(struct regmap *map, uint offset, void *valp, size_t val_len) +{ + void *ptr; + + ptr = map_physmem(map->ranges[0].start + offset, val_len, MAP_NOCACHE); + + switch (val_len) { + case REGMAP_SIZE_8: + *((u8 *)valp) = readb((u8 *)ptr); + break; + case REGMAP_SIZE_16: + *((u16 *)valp) = readw((u16 *)ptr); + break; + case REGMAP_SIZE_32: + *((u32 *)valp) = readl((u32 *)ptr); + break; +#if defined(readq) + case REGMAP_SIZE_64: + *((u64 *)valp) = readq((u64 *)ptr); + break; +#endif + default: + debug("%s: regmap size %zu unknown\n", __func__, val_len); + return -EINVAL; + } + return 0; +} + int regmap_read(struct regmap *map, uint offset, uint *valp) { - u32 *ptr = map_physmem(map->ranges[0].start + offset, 4, MAP_NOCACHE); + return regmap_raw_read(map, offset, valp, REGMAP_SIZE_32); +} - *valp = le32_to_cpu(readl(ptr)); +int regmap_raw_write(struct regmap *map, uint offset, const void *val, + size_t val_len) +{ + void *ptr; + + ptr = map_physmem(map->ranges[0].start + offset, val_len, MAP_NOCACHE); + + switch (val_len) { + case REGMAP_SIZE_8: + writeb(*((u8 *)val), (u8 *)ptr); + break; + case REGMAP_SIZE_16: + writew(*((u16 *)val), (u16 *)ptr); + break; + case REGMAP_SIZE_32: + writel(*((u32 *)val), (u32 *)ptr); + break; +#if defined(writeq) + case REGMAP_SIZE_64: + writeq(*((u64 *)val), (u64 *)ptr); + break; +#endif + default: + debug("%s: regmap size %zu unknown\n", __func__, val_len); + return -EINVAL; + } return 0; } int regmap_write(struct regmap *map, uint offset, uint val) { - u32 *ptr = map_physmem(map->ranges[0].start + offset, 4, MAP_NOCACHE); - - writel(cpu_to_le32(val), ptr); - - return 0; + return regmap_raw_write(map, offset, &val, REGMAP_SIZE_32); } int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val) diff --git a/include/regmap.h b/include/regmap.h index 32f75e06f5..f23664e8ba 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -8,6 +8,21 @@ #define __REGMAP_H /** + * enum regmap_size_t - Access sizes for regmap reads and writes + * + * @REGMAP_SIZE_8: 8-bit read/write access size + * @REGMAP_SIZE_16: 16-bit read/write access size + * @REGMAP_SIZE_32: 32-bit read/write access size + * @REGMAP_SIZE_64: 64-bit read/write access size + */ +enum regmap_size_t { + REGMAP_SIZE_8 = 1, + REGMAP_SIZE_16 = 2, + REGMAP_SIZE_32 = 4, + REGMAP_SIZE_64 = 8, +}; + +/** * struct regmap_range - a register map range * * @start: Start address @@ -41,6 +56,10 @@ struct regmap { * @offset: Offset in the regmap to write to * @val: Data to write to the regmap at the specified offset * + * Note that this function will only write values of 32 bit width to the + * regmap; if the size of data to be read is different, the regmap_raw_write + * function can be used. + * * Return: 0 if OK, -ve on error */ int regmap_write(struct regmap *map, uint offset, uint val); @@ -53,10 +72,49 @@ int regmap_write(struct regmap *map, uint offset, uint val); * @valp: Pointer to the buffer to receive the data read from the regmap * at the specified offset * + * Note that this function will only read values of 32 bit width from the + * regmap; if the size of data to be read is different, the regmap_raw_read + * function can be used. + * * Return: 0 if OK, -ve on error */ int regmap_read(struct regmap *map, uint offset, uint *valp); +/** + * regmap_raw_write() - Write a value of specified length to a regmap + * + * @map: Regmap to write to + * @offset: Offset in the regmap to write to + * @val: Value to write to the regmap at the specified offset + * @val_len: Length of the data to be written to the regmap + * + * Note that this function will, as opposed to regmap_write, write data of + * arbitrary length to the regmap, and not just 32-bit values, and is thus a + * generalized version of regmap_write. + * + * Return: 0 if OK, -ve on error + */ +int regmap_raw_write(struct regmap *map, uint offset, const void *val, + size_t val_len); + +/** + * regmap_raw_read() - Read a value of specified length from a regmap + * + * @map: Regmap to read from + * @offset: Offset in the regmap to read from + * @valp: Pointer to the buffer to receive the data read from the regmap + * at the specified offset + * @val_len: Length of the data to be read from the regmap + * + * Note that this function will, as opposed to regmap_read, read data of + * arbitrary length from the regmap, and not just 32-bit values, and is thus a + * generalized version of regmap_read. + * + * Return: 0 if OK, -ve on error + */ +int regmap_raw_read(struct regmap *map, uint offset, void *valp, + size_t val_len); + #define regmap_write32(map, ptr, member, val) \ regmap_write(map, (uint32_t *)(ptr)->member - (uint32_t *)(ptr), val) From patchwork Thu Oct 4 07:00:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978676 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkRx1Llcz9s55 for ; Thu, 4 Oct 2018 17:05:33 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id D2A1AC2219C; Thu, 4 Oct 2018 07:03:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 54751C221DE; Thu, 4 Oct 2018 07:01:41 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 4F175C21F9B; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id E50B0C21F9B for ; Thu, 4 Oct 2018 07:01:25 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdV-0005pi-5g; Thu, 04 Oct 2018 09:01:25 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:48 +0200 Message-Id: <20181004070055.1669-9-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 09/16] regmap: Support reading from specific range X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" It is useful to be able to treat the different ranges of a regmap separately to be able to use distinct offset for them, but this is currently not implemented in the regmap API. To preserve backwards compatibility, add regmap_read_range and regmap_write_range functions that take an additional parameter 'range_num' that identifies the range to operate on. Reviewed-by: Anatolij Gustschin Reviewed-by: Simon Glass Signed-off-by: Mario Six --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: No changes v4 -> v5: No changes v3 -> v4: No changes v2 -> v3: * Renamed the functions to regmap_{write,read}_range * Added function comments * Fixed style violations * Improved error handling v1 -> v2: New in v2 --- drivers/core/regmap.c | 49 ++++++++++++++++++++++++++++++++++++++++++++----- include/regmap.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 5 deletions(-) -- 2.11.0 diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index 916d9272ea..9b2e02af2e 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -188,11 +188,25 @@ int regmap_uninit(struct regmap *map) return 0; } -int regmap_raw_read(struct regmap *map, uint offset, void *valp, size_t val_len) +int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset, + void *valp, size_t val_len) { + struct regmap_range *range; void *ptr; - ptr = map_physmem(map->ranges[0].start + offset, val_len, MAP_NOCACHE); + if (range_num >= map->range_count) { + debug("%s: range index %d larger than range count\n", + __func__, range_num); + return -ERANGE; + } + range = &map->ranges[range_num]; + + ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE); + + if (offset + val_len > range->size) { + debug("%s: offset/size combination invalid\n", __func__); + return -ERANGE; + } switch (val_len) { case REGMAP_SIZE_8: @@ -213,20 +227,39 @@ int regmap_raw_read(struct regmap *map, uint offset, void *valp, size_t val_len) debug("%s: regmap size %zu unknown\n", __func__, val_len); return -EINVAL; } + return 0; } +int regmap_raw_read(struct regmap *map, uint offset, void *valp, size_t val_len) +{ + return regmap_raw_read_range(map, 0, offset, valp, val_len); +} + int regmap_read(struct regmap *map, uint offset, uint *valp) { return regmap_raw_read(map, offset, valp, REGMAP_SIZE_32); } -int regmap_raw_write(struct regmap *map, uint offset, const void *val, - size_t val_len) +int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset, + const void *val, size_t val_len) { + struct regmap_range *range; void *ptr; - ptr = map_physmem(map->ranges[0].start + offset, val_len, MAP_NOCACHE); + if (range_num >= map->range_count) { + debug("%s: range index %d larger than range count\n", + __func__, range_num); + return -ERANGE; + } + range = &map->ranges[range_num]; + + ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE); + + if (offset + val_len > range->size) { + debug("%s: offset/size combination invalid\n", __func__); + return -ERANGE; + } switch (val_len) { case REGMAP_SIZE_8: @@ -251,6 +284,12 @@ int regmap_raw_write(struct regmap *map, uint offset, const void *val, return 0; } +int regmap_raw_write(struct regmap *map, uint offset, const void *val, + size_t val_len) +{ + return regmap_raw_write_range(map, 0, offset, val, val_len); +} + int regmap_write(struct regmap *map, uint offset, uint val) { return regmap_raw_write(map, offset, &val, REGMAP_SIZE_32); diff --git a/include/regmap.h b/include/regmap.h index f23664e8ba..eba300da29 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -115,6 +115,37 @@ int regmap_raw_write(struct regmap *map, uint offset, const void *val, int regmap_raw_read(struct regmap *map, uint offset, void *valp, size_t val_len); +/** + * regmap_raw_write_range() - Write a value of specified length to a range of a + * regmap + * + * @map: Regmap to write to + * @range_num: Number of the range in the regmap to write to + * @offset: Offset in the regmap to write to + * @val: Value to write to the regmap at the specified offset + * @val_len: Length of the data to be written to the regmap + * + * Return: 0 if OK, -ve on error + */ +int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset, + const void *val, size_t val_len); + +/** + * regmap_raw_read_range() - Read a value of specified length from a range of a + * regmap + * + * @map: Regmap to read from + * @range_num: Number of the range in the regmap to write to + * @offset: Offset in the regmap to read from + * @valp: Pointer to the buffer to receive the data read from the regmap + * at the specified offset + * @val_len: Length of the data to be read from the regmap + * + * Return: 0 if OK, -ve on error + */ +int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset, + void *valp, size_t val_len); + #define regmap_write32(map, ptr, member, val) \ regmap_write(map, (uint32_t *)(ptr)->member - (uint32_t *)(ptr), val) From patchwork Thu Oct 4 07:00:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978679 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkVd3g4vz9s55 for ; Thu, 4 Oct 2018 17:07:53 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 3200EC22119; Thu, 4 Oct 2018 07:07:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id B346FC22201; Thu, 4 Oct 2018 07:01:48 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id F3B2DC2201E; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id 553DCC2219C for ; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdV-0005pi-9g; Thu, 04 Oct 2018 09:01:25 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:49 +0200 Message-Id: <20181004070055.1669-10-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 10/16] regmap: Define regmap_{get,set} X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" It would be convenient if one could use the regmap API in conjunction with register maps defined as structs (i.e. structs that directly mirror the memory layout of the registers in question). A similar approach was planned with the regmap_write32/regmap_read32 macros, but was never used. Hence, implement regmap_set/regmap_range_set and regmap_get/regmap_range_get macros, which, given a register map, a struct describing the layout of the register map, and a member name automatically produce regmap_read/regmap_write calls that access the specified member in the register map. Reviewed-by: Anatolij Gustschin Reviewed-by: Simon Glass Signed-off-by: Mario Six --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: No changes v4 -> v5: No changes v3 -> v4: No changes v2 -> v3: * Fixed style violations * Added documentation v1 -> v2: New in v2 --- include/regmap.h | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) -- 2.11.0 diff --git a/include/regmap.h b/include/regmap.h index eba300da29..3b7eea5f49 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -146,11 +146,57 @@ int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset, int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset, void *valp, size_t val_len); -#define regmap_write32(map, ptr, member, val) \ - regmap_write(map, (uint32_t *)(ptr)->member - (uint32_t *)(ptr), val) +/** + * regmap_range_set() - Set a value in a regmap range described by a struct + * @map: Regmap in which a value should be set + * @range: Range of the regmap in which a value should be set + * @type: Structure type that describes the memory layout of the regmap range + * @member: Member of the describing structure that should be set in the regmap + * range + * @val: Value which should be written to the regmap range + */ +#define regmap_range_set(map, range, type, member, val) \ + do { \ + typeof(((type *)0)->member) __tmp = val; \ + regmap_raw_write_range(map, range, offsetof(type, member), \ + &__tmp, sizeof(((type *)0)->member)); \ + } while (0) + +/** + * regmap_set() - Set a value in a regmap described by a struct + * @map: Regmap in which a value should be set + * @type: Structure type that describes the memory layout of the regmap + * @member: Member of the describing structure that should be set in the regmap + * @val: Value which should be written to the regmap + */ +#define regmap_set(map, type, member, val) \ + regmap_range_set(map, 0, type, member, val) -#define regmap_read32(map, ptr, member, valp) \ - regmap_read(map, (uint32_t *)(ptr)->member - (uint32_t *)(ptr), valp) +/** + * regmap_range_get() - Get a value from a regmap range described by a struct + * @map: Regmap from which a value should be read + * @range: Range of the regmap from which a value should be read + * @type: Structure type that describes the memory layout of the regmap + * range + * @member: Member of the describing structure that should be read in the + * regmap range + * @valp: Variable that receives the value read from the regmap range + */ +#define regmap_range_get(map, range, type, member, valp) \ + regmap_raw_read_range(map, range, offsetof(type, member), \ + (void *)valp, sizeof(((type *)0)->member)) + +/** + * regmap_get() - Get a value from a regmap described by a struct + * @map: Regmap from which a value should be read + * @type: Structure type that describes the memory layout of the regmap + * range + * @member: Member of the describing structure that should be read in the + * regmap + * @valp: Variable that receives the value read from the regmap + */ +#define regmap_get(map, type, member, valp) \ + regmap_range_get(map, 0, type, member, valp) /** * regmap_update_bits() - Perform a read/modify/write using a mask From patchwork Thu Oct 4 07:00:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978689 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42Qkdd4hk4z9s55 for ; Thu, 4 Oct 2018 17:13:57 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 5A692C221CB; Thu, 4 Oct 2018 07:04:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 4AA74C221ED; Thu, 4 Oct 2018 07:01:42 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 70BFDC22143; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id 07CEDC2201E for ; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdV-0005pi-Dc; Thu, 04 Oct 2018 09:01:25 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:50 +0200 Message-Id: <20181004070055.1669-11-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 11/16] test: regmap: Add test for regmap_{set, get} X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add test for regmap_{set,get} functions. Reviewed-by: Anatolij Gustschin Reviewed-by: Simon Glass Signed-off-by: Mario Six --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: No changes v4 -> v5: No changes v3 -> v4: No changes v2 -> v3: New in v3 --- test/dm/regmap.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) -- 2.11.0 diff --git a/test/dm/regmap.c b/test/dm/regmap.c index b28d6a6cd1..a8d7e6829e 100644 --- a/test/dm/regmap.c +++ b/test/dm/regmap.c @@ -116,3 +116,31 @@ static int dm_test_regmap_rw(struct unit_test_state *uts) } DM_TEST(dm_test_regmap_rw, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Get/Set test */ +static int dm_test_regmap_getset(struct unit_test_state *uts) +{ + struct udevice *dev; + struct regmap *map; + uint reg; + struct layout { + u32 val0; + u32 val1; + u32 val2; + u32 val3; + }; + + ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev)); + map = syscon_get_regmap(dev); + ut_assertok_ptr(map); + + regmap_set(map, struct layout, val0, 0xcacafafa); + regmap_set(map, struct layout, val3, 0x55aa2211); + + ut_assertok(regmap_get(map, struct layout, val0, ®)); + ut_assertok(regmap_get(map, struct layout, val3, ®)); + + return 0; +} + +DM_TEST(dm_test_regmap_getset, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); From patchwork Thu Oct 4 07:00:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978672 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkMY5vQpz9s55 for ; Thu, 4 Oct 2018 17:01:45 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 51EE2C221FB; Thu, 4 Oct 2018 07:01:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 21B52C2200C; Thu, 4 Oct 2018 07:01:34 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id C291BC221C0; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id 61A33C21F9B for ; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdV-0005pi-HP; Thu, 04 Oct 2018 09:01:25 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:51 +0200 Message-Id: <20181004070055.1669-12-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 12/16] regmap: Add endianness support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add support for switching the endianness of regmap accesses via the "little-endian", "big-endian", and "native-endian" boolean properties in the device tree. The default endianness is native endianness. Signed-off-by: Mario Six Reviewed-by: Simon Glass Reviewed-by: Daniel Schwierzeck --- v9 -> v10: * Switched to readb/writeb for 8-bit reads/writes v8 -> v9: New in v9 --- drivers/core/regmap.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++---- include/regmap.h | 14 ++++++ 2 files changed, 136 insertions(+), 8 deletions(-) -- 2.11.0 diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index 9b2e02af2e..507417321b 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -164,6 +164,15 @@ int regmap_init_mem(ofnode node, struct regmap **mapp) return ret; } + if (ofnode_read_bool(node, "little-endian")) + map->endianness = REGMAP_LITTLE_ENDIAN; + else if (ofnode_read_bool(node, "big-endian")) + map->endianness = REGMAP_BIG_ENDIAN; + else if (ofnode_read_bool(node, "native-endian")) + map->endianness = REGMAP_NATIVE_ENDIAN; + else /* Default: native endianness */ + map->endianness = REGMAP_NATIVE_ENDIAN; + *mapp = map; return 0; @@ -188,6 +197,55 @@ int regmap_uninit(struct regmap *map) return 0; } +static inline u8 __read_8(u8 *addr, enum regmap_endianness_t endianness) +{ + return readb(addr); +} + +static inline u16 __read_16(u16 *addr, enum regmap_endianness_t endianness) +{ + switch (endianness) { + case REGMAP_LITTLE_ENDIAN: + return in_le16(addr); + case REGMAP_BIG_ENDIAN: + return in_be16(addr); + case REGMAP_NATIVE_ENDIAN: + return readw(addr); + } + + return readw(addr); +} + +static inline u32 __read_32(u32 *addr, enum regmap_endianness_t endianness) +{ + switch (endianness) { + case REGMAP_LITTLE_ENDIAN: + return in_le32(addr); + case REGMAP_BIG_ENDIAN: + return in_be32(addr); + case REGMAP_NATIVE_ENDIAN: + return readl(addr); + } + + return readl(addr); +} + +#if defined(in_le64) && defined(readq) +static inline u64 __read_64(u64 *addr, enum regmap_endianness_t endianness) +{ + switch (endianness) { + case REGMAP_LITTLE_ENDIAN: + return in_le64(addr); + case REGMAP_BIG_ENDIAN: + return in_be64(addr); + case REGMAP_NATIVE_ENDIAN: + return readq(addr); + } + + return readq(addr); +} +#endif + int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset, void *valp, size_t val_len) { @@ -210,17 +268,17 @@ int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset, switch (val_len) { case REGMAP_SIZE_8: - *((u8 *)valp) = readb((u8 *)ptr); + *((u8 *)valp) = __read_8(ptr, map->endianness); break; case REGMAP_SIZE_16: - *((u16 *)valp) = readw((u16 *)ptr); + *((u16 *)valp) = __read_16(ptr, map->endianness); break; case REGMAP_SIZE_32: - *((u32 *)valp) = readl((u32 *)ptr); + *((u32 *)valp) = __read_32(ptr, map->endianness); break; #if defined(readq) case REGMAP_SIZE_64: - *((u64 *)valp) = readq((u64 *)ptr); + *((u64 *)valp) = __read_64(ptr, map->endianness); break; #endif default: @@ -241,6 +299,62 @@ int regmap_read(struct regmap *map, uint offset, uint *valp) return regmap_raw_read(map, offset, valp, REGMAP_SIZE_32); } +static inline void __write_8(u8 *addr, const u8 *val, + enum regmap_endianness_t endianness) +{ + writeb(*val, addr); +} + +static inline void __write_16(u16 *addr, const u16 *val, + enum regmap_endianness_t endianness) +{ + switch (endianness) { + case REGMAP_NATIVE_ENDIAN: + writew(*val, addr); + break; + case REGMAP_LITTLE_ENDIAN: + out_le16(addr, *val); + break; + case REGMAP_BIG_ENDIAN: + out_be16(addr, *val); + break; + } +} + +static inline void __write_32(u32 *addr, const u32 *val, + enum regmap_endianness_t endianness) +{ + switch (endianness) { + case REGMAP_NATIVE_ENDIAN: + writel(*val, addr); + break; + case REGMAP_LITTLE_ENDIAN: + out_le32(addr, *val); + break; + case REGMAP_BIG_ENDIAN: + out_be32(addr, *val); + break; + } +} + +#if defined(out_le64) && defined(writeq) +static inline void __write_64(u64 *addr, const u64 *val, + enum regmap_endianness_t endianness) +{ + switch (endianness) { + case REGMAP_NATIVE_ENDIAN: + writeq(*val, addr); + break; + case REGMAP_LITTLE_ENDIAN: + out_le64(addr, *val); + break; + case REGMAP_BIG_ENDIAN: + out_be64(addr, *val); + break; + } +} +#endif + int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset, const void *val, size_t val_len) { @@ -263,17 +377,17 @@ int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset, switch (val_len) { case REGMAP_SIZE_8: - writeb(*((u8 *)val), (u8 *)ptr); + __write_8(ptr, val, map->endianness); break; case REGMAP_SIZE_16: - writew(*((u16 *)val), (u16 *)ptr); + __write_16(ptr, val, map->endianness); break; case REGMAP_SIZE_32: - writel(*((u32 *)val), (u32 *)ptr); + __write_32(ptr, val, map->endianness); break; #if defined(writeq) case REGMAP_SIZE_64: - writeq(*((u64 *)val), (u64 *)ptr); + __write_64(ptr, val, map->endianness); break; #endif default: diff --git a/include/regmap.h b/include/regmap.h index 3b7eea5f49..98860c2732 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -23,6 +23,19 @@ enum regmap_size_t { }; /** + * enum regmap_endianness_t - Endianness for regmap reads and writes + * + * @REGMAP_NATIVE_ENDIAN: Native endian read/write accesses + * @REGMAP_LITTLE_ENDIAN: Little endian read/write accesses + * @REGMAP_BIG_ENDIAN: Big endian read/write accesses + */ +enum regmap_endianness_t { + REGMAP_NATIVE_ENDIAN, + REGMAP_LITTLE_ENDIAN, + REGMAP_BIG_ENDIAN, +}; + +/** * struct regmap_range - a register map range * * @start: Start address @@ -40,6 +53,7 @@ struct regmap_range { * @ranges: Array of ranges */ struct regmap { + enum regmap_endianness_t endianness; int range_count; struct regmap_range ranges[0]; }; From patchwork Thu Oct 4 07:00:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978673 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkNY6XbJz9s7h for ; Thu, 4 Oct 2018 17:02:37 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 8E2A4C22189; Thu, 4 Oct 2018 07:02:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id D9B4EC221A4; Thu, 4 Oct 2018 07:01:34 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id CCCC3C21F9B; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id 906FEC221A5 for ; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdV-0005pi-LS; Thu, 04 Oct 2018 09:01:25 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:52 +0200 Message-Id: <20181004070055.1669-13-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 13/16] regmap: Add overview documentation X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add some overview documentation that explains the purpose and some of the features and limitations of the regmap interface. Reviewed-by: Bin Meng Signed-off-by: Mario Six --- v9 -> v10: No changes v8 -> v9: * Amended for inclusion of endianness setting via DT v7 -> v8: New in v8 --- include/regmap.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) -- 2.11.0 diff --git a/include/regmap.h b/include/regmap.h index 98860c2732..b2b733fda6 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -8,6 +8,33 @@ #define __REGMAP_H /** + * DOC: Overview + * + * Regmaps are an abstraction mechanism that allows device drivers to access + * register maps irrespective of the underlying bus architecture. This entails + * that for devices that support multiple busses (e.g. I2C and SPI for a GPIO + * expander chip) only one driver has to be written. This driver will + * instantiate a regmap with a backend depending on the bus the device is + * attached to, and use the regmap API to access the register map through that + * bus transparently. + * + * Read and write functions are supplied, which can read/write data of + * arbitrary length from/to the regmap. + * + * The endianness of regmap accesses is selectable for each map through device + * tree settings via the boolean "little-endian", "big-endian", and + * "native-endian" properties. + * + * Furthermore, the register map described by a regmap can be split into + * multiple disjoint areas called ranges. In this way, register maps with + * "holes", i.e. areas of addressable memory that are not part of the register + * map, can be accessed in a concise manner. + * + * Currently, only a bare "mem" backend for regmaps is supported, which + * accesses the register map as regular IO-mapped memory. + */ + +/** * enum regmap_size_t - Access sizes for regmap reads and writes * * @REGMAP_SIZE_8: 8-bit read/write access size From patchwork Thu Oct 4 07:00:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978681 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkYX53Ccz9s55 for ; Thu, 4 Oct 2018 17:10:24 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 6925DC22181; Thu, 4 Oct 2018 07:03:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 3C017C221DC; Thu, 4 Oct 2018 07:01:40 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 3B0FEC22159; Thu, 4 Oct 2018 07:01:28 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id 260F7C2218A for ; Thu, 4 Oct 2018 07:01:28 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdV-0005pi-QS; Thu, 04 Oct 2018 09:01:25 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:53 +0200 Message-Id: <20181004070055.1669-14-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 14/16] misc: Sort Makefile entries X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Makefile entries should be sorted. Reviewed-by: Anatolij Gustschin Reviewed-by: Simon Glass Signed-off-by: Mario Six Signed-off-by: Anatolij Gustschin --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: No changes v4 -> v5: Drop re-ordered entries that are not in mainline (e.g. CONFIG_GDSYS_IOEP, CONFIG_MPC83XX_SERDES, misc_sandbox.o) v3 -> v4: No changes v2 -> v3: New in v3 --- drivers/misc/Makefile | 58 +++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) -- 2.11.0 diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index acf24c44fa..5987b96372 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -4,11 +4,6 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-$(CONFIG_MISC) += misc-uclass.o -obj-$(CONFIG_ALI152X) += ali512x.o -obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o -obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o -obj-$(CONFIG_DS4510) += ds4510.o -obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CROS_EC) += cros_ec.o obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o @@ -16,44 +11,49 @@ obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o obj-$(CONFIG_CROS_EC_SANDBOX) += cros_ec_sandbox.o obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o endif -obj-$(CONFIG_FSL_IIM) += fsl_iim.o -obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o -obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o -obj-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o -obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o -obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o -obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o -obj-$(CONFIG_NS87308) += ns87308.o -obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o ifdef CONFIG_DM_I2C ifndef CONFIG_SPL_BUILD obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o endif endif -obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o -obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o -obj-$(CONFIG_LED_STATUS) += status_led.o -obj-$(CONFIG_SANDBOX) += swap_case.o ifdef CONFIG_SPL_OF_PLATDATA ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SANDBOX) += spltest_sandbox.o endif endif -obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o -obj-$(CONFIG_TEGRA_CAR) += tegra_car.o -obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o -obj-$(CONFIG_TWL4030_LED) += twl4030_led.o +obj-$(CONFIG_ALI152X) += ali512x.o +obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o +obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o +obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o +obj-$(CONFIG_DS4510) += ds4510.o +obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o obj-$(CONFIG_FSL_IFC) += fsl_ifc.o +obj-$(CONFIG_FSL_IIM) += fsl_iim.o +obj-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o +obj-$(CONFIG_FS_LOADER) += fs_loader.o +obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o +obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o +obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o +obj-$(CONFIG_LED_STATUS) += status_led.o +obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o +obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o +obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o +obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o +obj-$(CONFIG_NS87308) += ns87308.o +obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o obj-$(CONFIG_PCA9551_LED) += pca9551_led.o -obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o -obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o +obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o obj-$(CONFIG_QFW) += qfw.o obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o -obj-$(CONFIG_STM32_RCC) += stm32_rcc.o +obj-$(CONFIG_SANDBOX) += swap_case.o +obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o +obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o +obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o obj-$(CONFIG_STM32MP_FUSE) += stm32mp_fuse.o +obj-$(CONFIG_STM32_RCC) += stm32_rcc.o obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o -obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o -obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o -obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o -obj-$(CONFIG_FS_LOADER) += fs_loader.o +obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o +obj-$(CONFIG_TEGRA_CAR) += tegra_car.o +obj-$(CONFIG_TWL4030_LED) += twl4030_led.o +obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o From patchwork Thu Oct 4 07:00:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978684 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkZV0FMqz9s55 for ; Thu, 4 Oct 2018 17:11:14 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id C1C37C221BF; Thu, 4 Oct 2018 07:02:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id D17B3C221CB; Thu, 4 Oct 2018 07:01:36 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id F399AC22197; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id BAF78C22143 for ; Thu, 4 Oct 2018 07:01:26 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdV-0005pi-UO; Thu, 04 Oct 2018 09:01:25 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:54 +0200 Message-Id: <20181004070055.1669-15-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 15/16] misc: Add gdsys_soc driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This patch adds a driver for the bus associated with a IHS FPGA. Reviewed-by: Simon Glass Signed-off-by: Mario Six --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: No changes v4 -> v5: No changes v3 -> v4: No changes v2 -> v3: * Fixed style violations * Added bindings file * Added more debug output in case of errors * Switched all printfs to debug * Documented the private data structure * Formatted documentation as proper kernel-doc * Expanded Kconfig description v1 -> v2: * Switched to correct uclass for IHS FPGA driver (now in MISC uclass) --- .../devicetree/bindings/misc/gdsys,soc.txt | 16 +++++ drivers/misc/Kconfig | 8 +++ drivers/misc/Makefile | 1 + drivers/misc/gdsys_soc.c | 74 ++++++++++++++++++++++ drivers/misc/gdsys_soc.h | 23 +++++++ 5 files changed, 122 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/gdsys,soc.txt create mode 100644 drivers/misc/gdsys_soc.c create mode 100644 drivers/misc/gdsys_soc.h -- 2.11.0 diff --git a/Documentation/devicetree/bindings/misc/gdsys,soc.txt b/Documentation/devicetree/bindings/misc/gdsys,soc.txt new file mode 100644 index 0000000000..278e935b16 --- /dev/null +++ b/Documentation/devicetree/bindings/misc/gdsys,soc.txt @@ -0,0 +1,16 @@ +gdsys soc bus driver + +This driver provides a simple interface for the busses associated with gdsys +IHS FPGAs. The bus itself contains devices whose register maps are contained +within the FPGA's register space. + +Required properties: +- fpga: A phandle to the controlling IHS FPGA + +Example: + +FPGA0BUS: fpga0bus { + compatible = "gdsys,soc"; + ranges = <0x0 0xe0600000 0x00004000>; + fpga = <&FPGA0>; +}; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b0fb73f692..c44cfa2aca 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -304,4 +304,12 @@ config FS_LOADER The consumer driver would then use this loader to program whatever, ie. the FPGA device. +config GDSYS_SOC + bool "Enable gdsys SOC driver" + depends on MISC + help + Support for gdsys IHS SOC, a simple bus associated with each gdsys + IHS (Integrated Hardware Systems) FPGA, which holds all devices whose + register maps are contained within the FPGA's register map. + endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 5987b96372..f6849c397a 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o obj-$(CONFIG_FS_LOADER) += fs_loader.o obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o +obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o obj-$(CONFIG_LED_STATUS) += status_led.o obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o diff --git a/drivers/misc/gdsys_soc.c b/drivers/misc/gdsys_soc.c new file mode 100644 index 0000000000..94a21e08af --- /dev/null +++ b/drivers/misc/gdsys_soc.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2017 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include +#include +#include + +#include "gdsys_soc.h" + +/** + * struct gdsys_soc_priv - Private data for gdsys soc bus + * @fpga: The gdsys IHS FPGA this bus is associated with + */ +struct gdsys_soc_priv { + struct udevice *fpga; +}; + +static const struct udevice_id gdsys_soc_ids[] = { + { .compatible = "gdsys,soc" }, + { /* sentinel */ } +}; + +int gdsys_soc_get_fpga(struct udevice *child, struct udevice **fpga) +{ + struct gdsys_soc_priv *bus_priv; + + if (!child->parent) { + debug("%s: Invalid parent\n", child->name); + return -EINVAL; + } + + if (!device_is_compatible(child->parent, "gdsys,soc")) { + debug("%s: Not child of a gdsys soc\n", child->name); + return -EINVAL; + } + + bus_priv = dev_get_priv(child->parent); + + *fpga = bus_priv->fpga; + + return 0; +} + +static int gdsys_soc_probe(struct udevice *dev) +{ + struct gdsys_soc_priv *priv = dev_get_priv(dev); + struct udevice *fpga; + int res = uclass_get_device_by_phandle(UCLASS_MISC, dev, "fpga", + &fpga); + if (res == -ENOENT) { + debug("%s: Could not find 'fpga' phandle\n", dev->name); + return -EINVAL; + } + + if (res == -ENODEV) { + debug("%s: Could not get FPGA device\n", dev->name); + return -EINVAL; + } + + priv->fpga = fpga; + + return 0; +} + +U_BOOT_DRIVER(gdsys_soc_bus) = { + .name = "gdsys_soc_bus", + .id = UCLASS_SIMPLE_BUS, + .of_match = gdsys_soc_ids, + .probe = gdsys_soc_probe, + .priv_auto_alloc_size = sizeof(struct gdsys_soc_priv), +}; diff --git a/drivers/misc/gdsys_soc.h b/drivers/misc/gdsys_soc.h new file mode 100644 index 0000000000..088d3b6523 --- /dev/null +++ b/drivers/misc/gdsys_soc.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2017 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#ifndef _GDSYS_SOC_H_ +#define _GDSYS_SOC_H_ + +/** + * gdsys_soc_get_fpga() - Retrieve pointer to parent bus' FPGA device + * @child: The child device on the FPGA bus needing access to the FPGA. + * @fpga: Pointer to the retrieved FPGA device. + * + * To access their register maps, devices on gdsys soc buses usually have + * facilitate the accessor function of the IHS FPGA their parent bus is + * attached to. To access the FPGA device from within the bus' children, this + * function returns a pointer to it. + * + * Return: 0 on success, -ve on failure + */ +int gdsys_soc_get_fpga(struct udevice *child, struct udevice **fpga); +#endif /* _GDSYS_SOC_H_ */ From patchwork Thu Oct 4 07:00:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Six X-Patchwork-Id: 978682 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdsys.cc Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42QkYb1x6Kz9s55 for ; Thu, 4 Oct 2018 17:10:27 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id E5E8BC22143; Thu, 4 Oct 2018 07:05:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 53E47C22207; Thu, 4 Oct 2018 07:01:46 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id AFD12C2201E; Thu, 4 Oct 2018 07:01:28 +0000 (UTC) Received: from smtprelay01.ispgateway.de (smtprelay01.ispgateway.de [80.67.29.23]) by lists.denx.de (Postfix) with ESMTPS id D4126C22143 for ; Thu, 4 Oct 2018 07:01:27 +0000 (UTC) Received: from [87.191.40.34] (helo=bob3.testumgebung.local) by smtprelay01.ispgateway.de with esmtpa (Exim 4.90_1) (envelope-from ) id 1g7xdW-0005pi-2V; Thu, 04 Oct 2018 09:01:26 +0200 From: Mario Six To: U-Boot Mailing List , Anatolij Gustschin , Daniel Schwierzeck , Simon Glass , Bin Meng Date: Thu, 4 Oct 2018 09:00:55 +0200 Message-Id: <20181004070055.1669-16-mario.six@gdsys.cc> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181004070055.1669-1-mario.six@gdsys.cc> References: <20181004070055.1669-1-mario.six@gdsys.cc> X-Df-Sender: bWFyaW8uc2l4QGdkc3lzLmNj Subject: [U-Boot] [PATCH v10 16/16] misc: Add IHS FPGA driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add a driver for gdsys IHS (Integrated Hardware Systems) FPGAs, which supports initialization of the FPGA, as well as information gathering. Reviewed-by: Simon Glass Signed-off-by: Mario Six --- v9 -> v10: No changes v8 -> v9: No changes v7 -> v8: No changes v6 -> v7: No changes v5 -> v6: No changes v4 -> v5: No changes v3 -> v4: * Switched from 'res' as the name for return variables to 'ret' v2 -> v3: * Fixed style violations * Added full documentation * Extracted some magic numbers to constants * Removed unnecessary includes * Extracted wait_for_fpga_done * Improved error handling and reporting * Added device-tree-binding files * Improved Kconfig entry v1 -> v2: New in v2 --- .../devicetree/bindings/misc/gdsys,iocon_fpga.txt | 19 + .../devicetree/bindings/misc/gdsys,iocpu_fpga.txt | 19 + drivers/misc/Kconfig | 9 + drivers/misc/Makefile | 1 + drivers/misc/ihs_fpga.c | 867 +++++++++++++++++++++ drivers/misc/ihs_fpga.h | 49 ++ 6 files changed, 964 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt create mode 100644 Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt create mode 100644 drivers/misc/ihs_fpga.c create mode 100644 drivers/misc/ihs_fpga.h -- 2.11.0 diff --git a/Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt b/Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt new file mode 100644 index 0000000000..acd466fdc6 --- /dev/null +++ b/Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt @@ -0,0 +1,19 @@ +gdsys IHS FPGA for CON devices + +The gdsys IHS FPGA is the main FPGA on gdsys CON devices. This driver provides +support for enabling and starting the FPGA, as well as verifying working bus +communication. + +Required properties: +- compatible: must be "gdsys,iocon_fpga" +- reset-gpios: List of GPIOs controlling the FPGA's reset +- done-gpios: List of GPIOs notifying whether the FPGA's reconfiguration is + done + +Example: + +FPGA0 { + compatible = "gdsys,iocon_fpga"; + reset-gpios = <&PPCPCA 26 0>; + done-gpios = <&GPIO_VB0 19 0>; +}; diff --git a/Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt b/Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt new file mode 100644 index 0000000000..819db22bf7 --- /dev/null +++ b/Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt @@ -0,0 +1,19 @@ +gdsys IHS FPGA for CPU devices + +The gdsys IHS FPGA is the main FPGA on gdsys CPU devices. This driver provides +support for enabling and starting the FPGA, as well as verifying working bus +communication. + +Required properties: +- compatible: must be "gdsys,iocpu_fpga" +- reset-gpios: List of GPIOs controlling the FPGA's reset +- done-gpios: List of GPIOs notifying whether the FPGA's reconfiguration is + done + +Example: + +FPGA0 { + compatible = "gdsys,iocpu_fpga"; + reset-gpios = <&PPCPCA 26 0>; + done-gpios = <&GPIO_VB0 19 0>; +}; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index c44cfa2aca..7097aa9f2f 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -312,4 +312,13 @@ config GDSYS_SOC IHS (Integrated Hardware Systems) FPGA, which holds all devices whose register maps are contained within the FPGA's register map. +config IHS_FPGA + bool "Enable IHS FPGA driver" + depends on MISC + help + Support IHS (Integrated Hardware Systems) FPGA, the main FPGAs on + gdsys devices, which supply the majority of the functionality offered + by the devices. This driver supports both CON and CPU variants of the + devices, depending on the device tree entry. + endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index f6849c397a..df5abd11a2 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o +obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o obj-$(CONFIG_LED_STATUS) += status_led.o obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o diff --git a/drivers/misc/ihs_fpga.c b/drivers/misc/ihs_fpga.c new file mode 100644 index 0000000000..f9e4b27a27 --- /dev/null +++ b/drivers/misc/ihs_fpga.c @@ -0,0 +1,867 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2017 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + * + * based on the ioep-fpga driver, which is + * + * (C) Copyright 2014 + * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de + */ + +#include +#include +#include +#include + +#include "ihs_fpga.h" + +/** + * struct ihs_fpga_priv - Private data structure for IHS FPGA driver + * @map: Register map for the FPGA's own register space + * @reset_gpio: GPIO to start FPGA reconfiguration + * @done_gpio: GPOI to read the 'ready' status of the FPGA + */ +struct ihs_fpga_priv { + struct regmap *map; + struct gpio_desc reset_gpio; + struct gpio_desc done_gpio; +}; + +/* Test pattern for reflection test */ +const u16 REFLECTION_TESTPATTERN = 0xdead; +/* Delay (in ms) for each round in the reflection test */ +const uint REFLECTION_TEST_DELAY = 100; +/* Maximum number of rounds in the reflection test */ +const uint REFLECTION_TEST_ROUNDS = 5; +/* Delay (in ms) for each round waiting for the FPGA's done GPIO */ +const uint FPGA_DONE_WAIT_DELAY = 100; +/* Maximum number of rounds for waiting for the FPGA's done GPIO */ +const uint FPGA_DONE_WAIT_ROUND = 5; + +/** + * enum pcb_video_type - Video type of the PCB + * @PCB_DVI_SL: Video type is DVI single-link + * @PCB_DP_165MPIX: Video type is DisplayPort (165Mpix) + * @PCB_DP_300MPIX: Video type is DisplayPort (300Mpix) + * @PCB_HDMI: Video type is HDMI + * @PCB_DP_1_2: Video type is DisplayPort 1.2 + * @PCB_HDMI_2_0: Video type is HDMI 2.0 + */ +enum pcb_video_type { + PCB_DVI_SL, + PCB_DP_165MPIX, + PCB_DP_300MPIX, + PCB_HDMI, + PCB_DP_1_2, + PCB_HDMI_2_0, +}; + +/** + * enum pcb_transmission_type - Transmission type of the PCB + * @PCB_CAT_1G: Transmission type is 1G Ethernet + * @PCB_FIBER_3G: Transmission type is 3G Fiber + * @PCB_CAT_10G: Transmission type is 10G Ethernet + * @PCB_FIBER_10G: Transmission type is 10G Fiber + */ +enum pcb_transmission_type { + PCB_CAT_1G, + PCB_FIBER_3G, + PCB_CAT_10G, + PCB_FIBER_10G, +}; + +/** + * enum carrier_speed - Speed of the FPGA's carrier + * @CARRIER_SPEED_1G: The carrier speed is 1G + * @CARRIER_SPEED_2_5G: The carrier speed is 2.5G + * @CARRIER_SPEED_3G: The carrier speed is 3G + * @CARRIER_SPEED_10G: The carrier speed is 10G + */ +enum carrier_speed { + CARRIER_SPEED_1G, + CARRIER_SPEED_3G, + CARRIER_SPEED_2_5G = CARRIER_SPEED_3G, + CARRIER_SPEED_10G, +}; + +/** + * enum ram_config - FPGA's RAM configuration + * @RAM_DDR2_32BIT_295MBPS: DDR2 32 bit at 295Mb/s + * @RAM_DDR3_32BIT_590MBPS: DDR3 32 bit at 590Mb/s + * @RAM_DDR3_48BIT_590MBPS: DDR3 48 bit at 590Mb/s + * @RAM_DDR3_64BIT_1800MBPS: DDR3 64 bit at 1800Mb/s + * @RAM_DDR3_48BIT_1800MBPS: DDR3 48 bit at 1800Mb/s + */ +enum ram_config { + RAM_DDR2_32BIT_295MBPS, + RAM_DDR3_32BIT_590MBPS, + RAM_DDR3_48BIT_590MBPS, + RAM_DDR3_64BIT_1800MBPS, + RAM_DDR3_48BIT_1800MBPS, +}; + +/** + * enum sysclock - Speed of the FPGA's system clock + * @SYSCLK_147456: System clock is 147.456 MHz + */ +enum sysclock { + SYSCLK_147456, +}; + +/** + * struct fpga_versions - Data read from the versions register + * @video_channel: Is the FPGA for a video channel (true) or main + * channel (false) device? + * @con_side: Is the FPGA for a CON (true) or a CPU (false) device? + * @pcb_video_type: Defines for whch video type the FPGA is configured + * @pcb_transmission_type: Defines for which transmission type the FPGA is + * configured + * @hw_version: Hardware version of the FPGA + */ +struct fpga_versions { + bool video_channel; + bool con_side; + enum pcb_video_type pcb_video_type; + enum pcb_transmission_type pcb_transmission_type; + unsigned int hw_version; +}; + +/** + * struct fpga_features - Data read from the features register + * @video_channels: Number of video channels supported + * @carriers: Number of carrier channels supported + * @carrier_speed: Speed of carriers + * @ram_config: RAM configuration of FPGA + * @sysclock: System clock speed of FPGA + * @pcm_tx: Support for PCM transmission + * @pcm_rx: Support for PCM reception + * @spdif_tx: Support for SPDIF audio transmission + * @spdif_rx: Support for SPDIF audio reception + * @usb2: Support for transparent USB2.0 + * @rs232: Support for bidirectional RS232 + * @compression_type1: Support for compression type 1 + * @compression_type2: Support for compression type 2 + * @compression_type3: Support for compression type 3 + * @interlace: Support for interlace image formats + * @osd: Support for a OSD + * @compression_pipes: Number of compression pipes supported + */ +struct fpga_features { + u8 video_channels; + u8 carriers; + enum carrier_speed carrier_speed; + enum ram_config ram_config; + enum sysclock sysclock; + bool pcm_tx; + bool pcm_rx; + bool spdif_tx; + bool spdif_rx; + bool usb2; + bool rs232; + bool compression_type1; + bool compression_type2; + bool compression_type3; + bool interlace; + bool osd; + bool compression_pipes; +}; + +#ifdef CONFIG_SYS_FPGA_FLAVOR_GAZERBEAM + +/** + * get_versions() - Fill structure with info from version register. + * @dev: FPGA device to be queried for information + * @versions: Pointer to the structure to fill with information from the + * versions register + * Return: 0 + */ +static int get_versions(struct udevice *dev, struct fpga_versions *versions) +{ + struct ihs_fpga_priv *priv = dev_get_priv(dev); + enum { + VERSIONS_FPGA_VIDEO_CHANNEL = BIT(12), + VERSIONS_FPGA_CON_SIDE = BIT(13), + VERSIONS_FPGA_SC = BIT(14), + VERSIONS_PCB_CON = BIT(9), + VERSIONS_PCB_SC = BIT(8), + VERSIONS_PCB_VIDEO_MASK = 0x3 << 6, + VERSIONS_PCB_VIDEO_DP_1_2 = 0x0 << 6, + VERSIONS_PCB_VIDEO_HDMI_2_0 = 0x1 << 6, + VERSIONS_PCB_TRANSMISSION_MASK = 0x3 << 4, + VERSIONS_PCB_TRANSMISSION_FIBER_10G = 0x0 << 4, + VERSIONS_PCB_TRANSMISSION_CAT_10G = 0x1 << 4, + VERSIONS_PCB_TRANSMISSION_FIBER_3G = 0x2 << 4, + VERSIONS_PCB_TRANSMISSION_CAT_1G = 0x3 << 4, + VERSIONS_HW_VER_MASK = 0xf << 0, + }; + u16 raw_versions; + + memset(versions, 0, sizeof(struct fpga_versions)); + + ihs_fpga_get(priv->map, versions, &raw_versions); + + versions->video_channel = raw_versions & VERSIONS_FPGA_VIDEO_CHANNEL; + versions->con_side = raw_versions & VERSIONS_FPGA_CON_SIDE; + + switch (raw_versions & VERSIONS_PCB_VIDEO_MASK) { + case VERSIONS_PCB_VIDEO_DP_1_2: + versions->pcb_video_type = PCB_DP_1_2; + break; + + case VERSIONS_PCB_VIDEO_HDMI_2_0: + versions->pcb_video_type = PCB_HDMI_2_0; + break; + } + + switch (raw_versions & VERSIONS_PCB_TRANSMISSION_MASK) { + case VERSIONS_PCB_TRANSMISSION_FIBER_10G: + versions->pcb_transmission_type = PCB_FIBER_10G; + break; + + case VERSIONS_PCB_TRANSMISSION_CAT_10G: + versions->pcb_transmission_type = PCB_CAT_10G; + break; + + case VERSIONS_PCB_TRANSMISSION_FIBER_3G: + versions->pcb_transmission_type = PCB_FIBER_3G; + break; + + case VERSIONS_PCB_TRANSMISSION_CAT_1G: + versions->pcb_transmission_type = PCB_CAT_1G; + break; + } + + versions->hw_version = raw_versions & VERSIONS_HW_VER_MASK; + + return 0; +} + +/** + * get_features() - Fill structure with info from features register. + * @dev: FPGA device to be queried for information + * @features: Pointer to the structure to fill with information from the + * features register + * Return: 0 + */ +static int get_features(struct udevice *dev, struct fpga_features *features) +{ + struct ihs_fpga_priv *priv = dev_get_priv(dev); + enum { + FEATURE_SPDIF_RX = BIT(15), + FEATURE_SPDIF_TX = BIT(14), + FEATURE_PCM_RX = BIT(13), + FEATURE_PCM_TX = BIT(12), + FEATURE_RAM_MASK = GENMASK(11, 8), + FEATURE_RAM_DDR2_32BIT_295MBPS = 0x0 << 8, + FEATURE_RAM_DDR3_32BIT_590MBPS = 0x1 << 8, + FEATURE_RAM_DDR3_48BIT_590MBPS = 0x2 << 8, + FEATURE_RAM_DDR3_64BIT_1800MBPS = 0x3 << 8, + FEATURE_RAM_DDR3_48BIT_1800MBPS = 0x4 << 8, + FEATURE_CARRIER_SPEED_MASK = GENMASK(7, 6), + FEATURE_CARRIER_SPEED_1G = 0x0 << 6, + FEATURE_CARRIER_SPEED_2_5G = 0x1 << 6, + FEATURE_CARRIER_SPEED_10G = 0x2 << 6, + FEATURE_CARRIERS_MASK = GENMASK(5, 4), + FEATURE_CARRIERS_0 = 0x0 << 4, + FEATURE_CARRIERS_1 = 0x1 << 4, + FEATURE_CARRIERS_2 = 0x2 << 4, + FEATURE_CARRIERS_4 = 0x3 << 4, + FEATURE_USB2 = BIT(3), + FEATURE_VIDEOCHANNELS_MASK = GENMASK(2, 0), + FEATURE_VIDEOCHANNELS_0 = 0x0 << 0, + FEATURE_VIDEOCHANNELS_1 = 0x1 << 0, + FEATURE_VIDEOCHANNELS_1_1 = 0x2 << 0, + FEATURE_VIDEOCHANNELS_2 = 0x3 << 0, + }; + + enum { + EXT_FEATURE_OSD = BIT(15), + EXT_FEATURE_ETHERNET = BIT(9), + EXT_FEATURE_INTERLACE = BIT(8), + EXT_FEATURE_RS232 = BIT(7), + EXT_FEATURE_COMPRESSION_PERF_MASK = GENMASK(6, 4), + EXT_FEATURE_COMPRESSION_PERF_1X = 0x0 << 4, + EXT_FEATURE_COMPRESSION_PERF_2X = 0x1 << 4, + EXT_FEATURE_COMPRESSION_PERF_4X = 0x2 << 4, + EXT_FEATURE_COMPRESSION_TYPE1 = BIT(0), + EXT_FEATURE_COMPRESSION_TYPE2 = BIT(1), + EXT_FEATURE_COMPRESSION_TYPE3 = BIT(2), + }; + + u16 raw_features; + u16 raw_extended_features; + + memset(features, 0, sizeof(struct fpga_features)); + + ihs_fpga_get(priv->map, features, &raw_features); + ihs_fpga_get(priv->map, extended_features, &raw_extended_features); + + switch (raw_features & FEATURE_VIDEOCHANNELS_MASK) { + case FEATURE_VIDEOCHANNELS_0: + features->video_channels = 0; + break; + + case FEATURE_VIDEOCHANNELS_1: + features->video_channels = 1; + break; + + case FEATURE_VIDEOCHANNELS_1_1: + case FEATURE_VIDEOCHANNELS_2: + features->video_channels = 2; + break; + }; + + switch (raw_features & FEATURE_CARRIERS_MASK) { + case FEATURE_CARRIERS_0: + features->carriers = 0; + break; + + case FEATURE_CARRIERS_1: + features->carriers = 1; + break; + + case FEATURE_CARRIERS_2: + features->carriers = 2; + break; + + case FEATURE_CARRIERS_4: + features->carriers = 4; + break; + } + + switch (raw_features & FEATURE_CARRIER_SPEED_MASK) { + case FEATURE_CARRIER_SPEED_1G: + features->carrier_speed = CARRIER_SPEED_1G; + break; + case FEATURE_CARRIER_SPEED_2_5G: + features->carrier_speed = CARRIER_SPEED_2_5G; + break; + case FEATURE_CARRIER_SPEED_10G: + features->carrier_speed = CARRIER_SPEED_10G; + break; + } + + switch (raw_features & FEATURE_RAM_MASK) { + case FEATURE_RAM_DDR2_32BIT_295MBPS: + features->ram_config = RAM_DDR2_32BIT_295MBPS; + break; + + case FEATURE_RAM_DDR3_32BIT_590MBPS: + features->ram_config = RAM_DDR3_32BIT_590MBPS; + break; + + case FEATURE_RAM_DDR3_48BIT_590MBPS: + features->ram_config = RAM_DDR3_48BIT_590MBPS; + break; + + case FEATURE_RAM_DDR3_64BIT_1800MBPS: + features->ram_config = RAM_DDR3_64BIT_1800MBPS; + break; + + case FEATURE_RAM_DDR3_48BIT_1800MBPS: + features->ram_config = RAM_DDR3_48BIT_1800MBPS; + break; + } + + features->pcm_tx = raw_features & FEATURE_PCM_TX; + features->pcm_rx = raw_features & FEATURE_PCM_RX; + features->spdif_tx = raw_features & FEATURE_SPDIF_TX; + features->spdif_rx = raw_features & FEATURE_SPDIF_RX; + features->usb2 = raw_features & FEATURE_USB2; + features->rs232 = raw_extended_features & EXT_FEATURE_RS232; + features->compression_type1 = raw_extended_features & + EXT_FEATURE_COMPRESSION_TYPE1; + features->compression_type2 = raw_extended_features & + EXT_FEATURE_COMPRESSION_TYPE2; + features->compression_type3 = raw_extended_features & + EXT_FEATURE_COMPRESSION_TYPE3; + features->interlace = raw_extended_features & EXT_FEATURE_INTERLACE; + features->osd = raw_extended_features & EXT_FEATURE_OSD; + features->compression_pipes = raw_extended_features & + EXT_FEATURE_COMPRESSION_PERF_MASK; + + return 0; +} + +#else + +/** + * get_versions() - Fill structure with info from version register. + * @fpga: Identifier of the FPGA device to be queried for information + * @versions: Pointer to the structure to fill with information from the + * versions register + * + * This is the legacy version and should be considered deprecated for new + * devices. + * + * Return: 0 + */ +static int get_versions(unsigned int fpga, struct fpga_versions *versions) +{ + enum { + /* HW version encoding is a mess, leave it for the moment */ + VERSIONS_HW_VER_MASK = 0xf << 0, + VERSIONS_PIX_CLOCK_GEN_IDT8N3QV01 = BIT(4), + VERSIONS_SFP = BIT(5), + VERSIONS_VIDEO_MASK = 0x7 << 6, + VERSIONS_VIDEO_DVI = 0x0 << 6, + VERSIONS_VIDEO_DP_165 = 0x1 << 6, + VERSIONS_VIDEO_DP_300 = 0x2 << 6, + VERSIONS_VIDEO_HDMI = 0x3 << 6, + VERSIONS_UT_MASK = 0xf << 12, + VERSIONS_UT_MAIN_SERVER = 0x0 << 12, + VERSIONS_UT_MAIN_USER = 0x1 << 12, + VERSIONS_UT_VIDEO_SERVER = 0x2 << 12, + VERSIONS_UT_VIDEO_USER = 0x3 << 12, + }; + u16 raw_versions; + + memset(versions, 0, sizeof(struct fpga_versions)); + + FPGA_GET_REG(fpga, versions, &raw_versions); + + switch (raw_versions & VERSIONS_UT_MASK) { + case VERSIONS_UT_MAIN_SERVER: + versions->video_channel = false; + versions->con_side = false; + break; + + case VERSIONS_UT_MAIN_USER: + versions->video_channel = false; + versions->con_side = true; + break; + + case VERSIONS_UT_VIDEO_SERVER: + versions->video_channel = true; + versions->con_side = false; + break; + + case VERSIONS_UT_VIDEO_USER: + versions->video_channel = true; + versions->con_side = true; + break; + } + + switch (raw_versions & VERSIONS_VIDEO_MASK) { + case VERSIONS_VIDEO_DVI: + versions->pcb_video_type = PCB_DVI_SL; + break; + + case VERSIONS_VIDEO_DP_165: + versions->pcb_video_type = PCB_DP_165MPIX; + break; + + case VERSIONS_VIDEO_DP_300: + versions->pcb_video_type = PCB_DP_300MPIX; + break; + + case VERSIONS_VIDEO_HDMI: + versions->pcb_video_type = PCB_HDMI; + break; + } + + versions->hw_version = raw_versions & VERSIONS_HW_VER_MASK; + + if (raw_versions & VERSIONS_SFP) + versions->pcb_transmission_type = PCB_FIBER_3G; + else + versions->pcb_transmission_type = PCB_CAT_1G; + + return 0; +} + +/** + * get_features() - Fill structure with info from features register. + * @fpga: Identifier of the FPGA device to be queried for information + * @features: Pointer to the structure to fill with information from the + * features register + * + * This is the legacy version and should be considered deprecated for new + * devices. + * + * Return: 0 + */ +static int get_features(unsigned int fpga, struct fpga_features *features) +{ + enum { + FEATURE_CARRIER_SPEED_2_5 = BIT(4), + FEATURE_RAM_MASK = 0x7 << 5, + FEATURE_RAM_DDR2_32BIT = 0x0 << 5, + FEATURE_RAM_DDR3_32BIT = 0x1 << 5, + FEATURE_RAM_DDR3_48BIT = 0x2 << 5, + FEATURE_PCM_AUDIO_TX = BIT(9), + FEATURE_PCM_AUDIO_RX = BIT(10), + FEATURE_OSD = BIT(11), + FEATURE_USB20 = BIT(12), + FEATURE_COMPRESSION_MASK = 7 << 13, + FEATURE_COMPRESSION_TYPE1 = 0x1 << 13, + FEATURE_COMPRESSION_TYPE1_TYPE2 = 0x3 << 13, + FEATURE_COMPRESSION_TYPE1_TYPE2_TYPE3 = 0x7 << 13, + }; + + enum { + EXTENDED_FEATURE_SPDIF_AUDIO_TX = BIT(0), + EXTENDED_FEATURE_SPDIF_AUDIO_RX = BIT(1), + EXTENDED_FEATURE_RS232 = BIT(2), + EXTENDED_FEATURE_COMPRESSION_PIPES = BIT(3), + EXTENDED_FEATURE_INTERLACE = BIT(4), + }; + + u16 raw_features; + u16 raw_extended_features; + + memset(features, 0, sizeof(struct fpga_features)); + + FPGA_GET_REG(fpga, fpga_features, &raw_features); + FPGA_GET_REG(fpga, fpga_ext_features, &raw_extended_features); + + features->video_channels = raw_features & 0x3; + features->carriers = (raw_features >> 2) & 0x3; + + features->carrier_speed = (raw_features & FEATURE_CARRIER_SPEED_2_5) + ? CARRIER_SPEED_2_5G : CARRIER_SPEED_1G; + + switch (raw_features & FEATURE_RAM_MASK) { + case FEATURE_RAM_DDR2_32BIT: + features->ram_config = RAM_DDR2_32BIT_295MBPS; + break; + + case FEATURE_RAM_DDR3_32BIT: + features->ram_config = RAM_DDR3_32BIT_590MBPS; + break; + + case FEATURE_RAM_DDR3_48BIT: + features->ram_config = RAM_DDR3_48BIT_590MBPS; + break; + } + + features->pcm_tx = raw_features & FEATURE_PCM_AUDIO_TX; + features->pcm_rx = raw_features & FEATURE_PCM_AUDIO_RX; + features->spdif_tx = raw_extended_features & + EXTENDED_FEATURE_SPDIF_AUDIO_TX; + features->spdif_rx = raw_extended_features & + EXTENDED_FEATURE_SPDIF_AUDIO_RX; + + features->usb2 = raw_features & FEATURE_USB20; + features->rs232 = raw_extended_features & EXTENDED_FEATURE_RS232; + + features->compression_type1 = false; + features->compression_type2 = false; + features->compression_type3 = false; + switch (raw_features & FEATURE_COMPRESSION_MASK) { + case FEATURE_COMPRESSION_TYPE1_TYPE2_TYPE3: + features->compression_type3 = true; + /* fall-through */ + case FEATURE_COMPRESSION_TYPE1_TYPE2: + features->compression_type2 = true; + /* fall-through */ + case FEATURE_COMPRESSION_TYPE1: + features->compression_type1 = true; + break; + } + + features->interlace = raw_extended_features & + EXTENDED_FEATURE_INTERLACE; + features->osd = raw_features & FEATURE_OSD; + features->compression_pipes = raw_extended_features & + EXTENDED_FEATURE_COMPRESSION_PIPES; + + return 0; +} + +#endif + +/** + * fpga_print_info() - Print information about FPGA device + * @dev: FPGA device to print information about + */ +static void fpga_print_info(struct udevice *dev) +{ + struct ihs_fpga_priv *priv = dev_get_priv(dev); + u16 fpga_version; + struct fpga_versions versions; + struct fpga_features features; + + ihs_fpga_get(priv->map, fpga_version, &fpga_version); + get_versions(dev, &versions); + get_features(dev, &features); + + if (versions.video_channel) + printf("Videochannel"); + else + printf("Mainchannel"); + + if (versions.con_side) + printf(" User"); + else + printf(" Server"); + + switch (versions.pcb_transmission_type) { + case PCB_CAT_1G: + case PCB_CAT_10G: + printf(" CAT"); + break; + case PCB_FIBER_3G: + case PCB_FIBER_10G: + printf(" Fiber"); + break; + }; + + switch (versions.pcb_video_type) { + case PCB_DVI_SL: + printf(" DVI,"); + break; + case PCB_DP_165MPIX: + printf(" DP 165MPix/s,"); + break; + case PCB_DP_300MPIX: + printf(" DP 300MPix/s,"); + break; + case PCB_HDMI: + printf(" HDMI,"); + break; + case PCB_DP_1_2: + printf(" DP 1.2,"); + break; + case PCB_HDMI_2_0: + printf(" HDMI 2.0,"); + break; + } + + printf(" FPGA V %d.%02d\n features: ", + fpga_version / 100, fpga_version % 100); + + if (!features.compression_type1 && + !features.compression_type2 && + !features.compression_type3) + printf("no compression, "); + + if (features.compression_type1) + printf("type1, "); + + if (features.compression_type2) + printf("type2, "); + + if (features.compression_type3) + printf("type3, "); + + printf("%sosd", features.osd ? "" : "no "); + + if (features.pcm_rx && features.pcm_tx) + printf(", pcm rx+tx"); + else if (features.pcm_rx) + printf(", pcm rx"); + else if (features.pcm_tx) + printf(", pcm tx"); + + if (features.spdif_rx && features.spdif_tx) + printf(", spdif rx+tx"); + else if (features.spdif_rx) + printf(", spdif rx"); + else if (features.spdif_tx) + printf(", spdif tx"); + + puts(",\n "); + + switch (features.sysclock) { + case SYSCLK_147456: + printf("clock 147.456 MHz"); + break; + } + + switch (features.ram_config) { + case RAM_DDR2_32BIT_295MBPS: + printf(", RAM 32 bit DDR2"); + break; + case RAM_DDR3_32BIT_590MBPS: + printf(", RAM 32 bit DDR3"); + break; + case RAM_DDR3_48BIT_590MBPS: + case RAM_DDR3_48BIT_1800MBPS: + printf(", RAM 48 bit DDR3"); + break; + case RAM_DDR3_64BIT_1800MBPS: + printf(", RAM 64 bit DDR3"); + break; + } + + printf(", %d carrier(s)", features.carriers); + + switch (features.carrier_speed) { + case CARRIER_SPEED_1G: + printf(", 1Gbit/s"); + break; + case CARRIER_SPEED_3G: + printf(", 3Gbit/s"); + break; + case CARRIER_SPEED_10G: + printf(", 10Gbit/s"); + break; + } + + printf(", %d video channel(s)\n", features.video_channels); +} + +/** + * do_reflection_test() - Run reflection test on a FPGA device + * @dev: FPGA device to run reflection test on + * + * Return: 0 if reflection test succeeded, -ve on error + */ +static int do_reflection_test(struct udevice *dev) +{ + struct ihs_fpga_priv *priv = dev_get_priv(dev); + int ctr = 0; + + while (1) { + u16 val; + + ihs_fpga_set(priv->map, reflection_low, REFLECTION_TESTPATTERN); + + ihs_fpga_get(priv->map, reflection_low, &val); + if (val == (~REFLECTION_TESTPATTERN & 0xffff)) + return -EIO; + + mdelay(REFLECTION_TEST_DELAY); + if (ctr++ > REFLECTION_TEST_ROUNDS) + return 0; + } +} + +/** + * wait_for_fpga_done() - Wait until 'done'-flag is set for FPGA device + * @dev: FPGA device whose done flag to wait for + * + * This function waits until it detects that the done-GPIO's value was changed + * to 1 by the FPGA, which indicates that the device is configured and ready to + * use. + * + * Return: 0 if done flag was detected, -ve on error + */ +static int wait_for_fpga_done(struct udevice *dev) +{ + struct ihs_fpga_priv *priv = dev_get_priv(dev); + int ctr = 0; + int done_val; + + while (1) { + done_val = dm_gpio_get_value(&priv->done_gpio); + if (done_val < 0) { + debug("%s: Error while reading done-GPIO (err = %d)\n", + dev->name, done_val); + return done_val; + } + + if (done_val) + return 0; + + mdelay(FPGA_DONE_WAIT_DELAY); + if (ctr++ > FPGA_DONE_WAIT_ROUND) { + debug("%s: FPGA init failed (done not detected)\n", + dev->name); + return -EIO; + } + } +} + +static int ihs_fpga_probe(struct udevice *dev) +{ + struct ihs_fpga_priv *priv = dev_get_priv(dev); + int ret; + + /* TODO(mario.six@gdsys.cc): Case of FPGA attached to MCLink bus */ + + ret = regmap_init_mem(dev_ofnode(dev), &priv->map); + if (ret) { + debug("%s: Could not initialize regmap (err = %d)", + dev->name, ret); + return ret; + } + + ret = gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset_gpio, + GPIOD_IS_OUT); + if (ret) { + debug("%s: Could not get reset-GPIO (err = %d)\n", + dev->name, ret); + return ret; + } + + if (!priv->reset_gpio.dev) { + debug("%s: Could not get reset-GPIO\n", dev->name); + return -ENOENT; + } + + ret = gpio_request_by_name(dev, "done-gpios", 0, &priv->done_gpio, + GPIOD_IS_IN); + if (ret) { + debug("%s: Could not get done-GPIO (err = %d)\n", + dev->name, ret); + return ret; + } + + if (!priv->done_gpio.dev) { + debug("%s: Could not get done-GPIO\n", dev->name); + return -ENOENT; + } + + ret = dm_gpio_set_value(&priv->reset_gpio, 1); + if (ret) { + debug("%s: Error while setting reset-GPIO (err = %d)\n", + dev->name, ret); + return ret; + } + + /* If FPGA already runs, don't initialize again */ + if (do_reflection_test(dev)) + goto reflection_ok; + + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) { + debug("%s: Error while setting reset-GPIO (err = %d)\n", + dev->name, ret); + return ret; + } + + ret = wait_for_fpga_done(dev); + if (ret) { + debug("%s: Error while waiting for FPGA done (err = %d)\n", + dev->name, ret); + return ret; + } + + udelay(10); + + ret = dm_gpio_set_value(&priv->reset_gpio, 1); + if (ret) { + debug("%s: Error while setting reset-GPIO (err = %d)\n", + dev->name, ret); + return ret; + } + + if (!do_reflection_test(dev)) { + debug("%s: Reflection test FAILED\n", dev->name); + return -EIO; + } + +reflection_ok: + printf("%s: Reflection test passed.\n", dev->name); + + fpga_print_info(dev); + + return 0; +} + +static const struct udevice_id ihs_fpga_ids[] = { + { .compatible = "gdsys,iocon_fpga" }, + { .compatible = "gdsys,iocpu_fpga" }, + { } +}; + +U_BOOT_DRIVER(ihs_fpga_bus) = { + .name = "ihs_fpga_bus", + .id = UCLASS_MISC, + .of_match = ihs_fpga_ids, + .probe = ihs_fpga_probe, + .priv_auto_alloc_size = sizeof(struct ihs_fpga_priv), +}; diff --git a/drivers/misc/ihs_fpga.h b/drivers/misc/ihs_fpga.h new file mode 100644 index 0000000000..efb5dabb9c --- /dev/null +++ b/drivers/misc/ihs_fpga.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +/** + * struct ihs_fpga_regs - IHS FPGA register map structure + * @reflection_low: Lower reflection register + * @versions: PCB versions register + * @fpga_version: FPGA versions register + * @features: FPGA features register + * @extended_features: FPGA extended features register + * @top_interrupt: Top interrupt register + * @top_interrupt_enable: Top interrupt enable register + * @status: FPGA status register + * @control: FPGA control register + * @extended_control: FPGA extended control register + */ +struct ihs_fpga_regs { + u16 reflection_low; + u16 versions; + u16 fpga_version; + u16 features; + u16 extended_features; + u16 top_interrupt; + u16 top_interrupt_enable; + u16 status; + u16 control; + u16 extended_control; +}; + +/** + * ihs_fpga_set() - Convenience macro to set values in FPGA register map + * @map: Register map to set a value in + * @member: Name of member (described by ihs_fpga_regs) to set + * @val: Value to set the member to + */ +#define ihs_fpga_set(map, member, val) \ + regmap_set(map, struct ihs_fpga_regs, member, val) + +/** + * ihs_fpga_get() - Convenience macro to get values from FPGA register map + * @map: Register map to read value from + * @member: Name of member (described by ihs_fpga_regs) to get + * @valp: Pointe to variable to receive the value read + */ +#define ihs_fpga_get(map, member, valp) \ + regmap_get(map, struct ihs_fpga_regs, member, valp)