18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * cb710/debug.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright by Michał Mirosław, 2008-2009 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#include <linux/cb710.h> 88c2ecf20Sopenharmony_ci#include <linux/kernel.h> 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#define CB710_REG_COUNT 0x80 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cistatic const u16 allow[CB710_REG_COUNT/16] = { 148c2ecf20Sopenharmony_ci 0xFFF0, 0xFFFF, 0xFFFF, 0xFFFF, 158c2ecf20Sopenharmony_ci 0xFFF0, 0xFFFF, 0xFFFF, 0xFFFF, 168c2ecf20Sopenharmony_ci}; 178c2ecf20Sopenharmony_cistatic const char *const prefix[ARRAY_SIZE(allow)] = { 188c2ecf20Sopenharmony_ci "MMC", "MMC", "MMC", "MMC", 198c2ecf20Sopenharmony_ci "MS?", "MS?", "SM?", "SM?" 208c2ecf20Sopenharmony_ci}; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic inline int allow_reg_read(unsigned block, unsigned offset, unsigned bits) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci unsigned mask = (1 << bits/8) - 1; 258c2ecf20Sopenharmony_ci offset *= bits/8; 268c2ecf20Sopenharmony_ci return ((allow[block] >> offset) & mask) == mask; 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define CB710_READ_REGS_TEMPLATE(t) \ 308c2ecf20Sopenharmony_cistatic void cb710_read_regs_##t(void __iomem *iobase, \ 318c2ecf20Sopenharmony_ci u##t *reg, unsigned select) \ 328c2ecf20Sopenharmony_ci{ \ 338c2ecf20Sopenharmony_ci unsigned i, j; \ 348c2ecf20Sopenharmony_ci \ 358c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(allow); ++i, reg += 16/(t/8)) { \ 368c2ecf20Sopenharmony_ci if (!(select & (1 << i))) \ 378c2ecf20Sopenharmony_ci continue; \ 388c2ecf20Sopenharmony_ci \ 398c2ecf20Sopenharmony_ci for (j = 0; j < 0x10/(t/8); ++j) { \ 408c2ecf20Sopenharmony_ci if (!allow_reg_read(i, j, t)) \ 418c2ecf20Sopenharmony_ci continue; \ 428c2ecf20Sopenharmony_ci reg[j] = ioread##t(iobase \ 438c2ecf20Sopenharmony_ci + (i << 4) + (j * (t/8))); \ 448c2ecf20Sopenharmony_ci } \ 458c2ecf20Sopenharmony_ci } \ 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic const char cb710_regf_8[] = "%02X"; 498c2ecf20Sopenharmony_cistatic const char cb710_regf_16[] = "%04X"; 508c2ecf20Sopenharmony_cistatic const char cb710_regf_32[] = "%08X"; 518c2ecf20Sopenharmony_cistatic const char cb710_xes[] = "xxxxxxxx"; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define CB710_DUMP_REGS_TEMPLATE(t) \ 548c2ecf20Sopenharmony_cistatic void cb710_dump_regs_##t(struct device *dev, \ 558c2ecf20Sopenharmony_ci const u##t *reg, unsigned select) \ 568c2ecf20Sopenharmony_ci{ \ 578c2ecf20Sopenharmony_ci const char *const xp = &cb710_xes[8 - t/4]; \ 588c2ecf20Sopenharmony_ci const char *const format = cb710_regf_##t; \ 598c2ecf20Sopenharmony_ci \ 608c2ecf20Sopenharmony_ci char msg[100], *p; \ 618c2ecf20Sopenharmony_ci unsigned i, j; \ 628c2ecf20Sopenharmony_ci \ 638c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(allow); ++i, reg += 16/(t/8)) { \ 648c2ecf20Sopenharmony_ci if (!(select & (1 << i))) \ 658c2ecf20Sopenharmony_ci continue; \ 668c2ecf20Sopenharmony_ci p = msg; \ 678c2ecf20Sopenharmony_ci for (j = 0; j < 0x10/(t/8); ++j) { \ 688c2ecf20Sopenharmony_ci *p++ = ' '; \ 698c2ecf20Sopenharmony_ci if (j == 8/(t/8)) \ 708c2ecf20Sopenharmony_ci *p++ = ' '; \ 718c2ecf20Sopenharmony_ci if (allow_reg_read(i, j, t)) \ 728c2ecf20Sopenharmony_ci p += sprintf(p, format, reg[j]); \ 738c2ecf20Sopenharmony_ci else \ 748c2ecf20Sopenharmony_ci p += sprintf(p, "%s", xp); \ 758c2ecf20Sopenharmony_ci } \ 768c2ecf20Sopenharmony_ci dev_dbg(dev, "%s 0x%02X %s\n", prefix[i], i << 4, msg); \ 778c2ecf20Sopenharmony_ci } \ 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#define CB710_READ_AND_DUMP_REGS_TEMPLATE(t) \ 818c2ecf20Sopenharmony_cistatic void cb710_read_and_dump_regs_##t(struct cb710_chip *chip, \ 828c2ecf20Sopenharmony_ci unsigned select) \ 838c2ecf20Sopenharmony_ci{ \ 848c2ecf20Sopenharmony_ci u##t regs[CB710_REG_COUNT/sizeof(u##t)]; \ 858c2ecf20Sopenharmony_ci \ 868c2ecf20Sopenharmony_ci memset(®s, 0, sizeof(regs)); \ 878c2ecf20Sopenharmony_ci cb710_read_regs_##t(chip->iobase, regs, select); \ 888c2ecf20Sopenharmony_ci cb710_dump_regs_##t(cb710_chip_dev(chip), regs, select); \ 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci#define CB710_REG_ACCESS_TEMPLATES(t) \ 928c2ecf20Sopenharmony_ci CB710_READ_REGS_TEMPLATE(t) \ 938c2ecf20Sopenharmony_ci CB710_DUMP_REGS_TEMPLATE(t) \ 948c2ecf20Sopenharmony_ci CB710_READ_AND_DUMP_REGS_TEMPLATE(t) 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ciCB710_REG_ACCESS_TEMPLATES(8) 978c2ecf20Sopenharmony_ciCB710_REG_ACCESS_TEMPLATES(16) 988c2ecf20Sopenharmony_ciCB710_REG_ACCESS_TEMPLATES(32) 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_civoid cb710_dump_regs(struct cb710_chip *chip, unsigned select) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci if (!(select & CB710_DUMP_REGS_MASK)) 1038c2ecf20Sopenharmony_ci select = CB710_DUMP_REGS_ALL; 1048c2ecf20Sopenharmony_ci if (!(select & CB710_DUMP_ACCESS_MASK)) 1058c2ecf20Sopenharmony_ci select |= CB710_DUMP_ACCESS_8; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci if (select & CB710_DUMP_ACCESS_32) 1088c2ecf20Sopenharmony_ci cb710_read_and_dump_regs_32(chip, select); 1098c2ecf20Sopenharmony_ci if (select & CB710_DUMP_ACCESS_16) 1108c2ecf20Sopenharmony_ci cb710_read_and_dump_regs_16(chip, select); 1118c2ecf20Sopenharmony_ci if (select & CB710_DUMP_ACCESS_8) 1128c2ecf20Sopenharmony_ci cb710_read_and_dump_regs_8(chip, select); 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cb710_dump_regs); 1158c2ecf20Sopenharmony_ci 116