From patchwork Tue Nov 5 11:46:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Jacques Hiblot X-Patchwork-Id: 1189615 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) 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=fail (p=quarantine dis=none) header.from=ti.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ti.com header.i=@ti.com header.b="kbiWBbx0"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 476nw64tTDz9sNT for ; Tue, 5 Nov 2019 22:47:34 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 52805C21E62; Tue, 5 Nov 2019 11:47: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=T_DKIM_INVALID 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 2A689C21C51; Tue, 5 Nov 2019 11:47:18 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 972AFC21C51; Tue, 5 Nov 2019 11:47:16 +0000 (UTC) Received: from lelv0143.ext.ti.com (lelv0143.ext.ti.com [198.47.23.248]) by lists.denx.de (Postfix) with ESMTPS id 09D95C21BE5 for ; Tue, 5 Nov 2019 11:47:15 +0000 (UTC) Received: from lelv0265.itg.ti.com ([10.180.67.224]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id xA5Bl6Ne004967; Tue, 5 Nov 2019 05:47:06 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1572954426; bh=S4OlNpOgtTvMcCU9f+vAJ+WUAvAVGigPkme4yPGDDzc=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=kbiWBbx03Alm1YARw5oA86HohApAS2mcAIaauqIJdhD52nFtRDnhykIjcidWhNVzt CNCHetN8cuiHubpimT1WmbiNlMdTZ+KHySbg5ZFL6y2rbVpN8JscDbuKbK2K14s+nd XTCy0djnB0ZUKPP8sbl99bYVBHIcOokvYLbCouDs= Received: from DLEE103.ent.ti.com (dlee103.ent.ti.com [157.170.170.33]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id xA5Bl61d088373 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 5 Nov 2019 05:47:06 -0600 Received: from DLEE103.ent.ti.com (157.170.170.33) by DLEE103.ent.ti.com (157.170.170.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5; Tue, 5 Nov 2019 05:46:51 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DLEE103.ent.ti.com (157.170.170.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5 via Frontend Transport; Tue, 5 Nov 2019 05:46:51 -0600 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id xA5Bl5xq016928; Tue, 5 Nov 2019 05:47:05 -0600 From: Jean-Jacques Hiblot To: , Date: Tue, 5 Nov 2019 12:46:57 +0100 Message-ID: <20191105114700.24989-2-jjhiblot@ti.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191105114700.24989-1-jjhiblot@ti.com> References: <20191105114700.24989-1-jjhiblot@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Cc: u-boot@lists.denx.de Subject: [U-Boot] [PATCH v2 1/4] regmap: Add devm_regmap_init() 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Most of new linux drivers are using managed-API to allocate resources. To ease porting drivers from linux to U-Boot, introduce devm_regmap_init() as a managed API to get a regmap from the device tree. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- Changes in v2: - Fix comment for devm_regmap_init() - Fix spelling in commit log drivers/core/regmap.c | 26 ++++++++++++++++++++++++++ include/regmap.h | 18 ++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index e9e55c9d16..f69ff6d12f 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -219,6 +219,32 @@ int regmap_init_mem(ofnode node, struct regmap **mapp) return 0; } + +static void devm_regmap_release(struct udevice *dev, void *res) +{ + regmap_uninit(*(struct regmap **)res); +} + +struct regmap *devm_regmap_init(struct udevice *dev, + const struct regmap_bus *bus, + void *bus_context, + const struct regmap_config *config) +{ + int rc; + struct regmap **mapp; + + mapp = devres_alloc(devm_regmap_release, sizeof(struct regmap *), + __GFP_ZERO); + if (unlikely(!mapp)) + return ERR_PTR(-ENOMEM); + + rc = regmap_init_mem(dev_ofnode(dev), mapp); + if (rc) + return ERR_PTR(rc); + + devres_add(dev, mapp); + return *mapp; +} #endif void *regmap_get_range(struct regmap *map, unsigned int range_num) diff --git a/include/regmap.h b/include/regmap.h index 9ada1af5ef..624cdd8c98 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -73,6 +73,9 @@ struct regmap_range { ulong size; }; +struct regmap_bus; +struct regmap_config; + /** * struct regmap - a way of accessing hardware/bus registers * @@ -333,6 +336,21 @@ int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count, int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index); +/** + * devm_regmap_init() - Initialise register map (device managed) + * + * @dev: Device that will be interacted with + * @bus: Bus-specific callbacks to use with device (IGNORED) + * @bus_context: Data passed to bus-specific callbacks (IGNORED) + * @config: Configuration for register map (IGNORED) + * + * @Return a valid pointer to a struct regmap or a ERR_PTR() on error. + * The structure is automatically freed when the device is unbound + */ +struct regmap *devm_regmap_init(struct udevice *dev, + const struct regmap_bus *bus, + void *bus_context, + const struct regmap_config *config); /** * regmap_get_range() - Obtain the base memory address of a regmap range * From patchwork Tue Nov 5 11:46:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Jacques Hiblot X-Patchwork-Id: 1189616 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) 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=fail (p=quarantine dis=none) header.from=ti.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ti.com header.i=@ti.com header.b="nPJG7kVo"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 476nwj1zJ7z9sNT for ; Tue, 5 Nov 2019 22:48:05 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 0EB21C21E02; Tue, 5 Nov 2019 11:47:33 +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=T_DKIM_INVALID 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 BBDD3C21E1A; Tue, 5 Nov 2019 11:47:19 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 780B1C21BE5; Tue, 5 Nov 2019 11:47:17 +0000 (UTC) Received: from lelv0143.ext.ti.com (lelv0143.ext.ti.com [198.47.23.248]) by lists.denx.de (Postfix) with ESMTPS id EAB45C21BE5 for ; Tue, 5 Nov 2019 11:47:16 +0000 (UTC) Received: from lelv0266.itg.ti.com ([10.180.67.225]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id xA5Bl7O8004972; Tue, 5 Nov 2019 05:47:07 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1572954427; bh=A4IkX4c6pe8pNXhBeAXnHJhRxsOsz0XGN4U81KdrX/c=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=nPJG7kVopQXU/RJkFp2pilNmtl5xQ6Ca78a/D+s05oWEAa6K9EV3ysvRjdCkT+mUO 0b1KHs1npsOJBGLR/kaeFBEKrNTM9O2CpaqNqQyiTHpTE3UPzrPEVrLAVznrKUPTre a2egU+BAc70itFIuRlHKOHsPd7AnTLjxkmYrFoec= Received: from DLEE105.ent.ti.com (dlee105.ent.ti.com [157.170.170.35]) by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id xA5Bl77F005535 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 5 Nov 2019 05:47:07 -0600 Received: from DLEE105.ent.ti.com (157.170.170.35) by DLEE105.ent.ti.com (157.170.170.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5; Tue, 5 Nov 2019 05:46:52 -0600 Received: from lelv0326.itg.ti.com (10.180.67.84) by DLEE105.ent.ti.com (157.170.170.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5 via Frontend Transport; Tue, 5 Nov 2019 05:46:52 -0600 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0326.itg.ti.com (8.15.2/8.15.2) with ESMTP id xA5Bl6Xp066230; Tue, 5 Nov 2019 05:47:07 -0600 From: Jean-Jacques Hiblot To: , Date: Tue, 5 Nov 2019 12:46:58 +0100 Message-ID: <20191105114700.24989-3-jjhiblot@ti.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191105114700.24989-1-jjhiblot@ti.com> References: <20191105114700.24989-1-jjhiblot@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Cc: u-boot@lists.denx.de Subject: [U-Boot] [PATCH v2 2/4] regmap: Allow providing read/write callbacks through struct regmap_config 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Some linux drivers provide their own read/write functions to access data from/of the regmap. Adding support for it. Signed-off-by: Jean-Jacques Hiblot Signed-off-by: Pratyush Yadav --- Changes in v2: - Only use custom accessors if {,SPL,TPL}_REGMAP_ACCESSORS is enabled drivers/core/Kconfig | 25 +++++++++++++++++++++++++ drivers/core/regmap.c | 22 ++++++++++++++++++++-- include/regmap.h | 28 +++++++++++++++++++++++++--- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index 3b95b5387b..3d836a63bf 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -129,6 +129,31 @@ config TPL_REGMAP support any bus type (I2C, SPI) but so far this only supports direct memory access. +config REGMAP_ACCESSORS + bool + depends on REGMAP + default y + +config SPL_REGMAP_ACCESSORS + bool "Support custom regmap accessors in SPL" + depends on SPL_REGMAP + help + Allow to use a regmap with custom accessors. The acessors are the + low-level functions actually performing the read and write + operations. + This option can be used to access registers that are not + memory-mapped. + +config TPL_REGMAP_ACCESSORS + bool "Support custom regmap accessors in TPL" + depends on TPL_REGMAP + help + Allow to use a regmap with custom accessors. The acessors are the + low-level functions actually performing the read and write + operations. + This option can be used to access registers that are not + memory-mapped. + config SYSCON bool "Support system controllers" depends on REGMAP diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index f69ff6d12f..10ae9f918a 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -31,7 +31,11 @@ static struct regmap *regmap_alloc(int count) if (!map) return NULL; map->range_count = count; - +#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS) + map->bus_context = NULL; + map->reg_read = NULL; + map->reg_write = NULL; +#endif return map; } @@ -241,7 +245,11 @@ struct regmap *devm_regmap_init(struct udevice *dev, rc = regmap_init_mem(dev_ofnode(dev), mapp); if (rc) return ERR_PTR(rc); - +#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS) + (*mapp)->reg_read = config->reg_read; + (*mapp)->reg_write = config->reg_write; + (*mapp)->bus_context = bus_context; +#endif devres_add(dev, mapp); return *mapp; } @@ -320,6 +328,11 @@ int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset, struct regmap_range *range; void *ptr; +#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS) + if (map->reg_read) + return map->reg_read(map->bus_context, offset, valp); +#endif + if (range_num >= map->range_count) { debug("%s: range index %d larger than range count\n", __func__, range_num); @@ -429,6 +442,11 @@ int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset, struct regmap_range *range; void *ptr; +#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS) + if (map->reg_write) + return map->reg_write(map->bus_context, offset, + *(unsigned int *)val); +#endif if (range_num >= map->range_count) { debug("%s: range index %d larger than range count\n", __func__, range_num); diff --git a/include/regmap.h b/include/regmap.h index 624cdd8c98..730e747d90 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -74,16 +74,38 @@ struct regmap_range { }; struct regmap_bus; -struct regmap_config; +/** + * struct regmap_config - a way of accessing hardware/bus registers + * + * @reg_read: Optional callback that if filled will be used to perform + * all the reads from the registers. Should only be provided for + * devices whose read operation cannot be represented as a simple + * read operation on a bus such as SPI, I2C, etc. Most of the + * devices do not need this. + * @reg_write: Same as above for writing. + */ +struct regmap_config { + int (*reg_read)(void *context, unsigned int reg, unsigned int *val); + int (*reg_write)(void *context, unsigned int reg, unsigned int val); +}; /** * struct regmap - a way of accessing hardware/bus registers * * @range_count: Number of ranges available within the map * @ranges: Array of ranges + * @bus_context: Data passed to bus-specific callbacks + * @reg_read: Optional callback that if filled will be used to perform + * all the reads from the registers. + * @reg_write: Same as above for writing. */ struct regmap { enum regmap_endianness_t endianness; +#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS) + void *bus_context; + int (*reg_read)(void *context, unsigned int reg, unsigned int *val); + int (*reg_write)(void *context, unsigned int reg, unsigned int val); +#endif int range_count; struct regmap_range ranges[0]; }; @@ -341,8 +363,8 @@ int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index); * * @dev: Device that will be interacted with * @bus: Bus-specific callbacks to use with device (IGNORED) - * @bus_context: Data passed to bus-specific callbacks (IGNORED) - * @config: Configuration for register map (IGNORED) + * @bus_context: Data passed to bus-specific callbacks + * @config: Configuration for register map * * @Return a valid pointer to a struct regmap or a ERR_PTR() on error. * The structure is automatically freed when the device is unbound From patchwork Tue Nov 5 11:46:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Jacques Hiblot X-Patchwork-Id: 1189618 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) 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=fail (p=quarantine dis=none) header.from=ti.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ti.com header.i=@ti.com header.b="Y+ir+Uaf"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 476nxm3xG6z9sPF for ; Tue, 5 Nov 2019 22:49:00 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 2593FC21E44; Tue, 5 Nov 2019 11:48:11 +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=T_DKIM_INVALID 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 C7496C21E29; Tue, 5 Nov 2019 11:48:03 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 97C48C21BE5; Tue, 5 Nov 2019 11:47:24 +0000 (UTC) Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141]) by lists.denx.de (Postfix) with ESMTPS id 91ACFC21E44 for ; Tue, 5 Nov 2019 11:47:20 +0000 (UTC) Received: from lelv0265.itg.ti.com ([10.180.67.224]) by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id xA5Bl90C037208; Tue, 5 Nov 2019 05:47:09 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1572954429; bh=PHv9vhZcsAd37d3BVo5ap9SCfzOzWmLZbvxwl+Zft5Q=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=Y+ir+UafH3FiGJOaO5X82PlwT8evoFaOlVRXpti7OwO2g5y6Xu6eJVasiefCdx5+d qI31O9ZsBT28SinOEs95unTZmys4shNgYWKImqZDoR6wTq1PCfp39MpBMhOTOL4P0G CfxiIbnUGyENzNlNDjbg8BCKZgx0D+6Wgxi59+24= Received: from DFLE109.ent.ti.com (dfle109.ent.ti.com [10.64.6.30]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id xA5Bl9Mu088424 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 5 Nov 2019 05:47:09 -0600 Received: from DFLE102.ent.ti.com (10.64.6.23) by DFLE109.ent.ti.com (10.64.6.30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5; Tue, 5 Nov 2019 05:46:54 -0600 Received: from lelv0326.itg.ti.com (10.180.67.84) by DFLE102.ent.ti.com (10.64.6.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Tue, 5 Nov 2019 05:46:54 -0600 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0326.itg.ti.com (8.15.2/8.15.2) with ESMTP id xA5Bl7Bp066256; Tue, 5 Nov 2019 05:47:08 -0600 From: Jean-Jacques Hiblot To: , Date: Tue, 5 Nov 2019 12:46:59 +0100 Message-ID: <20191105114700.24989-4-jjhiblot@ti.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191105114700.24989-1-jjhiblot@ti.com> References: <20191105114700.24989-1-jjhiblot@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Cc: u-boot@lists.denx.de Subject: [U-Boot] [PATCH v2 3/4] regmap: Add support for regmap fields 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" A regmap field is an abstraction available in Linux. It provides to access bitfields in a regmap without having to worry about shifts and masks. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- Changes in v2: None drivers/core/regmap.c | 77 ++++++++++++++++++++++++++++++ include/regmap.h | 108 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+) diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index 10ae9f918a..905bc0b63d 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -15,6 +15,14 @@ #include #include +struct regmap_field { + struct regmap *regmap; + unsigned int mask; + /* lsb */ + unsigned int shift; + unsigned int reg; +}; + DECLARE_GLOBAL_DATA_PTR; /** @@ -508,3 +516,72 @@ int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val) return regmap_write(map, offset, reg | (val & mask)); } + +int regmap_field_read(struct regmap_field *field, unsigned int *val) +{ + int ret; + unsigned int reg_val; + + ret = regmap_read(field->regmap, field->reg, ®_val); + if (ret != 0) + return ret; + + reg_val &= field->mask; + reg_val >>= field->shift; + *val = reg_val; + + return ret; +} + +int regmap_field_write(struct regmap_field *field, unsigned int val) +{ + return regmap_update_bits(field->regmap, field->reg, field->mask, + val << field->shift); +} + +static void regmap_field_init(struct regmap_field *rm_field, + struct regmap *regmap, + struct reg_field reg_field) +{ + rm_field->regmap = regmap; + rm_field->reg = reg_field.reg; + rm_field->shift = reg_field.lsb; + rm_field->mask = GENMASK(reg_field.msb, reg_field.lsb); +} + +struct regmap_field *devm_regmap_field_alloc(struct udevice *dev, + struct regmap *regmap, + struct reg_field reg_field) +{ + struct regmap_field *rm_field = devm_kzalloc(dev, sizeof(*rm_field), + GFP_KERNEL); + if (!rm_field) + return ERR_PTR(-ENOMEM); + + regmap_field_init(rm_field, regmap, reg_field); + + return rm_field; +} + +void devm_regmap_field_free(struct udevice *dev, struct regmap_field *field) +{ + devm_kfree(dev, field); +} + +struct regmap_field *regmap_field_alloc(struct regmap *regmap, + struct reg_field reg_field) +{ + struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL); + + if (!rm_field) + return ERR_PTR(-ENOMEM); + + regmap_field_init(rm_field, regmap, reg_field); + + return rm_field; +} + +void regmap_field_free(struct regmap_field *field) +{ + kfree(field); +} diff --git a/include/regmap.h b/include/regmap.h index 730e747d90..8619566a95 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -314,6 +314,43 @@ int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset, regmap_read_poll_timeout_test(map, addr, val, cond, sleep_us, \ timeout_ms, 0) \ +/** + * regmap_field_read_poll_timeout - Poll until a condition is met or a timeout + * occurs + * + * @field: Regmap field to read from + * @val: Unsigned integer variable to read the value into + * @cond: Break condition (usually involving @val) + * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). + * @timeout_ms: Timeout in ms, 0 means never timeout + * + * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_field_read + * error return value in case of a error read. In the two former cases, + * the last read value at @addr is stored in @val. + * + * This is modelled after the regmap_read_poll_timeout macros in linux but + * with millisecond timeout. + */ +#define regmap_field_read_poll_timeout(field, val, cond, sleep_us, timeout_ms) \ +({ \ + unsigned long __start = get_timer(0); \ + int __ret; \ + for (;;) { \ + __ret = regmap_field_read((field), &(val)); \ + if (__ret) \ + break; \ + if (cond) \ + break; \ + if ((timeout_ms) && get_timer(__start) > (timeout_ms)) { \ + __ret = regmap_field_read((field), &(val)); \ + break; \ + } \ + if ((sleep_us)) \ + udelay((sleep_us)); \ + } \ + __ret ?: ((cond) ? 0 : -ETIMEDOUT); \ +}) + /** * regmap_update_bits() - Perform a read/modify/write using a mask * @@ -390,4 +427,75 @@ void *regmap_get_range(struct regmap *map, unsigned int range_num); */ int regmap_uninit(struct regmap *map); +/** + * struct reg_field - Description of an register field + * + * @reg: Offset of the register within the regmap bank + * @lsb: lsb of the register field. + * @msb: msb of the register field. + * @id_size: port size if it has some ports + * @id_offset: address offset for each ports + */ +struct reg_field { + unsigned int reg; + unsigned int lsb; + unsigned int msb; +}; + +struct regmap_field; + +#define REG_FIELD(_reg, _lsb, _msb) { \ + .reg = _reg, \ + .lsb = _lsb, \ + .msb = _msb, \ + } + +/** + * devm_regmap_field_alloc() - Allocate and initialise a register field. + * + * @dev: Device that will be interacted with + * @regmap: regmap bank in which this register field is located. + * @reg_field: Register field with in the bank. + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap_field. The regmap_field will be automatically freed + * by the device management code. + */ +struct regmap_field *devm_regmap_field_alloc(struct udevice *dev, + struct regmap *regmap, + struct reg_field reg_field); +/** + * devm_regmap_field_free() - Free a register field allocated using + * devm_regmap_field_alloc. + * + * @dev: Device that will be interacted with + * @field: regmap field which should be freed. + * + * Free register field allocated using devm_regmap_field_alloc(). Usually + * drivers need not call this function, as the memory allocated via devm + * will be freed as per device-driver life-cyle. + */ +void devm_regmap_field_free(struct udevice *dev, struct regmap_field *field); + +/** + * regmap_field_write() - Write a value to a regmap field + * + * @field: Regmap field to write to + * @val: Data to write to the regmap at the specified offset + * + * Return: 0 if OK, -ve on error + */ +int regmap_field_write(struct regmap_field *field, unsigned int val); + +/** + * regmap_read() - Read a 32-bit value from a regmap + * + * @field: Regmap field to write to + * @valp: Pointer to the buffer to receive the data read from the regmap + * field + * + * Return: 0 if OK, -ve on error + */ +int regmap_field_read(struct regmap_field *field, unsigned int *val); + #endif From patchwork Tue Nov 5 11:47:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Jacques Hiblot X-Patchwork-Id: 1189619 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) 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=fail (p=quarantine dis=none) header.from=ti.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ti.com header.i=@ti.com header.b="dRsqrKbY"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 476nyD5f5qz9sNT for ; Tue, 5 Nov 2019 22:49:24 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 1D5BDC21C51; Tue, 5 Nov 2019 11:47:55 +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=T_DKIM_INVALID 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 D147EC21DFD; Tue, 5 Nov 2019 11:47:20 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 65797C21DD4; Tue, 5 Nov 2019 11:47:18 +0000 (UTC) Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141]) by lists.denx.de (Postfix) with ESMTPS id A615BC21D56 for ; Tue, 5 Nov 2019 11:47:17 +0000 (UTC) Received: from fllv0034.itg.ti.com ([10.64.40.246]) by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id xA5BlA5L037213; Tue, 5 Nov 2019 05:47:10 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1572954430; bh=enm5kMEVQAFx1p5qNQ1CbV8oVVh1qDZCxS887TePFjI=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=dRsqrKbYNw3l/EYlAgGB/apqwKCvhYYi0PO1/301+CptWLn+3rV0loPWiYTH2a1kE +v6eHT6lm6Tc+Ov2TABOVh+kEvyqUpjKFMiuK+06LG0+nkfrhaL4WXKWYwieZy5Fkl Fn0VKE7WsH6uO6RDpQpewM2efcjq8nKtIhnByHis= Received: from DLEE103.ent.ti.com (dlee103.ent.ti.com [157.170.170.33]) by fllv0034.itg.ti.com (8.15.2/8.15.2) with ESMTPS id xA5BlA7M014561 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 5 Nov 2019 05:47:10 -0600 Received: from DLEE106.ent.ti.com (157.170.170.36) by DLEE103.ent.ti.com (157.170.170.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5; Tue, 5 Nov 2019 05:46:55 -0600 Received: from fllv0040.itg.ti.com (10.64.41.20) by DLEE106.ent.ti.com (157.170.170.36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5 via Frontend Transport; Tue, 5 Nov 2019 05:47:10 -0600 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by fllv0040.itg.ti.com (8.15.2/8.15.2) with ESMTP id xA5Bl9fW102088; Tue, 5 Nov 2019 05:47:09 -0600 From: Jean-Jacques Hiblot To: , Date: Tue, 5 Nov 2019 12:47:00 +0100 Message-ID: <20191105114700.24989-5-jjhiblot@ti.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191105114700.24989-1-jjhiblot@ti.com> References: <20191105114700.24989-1-jjhiblot@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Cc: u-boot@lists.denx.de Subject: [U-Boot] [PATCH v2 4/4] test: dm: Add tests for regmap managed API and regmap fields 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The tests rely on a dummy driver to allocate and initialize the regmap and the regmap fields using the managed API. The first test checks that the read/write callbacks are used. The second test checks if regmap fields behave properly (mask and shift are ok) by peeking into the regmap. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- Changes in v2: None arch/sandbox/dts/test.dts | 13 +++ test/dm/regmap.c | 189 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index fdb08f2111..aa9eaec338 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -889,6 +889,19 @@ mdio: mdio-test { compatible = "sandbox,mdio"; }; + + some_regmapped-bus { + #address-cells = <0x1>; + #size-cells = <0x1>; + + ranges = <0x0 0x0 0x10>; + compatible = "simple-bus"; + + regmap-test_0 { + reg = <0 0x10>; + compatible = "sandbox,regmap_test"; + }; + }; }; #include "sandbox_pmic.dtsi" diff --git a/test/dm/regmap.c b/test/dm/regmap.c index 6fd1f20656..1a0dc78019 100644 --- a/test/dm/regmap.c +++ b/test/dm/regmap.c @@ -184,3 +184,192 @@ static int dm_test_regmap_poll(struct unit_test_state *uts) } DM_TEST(dm_test_regmap_poll, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +struct regmaptest_priv { + struct regmap *regmap; + struct regmap_field **fields; +}; + +#define REGMAP_TEST_BUF_SZ 12 +struct regmaptest_context { + unsigned short buffer[REGMAP_TEST_BUF_SZ]; +} ctx; + +static int regmaptest_write(void *context, unsigned int reg, unsigned int val) +{ + struct regmaptest_context *ctx = context; + + if (reg < ARRAY_SIZE(ctx->buffer)) { + ctx->buffer[reg] = val; + return 0; + } + return -ERANGE; +} + +static int regmaptest_read(void *context, unsigned int reg, unsigned int *val) +{ + struct regmaptest_context *ctx = context; + + if (reg < ARRAY_SIZE(ctx->buffer)) { + *val = ctx->buffer[reg]; + return 0; + } + + return -ERANGE; +} + +static struct regmap_config cfg = { + .reg_write = regmaptest_write, + .reg_read = regmaptest_read, +}; + +static const struct reg_field field_cfgs[] = { + { + .reg = 0, + .lsb = 0, + .msb = 6, + }, + { + .reg = 1, + .lsb = 4, + .msb = 12, + }, + { + .reg = 1, + .lsb = 12, + .msb = 15, + } +}; + +static int remaptest_probe(struct udevice *dev) +{ + struct regmaptest_priv *priv = dev_get_priv(dev); + struct regmap *regmap; + struct regmap_field *field; + int i; + static const int n = ARRAY_SIZE(field_cfgs); + + regmap = devm_regmap_init(dev, NULL, &ctx, &cfg); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + priv->regmap = regmap; + + priv->fields = devm_kzalloc(dev, sizeof(struct regmap_field *) * n, + GFP_KERNEL); + if (!priv->fields) + return -ENOMEM; + + for (i = 0 ; i < n; i++) { + field = devm_regmap_field_alloc(dev, regmap, field_cfgs[i]); + if (IS_ERR(field)) + return PTR_ERR(field); + priv->fields[i] = field; + } + return 0; +} + +static const struct udevice_id regmaptest_ids[] = { + { .compatible = "sandbox,regmap_test" }, + { } +}; + +U_BOOT_DRIVER(regmap_test) = { + .name = "regmaptest_drv", + .of_match = regmaptest_ids, + .id = UCLASS_NOP, + .probe = remaptest_probe, + .priv_auto_alloc_size = sizeof(struct regmaptest_priv), +}; + +static int dm_test_devm_regmap(struct unit_test_state *uts) +{ + int i = 0; + u32 val; + u16 pattern[REGMAP_TEST_BUF_SZ]; + struct udevice *dev; + struct regmaptest_priv *priv; + + ut_assertok(uclass_get_device_by_name(UCLASS_NOP, "regmap-test_0", + &dev)); + + priv = dev_get_priv(dev); + + srand(get_ticks() + rand()); + for (i = REGMAP_TEST_BUF_SZ - 1; i >= 0; i--) { + pattern[i] = rand() & 0xFFFF; + ut_assertok(regmap_write(priv->regmap, i, pattern[i])); + } + for (i = 0; i < REGMAP_TEST_BUF_SZ; i++) { + ut_assertok(regmap_read(priv->regmap, i, &val)); + ut_asserteq(val, ctx.buffer[i]); + ut_asserteq(val, pattern[i]); + } + + ut_asserteq(-ERANGE, regmap_write(priv->regmap, REGMAP_TEST_BUF_SZ, + val)); + ut_asserteq(-ERANGE, regmap_read(priv->regmap, REGMAP_TEST_BUF_SZ, + &val)); + ut_asserteq(-ERANGE, regmap_write(priv->regmap, -1, val)); + ut_asserteq(-ERANGE, regmap_read(priv->regmap, -1, &val)); + + return 0; +} +DM_TEST(dm_test_devm_regmap, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +static int test_one_field(struct unit_test_state *uts, + struct regmap *regmap, + struct regmap_field *field, + struct reg_field field_cfg) +{ + int j; + unsigned int val; + int mask = (1 << (field_cfg.msb - field_cfg.lsb + 1)) - 1; + int shift = field_cfg.lsb; + + ut_assertok(regmap_write(regmap, field_cfg.reg, 0)); + ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); + ut_asserteq(0, val); + + for (j = 0; j <= mask; j++) { + ut_assertok(regmap_field_write(field, j)); + ut_assertok(regmap_field_read(field, &val)); + ut_asserteq(j, val); + ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); + ut_asserteq(j << shift, val); + } + + ut_assertok(regmap_field_write(field, mask + 1)); + ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); + ut_asserteq(0, val); + + ut_assertok(regmap_field_write(field, 0xFFFF)); + ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); + ut_asserteq(mask << shift, val); + + ut_assertok(regmap_write(regmap, field_cfg.reg, 0xFFFF)); + ut_assertok(regmap_field_write(field, 0)); + ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); + ut_asserteq(0xFFFF & ~(mask << shift), val); + return 0; +} + +static int dm_test_devm_regmap_field(struct unit_test_state *uts) +{ + int i, rc; + struct udevice *dev; + struct regmaptest_priv *priv; + + ut_assertok(uclass_get_device_by_name(UCLASS_NOP, "regmap-test_0", + &dev)); + priv = dev_get_priv(dev); + + for (i = 0 ; i < ARRAY_SIZE(field_cfgs); i++) { + rc = test_one_field(uts, priv->regmap, priv->fields[i], + field_cfgs[i]); + if (rc) + break; + } + + return 0; +} +DM_TEST(dm_test_devm_regmap_field, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);