From afcc00b91f1865f6d0bbdb687dd642ce8a3c3c9e Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Thu, 3 Dec 2015 17:31:52 +0800 Subject: regmap: add 64-bit mode support Since the mmio has support the 64-bit has been supported for the 64-bit platform, so should the regmap core too. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 99 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) (limited to 'drivers/base/regmap/regmap.c') diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 4ac63c0e50c7..1791180dca02 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -245,6 +245,28 @@ static void regmap_format_32_native(void *buf, unsigned int val, *(u32 *)buf = val << shift; } +#ifdef CONFIG_64BIT +static void regmap_format_64_be(void *buf, unsigned int val, unsigned int shift) +{ + __be64 *b = buf; + + b[0] = cpu_to_be64(val << shift); +} + +static void regmap_format_64_le(void *buf, unsigned int val, unsigned int shift) +{ + __le64 *b = buf; + + b[0] = cpu_to_le64(val << shift); +} + +static void regmap_format_64_native(void *buf, unsigned int val, + unsigned int shift) +{ + *(u64 *)buf = val << shift; +} +#endif + static void regmap_parse_inplace_noop(void *buf) { } @@ -332,6 +354,41 @@ static unsigned int regmap_parse_32_native(const void *buf) return *(u32 *)buf; } +#ifdef CONFIG_64BIT +static unsigned int regmap_parse_64_be(const void *buf) +{ + const __be64 *b = buf; + + return be64_to_cpu(b[0]); +} + +static unsigned int regmap_parse_64_le(const void *buf) +{ + const __le64 *b = buf; + + return le64_to_cpu(b[0]); +} + +static void regmap_parse_64_be_inplace(void *buf) +{ + __be64 *b = buf; + + b[0] = be64_to_cpu(b[0]); +} + +static void regmap_parse_64_le_inplace(void *buf) +{ + __le64 *b = buf; + + b[0] = le64_to_cpu(b[0]); +} + +static unsigned int regmap_parse_64_native(const void *buf) +{ + return *(u64 *)buf; +} +#endif + static void regmap_lock_mutex(void *__map) { struct regmap *map = __map; @@ -712,6 +769,21 @@ struct regmap *__regmap_init(struct device *dev, } break; +#ifdef CONFIG_64BIT + case 64: + switch (reg_endian) { + case REGMAP_ENDIAN_BIG: + map->format.format_reg = regmap_format_64_be; + break; + case REGMAP_ENDIAN_NATIVE: + map->format.format_reg = regmap_format_64_native; + break; + default: + goto err_map; + } + break; +#endif + default: goto err_map; } @@ -771,6 +843,27 @@ struct regmap *__regmap_init(struct device *dev, goto err_map; } break; +#ifdef CONFIG_64BIT + switch (val_endian) { + case REGMAP_ENDIAN_BIG: + map->format.format_val = regmap_format_64_be; + map->format.parse_val = regmap_parse_64_be; + map->format.parse_inplace = regmap_parse_64_be_inplace; + break; + case REGMAP_ENDIAN_LITTLE: + map->format.format_val = regmap_format_64_le; + map->format.parse_val = regmap_parse_64_le; + map->format.parse_inplace = regmap_parse_64_le_inplace; + break; + case REGMAP_ENDIAN_NATIVE: + map->format.format_val = regmap_format_64_native; + map->format.parse_val = regmap_parse_64_native; + break; + default: + goto err_map; + } + break; +#endif } if (map->format.format_write) { @@ -2488,11 +2581,17 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, * we assume that the values are native * endian. */ + u64 *u64 = val; u32 *u32 = val; u16 *u16 = val; u8 *u8 = val; switch (map->format.val_bytes) { +#ifdef CONFIG_64BIT + case 8: + u64[i] = ival; + break; +#endif case 4: u32[i] = ival; break; -- cgit v1.2.3 From 19c04788f0e0ef778df39cdeaf8e9889d3020894 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Wed, 9 Dec 2015 17:11:53 +0800 Subject: regmap: fix the warning about unused variable The variable 'u64 *u64' should be only visible on 64-BIT platform. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/base/regmap/regmap.c') diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 1791180dca02..a0d30a0fd8cf 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -2581,7 +2581,9 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, * we assume that the values are native * endian. */ +#ifdef CONFIG_64BIT u64 *u64 = val; +#endif u32 *u32 = val; u16 *u16 = val; u8 *u8 = val; -- cgit v1.2.3 From 01c377bfe21a1050fd7cfd33699f7d8049dc2723 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 12 Dec 2015 15:59:14 +0300 Subject: regmap: shift wrapping bugs in 64 bit code We should cast these to 64bit so that we don't truncate away the high bits. Fixes: afcc00b91f18 ('regmap: add 64-bit mode support') Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/base/regmap/regmap.c') diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index a0d30a0fd8cf..9c167e73fdcd 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -250,20 +250,20 @@ static void regmap_format_64_be(void *buf, unsigned int val, unsigned int shift) { __be64 *b = buf; - b[0] = cpu_to_be64(val << shift); + b[0] = cpu_to_be64((u64)val << shift); } static void regmap_format_64_le(void *buf, unsigned int val, unsigned int shift) { __le64 *b = buf; - b[0] = cpu_to_le64(val << shift); + b[0] = cpu_to_le64((u64)val << shift); } static void regmap_format_64_native(void *buf, unsigned int val, unsigned int shift) { - *(u64 *)buf = val << shift; + *(u64 *)buf = (u64)val << shift; } #endif -- cgit v1.2.3 From 782035ea94dc4028c19e9f39857ce9756119ae94 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 12 Dec 2015 15:59:43 +0300 Subject: regmap: missing case statement This new code is unreachable. Presumably there was supposed to be a case statement there similar to the earlier code. Fixes: afcc00b91f18 ('regmap: add 64-bit mode support') Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/base/regmap/regmap.c') diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 9c167e73fdcd..d27fe2f0182e 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -844,6 +844,7 @@ struct regmap *__regmap_init(struct device *dev, } break; #ifdef CONFIG_64BIT + case 64: switch (val_endian) { case REGMAP_ENDIAN_BIG: map->format.format_val = regmap_format_64_be; -- cgit v1.2.3