1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Register map access API - MMIO support 4 // 5 // Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 6 7 #include <linux/clk.h> 8 #include <linux/err.h> 9 #include <linux/io.h> 10 #include <linux/module.h> 11 #include <linux/regmap.h> 12 #include <linux/slab.h> 13 #include <linux/swab.h> 14 15 #include "internal.h" 16 17 struct regmap_mmio_context { 18 void __iomem *regs; 19 unsigned int val_bytes; 20 bool big_endian; 21 22 bool attached_clk; 23 struct clk *clk; 24 25 void (*reg_write)(struct regmap_mmio_context *ctx, 26 unsigned int reg, unsigned int val); 27 unsigned int (*reg_read)(struct regmap_mmio_context *ctx, 28 unsigned int reg); 29 }; 30 31 static int regmap_mmio_regbits_check(size_t reg_bits) 32 { 33 switch (reg_bits) { 34 case 8: 35 case 16: 36 case 32: 37 return 0; 38 default: 39 return -EINVAL; 40 } 41 } 42 43 static int regmap_mmio_get_min_stride(size_t val_bits) 44 { 45 int min_stride; 46 47 switch (val_bits) { 48 case 8: 49 /* The core treats 0 as 1 */ 50 min_stride = 0; 51 break; 52 case 16: 53 min_stride = 2; 54 break; 55 case 32: 56 min_stride = 4; 57 break; 58 default: 59 return -EINVAL; 60 } 61 62 return min_stride; 63 } 64 65 static void regmap_mmio_write8(struct regmap_mmio_context *ctx, 66 unsigned int reg, 67 unsigned int val) 68 { 69 writeb(val, ctx->regs + reg); 70 } 71 72 static void regmap_mmio_write8_relaxed(struct regmap_mmio_context *ctx, 73 unsigned int reg, 74 unsigned int val) 75 { 76 writeb_relaxed(val, ctx->regs + reg); 77 } 78 79 static void regmap_mmio_iowrite8(struct regmap_mmio_context *ctx, 80 unsigned int reg, unsigned int val) 81 { 82 iowrite8(val, ctx->regs + reg); 83 } 84 85 static void regmap_mmio_write16le(struct regmap_mmio_context *ctx, 86 unsigned int reg, 87 unsigned int val) 88 { 89 writew(val, ctx->regs + reg); 90 } 91 92 static void regmap_mmio_write16le_relaxed(struct regmap_mmio_context *ctx, 93 unsigned int reg, 94 unsigned int val) 95 { 96 writew_relaxed(val, ctx->regs + reg); 97 } 98 99 static void regmap_mmio_iowrite16le(struct regmap_mmio_context *ctx, 100 unsigned int reg, unsigned int val) 101 { 102 iowrite16(val, ctx->regs + reg); 103 } 104 105 static void regmap_mmio_write16be(struct regmap_mmio_context *ctx, 106 unsigned int reg, 107 unsigned int val) 108 { 109 writew(swab16(val), ctx->regs + reg); 110 } 111 112 static void regmap_mmio_iowrite16be(struct regmap_mmio_context *ctx, 113 unsigned int reg, unsigned int val) 114 { 115 iowrite16be(val, ctx->regs + reg); 116 } 117 118 static void regmap_mmio_write32le(struct regmap_mmio_context *ctx, 119 unsigned int reg, 120 unsigned int val) 121 { 122 writel(val, ctx->regs + reg); 123 } 124 125 static void regmap_mmio_write32le_relaxed(struct regmap_mmio_context *ctx, 126 unsigned int reg, 127 unsigned int val) 128 { 129 writel_relaxed(val, ctx->regs + reg); 130 } 131 132 static void regmap_mmio_iowrite32le(struct regmap_mmio_context *ctx, 133 unsigned int reg, unsigned int val) 134 { 135 iowrite32(val, ctx->regs + reg); 136 } 137 138 static void regmap_mmio_write32be(struct regmap_mmio_context *ctx, 139 unsigned int reg, 140 unsigned int val) 141 { 142 writel(swab32(val), ctx->regs + reg); 143 } 144 145 static void regmap_mmio_iowrite32be(struct regmap_mmio_context *ctx, 146 unsigned int reg, unsigned int val) 147 { 148 iowrite32be(val, ctx->regs + reg); 149 } 150 151 static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val) 152 { 153 struct regmap_mmio_context *ctx = context; 154 int ret; 155 156 if (!IS_ERR(ctx->clk)) { 157 ret = clk_enable(ctx->clk); 158 if (ret < 0) 159 return ret; 160 } 161 162 ctx->reg_write(ctx, reg, val); 163 164 if (!IS_ERR(ctx->clk)) 165 clk_disable(ctx->clk); 166 167 return 0; 168 } 169 170 static int regmap_mmio_noinc_write(void *context, unsigned int reg, 171 const void *val, size_t val_count) 172 { 173 struct regmap_mmio_context *ctx = context; 174 int ret = 0; 175 int i; 176 177 if (!IS_ERR(ctx->clk)) { 178 ret = clk_enable(ctx->clk); 179 if (ret < 0) 180 return ret; 181 } 182 183 /* 184 * There are no native, assembly-optimized write single register 185 * operations for big endian, so fall back to emulation if this 186 * is needed. (Single bytes are fine, they are not affected by 187 * endianness.) 188 */ 189 if (ctx->big_endian && (ctx->val_bytes > 1)) { 190 switch (ctx->val_bytes) { 191 case 2: 192 { 193 const u16 *valp = (const u16 *)val; 194 for (i = 0; i < val_count; i++) 195 writew(swab16(valp[i]), ctx->regs + reg); 196 goto out_clk; 197 } 198 case 4: 199 { 200 const u32 *valp = (const u32 *)val; 201 for (i = 0; i < val_count; i++) 202 writel(swab32(valp[i]), ctx->regs + reg); 203 goto out_clk; 204 } 205 default: 206 ret = -EINVAL; 207 goto out_clk; 208 } 209 } 210 211 switch (ctx->val_bytes) { 212 case 1: 213 writesb(ctx->regs + reg, (const u8 *)val, val_count); 214 break; 215 case 2: 216 writesw(ctx->regs + reg, (const u16 *)val, val_count); 217 break; 218 case 4: 219 writesl(ctx->regs + reg, (const u32 *)val, val_count); 220 break; 221 default: 222 ret = -EINVAL; 223 break; 224 } 225 226 out_clk: 227 if (!IS_ERR(ctx->clk)) 228 clk_disable(ctx->clk); 229 230 return ret; 231 } 232 233 static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx, 234 unsigned int reg) 235 { 236 return readb(ctx->regs + reg); 237 } 238 239 static unsigned int regmap_mmio_read8_relaxed(struct regmap_mmio_context *ctx, 240 unsigned int reg) 241 { 242 return readb_relaxed(ctx->regs + reg); 243 } 244 245 static unsigned int regmap_mmio_ioread8(struct regmap_mmio_context *ctx, 246 unsigned int reg) 247 { 248 return ioread8(ctx->regs + reg); 249 } 250 251 static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx, 252 unsigned int reg) 253 { 254 return readw(ctx->regs + reg); 255 } 256 257 static unsigned int regmap_mmio_read16le_relaxed(struct regmap_mmio_context *ctx, 258 unsigned int reg) 259 { 260 return readw_relaxed(ctx->regs + reg); 261 } 262 263 static unsigned int regmap_mmio_ioread16le(struct regmap_mmio_context *ctx, 264 unsigned int reg) 265 { 266 return ioread16(ctx->regs + reg); 267 } 268 269 static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx, 270 unsigned int reg) 271 { 272 return swab16(readw(ctx->regs + reg)); 273 } 274 275 static unsigned int regmap_mmio_ioread16be(struct regmap_mmio_context *ctx, 276 unsigned int reg) 277 { 278 return ioread16be(ctx->regs + reg); 279 } 280 281 static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx, 282 unsigned int reg) 283 { 284 return readl(ctx->regs + reg); 285 } 286 287 static unsigned int regmap_mmio_read32le_relaxed(struct regmap_mmio_context *ctx, 288 unsigned int reg) 289 { 290 return readl_relaxed(ctx->regs + reg); 291 } 292 293 static unsigned int regmap_mmio_ioread32le(struct regmap_mmio_context *ctx, 294 unsigned int reg) 295 { 296 return ioread32(ctx->regs + reg); 297 } 298 299 static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx, 300 unsigned int reg) 301 { 302 return swab32(readl(ctx->regs + reg)); 303 } 304 305 static unsigned int regmap_mmio_ioread32be(struct regmap_mmio_context *ctx, 306 unsigned int reg) 307 { 308 return ioread32be(ctx->regs + reg); 309 } 310 311 static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val) 312 { 313 struct regmap_mmio_context *ctx = context; 314 int ret; 315 316 if (!IS_ERR(ctx->clk)) { 317 ret = clk_enable(ctx->clk); 318 if (ret < 0) 319 return ret; 320 } 321 322 *val = ctx->reg_read(ctx, reg); 323 324 if (!IS_ERR(ctx->clk)) 325 clk_disable(ctx->clk); 326 327 return 0; 328 } 329 330 static int regmap_mmio_noinc_read(void *context, unsigned int reg, 331 void *val, size_t val_count) 332 { 333 struct regmap_mmio_context *ctx = context; 334 int ret = 0; 335 336 if (!IS_ERR(ctx->clk)) { 337 ret = clk_enable(ctx->clk); 338 if (ret < 0) 339 return ret; 340 } 341 342 switch (ctx->val_bytes) { 343 case 1: 344 readsb(ctx->regs + reg, (u8 *)val, val_count); 345 break; 346 case 2: 347 readsw(ctx->regs + reg, (u16 *)val, val_count); 348 break; 349 case 4: 350 readsl(ctx->regs + reg, (u32 *)val, val_count); 351 break; 352 default: 353 ret = -EINVAL; 354 goto out_clk; 355 } 356 357 /* 358 * There are no native, assembly-optimized write single register 359 * operations for big endian, so fall back to emulation if this 360 * is needed. (Single bytes are fine, they are not affected by 361 * endianness.) 362 */ 363 if (ctx->big_endian && (ctx->val_bytes > 1)) { 364 switch (ctx->val_bytes) { 365 case 2: 366 swab16_array(val, val_count); 367 break; 368 case 4: 369 swab32_array(val, val_count); 370 break; 371 default: 372 ret = -EINVAL; 373 break; 374 } 375 } 376 377 out_clk: 378 if (!IS_ERR(ctx->clk)) 379 clk_disable(ctx->clk); 380 381 return ret; 382 } 383 384 385 static void regmap_mmio_free_context(void *context) 386 { 387 struct regmap_mmio_context *ctx = context; 388 389 if (!IS_ERR(ctx->clk)) { 390 clk_unprepare(ctx->clk); 391 if (!ctx->attached_clk) 392 clk_put(ctx->clk); 393 } 394 kfree(context); 395 } 396 397 static const struct regmap_bus regmap_mmio = { 398 .fast_io = true, 399 .reg_write = regmap_mmio_write, 400 .reg_read = regmap_mmio_read, 401 .reg_noinc_write = regmap_mmio_noinc_write, 402 .reg_noinc_read = regmap_mmio_noinc_read, 403 .free_context = regmap_mmio_free_context, 404 .val_format_endian_default = REGMAP_ENDIAN_LITTLE, 405 }; 406 407 static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, 408 const char *clk_id, 409 void __iomem *regs, 410 const struct regmap_config *config) 411 { 412 struct regmap_mmio_context *ctx; 413 int min_stride; 414 int ret; 415 416 ret = regmap_mmio_regbits_check(config->reg_bits); 417 if (ret) 418 return ERR_PTR(ret); 419 420 if (config->pad_bits) 421 return ERR_PTR(-EINVAL); 422 423 min_stride = regmap_mmio_get_min_stride(config->val_bits); 424 if (min_stride < 0) 425 return ERR_PTR(min_stride); 426 427 if (config->reg_stride && config->reg_stride < min_stride) 428 return ERR_PTR(-EINVAL); 429 430 if (config->use_relaxed_mmio && config->io_port) 431 return ERR_PTR(-EINVAL); 432 433 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 434 if (!ctx) 435 return ERR_PTR(-ENOMEM); 436 437 ctx->regs = regs; 438 ctx->val_bytes = config->val_bits / 8; 439 ctx->clk = ERR_PTR(-ENODEV); 440 441 switch (regmap_get_val_endian(dev, ®map_mmio, config)) { 442 case REGMAP_ENDIAN_DEFAULT: 443 case REGMAP_ENDIAN_LITTLE: 444 #ifdef __LITTLE_ENDIAN 445 case REGMAP_ENDIAN_NATIVE: 446 #endif 447 switch (config->val_bits) { 448 case 8: 449 if (config->io_port) { 450 ctx->reg_read = regmap_mmio_ioread8; 451 ctx->reg_write = regmap_mmio_iowrite8; 452 } else if (config->use_relaxed_mmio) { 453 ctx->reg_read = regmap_mmio_read8_relaxed; 454 ctx->reg_write = regmap_mmio_write8_relaxed; 455 } else { 456 ctx->reg_read = regmap_mmio_read8; 457 ctx->reg_write = regmap_mmio_write8; 458 } 459 break; 460 case 16: 461 if (config->io_port) { 462 ctx->reg_read = regmap_mmio_ioread16le; 463 ctx->reg_write = regmap_mmio_iowrite16le; 464 } else if (config->use_relaxed_mmio) { 465 ctx->reg_read = regmap_mmio_read16le_relaxed; 466 ctx->reg_write = regmap_mmio_write16le_relaxed; 467 } else { 468 ctx->reg_read = regmap_mmio_read16le; 469 ctx->reg_write = regmap_mmio_write16le; 470 } 471 break; 472 case 32: 473 if (config->io_port) { 474 ctx->reg_read = regmap_mmio_ioread32le; 475 ctx->reg_write = regmap_mmio_iowrite32le; 476 } else if (config->use_relaxed_mmio) { 477 ctx->reg_read = regmap_mmio_read32le_relaxed; 478 ctx->reg_write = regmap_mmio_write32le_relaxed; 479 } else { 480 ctx->reg_read = regmap_mmio_read32le; 481 ctx->reg_write = regmap_mmio_write32le; 482 } 483 break; 484 default: 485 ret = -EINVAL; 486 goto err_free; 487 } 488 break; 489 case REGMAP_ENDIAN_BIG: 490 #ifdef __BIG_ENDIAN 491 case REGMAP_ENDIAN_NATIVE: 492 #endif 493 ctx->big_endian = true; 494 switch (config->val_bits) { 495 case 8: 496 if (config->io_port) { 497 ctx->reg_read = regmap_mmio_ioread8; 498 ctx->reg_write = regmap_mmio_iowrite8; 499 } else { 500 ctx->reg_read = regmap_mmio_read8; 501 ctx->reg_write = regmap_mmio_write8; 502 } 503 break; 504 case 16: 505 if (config->io_port) { 506 ctx->reg_read = regmap_mmio_ioread16be; 507 ctx->reg_write = regmap_mmio_iowrite16be; 508 } else { 509 ctx->reg_read = regmap_mmio_read16be; 510 ctx->reg_write = regmap_mmio_write16be; 511 } 512 break; 513 case 32: 514 if (config->io_port) { 515 ctx->reg_read = regmap_mmio_ioread32be; 516 ctx->reg_write = regmap_mmio_iowrite32be; 517 } else { 518 ctx->reg_read = regmap_mmio_read32be; 519 ctx->reg_write = regmap_mmio_write32be; 520 } 521 break; 522 default: 523 ret = -EINVAL; 524 goto err_free; 525 } 526 break; 527 default: 528 ret = -EINVAL; 529 goto err_free; 530 } 531 532 if (clk_id == NULL) 533 return ctx; 534 535 ctx->clk = clk_get(dev, clk_id); 536 if (IS_ERR(ctx->clk)) { 537 ret = PTR_ERR(ctx->clk); 538 goto err_free; 539 } 540 541 ret = clk_prepare(ctx->clk); 542 if (ret < 0) { 543 clk_put(ctx->clk); 544 goto err_free; 545 } 546 547 return ctx; 548 549 err_free: 550 kfree(ctx); 551 552 return ERR_PTR(ret); 553 } 554 555 struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id, 556 void __iomem *regs, 557 const struct regmap_config *config, 558 struct lock_class_key *lock_key, 559 const char *lock_name) 560 { 561 struct regmap_mmio_context *ctx; 562 563 ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); 564 if (IS_ERR(ctx)) 565 return ERR_CAST(ctx); 566 567 return __regmap_init(dev, ®map_mmio, ctx, config, 568 lock_key, lock_name); 569 } 570 EXPORT_SYMBOL_GPL(__regmap_init_mmio_clk); 571 572 struct regmap *__devm_regmap_init_mmio_clk(struct device *dev, 573 const char *clk_id, 574 void __iomem *regs, 575 const struct regmap_config *config, 576 struct lock_class_key *lock_key, 577 const char *lock_name) 578 { 579 struct regmap_mmio_context *ctx; 580 581 ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); 582 if (IS_ERR(ctx)) 583 return ERR_CAST(ctx); 584 585 return __devm_regmap_init(dev, ®map_mmio, ctx, config, 586 lock_key, lock_name); 587 } 588 EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk); 589 590 int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk) 591 { 592 struct regmap_mmio_context *ctx = map->bus_context; 593 594 ctx->clk = clk; 595 ctx->attached_clk = true; 596 597 return clk_prepare(ctx->clk); 598 } 599 EXPORT_SYMBOL_GPL(regmap_mmio_attach_clk); 600 601 void regmap_mmio_detach_clk(struct regmap *map) 602 { 603 struct regmap_mmio_context *ctx = map->bus_context; 604 605 clk_unprepare(ctx->clk); 606 607 ctx->attached_clk = false; 608 ctx->clk = NULL; 609 } 610 EXPORT_SYMBOL_GPL(regmap_mmio_detach_clk); 611 612 MODULE_LICENSE("GPL v2"); 613