1/* 2 * Copyright (C) ST-Ericsson SA 2010 3 * 4 * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson. 5 * License Terms: GNU General Public License v2 6 */ 7 8#include <linux/seq_file.h> 9#include <linux/uaccess.h> 10#include <linux/fs.h> 11#include <linux/module.h> 12#include <linux/debugfs.h> 13#include <linux/platform_device.h> 14 15#include <linux/mfd/abx500.h> 16#include <linux/mfd/abx500/ab8500.h> 17 18static u32 debug_bank; 19static u32 debug_address; 20 21/** 22 * struct ab8500_reg_range 23 * @first: the first address of the range 24 * @last: the last address of the range 25 * @perm: access permissions for the range 26 */ 27struct ab8500_reg_range { 28 u8 first; 29 u8 last; 30 u8 perm; 31}; 32 33/** 34 * struct ab8500_i2c_ranges 35 * @num_ranges: the number of ranges in the list 36 * @bankid: bank identifier 37 * @range: the list of register ranges 38 */ 39struct ab8500_i2c_ranges { 40 u8 num_ranges; 41 u8 bankid; 42 const struct ab8500_reg_range *range; 43}; 44 45#define AB8500_NAME_STRING "ab8500" 46#define AB8500_NUM_BANKS 22 47 48#define AB8500_REV_REG 0x80 49 50static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { 51 [0x0] = { 52 .num_ranges = 0, 53 .range = 0, 54 }, 55 [AB8500_SYS_CTRL1_BLOCK] = { 56 .num_ranges = 3, 57 .range = (struct ab8500_reg_range[]) { 58 { 59 .first = 0x00, 60 .last = 0x02, 61 }, 62 { 63 .first = 0x42, 64 .last = 0x42, 65 }, 66 { 67 .first = 0x80, 68 .last = 0x81, 69 }, 70 }, 71 }, 72 [AB8500_SYS_CTRL2_BLOCK] = { 73 .num_ranges = 4, 74 .range = (struct ab8500_reg_range[]) { 75 { 76 .first = 0x00, 77 .last = 0x0D, 78 }, 79 { 80 .first = 0x0F, 81 .last = 0x17, 82 }, 83 { 84 .first = 0x30, 85 .last = 0x30, 86 }, 87 { 88 .first = 0x32, 89 .last = 0x33, 90 }, 91 }, 92 }, 93 [AB8500_REGU_CTRL1] = { 94 .num_ranges = 3, 95 .range = (struct ab8500_reg_range[]) { 96 { 97 .first = 0x00, 98 .last = 0x00, 99 }, 100 { 101 .first = 0x03, 102 .last = 0x10, 103 }, 104 { 105 .first = 0x80, 106 .last = 0x84, 107 }, 108 }, 109 }, 110 [AB8500_REGU_CTRL2] = { 111 .num_ranges = 5, 112 .range = (struct ab8500_reg_range[]) { 113 { 114 .first = 0x00, 115 .last = 0x15, 116 }, 117 { 118 .first = 0x17, 119 .last = 0x19, 120 }, 121 { 122 .first = 0x1B, 123 .last = 0x1D, 124 }, 125 { 126 .first = 0x1F, 127 .last = 0x22, 128 }, 129 { 130 .first = 0x40, 131 .last = 0x44, 132 }, 133 /* 0x80-0x8B is SIM registers and should 134 * not be accessed from here */ 135 }, 136 }, 137 [AB8500_USB] = { 138 .num_ranges = 2, 139 .range = (struct ab8500_reg_range[]) { 140 { 141 .first = 0x80, 142 .last = 0x83, 143 }, 144 { 145 .first = 0x87, 146 .last = 0x8A, 147 }, 148 }, 149 }, 150 [AB8500_TVOUT] = { 151 .num_ranges = 9, 152 .range = (struct ab8500_reg_range[]) { 153 { 154 .first = 0x00, 155 .last = 0x12, 156 }, 157 { 158 .first = 0x15, 159 .last = 0x17, 160 }, 161 { 162 .first = 0x19, 163 .last = 0x21, 164 }, 165 { 166 .first = 0x27, 167 .last = 0x2C, 168 }, 169 { 170 .first = 0x41, 171 .last = 0x41, 172 }, 173 { 174 .first = 0x45, 175 .last = 0x5B, 176 }, 177 { 178 .first = 0x5D, 179 .last = 0x5D, 180 }, 181 { 182 .first = 0x69, 183 .last = 0x69, 184 }, 185 { 186 .first = 0x80, 187 .last = 0x81, 188 }, 189 }, 190 }, 191 [AB8500_DBI] = { 192 .num_ranges = 0, 193 .range = NULL, 194 }, 195 [AB8500_ECI_AV_ACC] = { 196 .num_ranges = 1, 197 .range = (struct ab8500_reg_range[]) { 198 { 199 .first = 0x80, 200 .last = 0x82, 201 }, 202 }, 203 }, 204 [0x9] = { 205 .num_ranges = 0, 206 .range = NULL, 207 }, 208 [AB8500_GPADC] = { 209 .num_ranges = 1, 210 .range = (struct ab8500_reg_range[]) { 211 { 212 .first = 0x00, 213 .last = 0x08, 214 }, 215 }, 216 }, 217 [AB8500_CHARGER] = { 218 .num_ranges = 8, 219 .range = (struct ab8500_reg_range[]) { 220 { 221 .first = 0x00, 222 .last = 0x03, 223 }, 224 { 225 .first = 0x05, 226 .last = 0x05, 227 }, 228 { 229 .first = 0x40, 230 .last = 0x40, 231 }, 232 { 233 .first = 0x42, 234 .last = 0x42, 235 }, 236 { 237 .first = 0x44, 238 .last = 0x44, 239 }, 240 { 241 .first = 0x50, 242 .last = 0x55, 243 }, 244 { 245 .first = 0x80, 246 .last = 0x82, 247 }, 248 { 249 .first = 0xC0, 250 .last = 0xC2, 251 }, 252 }, 253 }, 254 [AB8500_GAS_GAUGE] = { 255 .num_ranges = 3, 256 .range = (struct ab8500_reg_range[]) { 257 { 258 .first = 0x00, 259 .last = 0x00, 260 }, 261 { 262 .first = 0x07, 263 .last = 0x0A, 264 }, 265 { 266 .first = 0x10, 267 .last = 0x14, 268 }, 269 }, 270 }, 271 [AB8500_AUDIO] = { 272 .num_ranges = 1, 273 .range = (struct ab8500_reg_range[]) { 274 { 275 .first = 0x00, 276 .last = 0x6F, 277 }, 278 }, 279 }, 280 [AB8500_INTERRUPT] = { 281 .num_ranges = 0, 282 .range = NULL, 283 }, 284 [AB8500_RTC] = { 285 .num_ranges = 1, 286 .range = (struct ab8500_reg_range[]) { 287 { 288 .first = 0x00, 289 .last = 0x0F, 290 }, 291 }, 292 }, 293 [AB8500_MISC] = { 294 .num_ranges = 8, 295 .range = (struct ab8500_reg_range[]) { 296 { 297 .first = 0x00, 298 .last = 0x05, 299 }, 300 { 301 .first = 0x10, 302 .last = 0x15, 303 }, 304 { 305 .first = 0x20, 306 .last = 0x25, 307 }, 308 { 309 .first = 0x30, 310 .last = 0x35, 311 }, 312 { 313 .first = 0x40, 314 .last = 0x45, 315 }, 316 { 317 .first = 0x50, 318 .last = 0x50, 319 }, 320 { 321 .first = 0x60, 322 .last = 0x67, 323 }, 324 { 325 .first = 0x80, 326 .last = 0x80, 327 }, 328 }, 329 }, 330 [0x11] = { 331 .num_ranges = 0, 332 .range = NULL, 333 }, 334 [0x12] = { 335 .num_ranges = 0, 336 .range = NULL, 337 }, 338 [0x13] = { 339 .num_ranges = 0, 340 .range = NULL, 341 }, 342 [0x14] = { 343 .num_ranges = 0, 344 .range = NULL, 345 }, 346 [AB8500_OTP_EMUL] = { 347 .num_ranges = 1, 348 .range = (struct ab8500_reg_range[]) { 349 { 350 .first = 0x01, 351 .last = 0x0F, 352 }, 353 }, 354 }, 355}; 356 357static int ab8500_registers_print(struct seq_file *s, void *p) 358{ 359 struct device *dev = s->private; 360 unsigned int i; 361 u32 bank = debug_bank; 362 363 seq_printf(s, AB8500_NAME_STRING " register values:\n"); 364 365 seq_printf(s, " bank %u:\n", bank); 366 for (i = 0; i < debug_ranges[bank].num_ranges; i++) { 367 u32 reg; 368 369 for (reg = debug_ranges[bank].range[i].first; 370 reg <= debug_ranges[bank].range[i].last; 371 reg++) { 372 u8 value; 373 int err; 374 375 err = abx500_get_register_interruptible(dev, 376 (u8)bank, (u8)reg, &value); 377 if (err < 0) { 378 dev_err(dev, "ab->read fail %d\n", err); 379 return err; 380 } 381 382 err = seq_printf(s, " [%u/0x%02X]: 0x%02X\n", bank, 383 reg, value); 384 if (err < 0) { 385 dev_err(dev, "seq_printf overflow\n"); 386 /* Error is not returned here since 387 * the output is wanted in any case */ 388 return 0; 389 } 390 } 391 } 392 return 0; 393} 394 395static int ab8500_registers_open(struct inode *inode, struct file *file) 396{ 397 return single_open(file, ab8500_registers_print, inode->i_private); 398} 399 400static const struct file_operations ab8500_registers_fops = { 401 .open = ab8500_registers_open, 402 .read = seq_read, 403 .llseek = seq_lseek, 404 .release = single_release, 405 .owner = THIS_MODULE, 406}; 407 408static int ab8500_bank_print(struct seq_file *s, void *p) 409{ 410 return seq_printf(s, "%d\n", debug_bank); 411} 412 413static int ab8500_bank_open(struct inode *inode, struct file *file) 414{ 415 return single_open(file, ab8500_bank_print, inode->i_private); 416} 417 418static ssize_t ab8500_bank_write(struct file *file, 419 const char __user *user_buf, 420 size_t count, loff_t *ppos) 421{ 422 struct device *dev = ((struct seq_file *)(file->private_data))->private; 423 unsigned long user_bank; 424 int err; 425 426 /* Get userspace string and assure termination */ 427 err = kstrtoul_from_user(user_buf, count, 0, &user_bank); 428 if (err) 429 return err; 430 431 if (user_bank >= AB8500_NUM_BANKS) { 432 dev_err(dev, "debugfs error input > number of banks\n"); 433 return -EINVAL; 434 } 435 436 debug_bank = user_bank; 437 438 return count; 439} 440 441static int ab8500_address_print(struct seq_file *s, void *p) 442{ 443 return seq_printf(s, "0x%02X\n", debug_address); 444} 445 446static int ab8500_address_open(struct inode *inode, struct file *file) 447{ 448 return single_open(file, ab8500_address_print, inode->i_private); 449} 450 451static ssize_t ab8500_address_write(struct file *file, 452 const char __user *user_buf, 453 size_t count, loff_t *ppos) 454{ 455 struct device *dev = ((struct seq_file *)(file->private_data))->private; 456 unsigned long user_address; 457 int err; 458 459 /* Get userspace string and assure termination */ 460 err = kstrtoul_from_user(user_buf, count, 0, &user_address); 461 if (err) 462 return err; 463 464 if (user_address > 0xff) { 465 dev_err(dev, "debugfs error input > 0xff\n"); 466 return -EINVAL; 467 } 468 debug_address = user_address; 469 return count; 470} 471 472static int ab8500_val_print(struct seq_file *s, void *p) 473{ 474 struct device *dev = s->private; 475 int ret; 476 u8 regvalue; 477 478 ret = abx500_get_register_interruptible(dev, 479 (u8)debug_bank, (u8)debug_address, ®value); 480 if (ret < 0) { 481 dev_err(dev, "abx500_get_reg fail %d, %d\n", 482 ret, __LINE__); 483 return -EINVAL; 484 } 485 seq_printf(s, "0x%02X\n", regvalue); 486 487 return 0; 488} 489 490static int ab8500_val_open(struct inode *inode, struct file *file) 491{ 492 return single_open(file, ab8500_val_print, inode->i_private); 493} 494 495static ssize_t ab8500_val_write(struct file *file, 496 const char __user *user_buf, 497 size_t count, loff_t *ppos) 498{ 499 struct device *dev = ((struct seq_file *)(file->private_data))->private; 500 unsigned long user_val; 501 int err; 502 503 /* Get userspace string and assure termination */ 504 err = kstrtoul_from_user(user_buf, count, 0, &user_val); 505 if (err) 506 return err; 507 508 if (user_val > 0xff) { 509 dev_err(dev, "debugfs error input > 0xff\n"); 510 return -EINVAL; 511 } 512 err = abx500_set_register_interruptible(dev, 513 (u8)debug_bank, debug_address, (u8)user_val); 514 if (err < 0) { 515 printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__); 516 return -EINVAL; 517 } 518 519 return count; 520} 521 522static const struct file_operations ab8500_bank_fops = { 523 .open = ab8500_bank_open, 524 .write = ab8500_bank_write, 525 .read = seq_read, 526 .llseek = seq_lseek, 527 .release = single_release, 528 .owner = THIS_MODULE, 529}; 530 531static const struct file_operations ab8500_address_fops = { 532 .open = ab8500_address_open, 533 .write = ab8500_address_write, 534 .read = seq_read, 535 .llseek = seq_lseek, 536 .release = single_release, 537 .owner = THIS_MODULE, 538}; 539 540static const struct file_operations ab8500_val_fops = { 541 .open = ab8500_val_open, 542 .write = ab8500_val_write, 543 .read = seq_read, 544 .llseek = seq_lseek, 545 .release = single_release, 546 .owner = THIS_MODULE, 547}; 548 549static struct dentry *ab8500_dir; 550static struct dentry *ab8500_reg_file; 551static struct dentry *ab8500_bank_file; 552static struct dentry *ab8500_address_file; 553static struct dentry *ab8500_val_file; 554 555static int __devinit ab8500_debug_probe(struct platform_device *plf) 556{ 557 debug_bank = AB8500_MISC; 558 debug_address = AB8500_REV_REG & 0x00FF; 559 560 ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); 561 if (!ab8500_dir) 562 goto exit_no_debugfs; 563 564 ab8500_reg_file = debugfs_create_file("all-bank-registers", 565 S_IRUGO, ab8500_dir, &plf->dev, &ab8500_registers_fops); 566 if (!ab8500_reg_file) 567 goto exit_destroy_dir; 568 569 ab8500_bank_file = debugfs_create_file("register-bank", 570 (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_bank_fops); 571 if (!ab8500_bank_file) 572 goto exit_destroy_reg; 573 574 ab8500_address_file = debugfs_create_file("register-address", 575 (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, 576 &ab8500_address_fops); 577 if (!ab8500_address_file) 578 goto exit_destroy_bank; 579 580 ab8500_val_file = debugfs_create_file("register-value", 581 (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_val_fops); 582 if (!ab8500_val_file) 583 goto exit_destroy_address; 584 585 return 0; 586 587exit_destroy_address: 588 debugfs_remove(ab8500_address_file); 589exit_destroy_bank: 590 debugfs_remove(ab8500_bank_file); 591exit_destroy_reg: 592 debugfs_remove(ab8500_reg_file); 593exit_destroy_dir: 594 debugfs_remove(ab8500_dir); 595exit_no_debugfs: 596 dev_err(&plf->dev, "failed to create debugfs entries.\n"); 597 return -ENOMEM; 598} 599 600static int __devexit ab8500_debug_remove(struct platform_device *plf) 601{ 602 debugfs_remove(ab8500_val_file); 603 debugfs_remove(ab8500_address_file); 604 debugfs_remove(ab8500_bank_file); 605 debugfs_remove(ab8500_reg_file); 606 debugfs_remove(ab8500_dir); 607 608 return 0; 609} 610 611static struct platform_driver ab8500_debug_driver = { 612 .driver = { 613 .name = "ab8500-debug", 614 .owner = THIS_MODULE, 615 }, 616 .probe = ab8500_debug_probe, 617 .remove = __devexit_p(ab8500_debug_remove) 618}; 619 620static int __init ab8500_debug_init(void) 621{ 622 return platform_driver_register(&ab8500_debug_driver); 623} 624 625static void __exit ab8500_debug_exit(void) 626{ 627 platform_driver_unregister(&ab8500_debug_driver); 628} 629subsys_initcall(ab8500_debug_init); 630module_exit(ab8500_debug_exit); 631 632MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com"); 633MODULE_DESCRIPTION("AB8500 DEBUG"); 634MODULE_LICENSE("GPL v2"); 635