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 #ifdef CONFIG_64BIT 206 case 8: 207 { 208 const u64 *valp = (const u64 *)val; 209 for (i = 0; i < val_count; i++) 210 writeq(swab64(valp[i]), ctx->regs + reg); 211 goto out_clk; 212 } 213 #endif 214 default: 215 ret = -EINVAL; 216 goto out_clk; 217 } 218 } 219 220 switch (ctx->val_bytes) { 221 case 1: 222 writesb(ctx->regs + reg, (const u8 *)val, val_count); 223 break; 224 case 2: 225 writesw(ctx->regs + reg, (const u16 *)val, val_count); 226 break; 227 case 4: 228 writesl(ctx->regs + reg, (const u32 *)val, val_count); 229 break; 230 #ifdef CONFIG_64BIT 231 case 8: 232 writesq(ctx->regs + reg, (const u64 *)val, val_count); 233 break; 234 #endif 235 default: 236 ret = -EINVAL; 237 break; 238 } 239 240 out_clk: 241 if (!IS_ERR(ctx->clk)) 242 clk_disable(ctx->clk); 243 244 return ret; 245 } 246 247 static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx, 248 unsigned int reg) 249 { 250 return readb(ctx->regs + reg); 251 } 252 253 static unsigned int regmap_mmio_read8_relaxed(struct regmap_mmio_context *ctx, 254 unsigned int reg) 255 { 256 return readb_relaxed(ctx->regs + reg); 257 } 258 259 static unsigned int regmap_mmio_ioread8(struct regmap_mmio_context *ctx, 260 unsigned int reg) 261 { 262 return ioread8(ctx->regs + reg); 263 } 264 265 static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx, 266 unsigned int reg) 267 { 268 return readw(ctx->regs + reg); 269 } 270 271 static unsigned int regmap_mmio_read16le_relaxed(struct regmap_mmio_context *ctx, 272 unsigned int reg) 273 { 274 return readw_relaxed(ctx->regs + reg); 275 } 276 277 static unsigned int regmap_mmio_ioread16le(struct regmap_mmio_context *ctx, 278 unsigned int reg) 279 { 280 return ioread16(ctx->regs + reg); 281 } 282 283 static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx, 284 unsigned int reg) 285 { 286 return swab16(readw(ctx->regs + reg)); 287 } 288 289 static unsigned int regmap_mmio_ioread16be(struct regmap_mmio_context *ctx, 290 unsigned int reg) 291 { 292 return ioread16be(ctx->regs + reg); 293 } 294 295 static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx, 296 unsigned int reg) 297 { 298 return readl(ctx->regs + reg); 299 } 300 301 static unsigned int regmap_mmio_read32le_relaxed(struct regmap_mmio_context *ctx, 302 unsigned int reg) 303 { 304 return readl_relaxed(ctx->regs + reg); 305 } 306 307 static unsigned int regmap_mmio_ioread32le(struct regmap_mmio_context *ctx, 308 unsigned int reg) 309 { 310 return ioread32(ctx->regs + reg); 311 } 312 313 static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx, 314 unsigned int reg) 315 { 316 return swab32(readl(ctx->regs + reg)); 317 } 318 319 static unsigned int regmap_mmio_ioread32be(struct regmap_mmio_context *ctx, 320 unsigned int reg) 321 { 322 return ioread32be(ctx->regs + reg); 323 } 324 325 static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val) 326 { 327 struct regmap_mmio_context *ctx = context; 328 int ret; 329 330 if (!IS_ERR(ctx->clk)) { 331 ret = clk_enable(ctx->clk); 332 if (ret < 0) 333 return ret; 334 } 335 336 *val = ctx->reg_read(ctx, reg); 337 338 if (!IS_ERR(ctx->clk)) 339 clk_disable(ctx->clk); 340 341 return 0; 342 } 343 344 static int regmap_mmio_noinc_read(void *context, unsigned int reg, 345 void *val, size_t val_count) 346 { 347 struct regmap_mmio_context *ctx = context; 348 int ret = 0; 349 350 if (!IS_ERR(ctx->clk)) { 351 ret = clk_enable(ctx->clk); 352 if (ret < 0) 353 return ret; 354 } 355 356 switch (ctx->val_bytes) { 357 case 1: 358 readsb(ctx->regs + reg, (u8 *)val, val_count); 359 break; 360 case 2: 361 readsw(ctx->regs + reg, (u16 *)val, val_count); 362 break; 363 case 4: 364 readsl(ctx->regs + reg, (u32 *)val, val_count); 365 break; 366 #ifdef CONFIG_64BIT 367 case 8: 368 readsq(ctx->regs + reg, (u64 *)val, val_count); 369 break; 370 #endif 371 default: 372 ret = -EINVAL; 373 goto out_clk; 374 } 375 376 /* 377 * There are no native, assembly-optimized write single register 378 * operations for big endian, so fall back to emulation if this 379 * is needed. (Single bytes are fine, they are not affected by 380 * endianness.) 381 */ 382 if (ctx->big_endian && (ctx->val_bytes > 1)) { 383 switch (ctx->val_bytes) { 384 case 2: 385 swab16_array(val, val_count); 386 break; 387 case 4: 388 swab32_array(val, val_count); 389 break; 390 #ifdef CONFIG_64BIT 391 case 8: 392 swab64_array(val, val_count); 393 break; 394 #endif 395 default: 396 ret = -EINVAL; 397 break; 398 } 399 } 400 401 out_clk: 402 if (!IS_ERR(ctx->clk)) 403 clk_disable(ctx->clk); 404 405 return ret; 406 } 407 408 409 static void regmap_mmio_free_context(void *context) 410 { 411 struct regmap_mmio_context *ctx = context; 412 413 if (!IS_ERR(ctx->clk)) { 414 clk_unprepare(ctx->clk); 415 if (!ctx->attached_clk) 416 clk_put(ctx->clk); 417 } 418 kfree(context); 419 } 420 421 static const struct regmap_bus regmap_mmio = { 422 .fast_io = true, 423 .reg_write = regmap_mmio_write, 424 .reg_read = regmap_mmio_read, 425 .reg_noinc_write = regmap_mmio_noinc_write, 426 .reg_noinc_read = regmap_mmio_noinc_read, 427 .free_context = regmap_mmio_free_context, 428 .val_format_endian_default = REGMAP_ENDIAN_LITTLE, 429 }; 430 431 static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, 432 const char *clk_id, 433 void __iomem *regs, 434 const struct regmap_config *config) 435 { 436 struct regmap_mmio_context *ctx; 437 int min_stride; 438 int ret; 439 440 ret = regmap_mmio_regbits_check(config->reg_bits); 441 if (ret) 442 return ERR_PTR(ret); 443 444 if (config->pad_bits) 445 return ERR_PTR(-EINVAL); 446 447 min_stride = regmap_mmio_get_min_stride(config->val_bits); 448 if (min_stride < 0) 449 return ERR_PTR(min_stride); 450 451 if (config->reg_stride < min_stride) 452 return ERR_PTR(-EINVAL); 453 454 if (config->use_relaxed_mmio && config->io_port) 455 return ERR_PTR(-EINVAL); 456 457 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 458 if (!ctx) 459 return ERR_PTR(-ENOMEM); 460 461 ctx->regs = regs; 462 ctx->val_bytes = config->val_bits / 8; 463 ctx->clk = ERR_PTR(-ENODEV); 464 465 switch (regmap_get_val_endian(dev, ®map_mmio, config)) { 466 case REGMAP_ENDIAN_DEFAULT: 467 case REGMAP_ENDIAN_LITTLE: 468 #ifdef __LITTLE_ENDIAN 469 case REGMAP_ENDIAN_NATIVE: 470 #endif 471 switch (config->val_bits) { 472 case 8: 473 if (config->io_port) { 474 ctx->reg_read = regmap_mmio_ioread8; 475 ctx->reg_write = regmap_mmio_iowrite8; 476 } else if (config->use_relaxed_mmio) { 477 ctx->reg_read = regmap_mmio_read8_relaxed; 478 ctx->reg_write = regmap_mmio_write8_relaxed; 479 } else { 480 ctx->reg_read = regmap_mmio_read8; 481 ctx->reg_write = regmap_mmio_write8; 482 } 483 break; 484 case 16: 485 if (config->io_port) { 486 ctx->reg_read = regmap_mmio_ioread16le; 487 ctx->reg_write = regmap_mmio_iowrite16le; 488 } else if (config->use_relaxed_mmio) { 489 ctx->reg_read = regmap_mmio_read16le_relaxed; 490 ctx->reg_write = regmap_mmio_write16le_relaxed; 491 } else { 492 ctx->reg_read = regmap_mmio_read16le; 493 ctx->reg_write = regmap_mmio_write16le; 494 } 495 break; 496 case 32: 497 if (config->io_port) { 498 ctx->reg_read = regmap_mmio_ioread32le; 499 ctx->reg_write = regmap_mmio_iowrite32le; 500 } else if (config->use_relaxed_mmio) { 501 ctx->reg_read = regmap_mmio_read32le_relaxed; 502 ctx->reg_write = regmap_mmio_write32le_relaxed; 503 } else { 504 ctx->reg_read = regmap_mmio_read32le; 505 ctx->reg_write = regmap_mmio_write32le; 506 } 507 break; 508 default: 509 ret = -EINVAL; 510 goto err_free; 511 } 512 break; 513 case REGMAP_ENDIAN_BIG: 514 #ifdef __BIG_ENDIAN 515 case REGMAP_ENDIAN_NATIVE: 516 #endif 517 ctx->big_endian = true; 518 switch (config->val_bits) { 519 case 8: 520 if (config->io_port) { 521 ctx->reg_read = regmap_mmio_ioread8; 522 ctx->reg_write = regmap_mmio_iowrite8; 523 } else { 524 ctx->reg_read = regmap_mmio_read8; 525 ctx->reg_write = regmap_mmio_write8; 526 } 527 break; 528 case 16: 529 if (config->io_port) { 530 ctx->reg_read = regmap_mmio_ioread16be; 531 ctx->reg_write = regmap_mmio_iowrite16be; 532 } else { 533 ctx->reg_read = regmap_mmio_read16be; 534 ctx->reg_write = regmap_mmio_write16be; 535 } 536 break; 537 case 32: 538 if (config->io_port) { 539 ctx->reg_read = regmap_mmio_ioread32be; 540 ctx->reg_write = regmap_mmio_iowrite32be; 541 } else { 542 ctx->reg_read = regmap_mmio_read32be; 543 ctx->reg_write = regmap_mmio_write32be; 544 } 545 break; 546 default: 547 ret = -EINVAL; 548 goto err_free; 549 } 550 break; 551 default: 552 ret = -EINVAL; 553 goto err_free; 554 } 555 556 if (clk_id == NULL) 557 return ctx; 558 559 ctx->clk = clk_get(dev, clk_id); 560 if (IS_ERR(ctx->clk)) { 561 ret = PTR_ERR(ctx->clk); 562 goto err_free; 563 } 564 565 ret = clk_prepare(ctx->clk); 566 if (ret < 0) { 567 clk_put(ctx->clk); 568 goto err_free; 569 } 570 571 return ctx; 572 573 err_free: 574 kfree(ctx); 575 576 return ERR_PTR(ret); 577 } 578 579 struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id, 580 void __iomem *regs, 581 const struct regmap_config *config, 582 struct lock_class_key *lock_key, 583 const char *lock_name) 584 { 585 struct regmap_mmio_context *ctx; 586 587 ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); 588 if (IS_ERR(ctx)) 589 return ERR_CAST(ctx); 590 591 return __regmap_init(dev, ®map_mmio, ctx, config, 592 lock_key, lock_name); 593 } 594 EXPORT_SYMBOL_GPL(__regmap_init_mmio_clk); 595 596 struct regmap *__devm_regmap_init_mmio_clk(struct device *dev, 597 const char *clk_id, 598 void __iomem *regs, 599 const struct regmap_config *config, 600 struct lock_class_key *lock_key, 601 const char *lock_name) 602 { 603 struct regmap_mmio_context *ctx; 604 605 ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); 606 if (IS_ERR(ctx)) 607 return ERR_CAST(ctx); 608 609 return __devm_regmap_init(dev, ®map_mmio, ctx, config, 610 lock_key, lock_name); 611 } 612 EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk); 613 614 int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk) 615 { 616 struct regmap_mmio_context *ctx = map->bus_context; 617 618 ctx->clk = clk; 619 ctx->attached_clk = true; 620 621 return clk_prepare(ctx->clk); 622 } 623 EXPORT_SYMBOL_GPL(regmap_mmio_attach_clk); 624 625 void regmap_mmio_detach_clk(struct regmap *map) 626 { 627 struct regmap_mmio_context *ctx = map->bus_context; 628 629 clk_unprepare(ctx->clk); 630 631 ctx->attached_clk = false; 632 ctx->clk = NULL; 633 } 634 EXPORT_SYMBOL_GPL(regmap_mmio_detach_clk); 635 636 MODULE_LICENSE("GPL v2"); 637