Blame view
drivers/base/regmap/regmap-mmio.c
7.65 KB
45f5ff810 regmap: add MMIO ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * Register map access API - MMIO support * * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
878ec67b3 regmap: mmio: add... |
18 |
#include <linux/clk.h> |
45f5ff810 regmap: add MMIO ... |
19 |
#include <linux/err.h> |
45f5ff810 regmap: add MMIO ... |
20 21 22 23 |
#include <linux/io.h> #include <linux/module.h> #include <linux/regmap.h> #include <linux/slab.h> |
0dbdb76c0 regmap: mmio: Par... |
24 |
#include "internal.h" |
45f5ff810 regmap: add MMIO ... |
25 26 27 |
struct regmap_mmio_context { void __iomem *regs; unsigned val_bytes; |
878ec67b3 regmap: mmio: add... |
28 |
struct clk *clk; |
45f5ff810 regmap: add MMIO ... |
29 |
|
922a9f936 regmap: mmio: Con... |
30 31 32 33 34 |
void (*reg_write)(struct regmap_mmio_context *ctx, unsigned int reg, unsigned int val); unsigned int (*reg_read)(struct regmap_mmio_context *ctx, unsigned int reg); }; |
41b0c2c97 regmap: mmio: add... |
35 |
|
451485ba6 regmap: mmio: Add... |
36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
static int regmap_mmio_regbits_check(size_t reg_bits) { switch (reg_bits) { case 8: case 16: case 32: #ifdef CONFIG_64BIT case 64: #endif return 0; default: return -EINVAL; } } |
75fb0aaea regmap: mmio: Add... |
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
static int regmap_mmio_get_min_stride(size_t val_bits) { int min_stride; switch (val_bits) { case 8: /* The core treats 0 as 1 */ min_stride = 0; return 0; case 16: min_stride = 2; break; case 32: min_stride = 4; break; #ifdef CONFIG_64BIT case 64: min_stride = 8; break; #endif default: return -EINVAL; } return min_stride; } |
922a9f936 regmap: mmio: Con... |
76 77 78 79 80 81 82 83 84 85 |
static void regmap_mmio_write8(struct regmap_mmio_context *ctx, unsigned int reg, unsigned int val) { writeb(val, ctx->regs + reg); } static void regmap_mmio_write16le(struct regmap_mmio_context *ctx, unsigned int reg, unsigned int val) |
41b0c2c97 regmap: mmio: add... |
86 |
{ |
922a9f936 regmap: mmio: Con... |
87 |
writew(val, ctx->regs + reg); |
41b0c2c97 regmap: mmio: add... |
88 |
} |
922a9f936 regmap: mmio: Con... |
89 90 91 |
static void regmap_mmio_write16be(struct regmap_mmio_context *ctx, unsigned int reg, unsigned int val) |
88cb32c65 regmap: mmio: Fix... |
92 |
{ |
922a9f936 regmap: mmio: Con... |
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
iowrite16be(val, ctx->regs + reg); } static void regmap_mmio_write32le(struct regmap_mmio_context *ctx, unsigned int reg, unsigned int val) { writel(val, ctx->regs + reg); } static void regmap_mmio_write32be(struct regmap_mmio_context *ctx, unsigned int reg, unsigned int val) { iowrite32be(val, ctx->regs + reg); } |
88cb32c65 regmap: mmio: Fix... |
109 |
#ifdef CONFIG_64BIT |
922a9f936 regmap: mmio: Con... |
110 111 112 113 114 |
static void regmap_mmio_write64le(struct regmap_mmio_context *ctx, unsigned int reg, unsigned int val) { writeq(val, ctx->regs + reg); |
41b0c2c97 regmap: mmio: add... |
115 |
} |
922a9f936 regmap: mmio: Con... |
116 |
#endif |
41b0c2c97 regmap: mmio: add... |
117 |
|
922a9f936 regmap: mmio: Con... |
118 |
static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val) |
45f5ff810 regmap: add MMIO ... |
119 120 |
{ struct regmap_mmio_context *ctx = context; |
878ec67b3 regmap: mmio: add... |
121 |
int ret; |
45f5ff810 regmap: add MMIO ... |
122 |
|
6b8e090ec regmap: use IS_ER... |
123 |
if (!IS_ERR(ctx->clk)) { |
878ec67b3 regmap: mmio: add... |
124 125 126 127 |
ret = clk_enable(ctx->clk); if (ret < 0) return ret; } |
922a9f936 regmap: mmio: Con... |
128 |
ctx->reg_write(ctx, reg, val); |
45f5ff810 regmap: add MMIO ... |
129 |
|
6b8e090ec regmap: use IS_ER... |
130 |
if (!IS_ERR(ctx->clk)) |
878ec67b3 regmap: mmio: add... |
131 |
clk_disable(ctx->clk); |
45f5ff810 regmap: add MMIO ... |
132 133 |
return 0; } |
922a9f936 regmap: mmio: Con... |
134 135 |
static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx, unsigned int reg) |
45f5ff810 regmap: add MMIO ... |
136 |
{ |
922a9f936 regmap: mmio: Con... |
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
return readb(ctx->regs + reg); } static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx, unsigned int reg) { return readw(ctx->regs + reg); } static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx, unsigned int reg) { return ioread16be(ctx->regs + reg); } static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx, unsigned int reg) { return readl(ctx->regs + reg); } |
932580409 regmap: mmio: Add... |
157 |
|
922a9f936 regmap: mmio: Con... |
158 159 160 161 162 |
static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx, unsigned int reg) { return ioread32be(ctx->regs + reg); } |
40606dba4 regmap: mmio: con... |
163 |
|
922a9f936 regmap: mmio: Con... |
164 165 166 167 168 |
#ifdef CONFIG_64BIT static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx, unsigned int reg) { return readq(ctx->regs + reg); |
45f5ff810 regmap: add MMIO ... |
169 |
} |
922a9f936 regmap: mmio: Con... |
170 |
#endif |
45f5ff810 regmap: add MMIO ... |
171 |
|
922a9f936 regmap: mmio: Con... |
172 |
static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val) |
45f5ff810 regmap: add MMIO ... |
173 174 |
{ struct regmap_mmio_context *ctx = context; |
878ec67b3 regmap: mmio: add... |
175 |
int ret; |
45f5ff810 regmap: add MMIO ... |
176 |
|
6b8e090ec regmap: use IS_ER... |
177 |
if (!IS_ERR(ctx->clk)) { |
878ec67b3 regmap: mmio: add... |
178 179 180 181 |
ret = clk_enable(ctx->clk); if (ret < 0) return ret; } |
922a9f936 regmap: mmio: Con... |
182 |
*val = ctx->reg_read(ctx, reg); |
45f5ff810 regmap: add MMIO ... |
183 |
|
6b8e090ec regmap: use IS_ER... |
184 |
if (!IS_ERR(ctx->clk)) |
878ec67b3 regmap: mmio: add... |
185 |
clk_disable(ctx->clk); |
45f5ff810 regmap: add MMIO ... |
186 187 188 189 190 |
return 0; } static void regmap_mmio_free_context(void *context) { |
878ec67b3 regmap: mmio: add... |
191 |
struct regmap_mmio_context *ctx = context; |
6b8e090ec regmap: use IS_ER... |
192 |
if (!IS_ERR(ctx->clk)) { |
878ec67b3 regmap: mmio: add... |
193 194 195 |
clk_unprepare(ctx->clk); clk_put(ctx->clk); } |
45f5ff810 regmap: add MMIO ... |
196 197 |
kfree(context); } |
922a9f936 regmap: mmio: Con... |
198 |
static const struct regmap_bus regmap_mmio = { |
45f5ff810 regmap: add MMIO ... |
199 |
.fast_io = true, |
922a9f936 regmap: mmio: Con... |
200 201 |
.reg_write = regmap_mmio_write, .reg_read = regmap_mmio_read, |
45f5ff810 regmap: add MMIO ... |
202 |
.free_context = regmap_mmio_free_context, |
2ed94f6fd regmap: mmio: Exp... |
203 |
.val_format_endian_default = REGMAP_ENDIAN_LITTLE, |
45f5ff810 regmap: add MMIO ... |
204 |
}; |
878ec67b3 regmap: mmio: add... |
205 206 207 |
static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, const char *clk_id, void __iomem *regs, |
45f5ff810 regmap: add MMIO ... |
208 209 210 |
const struct regmap_config *config) { struct regmap_mmio_context *ctx; |
f01ee60ff regmap: implement... |
211 |
int min_stride; |
878ec67b3 regmap: mmio: add... |
212 |
int ret; |
45f5ff810 regmap: add MMIO ... |
213 |
|
451485ba6 regmap: mmio: Add... |
214 215 216 |
ret = regmap_mmio_regbits_check(config->reg_bits); if (ret) return ERR_PTR(ret); |
45f5ff810 regmap: add MMIO ... |
217 218 219 |
if (config->pad_bits) return ERR_PTR(-EINVAL); |
75fb0aaea regmap: mmio: Add... |
220 221 222 |
min_stride = regmap_mmio_get_min_stride(config->val_bits); if (min_stride < 0) return ERR_PTR(min_stride); |
45f5ff810 regmap: add MMIO ... |
223 |
|
f01ee60ff regmap: implement... |
224 225 |
if (config->reg_stride < min_stride) return ERR_PTR(-EINVAL); |
463351194 regmap: Fix incor... |
226 |
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
45f5ff810 regmap: add MMIO ... |
227 228 229 230 231 |
if (!ctx) return ERR_PTR(-ENOMEM); ctx->regs = regs; ctx->val_bytes = config->val_bits / 8; |
6b8e090ec regmap: use IS_ER... |
232 |
ctx->clk = ERR_PTR(-ENODEV); |
45f5ff810 regmap: add MMIO ... |
233 |
|
0dbdb76c0 regmap: mmio: Par... |
234 |
switch (regmap_get_val_endian(dev, ®map_mmio, config)) { |
922a9f936 regmap: mmio: Con... |
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
case REGMAP_ENDIAN_DEFAULT: case REGMAP_ENDIAN_LITTLE: #ifdef __LITTLE_ENDIAN case REGMAP_ENDIAN_NATIVE: #endif switch (config->val_bits) { case 8: ctx->reg_read = regmap_mmio_read8; ctx->reg_write = regmap_mmio_write8; break; case 16: ctx->reg_read = regmap_mmio_read16le; ctx->reg_write = regmap_mmio_write16le; break; case 32: ctx->reg_read = regmap_mmio_read32le; ctx->reg_write = regmap_mmio_write32le; break; #ifdef CONFIG_64BIT case 64: ctx->reg_read = regmap_mmio_read64le; ctx->reg_write = regmap_mmio_write64le; break; #endif default: ret = -EINVAL; goto err_free; } break; case REGMAP_ENDIAN_BIG: #ifdef __BIG_ENDIAN case REGMAP_ENDIAN_NATIVE: #endif switch (config->val_bits) { case 8: ctx->reg_read = regmap_mmio_read8; ctx->reg_write = regmap_mmio_write8; break; case 16: ctx->reg_read = regmap_mmio_read16be; ctx->reg_write = regmap_mmio_write16be; break; case 32: ctx->reg_read = regmap_mmio_read32be; ctx->reg_write = regmap_mmio_write32be; break; default: ret = -EINVAL; goto err_free; } break; default: ret = -EINVAL; goto err_free; } |
878ec67b3 regmap: mmio: add... |
290 |
ctx->clk = clk_get(dev, clk_id); |
f08f7d7fa MLK-12284-1 regma... |
291 292 293 294 295 296 297 298 |
if (!IS_ERR(ctx->clk)) { ret = clk_prepare(ctx->clk); if (ret < 0) { clk_put(ctx->clk); goto err_free; } } else { ctx->clk = NULL; |
878ec67b3 regmap: mmio: add... |
299 |
} |
45f5ff810 regmap: add MMIO ... |
300 |
return ctx; |
878ec67b3 regmap: mmio: add... |
301 302 303 304 305 |
err_free: kfree(ctx); return ERR_PTR(ret); |
45f5ff810 regmap: add MMIO ... |
306 |
} |
3cfe7a74d regmap: Use diffe... |
307 308 309 310 311 |
struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id, void __iomem *regs, const struct regmap_config *config, struct lock_class_key *lock_key, const char *lock_name) |
45f5ff810 regmap: add MMIO ... |
312 313 |
{ struct regmap_mmio_context *ctx; |
878ec67b3 regmap: mmio: add... |
314 |
ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); |
45f5ff810 regmap: add MMIO ... |
315 316 |
if (IS_ERR(ctx)) return ERR_CAST(ctx); |
3cfe7a74d regmap: Use diffe... |
317 318 |
return __regmap_init(dev, ®map_mmio, ctx, config, lock_key, lock_name); |
45f5ff810 regmap: add MMIO ... |
319 |
} |
3cfe7a74d regmap: Use diffe... |
320 |
EXPORT_SYMBOL_GPL(__regmap_init_mmio_clk); |
45f5ff810 regmap: add MMIO ... |
321 |
|
3cfe7a74d regmap: Use diffe... |
322 323 324 325 326 327 |
struct regmap *__devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id, void __iomem *regs, const struct regmap_config *config, struct lock_class_key *lock_key, const char *lock_name) |
45f5ff810 regmap: add MMIO ... |
328 329 |
{ struct regmap_mmio_context *ctx; |
878ec67b3 regmap: mmio: add... |
330 |
ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); |
45f5ff810 regmap: add MMIO ... |
331 332 |
if (IS_ERR(ctx)) return ERR_CAST(ctx); |
3cfe7a74d regmap: Use diffe... |
333 334 |
return __devm_regmap_init(dev, ®map_mmio, ctx, config, lock_key, lock_name); |
45f5ff810 regmap: add MMIO ... |
335 |
} |
3cfe7a74d regmap: Use diffe... |
336 |
EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk); |
45f5ff810 regmap: add MMIO ... |
337 338 |
MODULE_LICENSE("GPL v2"); |