diff options
author | Mark Brown <broonie@kernel.org> | 2016-02-21 22:02:02 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-02-21 22:02:02 -0500 |
commit | 99777b07efe3b533b4b6c67e59ad9138607c0467 (patch) | |
tree | ea3c53dfa6031d7c514670d860d36b4edb7a53a6 | |
parent | 56e5fd8feb286ab71f4ca7674505b0d17967376d (diff) | |
parent | aacaaa4c8e1cd3b813a3b77c9855e53d96381f40 (diff) |
Merge branch 'topic/mmio' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap into asoc-fsl-ssl
-rw-r--r-- | Documentation/devicetree/bindings/regmap/regmap.txt | 11 | ||||
-rw-r--r-- | arch/mips/boot/dts/brcm/bcm6328.dtsi | 2 | ||||
-rw-r--r-- | arch/mips/boot/dts/brcm/bcm6368.dtsi | 2 | ||||
-rw-r--r-- | arch/mips/boot/dts/brcm/bcm7125.dtsi | 2 | ||||
-rw-r--r-- | arch/mips/boot/dts/brcm/bcm7346.dtsi | 2 | ||||
-rw-r--r-- | arch/mips/boot/dts/brcm/bcm7358.dtsi | 2 | ||||
-rw-r--r-- | arch/mips/boot/dts/brcm/bcm7360.dtsi | 2 | ||||
-rw-r--r-- | arch/mips/boot/dts/brcm/bcm7362.dtsi | 2 | ||||
-rw-r--r-- | arch/mips/boot/dts/brcm/bcm7420.dtsi | 2 | ||||
-rw-r--r-- | arch/mips/boot/dts/brcm/bcm7425.dtsi | 2 | ||||
-rw-r--r-- | arch/mips/boot/dts/brcm/bcm7435.dtsi | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regcache.c | 41 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-mmio.c | 259 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 5 |
14 files changed, 191 insertions, 145 deletions
diff --git a/Documentation/devicetree/bindings/regmap/regmap.txt b/Documentation/devicetree/bindings/regmap/regmap.txt index b494f8b8ef72..e98a9652ccc8 100644 --- a/Documentation/devicetree/bindings/regmap/regmap.txt +++ b/Documentation/devicetree/bindings/regmap/regmap.txt | |||
@@ -5,15 +5,18 @@ Index Device Endianness properties | |||
5 | --------------------------------------------------- | 5 | --------------------------------------------------- |
6 | 1 BE 'big-endian' | 6 | 1 BE 'big-endian' |
7 | 2 LE 'little-endian' | 7 | 2 LE 'little-endian' |
8 | 3 Native 'native-endian' | ||
8 | 9 | ||
9 | For one device driver, which will run in different scenarios above | 10 | For one device driver, which will run in different scenarios above |
10 | on different SoCs using the devicetree, we need one way to simplify | 11 | on different SoCs using the devicetree, we need one way to simplify |
11 | this. | 12 | this. |
12 | 13 | ||
13 | Required properties: | 14 | Optional properties: |
14 | - {big,little}-endian: these are boolean properties, if absent | 15 | - {big,little,native}-endian: these are boolean properties, if absent |
15 | meaning that the CPU and the Device are in the same endianness mode, | 16 | then the implementation will choose a default based on the device |
16 | these properties are for register values and all the buffers only. | 17 | being controlled. These properties are for register values and all |
18 | the buffers only. Native endian means that the CPU and device have | ||
19 | the same endianness. | ||
17 | 20 | ||
18 | Examples: | 21 | Examples: |
19 | Scenario 1 : CPU in LE mode & device in LE mode. | 22 | Scenario 1 : CPU in LE mode & device in LE mode. |
diff --git a/arch/mips/boot/dts/brcm/bcm6328.dtsi b/arch/mips/boot/dts/brcm/bcm6328.dtsi index d61b1616b604..9d19236f53e7 100644 --- a/arch/mips/boot/dts/brcm/bcm6328.dtsi +++ b/arch/mips/boot/dts/brcm/bcm6328.dtsi | |||
@@ -74,7 +74,7 @@ | |||
74 | timer: timer@10000040 { | 74 | timer: timer@10000040 { |
75 | compatible = "syscon"; | 75 | compatible = "syscon"; |
76 | reg = <0x10000040 0x2c>; | 76 | reg = <0x10000040 0x2c>; |
77 | little-endian; | 77 | native-endian; |
78 | }; | 78 | }; |
79 | 79 | ||
80 | reboot { | 80 | reboot { |
diff --git a/arch/mips/boot/dts/brcm/bcm6368.dtsi b/arch/mips/boot/dts/brcm/bcm6368.dtsi index 9c8d3fe28b31..1f6b9b5cddb4 100644 --- a/arch/mips/boot/dts/brcm/bcm6368.dtsi +++ b/arch/mips/boot/dts/brcm/bcm6368.dtsi | |||
@@ -54,7 +54,7 @@ | |||
54 | periph_cntl: syscon@10000000 { | 54 | periph_cntl: syscon@10000000 { |
55 | compatible = "syscon"; | 55 | compatible = "syscon"; |
56 | reg = <0x10000000 0x14>; | 56 | reg = <0x10000000 0x14>; |
57 | little-endian; | 57 | native-endian; |
58 | }; | 58 | }; |
59 | 59 | ||
60 | reboot: syscon-reboot@10000008 { | 60 | reboot: syscon-reboot@10000008 { |
diff --git a/arch/mips/boot/dts/brcm/bcm7125.dtsi b/arch/mips/boot/dts/brcm/bcm7125.dtsi index 1a7efa883c5e..3ae16053a0c9 100644 --- a/arch/mips/boot/dts/brcm/bcm7125.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7125.dtsi | |||
@@ -98,7 +98,7 @@ | |||
98 | sun_top_ctrl: syscon@404000 { | 98 | sun_top_ctrl: syscon@404000 { |
99 | compatible = "brcm,bcm7125-sun-top-ctrl", "syscon"; | 99 | compatible = "brcm,bcm7125-sun-top-ctrl", "syscon"; |
100 | reg = <0x404000 0x60c>; | 100 | reg = <0x404000 0x60c>; |
101 | little-endian; | 101 | native-endian; |
102 | }; | 102 | }; |
103 | 103 | ||
104 | reboot { | 104 | reboot { |
diff --git a/arch/mips/boot/dts/brcm/bcm7346.dtsi b/arch/mips/boot/dts/brcm/bcm7346.dtsi index d4bf52cfcf17..be7991917d29 100644 --- a/arch/mips/boot/dts/brcm/bcm7346.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7346.dtsi | |||
@@ -118,7 +118,7 @@ | |||
118 | sun_top_ctrl: syscon@404000 { | 118 | sun_top_ctrl: syscon@404000 { |
119 | compatible = "brcm,bcm7346-sun-top-ctrl", "syscon"; | 119 | compatible = "brcm,bcm7346-sun-top-ctrl", "syscon"; |
120 | reg = <0x404000 0x51c>; | 120 | reg = <0x404000 0x51c>; |
121 | little-endian; | 121 | native-endian; |
122 | }; | 122 | }; |
123 | 123 | ||
124 | reboot { | 124 | reboot { |
diff --git a/arch/mips/boot/dts/brcm/bcm7358.dtsi b/arch/mips/boot/dts/brcm/bcm7358.dtsi index 8e2501694d03..060805be619a 100644 --- a/arch/mips/boot/dts/brcm/bcm7358.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7358.dtsi | |||
@@ -112,7 +112,7 @@ | |||
112 | sun_top_ctrl: syscon@404000 { | 112 | sun_top_ctrl: syscon@404000 { |
113 | compatible = "brcm,bcm7358-sun-top-ctrl", "syscon"; | 113 | compatible = "brcm,bcm7358-sun-top-ctrl", "syscon"; |
114 | reg = <0x404000 0x51c>; | 114 | reg = <0x404000 0x51c>; |
115 | little-endian; | 115 | native-endian; |
116 | }; | 116 | }; |
117 | 117 | ||
118 | reboot { | 118 | reboot { |
diff --git a/arch/mips/boot/dts/brcm/bcm7360.dtsi b/arch/mips/boot/dts/brcm/bcm7360.dtsi index 7e5f76040fb8..bcdb09bfe07b 100644 --- a/arch/mips/boot/dts/brcm/bcm7360.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7360.dtsi | |||
@@ -112,7 +112,7 @@ | |||
112 | sun_top_ctrl: syscon@404000 { | 112 | sun_top_ctrl: syscon@404000 { |
113 | compatible = "brcm,bcm7360-sun-top-ctrl", "syscon"; | 113 | compatible = "brcm,bcm7360-sun-top-ctrl", "syscon"; |
114 | reg = <0x404000 0x51c>; | 114 | reg = <0x404000 0x51c>; |
115 | little-endian; | 115 | native-endian; |
116 | }; | 116 | }; |
117 | 117 | ||
118 | reboot { | 118 | reboot { |
diff --git a/arch/mips/boot/dts/brcm/bcm7362.dtsi b/arch/mips/boot/dts/brcm/bcm7362.dtsi index c739ea77acb0..d3b1b762e6c3 100644 --- a/arch/mips/boot/dts/brcm/bcm7362.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7362.dtsi | |||
@@ -118,7 +118,7 @@ | |||
118 | sun_top_ctrl: syscon@404000 { | 118 | sun_top_ctrl: syscon@404000 { |
119 | compatible = "brcm,bcm7362-sun-top-ctrl", "syscon"; | 119 | compatible = "brcm,bcm7362-sun-top-ctrl", "syscon"; |
120 | reg = <0x404000 0x51c>; | 120 | reg = <0x404000 0x51c>; |
121 | little-endian; | 121 | native-endian; |
122 | }; | 122 | }; |
123 | 123 | ||
124 | reboot { | 124 | reboot { |
diff --git a/arch/mips/boot/dts/brcm/bcm7420.dtsi b/arch/mips/boot/dts/brcm/bcm7420.dtsi index 5f55d0a50a28..3302a1b8a5c9 100644 --- a/arch/mips/boot/dts/brcm/bcm7420.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7420.dtsi | |||
@@ -99,7 +99,7 @@ | |||
99 | sun_top_ctrl: syscon@404000 { | 99 | sun_top_ctrl: syscon@404000 { |
100 | compatible = "brcm,bcm7420-sun-top-ctrl", "syscon"; | 100 | compatible = "brcm,bcm7420-sun-top-ctrl", "syscon"; |
101 | reg = <0x404000 0x60c>; | 101 | reg = <0x404000 0x60c>; |
102 | little-endian; | 102 | native-endian; |
103 | }; | 103 | }; |
104 | 104 | ||
105 | reboot { | 105 | reboot { |
diff --git a/arch/mips/boot/dts/brcm/bcm7425.dtsi b/arch/mips/boot/dts/brcm/bcm7425.dtsi index e24d41ab4e30..15b27aae15a9 100644 --- a/arch/mips/boot/dts/brcm/bcm7425.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7425.dtsi | |||
@@ -100,7 +100,7 @@ | |||
100 | sun_top_ctrl: syscon@404000 { | 100 | sun_top_ctrl: syscon@404000 { |
101 | compatible = "brcm,bcm7425-sun-top-ctrl", "syscon"; | 101 | compatible = "brcm,bcm7425-sun-top-ctrl", "syscon"; |
102 | reg = <0x404000 0x51c>; | 102 | reg = <0x404000 0x51c>; |
103 | little-endian; | 103 | native-endian; |
104 | }; | 104 | }; |
105 | 105 | ||
106 | reboot { | 106 | reboot { |
diff --git a/arch/mips/boot/dts/brcm/bcm7435.dtsi b/arch/mips/boot/dts/brcm/bcm7435.dtsi index 8b9432cc062b..adb33e355043 100644 --- a/arch/mips/boot/dts/brcm/bcm7435.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7435.dtsi | |||
@@ -114,7 +114,7 @@ | |||
114 | sun_top_ctrl: syscon@404000 { | 114 | sun_top_ctrl: syscon@404000 { |
115 | compatible = "brcm,bcm7425-sun-top-ctrl", "syscon"; | 115 | compatible = "brcm,bcm7425-sun-top-ctrl", "syscon"; |
116 | reg = <0x404000 0x51c>; | 116 | reg = <0x404000 0x51c>; |
117 | little-endian; | 117 | native-endian; |
118 | }; | 118 | }; |
119 | 119 | ||
120 | reboot { | 120 | reboot { |
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 348be3a35410..cccceb599b02 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c | |||
@@ -30,7 +30,7 @@ static int regcache_hw_init(struct regmap *map) | |||
30 | int i, j; | 30 | int i, j; |
31 | int ret; | 31 | int ret; |
32 | int count; | 32 | int count; |
33 | unsigned int val; | 33 | unsigned int reg, val; |
34 | void *tmp_buf; | 34 | void *tmp_buf; |
35 | 35 | ||
36 | if (!map->num_reg_defaults_raw) | 36 | if (!map->num_reg_defaults_raw) |
@@ -67,27 +67,46 @@ static int regcache_hw_init(struct regmap *map) | |||
67 | ret = regmap_raw_read(map, 0, tmp_buf, | 67 | ret = regmap_raw_read(map, 0, tmp_buf, |
68 | map->num_reg_defaults_raw); | 68 | map->num_reg_defaults_raw); |
69 | map->cache_bypass = cache_bypass; | 69 | map->cache_bypass = cache_bypass; |
70 | if (ret < 0) | 70 | if (ret == 0) { |
71 | goto err_cache_free; | 71 | map->reg_defaults_raw = tmp_buf; |
72 | 72 | map->cache_free = 1; | |
73 | map->reg_defaults_raw = tmp_buf; | 73 | } else { |
74 | map->cache_free = 1; | 74 | kfree(tmp_buf); |
75 | } | ||
75 | } | 76 | } |
76 | 77 | ||
77 | /* fill the reg_defaults */ | 78 | /* fill the reg_defaults */ |
78 | for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { | 79 | for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { |
79 | if (regmap_volatile(map, i * map->reg_stride)) | 80 | reg = i * map->reg_stride; |
81 | |||
82 | if (!regmap_readable(map, reg)) | ||
80 | continue; | 83 | continue; |
81 | val = regcache_get_val(map, map->reg_defaults_raw, i); | 84 | |
82 | map->reg_defaults[j].reg = i * map->reg_stride; | 85 | if (regmap_volatile(map, reg)) |
86 | continue; | ||
87 | |||
88 | if (map->reg_defaults_raw) { | ||
89 | val = regcache_get_val(map, map->reg_defaults_raw, i); | ||
90 | } else { | ||
91 | bool cache_bypass = map->cache_bypass; | ||
92 | |||
93 | map->cache_bypass = true; | ||
94 | ret = regmap_read(map, reg, &val); | ||
95 | map->cache_bypass = cache_bypass; | ||
96 | if (ret != 0) { | ||
97 | dev_err(map->dev, "Failed to read %d: %d\n", | ||
98 | reg, ret); | ||
99 | goto err_free; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | map->reg_defaults[j].reg = reg; | ||
83 | map->reg_defaults[j].def = val; | 104 | map->reg_defaults[j].def = val; |
84 | j++; | 105 | j++; |
85 | } | 106 | } |
86 | 107 | ||
87 | return 0; | 108 | return 0; |
88 | 109 | ||
89 | err_cache_free: | ||
90 | kfree(tmp_buf); | ||
91 | err_free: | 110 | err_free: |
92 | kfree(map->reg_defaults); | 111 | kfree(map->reg_defaults); |
93 | 112 | ||
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index eea51569f0eb..7526906ca080 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c | |||
@@ -25,26 +25,14 @@ | |||
25 | 25 | ||
26 | struct regmap_mmio_context { | 26 | struct regmap_mmio_context { |
27 | void __iomem *regs; | 27 | void __iomem *regs; |
28 | unsigned reg_bytes; | ||
29 | unsigned val_bytes; | 28 | unsigned val_bytes; |
30 | unsigned pad_bytes; | ||
31 | struct clk *clk; | 29 | struct clk *clk; |
32 | }; | ||
33 | 30 | ||
34 | static inline void regmap_mmio_regsize_check(size_t reg_size) | 31 | void (*reg_write)(struct regmap_mmio_context *ctx, |
35 | { | 32 | unsigned int reg, unsigned int val); |
36 | switch (reg_size) { | 33 | unsigned int (*reg_read)(struct regmap_mmio_context *ctx, |
37 | case 1: | 34 | unsigned int reg); |
38 | case 2: | 35 | }; |
39 | case 4: | ||
40 | #ifdef CONFIG_64BIT | ||
41 | case 8: | ||
42 | #endif | ||
43 | break; | ||
44 | default: | ||
45 | BUG(); | ||
46 | } | ||
47 | } | ||
48 | 36 | ||
49 | static int regmap_mmio_regbits_check(size_t reg_bits) | 37 | static int regmap_mmio_regbits_check(size_t reg_bits) |
50 | { | 38 | { |
@@ -88,72 +76,62 @@ static int regmap_mmio_get_min_stride(size_t val_bits) | |||
88 | return min_stride; | 76 | return min_stride; |
89 | } | 77 | } |
90 | 78 | ||
91 | static inline void regmap_mmio_count_check(size_t count, u32 offset) | 79 | static void regmap_mmio_write8(struct regmap_mmio_context *ctx, |
80 | unsigned int reg, | ||
81 | unsigned int val) | ||
82 | { | ||
83 | writeb(val, ctx->regs + reg); | ||
84 | } | ||
85 | |||
86 | static void regmap_mmio_write16le(struct regmap_mmio_context *ctx, | ||
87 | unsigned int reg, | ||
88 | unsigned int val) | ||
92 | { | 89 | { |
93 | BUG_ON(count <= offset); | 90 | writew(val, ctx->regs + reg); |
94 | } | 91 | } |
95 | 92 | ||
96 | static inline unsigned int | 93 | static void regmap_mmio_write16be(struct regmap_mmio_context *ctx, |
97 | regmap_mmio_get_offset(const void *reg, size_t reg_size) | 94 | unsigned int reg, |
95 | unsigned int val) | ||
98 | { | 96 | { |
99 | switch (reg_size) { | 97 | iowrite16be(val, ctx->regs + reg); |
100 | case 1: | 98 | } |
101 | return *(u8 *)reg; | 99 | |
102 | case 2: | 100 | static void regmap_mmio_write32le(struct regmap_mmio_context *ctx, |
103 | return *(u16 *)reg; | 101 | unsigned int reg, |
104 | case 4: | 102 | unsigned int val) |
105 | return *(u32 *)reg; | 103 | { |
104 | writel(val, ctx->regs + reg); | ||
105 | } | ||
106 | |||
107 | static void regmap_mmio_write32be(struct regmap_mmio_context *ctx, | ||
108 | unsigned int reg, | ||
109 | unsigned int val) | ||
110 | { | ||
111 | iowrite32be(val, ctx->regs + reg); | ||
112 | } | ||
113 | |||
106 | #ifdef CONFIG_64BIT | 114 | #ifdef CONFIG_64BIT |
107 | case 8: | 115 | static void regmap_mmio_write64le(struct regmap_mmio_context *ctx, |
108 | return *(u64 *)reg; | 116 | unsigned int reg, |
109 | #endif | 117 | unsigned int val) |
110 | default: | 118 | { |
111 | BUG(); | 119 | writeq(val, ctx->regs + reg); |
112 | } | ||
113 | } | 120 | } |
121 | #endif | ||
114 | 122 | ||
115 | static int regmap_mmio_gather_write(void *context, | 123 | static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val) |
116 | const void *reg, size_t reg_size, | ||
117 | const void *val, size_t val_size) | ||
118 | { | 124 | { |
119 | struct regmap_mmio_context *ctx = context; | 125 | struct regmap_mmio_context *ctx = context; |
120 | unsigned int offset; | ||
121 | int ret; | 126 | int ret; |
122 | 127 | ||
123 | regmap_mmio_regsize_check(reg_size); | ||
124 | |||
125 | if (!IS_ERR(ctx->clk)) { | 128 | if (!IS_ERR(ctx->clk)) { |
126 | ret = clk_enable(ctx->clk); | 129 | ret = clk_enable(ctx->clk); |
127 | if (ret < 0) | 130 | if (ret < 0) |
128 | return ret; | 131 | return ret; |
129 | } | 132 | } |
130 | 133 | ||
131 | offset = regmap_mmio_get_offset(reg, reg_size); | 134 | ctx->reg_write(ctx, reg, val); |
132 | |||
133 | while (val_size) { | ||
134 | switch (ctx->val_bytes) { | ||
135 | case 1: | ||
136 | writeb(*(u8 *)val, ctx->regs + offset); | ||
137 | break; | ||
138 | case 2: | ||
139 | writew(*(u16 *)val, ctx->regs + offset); | ||
140 | break; | ||
141 | case 4: | ||
142 | writel(*(u32 *)val, ctx->regs + offset); | ||
143 | break; | ||
144 | #ifdef CONFIG_64BIT | ||
145 | case 8: | ||
146 | writeq(*(u64 *)val, ctx->regs + offset); | ||
147 | break; | ||
148 | #endif | ||
149 | default: | ||
150 | /* Should be caught by regmap_mmio_check_config */ | ||
151 | BUG(); | ||
152 | } | ||
153 | val_size -= ctx->val_bytes; | ||
154 | val += ctx->val_bytes; | ||
155 | offset += ctx->val_bytes; | ||
156 | } | ||
157 | 135 | ||
158 | if (!IS_ERR(ctx->clk)) | 136 | if (!IS_ERR(ctx->clk)) |
159 | clk_disable(ctx->clk); | 137 | clk_disable(ctx->clk); |
@@ -161,59 +139,56 @@ static int regmap_mmio_gather_write(void *context, | |||
161 | return 0; | 139 | return 0; |
162 | } | 140 | } |
163 | 141 | ||
164 | static int regmap_mmio_write(void *context, const void *data, size_t count) | 142 | static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx, |
143 | unsigned int reg) | ||
165 | { | 144 | { |
166 | struct regmap_mmio_context *ctx = context; | 145 | return readb(ctx->regs + reg); |
167 | unsigned int offset = ctx->reg_bytes + ctx->pad_bytes; | 146 | } |
147 | |||
148 | static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx, | ||
149 | unsigned int reg) | ||
150 | { | ||
151 | return readw(ctx->regs + reg); | ||
152 | } | ||
153 | |||
154 | static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx, | ||
155 | unsigned int reg) | ||
156 | { | ||
157 | return ioread16be(ctx->regs + reg); | ||
158 | } | ||
159 | |||
160 | static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx, | ||
161 | unsigned int reg) | ||
162 | { | ||
163 | return readl(ctx->regs + reg); | ||
164 | } | ||
168 | 165 | ||
169 | regmap_mmio_count_check(count, offset); | 166 | static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx, |
167 | unsigned int reg) | ||
168 | { | ||
169 | return ioread32be(ctx->regs + reg); | ||
170 | } | ||
170 | 171 | ||
171 | return regmap_mmio_gather_write(context, data, ctx->reg_bytes, | 172 | #ifdef CONFIG_64BIT |
172 | data + offset, count - offset); | 173 | static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx, |
174 | unsigned int reg) | ||
175 | { | ||
176 | return readq(ctx->regs + reg); | ||
173 | } | 177 | } |
178 | #endif | ||
174 | 179 | ||
175 | static int regmap_mmio_read(void *context, | 180 | static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val) |
176 | const void *reg, size_t reg_size, | ||
177 | void *val, size_t val_size) | ||
178 | { | 181 | { |
179 | struct regmap_mmio_context *ctx = context; | 182 | struct regmap_mmio_context *ctx = context; |
180 | unsigned int offset; | ||
181 | int ret; | 183 | int ret; |
182 | 184 | ||
183 | regmap_mmio_regsize_check(reg_size); | ||
184 | |||
185 | if (!IS_ERR(ctx->clk)) { | 185 | if (!IS_ERR(ctx->clk)) { |
186 | ret = clk_enable(ctx->clk); | 186 | ret = clk_enable(ctx->clk); |
187 | if (ret < 0) | 187 | if (ret < 0) |
188 | return ret; | 188 | return ret; |
189 | } | 189 | } |
190 | 190 | ||
191 | offset = regmap_mmio_get_offset(reg, reg_size); | 191 | *val = ctx->reg_read(ctx, reg); |
192 | |||
193 | while (val_size) { | ||
194 | switch (ctx->val_bytes) { | ||
195 | case 1: | ||
196 | *(u8 *)val = readb(ctx->regs + offset); | ||
197 | break; | ||
198 | case 2: | ||
199 | *(u16 *)val = readw(ctx->regs + offset); | ||
200 | break; | ||
201 | case 4: | ||
202 | *(u32 *)val = readl(ctx->regs + offset); | ||
203 | break; | ||
204 | #ifdef CONFIG_64BIT | ||
205 | case 8: | ||
206 | *(u64 *)val = readq(ctx->regs + offset); | ||
207 | break; | ||
208 | #endif | ||
209 | default: | ||
210 | /* Should be caught by regmap_mmio_check_config */ | ||
211 | BUG(); | ||
212 | } | ||
213 | val_size -= ctx->val_bytes; | ||
214 | val += ctx->val_bytes; | ||
215 | offset += ctx->val_bytes; | ||
216 | } | ||
217 | 192 | ||
218 | if (!IS_ERR(ctx->clk)) | 193 | if (!IS_ERR(ctx->clk)) |
219 | clk_disable(ctx->clk); | 194 | clk_disable(ctx->clk); |
@@ -232,14 +207,11 @@ static void regmap_mmio_free_context(void *context) | |||
232 | kfree(context); | 207 | kfree(context); |
233 | } | 208 | } |
234 | 209 | ||
235 | static struct regmap_bus regmap_mmio = { | 210 | static const struct regmap_bus regmap_mmio = { |
236 | .fast_io = true, | 211 | .fast_io = true, |
237 | .write = regmap_mmio_write, | 212 | .reg_write = regmap_mmio_write, |
238 | .gather_write = regmap_mmio_gather_write, | 213 | .reg_read = regmap_mmio_read, |
239 | .read = regmap_mmio_read, | ||
240 | .free_context = regmap_mmio_free_context, | 214 | .free_context = regmap_mmio_free_context, |
241 | .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
242 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
243 | }; | 215 | }; |
244 | 216 | ||
245 | static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, | 217 | static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, |
@@ -265,24 +237,71 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, | |||
265 | if (config->reg_stride < min_stride) | 237 | if (config->reg_stride < min_stride) |
266 | return ERR_PTR(-EINVAL); | 238 | return ERR_PTR(-EINVAL); |
267 | 239 | ||
268 | switch (config->reg_format_endian) { | ||
269 | case REGMAP_ENDIAN_DEFAULT: | ||
270 | case REGMAP_ENDIAN_NATIVE: | ||
271 | break; | ||
272 | default: | ||
273 | return ERR_PTR(-EINVAL); | ||
274 | } | ||
275 | |||
276 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | 240 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
277 | if (!ctx) | 241 | if (!ctx) |
278 | return ERR_PTR(-ENOMEM); | 242 | return ERR_PTR(-ENOMEM); |
279 | 243 | ||
280 | ctx->regs = regs; | 244 | ctx->regs = regs; |
281 | ctx->val_bytes = config->val_bits / 8; | 245 | ctx->val_bytes = config->val_bits / 8; |
282 | ctx->reg_bytes = config->reg_bits / 8; | ||
283 | ctx->pad_bytes = config->pad_bits / 8; | ||
284 | ctx->clk = ERR_PTR(-ENODEV); | 246 | ctx->clk = ERR_PTR(-ENODEV); |
285 | 247 | ||
248 | switch (config->reg_format_endian) { | ||
249 | case REGMAP_ENDIAN_DEFAULT: | ||
250 | case REGMAP_ENDIAN_LITTLE: | ||
251 | #ifdef __LITTLE_ENDIAN | ||
252 | case REGMAP_ENDIAN_NATIVE: | ||
253 | #endif | ||
254 | switch (config->val_bits) { | ||
255 | case 8: | ||
256 | ctx->reg_read = regmap_mmio_read8; | ||
257 | ctx->reg_write = regmap_mmio_write8; | ||
258 | break; | ||
259 | case 16: | ||
260 | ctx->reg_read = regmap_mmio_read16le; | ||
261 | ctx->reg_write = regmap_mmio_write16le; | ||
262 | break; | ||
263 | case 32: | ||
264 | ctx->reg_read = regmap_mmio_read32le; | ||
265 | ctx->reg_write = regmap_mmio_write32le; | ||
266 | break; | ||
267 | #ifdef CONFIG_64BIT | ||
268 | case 64: | ||
269 | ctx->reg_read = regmap_mmio_read64le; | ||
270 | ctx->reg_write = regmap_mmio_write64le; | ||
271 | break; | ||
272 | #endif | ||
273 | default: | ||
274 | ret = -EINVAL; | ||
275 | goto err_free; | ||
276 | } | ||
277 | break; | ||
278 | case REGMAP_ENDIAN_BIG: | ||
279 | #ifdef __BIG_ENDIAN | ||
280 | case REGMAP_ENDIAN_NATIVE: | ||
281 | #endif | ||
282 | switch (config->val_bits) { | ||
283 | case 8: | ||
284 | ctx->reg_read = regmap_mmio_read8; | ||
285 | ctx->reg_write = regmap_mmio_write8; | ||
286 | break; | ||
287 | case 16: | ||
288 | ctx->reg_read = regmap_mmio_read16be; | ||
289 | ctx->reg_write = regmap_mmio_write16be; | ||
290 | break; | ||
291 | case 32: | ||
292 | ctx->reg_read = regmap_mmio_read32be; | ||
293 | ctx->reg_write = regmap_mmio_write32be; | ||
294 | break; | ||
295 | default: | ||
296 | ret = -EINVAL; | ||
297 | goto err_free; | ||
298 | } | ||
299 | break; | ||
300 | default: | ||
301 | ret = -EINVAL; | ||
302 | goto err_free; | ||
303 | } | ||
304 | |||
286 | if (clk_id == NULL) | 305 | if (clk_id == NULL) |
287 | return ctx; | 306 | return ctx; |
288 | 307 | ||
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index ee54e841de4a..e2f68807d970 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -557,6 +557,8 @@ enum regmap_endian regmap_get_val_endian(struct device *dev, | |||
557 | endian = REGMAP_ENDIAN_BIG; | 557 | endian = REGMAP_ENDIAN_BIG; |
558 | else if (of_property_read_bool(np, "little-endian")) | 558 | else if (of_property_read_bool(np, "little-endian")) |
559 | endian = REGMAP_ENDIAN_LITTLE; | 559 | endian = REGMAP_ENDIAN_LITTLE; |
560 | else if (of_property_read_bool(np, "native-endian")) | ||
561 | endian = REGMAP_ENDIAN_NATIVE; | ||
560 | 562 | ||
561 | /* If the endianness was specified in DT, use that */ | 563 | /* If the endianness was specified in DT, use that */ |
562 | if (endian != REGMAP_ENDIAN_DEFAULT) | 564 | if (endian != REGMAP_ENDIAN_DEFAULT) |
@@ -2253,6 +2255,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
2253 | 2255 | ||
2254 | WARN_ON(!map->bus); | 2256 | WARN_ON(!map->bus); |
2255 | 2257 | ||
2258 | if (!map->bus || !map->bus->read) | ||
2259 | return -EINVAL; | ||
2260 | |||
2256 | range = _regmap_range_lookup(map, reg); | 2261 | range = _regmap_range_lookup(map, reg); |
2257 | if (range) { | 2262 | if (range) { |
2258 | ret = _regmap_select_page(map, ®, range, | 2263 | ret = _regmap_select_page(map, ®, range, |