aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2011-09-22 02:22:33 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2011-10-24 08:09:16 -0400
commit94be70d4b279ba1b35119a3340833ffcc798c2e2 (patch)
treeb447c0c927d8403895e44f9f42e9e436ed9210c7 /drivers/mfd
parentb7ddac53df5097e8437ca40316caf79885d31946 (diff)
mfd: Break out ab5500 debugfs code
This breaks the debugfs portions of the AB5500 driver into its own file. Split off a _raw function to access registers since we don't want to expose a generically named function globally. Move all required data structures to a shared ab5500-core.h file. Cc: Mattias Wallin <mattias.wallin@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Kconfig8
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/ab5500-core.c907
-rw-r--r--drivers/mfd/ab5500-core.h87
-rw-r--r--drivers/mfd/ab5500-debugfs.c806
-rw-r--r--drivers/mfd/ab5500-debugfs.h22
6 files changed, 941 insertions, 890 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 8594de8b86a0..f22bd2f0ecc3 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -572,6 +572,14 @@ config AB5500_CORE
572 chip. This connects to the db5500 chip via the I2C bus via PRCMU. 572 chip. This connects to the db5500 chip via the I2C bus via PRCMU.
573 This chip embeds various other multimedia funtionalities as well. 573 This chip embeds various other multimedia funtionalities as well.
574 574
575config AB5500_DEBUG
576 bool "Enable debug info via debugfs"
577 depends on AB5500_CORE && DEBUG_FS
578 default y if DEBUG_FS
579 help
580 Select this option if you want debug information from the AB5500
581 using the debug filesystem, debugfs.
582
575config AB8500_CORE 583config AB8500_CORE
576 bool "ST-Ericsson AB8500 Mixed Signal Power Management chip" 584 bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
577 depends on GENERIC_HARDIRQS && ABX500_CORE 585 depends on GENERIC_HARDIRQS && ABX500_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 457fed8474cf..7ed553d8157a 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
81obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o 81obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
82obj-$(CONFIG_AB3550_CORE) += ab3550-core.o 82obj-$(CONFIG_AB3550_CORE) += ab3550-core.o
83obj-$(CONFIG_AB5500_CORE) += ab5500-core.o 83obj-$(CONFIG_AB5500_CORE) += ab5500-core.o
84obj-$(CONFIG_AB5500_DEBUG) += ab5500-debugfs.o
84obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o 85obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
85obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o 86obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o
86obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o 87obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
diff --git a/drivers/mfd/ab5500-core.c b/drivers/mfd/ab5500-core.c
index afec0f2ede42..4175544b491b 100644
--- a/drivers/mfd/ab5500-core.c
+++ b/drivers/mfd/ab5500-core.c
@@ -21,9 +21,6 @@
21#include <linux/irq.h> 21#include <linux/irq.h>
22#include <linux/interrupt.h> 22#include <linux/interrupt.h>
23#include <linux/random.h> 23#include <linux/random.h>
24#include <linux/debugfs.h>
25#include <linux/seq_file.h>
26#include <linux/uaccess.h>
27#include <linux/mfd/ab5500/ab5500.h> 24#include <linux/mfd/ab5500/ab5500.h>
28#include <linux/mfd/abx500.h> 25#include <linux/mfd/abx500.h>
29#include <linux/list.h> 26#include <linux/list.h>
@@ -33,87 +30,13 @@
33#include <linux/version.h> 30#include <linux/version.h>
34#include <linux/mfd/db5500-prcmu.h> 31#include <linux/mfd/db5500-prcmu.h>
35 32
33#include "ab5500-core.h"
34#include "ab5500-debugfs.h"
35
36#define AB5500_NUM_EVENT_REG 23 36#define AB5500_NUM_EVENT_REG 23
37#define AB5500_IT_LATCH0_REG 0x40 37#define AB5500_IT_LATCH0_REG 0x40
38#define AB5500_IT_MASK0_REG 0x60 38#define AB5500_IT_MASK0_REG 0x60
39 39
40/* Read/write operation values. */
41#define AB5500_PERM_RD (0x01)
42#define AB5500_PERM_WR (0x02)
43
44/* Read/write permissions. */
45#define AB5500_PERM_RO (AB5500_PERM_RD)
46#define AB5500_PERM_RW (AB5500_PERM_RD | AB5500_PERM_WR)
47
48#define AB5500_MASK_BASE (0x60)
49#define AB5500_MASK_END (0x79)
50#define AB5500_CHIP_ID (0x20)
51
52/**
53 * struct ab5500_bank
54 * @slave_addr: I2C slave_addr found in AB5500 specification
55 * @name: Documentation name of the bank. For reference
56 */
57struct ab5500_bank {
58 u8 slave_addr;
59 const char *name;
60};
61
62static const struct ab5500_bank bankinfo[AB5500_NUM_BANKS] = {
63 [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
64 AB5500_ADDR_VIT_IO_I2C_CLK_TST_OTP, "VIT_IO_I2C_CLK_TST_OTP"},
65 [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
66 AB5500_ADDR_VDDDIG_IO_I2C_CLK_TST, "VDDDIG_IO_I2C_CLK_TST"},
67 [AB5500_BANK_VDENC] = {AB5500_ADDR_VDENC, "VDENC"},
68 [AB5500_BANK_SIM_USBSIM] = {AB5500_ADDR_SIM_USBSIM, "SIM_USBSIM"},
69 [AB5500_BANK_LED] = {AB5500_ADDR_LED, "LED"},
70 [AB5500_BANK_ADC] = {AB5500_ADDR_ADC, "ADC"},
71 [AB5500_BANK_RTC] = {AB5500_ADDR_RTC, "RTC"},
72 [AB5500_BANK_STARTUP] = {AB5500_ADDR_STARTUP, "STARTUP"},
73 [AB5500_BANK_DBI_ECI] = {AB5500_ADDR_DBI_ECI, "DBI-ECI"},
74 [AB5500_BANK_CHG] = {AB5500_ADDR_CHG, "CHG"},
75 [AB5500_BANK_FG_BATTCOM_ACC] = {
76 AB5500_ADDR_FG_BATTCOM_ACC, "FG_BATCOM_ACC"},
77 [AB5500_BANK_USB] = {AB5500_ADDR_USB, "USB"},
78 [AB5500_BANK_IT] = {AB5500_ADDR_IT, "IT"},
79 [AB5500_BANK_VIBRA] = {AB5500_ADDR_VIBRA, "VIBRA"},
80 [AB5500_BANK_AUDIO_HEADSETUSB] = {
81 AB5500_ADDR_AUDIO_HEADSETUSB, "AUDIO_HEADSETUSB"},
82};
83
84/**
85 * struct ab5500_reg_range
86 * @first: the first address of the range
87 * @last: the last address of the range
88 * @perm: access permissions for the range
89 */
90struct ab5500_reg_range {
91 u8 first;
92 u8 last;
93 u8 perm;
94};
95
96/**
97 * struct ab5500_i2c_ranges
98 * @count: the number of ranges in the list
99 * @range: the list of register ranges
100 */
101struct ab5500_i2c_ranges {
102 u8 nranges;
103 u8 bankid;
104 const struct ab5500_reg_range *range;
105};
106
107/**
108 * struct ab5500_i2c_banks
109 * @count: the number of ranges in the list
110 * @range: the list of register ranges
111 */
112struct ab5500_i2c_banks {
113 u8 nbanks;
114 const struct ab5500_i2c_ranges *bank;
115};
116
117/* 40/*
118 * Permissible register ranges for reading and writing per device and bank. 41 * Permissible register ranges for reading and writing per device and bank.
119 * 42 *
@@ -1073,8 +996,9 @@ static struct mfd_cell ab5500_devs[AB5500_NUM_DEVICES] = {
1073/* 996/*
1074 * Functionality for getting/setting register values. 997 * Functionality for getting/setting register values.
1075 */ 998 */
1076static int get_register_interruptible(struct ab5500 *ab, u8 bank, u8 reg, 999int ab5500_get_register_interruptible_raw(struct ab5500 *ab,
1077 u8 *value) 1000 u8 bank, u8 reg,
1001 u8 *value)
1078{ 1002{
1079 int err; 1003 int err;
1080 1004
@@ -1121,7 +1045,7 @@ out:
1121 return err; 1045 return err;
1122} 1046}
1123 1047
1124static int mask_and_set_register_interruptible(struct ab5500 *ab, u8 bank, 1048int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank,
1125 u8 reg, u8 bitmask, u8 bitvalues) 1049 u8 reg, u8 bitmask, u8 bitvalues)
1126{ 1050{
1127 int err = 0; 1051 int err = 0;
@@ -1158,7 +1082,8 @@ static int mask_and_set_register_interruptible(struct ab5500 *ab, u8 bank,
1158static int 1082static int
1159set_register_interruptible(struct ab5500 *ab, u8 bank, u8 reg, u8 value) 1083set_register_interruptible(struct ab5500 *ab, u8 bank, u8 reg, u8 value)
1160{ 1084{
1161 return mask_and_set_register_interruptible(ab, bank, reg, 0xff, value); 1085 return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg,
1086 0xff, value);
1162} 1087}
1163 1088
1164/* 1089/*
@@ -1261,7 +1186,7 @@ static int ab5500_mask_and_set_register_interruptible(struct device *dev,
1261 return -EINVAL; 1186 return -EINVAL;
1262 1187
1263 ab = dev_get_drvdata(dev->parent); 1188 ab = dev_get_drvdata(dev->parent);
1264 return mask_and_set_register_interruptible(ab, bank, reg, 1189 return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg,
1265 bitmask, bitvalues); 1190 bitmask, bitvalues);
1266} 1191}
1267 1192
@@ -1283,7 +1208,7 @@ static int ab5500_get_register_interruptible(struct device *dev, u8 bank,
1283 return -EINVAL; 1208 return -EINVAL;
1284 1209
1285 ab = dev_get_drvdata(dev->parent); 1210 ab = dev_get_drvdata(dev->parent);
1286 return get_register_interruptible(ab, bank, reg, value); 1211 return ab5500_get_register_interruptible_raw(ab, bank, reg, value);
1287} 1212}
1288 1213
1289static int ab5500_get_register_page_interruptible(struct device *dev, u8 bank, 1214static int ab5500_get_register_page_interruptible(struct device *dev, u8 bank,
@@ -1327,806 +1252,6 @@ static struct abx500_ops ab5500_ops = {
1327 .startup_irq_enabled = NULL, 1252 .startup_irq_enabled = NULL,
1328}; 1253};
1329 1254
1330#ifdef CONFIG_DEBUG_FS
1331static struct ab5500_i2c_ranges ab5500_reg_ranges[AB5500_NUM_BANKS] = {
1332 [AB5500_BANK_LED] = {
1333 .bankid = AB5500_BANK_LED,
1334 .nranges = 1,
1335 .range = (struct ab5500_reg_range[]) {
1336 {
1337 .first = 0x00,
1338 .last = 0x0C,
1339 .perm = AB5500_PERM_RW,
1340 },
1341 },
1342 },
1343 [AB5500_BANK_ADC] = {
1344 .bankid = AB5500_BANK_ADC,
1345 .nranges = 6,
1346 .range = (struct ab5500_reg_range[]) {
1347 {
1348 .first = 0x1F,
1349 .last = 0x22,
1350 .perm = AB5500_PERM_RO,
1351 },
1352 {
1353 .first = 0x23,
1354 .last = 0x24,
1355 .perm = AB5500_PERM_RW,
1356 },
1357 {
1358 .first = 0x26,
1359 .last = 0x2D,
1360 .perm = AB5500_PERM_RO,
1361 },
1362 {
1363 .first = 0x2F,
1364 .last = 0x34,
1365 .perm = AB5500_PERM_RW,
1366 },
1367 {
1368 .first = 0x37,
1369 .last = 0x57,
1370 .perm = AB5500_PERM_RW,
1371 },
1372 {
1373 .first = 0x58,
1374 .last = 0x58,
1375 .perm = AB5500_PERM_RO,
1376 },
1377 },
1378 },
1379 [AB5500_BANK_RTC] = {
1380 .bankid = AB5500_BANK_RTC,
1381 .nranges = 2,
1382 .range = (struct ab5500_reg_range[]) {
1383 {
1384 .first = 0x00,
1385 .last = 0x04,
1386 .perm = AB5500_PERM_RW,
1387 },
1388 {
1389 .first = 0x06,
1390 .last = 0x0C,
1391 .perm = AB5500_PERM_RW,
1392 },
1393 },
1394 },
1395 [AB5500_BANK_STARTUP] = {
1396 .bankid = AB5500_BANK_STARTUP,
1397 .nranges = 12,
1398 .range = (struct ab5500_reg_range[]) {
1399 {
1400 .first = 0x00,
1401 .last = 0x01,
1402 .perm = AB5500_PERM_RW,
1403 },
1404 {
1405 .first = 0x1F,
1406 .last = 0x1F,
1407 .perm = AB5500_PERM_RW,
1408 },
1409 {
1410 .first = 0x2E,
1411 .last = 0x2E,
1412 .perm = AB5500_PERM_RO,
1413 },
1414 {
1415 .first = 0x2F,
1416 .last = 0x30,
1417 .perm = AB5500_PERM_RW,
1418 },
1419 {
1420 .first = 0x50,
1421 .last = 0x51,
1422 .perm = AB5500_PERM_RW,
1423 },
1424 {
1425 .first = 0x60,
1426 .last = 0x61,
1427 .perm = AB5500_PERM_RW,
1428 },
1429 {
1430 .first = 0x66,
1431 .last = 0x8A,
1432 .perm = AB5500_PERM_RW,
1433 },
1434 {
1435 .first = 0x8C,
1436 .last = 0x96,
1437 .perm = AB5500_PERM_RW,
1438 },
1439 {
1440 .first = 0xAA,
1441 .last = 0xB4,
1442 .perm = AB5500_PERM_RW,
1443 },
1444 {
1445 .first = 0xB7,
1446 .last = 0xBF,
1447 .perm = AB5500_PERM_RW,
1448 },
1449 {
1450 .first = 0xC1,
1451 .last = 0xCA,
1452 .perm = AB5500_PERM_RW,
1453 },
1454 {
1455 .first = 0xD3,
1456 .last = 0xE0,
1457 .perm = AB5500_PERM_RW,
1458 },
1459 },
1460 },
1461 [AB5500_BANK_DBI_ECI] = {
1462 .bankid = AB5500_BANK_DBI_ECI,
1463 .nranges = 3,
1464 .range = (struct ab5500_reg_range[]) {
1465 {
1466 .first = 0x00,
1467 .last = 0x07,
1468 .perm = AB5500_PERM_RW,
1469 },
1470 {
1471 .first = 0x10,
1472 .last = 0x10,
1473 .perm = AB5500_PERM_RW,
1474 },
1475 {
1476 .first = 0x13,
1477 .last = 0x13,
1478 .perm = AB5500_PERM_RW,
1479 },
1480 },
1481 },
1482 [AB5500_BANK_CHG] = {
1483 .bankid = AB5500_BANK_CHG,
1484 .nranges = 2,
1485 .range = (struct ab5500_reg_range[]) {
1486 {
1487 .first = 0x11,
1488 .last = 0x11,
1489 .perm = AB5500_PERM_RO,
1490 },
1491 {
1492 .first = 0x12,
1493 .last = 0x1B,
1494 .perm = AB5500_PERM_RW,
1495 },
1496 },
1497 },
1498 [AB5500_BANK_FG_BATTCOM_ACC] = {
1499 .bankid = AB5500_BANK_FG_BATTCOM_ACC,
1500 .nranges = 2,
1501 .range = (struct ab5500_reg_range[]) {
1502 {
1503 .first = 0x00,
1504 .last = 0x0B,
1505 .perm = AB5500_PERM_RO,
1506 },
1507 {
1508 .first = 0x0C,
1509 .last = 0x10,
1510 .perm = AB5500_PERM_RW,
1511 },
1512 },
1513 },
1514 [AB5500_BANK_USB] = {
1515 .bankid = AB5500_BANK_USB,
1516 .nranges = 12,
1517 .range = (struct ab5500_reg_range[]) {
1518 {
1519 .first = 0x01,
1520 .last = 0x01,
1521 .perm = AB5500_PERM_RW,
1522 },
1523 {
1524 .first = 0x80,
1525 .last = 0x83,
1526 .perm = AB5500_PERM_RW,
1527 },
1528 {
1529 .first = 0x87,
1530 .last = 0x8A,
1531 .perm = AB5500_PERM_RW,
1532 },
1533 {
1534 .first = 0x8B,
1535 .last = 0x8B,
1536 .perm = AB5500_PERM_RO,
1537 },
1538 {
1539 .first = 0x91,
1540 .last = 0x92,
1541 .perm = AB5500_PERM_RO,
1542 },
1543 {
1544 .first = 0x93,
1545 .last = 0x93,
1546 .perm = AB5500_PERM_RW,
1547 },
1548 {
1549 .first = 0x94,
1550 .last = 0x94,
1551 .perm = AB5500_PERM_RO,
1552 },
1553 {
1554 .first = 0xA8,
1555 .last = 0xB0,
1556 .perm = AB5500_PERM_RO,
1557 },
1558 {
1559 .first = 0xB2,
1560 .last = 0xB2,
1561 .perm = AB5500_PERM_RO,
1562 },
1563 {
1564 .first = 0xB4,
1565 .last = 0xBC,
1566 .perm = AB5500_PERM_RO,
1567 },
1568 {
1569 .first = 0xBF,
1570 .last = 0xBF,
1571 .perm = AB5500_PERM_RO,
1572 },
1573 {
1574 .first = 0xC1,
1575 .last = 0xC5,
1576 .perm = AB5500_PERM_RO,
1577 },
1578 },
1579 },
1580 [AB5500_BANK_IT] = {
1581 .bankid = AB5500_BANK_IT,
1582 .nranges = 4,
1583 .range = (struct ab5500_reg_range[]) {
1584 {
1585 .first = 0x00,
1586 .last = 0x02,
1587 .perm = AB5500_PERM_RO,
1588 },
1589 {
1590 .first = 0x20,
1591 .last = 0x36,
1592 .perm = AB5500_PERM_RO,
1593 },
1594 {
1595 .first = 0x40,
1596 .last = 0x56,
1597 .perm = AB5500_PERM_RO,
1598 },
1599 {
1600 .first = 0x60,
1601 .last = 0x76,
1602 .perm = AB5500_PERM_RO,
1603 },
1604 },
1605 },
1606 [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
1607 .bankid = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST,
1608 .nranges = 7,
1609 .range = (struct ab5500_reg_range[]) {
1610 {
1611 .first = 0x02,
1612 .last = 0x02,
1613 .perm = AB5500_PERM_RW,
1614 },
1615 {
1616 .first = 0x12,
1617 .last = 0x12,
1618 .perm = AB5500_PERM_RW,
1619 },
1620 {
1621 .first = 0x30,
1622 .last = 0x34,
1623 .perm = AB5500_PERM_RW,
1624 },
1625 {
1626 .first = 0x40,
1627 .last = 0x44,
1628 .perm = AB5500_PERM_RW,
1629 },
1630 {
1631 .first = 0x50,
1632 .last = 0x54,
1633 .perm = AB5500_PERM_RW,
1634 },
1635 {
1636 .first = 0x60,
1637 .last = 0x64,
1638 .perm = AB5500_PERM_RW,
1639 },
1640 {
1641 .first = 0x70,
1642 .last = 0x74,
1643 .perm = AB5500_PERM_RW,
1644 },
1645 },
1646 },
1647 [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
1648 .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
1649 .nranges = 13,
1650 .range = (struct ab5500_reg_range[]) {
1651 {
1652 .first = 0x01,
1653 .last = 0x01,
1654 .perm = AB5500_PERM_RW,
1655 },
1656 {
1657 .first = 0x02,
1658 .last = 0x02,
1659 .perm = AB5500_PERM_RO,
1660 },
1661 {
1662 .first = 0x0D,
1663 .last = 0x0F,
1664 .perm = AB5500_PERM_RW,
1665 },
1666 {
1667 .first = 0x1C,
1668 .last = 0x1C,
1669 .perm = AB5500_PERM_RW,
1670 },
1671 {
1672 .first = 0x1E,
1673 .last = 0x1E,
1674 .perm = AB5500_PERM_RW,
1675 },
1676 {
1677 .first = 0x20,
1678 .last = 0x21,
1679 .perm = AB5500_PERM_RW,
1680 },
1681 {
1682 .first = 0x25,
1683 .last = 0x25,
1684 .perm = AB5500_PERM_RW,
1685 },
1686 {
1687 .first = 0x28,
1688 .last = 0x2A,
1689 .perm = AB5500_PERM_RW,
1690 },
1691 {
1692 .first = 0x30,
1693 .last = 0x33,
1694 .perm = AB5500_PERM_RW,
1695 },
1696 {
1697 .first = 0x40,
1698 .last = 0x43,
1699 .perm = AB5500_PERM_RW,
1700 },
1701 {
1702 .first = 0x50,
1703 .last = 0x53,
1704 .perm = AB5500_PERM_RW,
1705 },
1706 {
1707 .first = 0x60,
1708 .last = 0x63,
1709 .perm = AB5500_PERM_RW,
1710 },
1711 {
1712 .first = 0x70,
1713 .last = 0x73,
1714 .perm = AB5500_PERM_RW,
1715 },
1716 },
1717 },
1718 [AB5500_BANK_VIBRA] = {
1719 .bankid = AB5500_BANK_VIBRA,
1720 .nranges = 2,
1721 .range = (struct ab5500_reg_range[]) {
1722 {
1723 .first = 0x10,
1724 .last = 0x13,
1725 .perm = AB5500_PERM_RW,
1726 },
1727 {
1728 .first = 0xFE,
1729 .last = 0xFE,
1730 .perm = AB5500_PERM_RW,
1731 },
1732 },
1733 },
1734 [AB5500_BANK_AUDIO_HEADSETUSB] = {
1735 .bankid = AB5500_BANK_AUDIO_HEADSETUSB,
1736 .nranges = 2,
1737 .range = (struct ab5500_reg_range[]) {
1738 {
1739 .first = 0x00,
1740 .last = 0x48,
1741 .perm = AB5500_PERM_RW,
1742 },
1743 {
1744 .first = 0xEB,
1745 .last = 0xFB,
1746 .perm = AB5500_PERM_RW,
1747 },
1748 },
1749 },
1750 [AB5500_BANK_SIM_USBSIM] = {
1751 .bankid = AB5500_BANK_SIM_USBSIM,
1752 .nranges = 1,
1753 .range = (struct ab5500_reg_range[]) {
1754 {
1755 .first = 0x13,
1756 .last = 0x19,
1757 .perm = AB5500_PERM_RW,
1758 },
1759 },
1760 },
1761 [AB5500_BANK_VDENC] = {
1762 .bankid = AB5500_BANK_VDENC,
1763 .nranges = 12,
1764 .range = (struct ab5500_reg_range[]) {
1765 {
1766 .first = 0x00,
1767 .last = 0x08,
1768 .perm = AB5500_PERM_RW,
1769 },
1770 {
1771 .first = 0x09,
1772 .last = 0x09,
1773 .perm = AB5500_PERM_RO,
1774 },
1775 {
1776 .first = 0x0A,
1777 .last = 0x12,
1778 .perm = AB5500_PERM_RW,
1779 },
1780 {
1781 .first = 0x15,
1782 .last = 0x19,
1783 .perm = AB5500_PERM_RW,
1784 },
1785 {
1786 .first = 0x1B,
1787 .last = 0x21,
1788 .perm = AB5500_PERM_RW,
1789 },
1790 {
1791 .first = 0x27,
1792 .last = 0x2C,
1793 .perm = AB5500_PERM_RW,
1794 },
1795 {
1796 .first = 0x41,
1797 .last = 0x41,
1798 .perm = AB5500_PERM_RW,
1799 },
1800 {
1801 .first = 0x45,
1802 .last = 0x5B,
1803 .perm = AB5500_PERM_RW,
1804 },
1805 {
1806 .first = 0x5D,
1807 .last = 0x5D,
1808 .perm = AB5500_PERM_RW,
1809 },
1810 {
1811 .first = 0x69,
1812 .last = 0x69,
1813 .perm = AB5500_PERM_RW,
1814 },
1815 {
1816 .first = 0x6C,
1817 .last = 0x6D,
1818 .perm = AB5500_PERM_RW,
1819 },
1820 {
1821 .first = 0x80,
1822 .last = 0x81,
1823 .perm = AB5500_PERM_RW,
1824 },
1825 },
1826 },
1827};
1828static int ab5500_registers_print(struct seq_file *s, void *p)
1829{
1830 struct ab5500 *ab = s->private;
1831 unsigned int i;
1832 u8 bank = (u8)ab->debug_bank;
1833
1834 seq_printf(s, "ab5500 register values:\n");
1835 for (bank = 0; bank < AB5500_NUM_BANKS; bank++) {
1836 seq_printf(s, " bank %u, %s (0x%x):\n", bank,
1837 bankinfo[bank].name,
1838 bankinfo[bank].slave_addr);
1839 for (i = 0; i < ab5500_reg_ranges[bank].nranges; i++) {
1840 u8 reg;
1841 int err;
1842
1843 for (reg = ab5500_reg_ranges[bank].range[i].first;
1844 reg <= ab5500_reg_ranges[bank].range[i].last;
1845 reg++) {
1846 u8 value;
1847
1848 err = get_register_interruptible(ab, bank, reg,
1849 &value);
1850 if (err < 0) {
1851 dev_err(ab->dev, "get_reg failed %d"
1852 "bank 0x%x reg 0x%x\n",
1853 err, bank, reg);
1854 return err;
1855 }
1856
1857 err = seq_printf(s, "[%d/0x%02X]: 0x%02X\n",
1858 bank, reg, value);
1859 if (err < 0) {
1860 dev_err(ab->dev,
1861 "seq_printf overflow\n");
1862 /*
1863 * Error is not returned here since
1864 * the output is wanted in any case
1865 */
1866 return 0;
1867 }
1868 }
1869 }
1870 }
1871 return 0;
1872}
1873
1874static int ab5500_registers_open(struct inode *inode, struct file *file)
1875{
1876 return single_open(file, ab5500_registers_print, inode->i_private);
1877}
1878
1879static const struct file_operations ab5500_registers_fops = {
1880 .open = ab5500_registers_open,
1881 .read = seq_read,
1882 .llseek = seq_lseek,
1883 .release = single_release,
1884 .owner = THIS_MODULE,
1885};
1886
1887static int ab5500_bank_print(struct seq_file *s, void *p)
1888{
1889 struct ab5500 *ab = s->private;
1890
1891 seq_printf(s, "%d\n", ab->debug_bank);
1892 return 0;
1893}
1894
1895static int ab5500_bank_open(struct inode *inode, struct file *file)
1896{
1897 return single_open(file, ab5500_bank_print, inode->i_private);
1898}
1899
1900static ssize_t ab5500_bank_write(struct file *file,
1901 const char __user *user_buf,
1902 size_t count, loff_t *ppos)
1903{
1904 struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
1905 char buf[32];
1906 int buf_size;
1907 unsigned long user_bank;
1908 int err;
1909
1910 /* Get userspace string and assure termination */
1911 buf_size = min(count, (sizeof(buf) - 1));
1912 if (copy_from_user(buf, user_buf, buf_size))
1913 return -EFAULT;
1914 buf[buf_size] = 0;
1915
1916 err = strict_strtoul(buf, 0, &user_bank);
1917 if (err)
1918 return -EINVAL;
1919
1920 if (user_bank >= AB5500_NUM_BANKS) {
1921 dev_err(ab->dev,
1922 "debugfs error input > number of banks\n");
1923 return -EINVAL;
1924 }
1925
1926 ab->debug_bank = user_bank;
1927
1928 return buf_size;
1929}
1930
1931static int ab5500_address_print(struct seq_file *s, void *p)
1932{
1933 struct ab5500 *ab = s->private;
1934
1935 seq_printf(s, "0x%02X\n", ab->debug_address);
1936 return 0;
1937}
1938
1939static int ab5500_address_open(struct inode *inode, struct file *file)
1940{
1941 return single_open(file, ab5500_address_print, inode->i_private);
1942}
1943
1944static ssize_t ab5500_address_write(struct file *file,
1945 const char __user *user_buf,
1946 size_t count, loff_t *ppos)
1947{
1948 struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
1949 char buf[32];
1950 int buf_size;
1951 unsigned long user_address;
1952 int err;
1953
1954 /* Get userspace string and assure termination */
1955 buf_size = min(count, (sizeof(buf) - 1));
1956 if (copy_from_user(buf, user_buf, buf_size))
1957 return -EFAULT;
1958 buf[buf_size] = 0;
1959
1960 err = strict_strtoul(buf, 0, &user_address);
1961 if (err)
1962 return -EINVAL;
1963 if (user_address > 0xff) {
1964 dev_err(ab->dev,
1965 "debugfs error input > 0xff\n");
1966 return -EINVAL;
1967 }
1968 ab->debug_address = user_address;
1969 return buf_size;
1970}
1971
1972static int ab5500_val_print(struct seq_file *s, void *p)
1973{
1974 struct ab5500 *ab = s->private;
1975 int err;
1976 u8 regvalue;
1977
1978 err = get_register_interruptible(ab, (u8)ab->debug_bank,
1979 (u8)ab->debug_address, &regvalue);
1980 if (err) {
1981 dev_err(ab->dev, "get_reg failed %d, bank 0x%x"
1982 ", reg 0x%x\n", err, ab->debug_bank,
1983 ab->debug_address);
1984 return -EINVAL;
1985 }
1986 seq_printf(s, "0x%02X\n", regvalue);
1987
1988 return 0;
1989}
1990
1991static int ab5500_val_open(struct inode *inode, struct file *file)
1992{
1993 return single_open(file, ab5500_val_print, inode->i_private);
1994}
1995
1996static ssize_t ab5500_val_write(struct file *file,
1997 const char __user *user_buf,
1998 size_t count, loff_t *ppos)
1999{
2000 struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
2001 char buf[32];
2002 int buf_size;
2003 unsigned long user_val;
2004 int err;
2005 u8 regvalue;
2006
2007 /* Get userspace string and assure termination */
2008 buf_size = min(count, (sizeof(buf)-1));
2009 if (copy_from_user(buf, user_buf, buf_size))
2010 return -EFAULT;
2011 buf[buf_size] = 0;
2012
2013 err = strict_strtoul(buf, 0, &user_val);
2014 if (err)
2015 return -EINVAL;
2016 if (user_val > 0xff) {
2017 dev_err(ab->dev,
2018 "debugfs error input > 0xff\n");
2019 return -EINVAL;
2020 }
2021 err = mask_and_set_register_interruptible(
2022 ab, (u8)ab->debug_bank,
2023 (u8)ab->debug_address, 0xFF, (u8)user_val);
2024 if (err)
2025 return -EINVAL;
2026
2027 get_register_interruptible(ab, (u8)ab->debug_bank,
2028 (u8)ab->debug_address, &regvalue);
2029 if (err)
2030 return -EINVAL;
2031
2032 return buf_size;
2033}
2034
2035static const struct file_operations ab5500_bank_fops = {
2036 .open = ab5500_bank_open,
2037 .write = ab5500_bank_write,
2038 .read = seq_read,
2039 .llseek = seq_lseek,
2040 .release = single_release,
2041 .owner = THIS_MODULE,
2042};
2043
2044static const struct file_operations ab5500_address_fops = {
2045 .open = ab5500_address_open,
2046 .write = ab5500_address_write,
2047 .read = seq_read,
2048 .llseek = seq_lseek,
2049 .release = single_release,
2050 .owner = THIS_MODULE,
2051};
2052
2053static const struct file_operations ab5500_val_fops = {
2054 .open = ab5500_val_open,
2055 .write = ab5500_val_write,
2056 .read = seq_read,
2057 .llseek = seq_lseek,
2058 .release = single_release,
2059 .owner = THIS_MODULE,
2060};
2061
2062static struct dentry *ab5500_dir;
2063static struct dentry *ab5500_reg_file;
2064static struct dentry *ab5500_bank_file;
2065static struct dentry *ab5500_address_file;
2066static struct dentry *ab5500_val_file;
2067
2068static inline void ab5500_setup_debugfs(struct ab5500 *ab)
2069{
2070 ab->debug_bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP;
2071 ab->debug_address = AB5500_CHIP_ID;
2072
2073 ab5500_dir = debugfs_create_dir("ab5500", NULL);
2074 if (!ab5500_dir)
2075 goto exit_no_debugfs;
2076
2077 ab5500_reg_file = debugfs_create_file("all-bank-registers",
2078 S_IRUGO, ab5500_dir, ab, &ab5500_registers_fops);
2079 if (!ab5500_reg_file)
2080 goto exit_destroy_dir;
2081
2082 ab5500_bank_file = debugfs_create_file("register-bank",
2083 (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_bank_fops);
2084 if (!ab5500_bank_file)
2085 goto exit_destroy_reg;
2086
2087 ab5500_address_file = debugfs_create_file("register-address",
2088 (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_address_fops);
2089 if (!ab5500_address_file)
2090 goto exit_destroy_bank;
2091
2092 ab5500_val_file = debugfs_create_file("register-value",
2093 (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_val_fops);
2094 if (!ab5500_val_file)
2095 goto exit_destroy_address;
2096
2097 return;
2098
2099exit_destroy_address:
2100 debugfs_remove(ab5500_address_file);
2101exit_destroy_bank:
2102 debugfs_remove(ab5500_bank_file);
2103exit_destroy_reg:
2104 debugfs_remove(ab5500_reg_file);
2105exit_destroy_dir:
2106 debugfs_remove(ab5500_dir);
2107exit_no_debugfs:
2108 dev_err(ab->dev, "failed to create debugfs entries.\n");
2109 return;
2110}
2111
2112static inline void ab5500_remove_debugfs(void)
2113{
2114 debugfs_remove(ab5500_val_file);
2115 debugfs_remove(ab5500_address_file);
2116 debugfs_remove(ab5500_bank_file);
2117 debugfs_remove(ab5500_reg_file);
2118 debugfs_remove(ab5500_dir);
2119}
2120
2121#else /* !CONFIG_DEBUG_FS */
2122static inline void ab5500_setup_debugfs(struct ab5500 *ab)
2123{
2124}
2125static inline void ab5500_remove_debugfs(void)
2126{
2127}
2128#endif
2129
2130/* 1255/*
2131 * ab5500_setup : Basic set-up, datastructure creation/destruction 1256 * ab5500_setup : Basic set-up, datastructure creation/destruction
2132 * and I2C interface.This sets up a default config 1257 * and I2C interface.This sets up a default config
@@ -2142,7 +1267,7 @@ static int __init ab5500_setup(struct ab5500 *ab,
2142 int i; 1267 int i;
2143 1268
2144 for (i = 0; i < size; i++) { 1269 for (i = 0; i < size; i++) {
2145 err = mask_and_set_register_interruptible(ab, 1270 err = ab5500_mask_and_set_register_interruptible_raw(ab,
2146 settings[i].bank, 1271 settings[i].bank,
2147 settings[i].reg, 1272 settings[i].reg,
2148 0xFF, settings[i].setting); 1273 0xFF, settings[i].setting);
@@ -2205,8 +1330,9 @@ static int __init ab5500_probe(struct platform_device *pdev)
2205 platform_set_drvdata(pdev, ab); 1330 platform_set_drvdata(pdev, ab);
2206 1331
2207 /* Read chip ID register */ 1332 /* Read chip ID register */
2208 err = get_register_interruptible(ab, AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, 1333 err = ab5500_get_register_interruptible_raw(ab,
2209 AB5500_CHIP_ID, &ab->chip_id); 1334 AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
1335 AB5500_CHIP_ID, &ab->chip_id);
2210 if (err) { 1336 if (err) {
2211 dev_err(&pdev->dev, "could not communicate with the analog " 1337 dev_err(&pdev->dev, "could not communicate with the analog "
2212 "baseband chip\n"); 1338 "baseband chip\n");
@@ -2233,7 +1359,8 @@ static int __init ab5500_probe(struct platform_device *pdev)
2233 u8 maskreg = AB5500_IT_MASK0_REG + i; 1359 u8 maskreg = AB5500_IT_MASK0_REG + i;
2234 u8 val; 1360 u8 val;
2235 1361
2236 get_register_interruptible(ab, AB5500_BANK_IT, latchreg, &val); 1362 ab5500_get_register_interruptible_raw(ab, AB5500_BANK_IT,
1363 latchreg, &val);
2237 set_register_interruptible(ab, AB5500_BANK_IT, maskreg, 0xff); 1364 set_register_interruptible(ab, AB5500_BANK_IT, maskreg, 0xff);
2238 ab->mask[i] = ab->oldmask[i] = 0xff; 1365 ab->mask[i] = ab->oldmask[i] = 0xff;
2239 } 1366 }
diff --git a/drivers/mfd/ab5500-core.h b/drivers/mfd/ab5500-core.h
new file mode 100644
index 000000000000..63b30b17e4f3
--- /dev/null
+++ b/drivers/mfd/ab5500-core.h
@@ -0,0 +1,87 @@
1/*
2 * Copyright (C) 2011 ST-Ericsson
3 * License terms: GNU General Public License (GPL) version 2
4 * Shared definitions and data structures for the AB5500 MFD driver
5 */
6
7/* Read/write operation values. */
8#define AB5500_PERM_RD (0x01)
9#define AB5500_PERM_WR (0x02)
10
11/* Read/write permissions. */
12#define AB5500_PERM_RO (AB5500_PERM_RD)
13#define AB5500_PERM_RW (AB5500_PERM_RD | AB5500_PERM_WR)
14
15#define AB5500_MASK_BASE (0x60)
16#define AB5500_MASK_END (0x79)
17#define AB5500_CHIP_ID (0x20)
18
19/**
20 * struct ab5500_reg_range
21 * @first: the first address of the range
22 * @last: the last address of the range
23 * @perm: access permissions for the range
24 */
25struct ab5500_reg_range {
26 u8 first;
27 u8 last;
28 u8 perm;
29};
30
31/**
32 * struct ab5500_i2c_ranges
33 * @count: the number of ranges in the list
34 * @range: the list of register ranges
35 */
36struct ab5500_i2c_ranges {
37 u8 nranges;
38 u8 bankid;
39 const struct ab5500_reg_range *range;
40};
41
42/**
43 * struct ab5500_i2c_banks
44 * @count: the number of ranges in the list
45 * @range: the list of register ranges
46 */
47struct ab5500_i2c_banks {
48 u8 nbanks;
49 const struct ab5500_i2c_ranges *bank;
50};
51
52/**
53 * struct ab5500_bank
54 * @slave_addr: I2C slave_addr found in AB5500 specification
55 * @name: Documentation name of the bank. For reference
56 */
57struct ab5500_bank {
58 u8 slave_addr;
59 const char *name;
60};
61
62static const struct ab5500_bank bankinfo[AB5500_NUM_BANKS] = {
63 [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
64 AB5500_ADDR_VIT_IO_I2C_CLK_TST_OTP, "VIT_IO_I2C_CLK_TST_OTP"},
65 [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
66 AB5500_ADDR_VDDDIG_IO_I2C_CLK_TST, "VDDDIG_IO_I2C_CLK_TST"},
67 [AB5500_BANK_VDENC] = {AB5500_ADDR_VDENC, "VDENC"},
68 [AB5500_BANK_SIM_USBSIM] = {AB5500_ADDR_SIM_USBSIM, "SIM_USBSIM"},
69 [AB5500_BANK_LED] = {AB5500_ADDR_LED, "LED"},
70 [AB5500_BANK_ADC] = {AB5500_ADDR_ADC, "ADC"},
71 [AB5500_BANK_RTC] = {AB5500_ADDR_RTC, "RTC"},
72 [AB5500_BANK_STARTUP] = {AB5500_ADDR_STARTUP, "STARTUP"},
73 [AB5500_BANK_DBI_ECI] = {AB5500_ADDR_DBI_ECI, "DBI-ECI"},
74 [AB5500_BANK_CHG] = {AB5500_ADDR_CHG, "CHG"},
75 [AB5500_BANK_FG_BATTCOM_ACC] = {
76 AB5500_ADDR_FG_BATTCOM_ACC, "FG_BATCOM_ACC"},
77 [AB5500_BANK_USB] = {AB5500_ADDR_USB, "USB"},
78 [AB5500_BANK_IT] = {AB5500_ADDR_IT, "IT"},
79 [AB5500_BANK_VIBRA] = {AB5500_ADDR_VIBRA, "VIBRA"},
80 [AB5500_BANK_AUDIO_HEADSETUSB] = {
81 AB5500_ADDR_AUDIO_HEADSETUSB, "AUDIO_HEADSETUSB"},
82};
83
84int ab5500_get_register_interruptible_raw(struct ab5500 *ab, u8 bank, u8 reg,
85 u8 *value);
86int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank,
87 u8 reg, u8 bitmask, u8 bitvalues);
diff --git a/drivers/mfd/ab5500-debugfs.c b/drivers/mfd/ab5500-debugfs.c
new file mode 100644
index 000000000000..6be1fe6b5f9a
--- /dev/null
+++ b/drivers/mfd/ab5500-debugfs.c
@@ -0,0 +1,806 @@
1/*
2 * Copyright (C) 2011 ST-Ericsson
3 * License terms: GNU General Public License (GPL) version 2
4 * Debugfs support for the AB5500 MFD driver
5 */
6
7#include <linux/debugfs.h>
8#include <linux/seq_file.h>
9#include <linux/mfd/ab5500/ab5500.h>
10#include <linux/mfd/abx500.h>
11#include <linux/uaccess.h>
12
13#include "ab5500-core.h"
14#include "ab5500-debugfs.h"
15
16static struct ab5500_i2c_ranges ab5500_reg_ranges[AB5500_NUM_BANKS] = {
17 [AB5500_BANK_LED] = {
18 .bankid = AB5500_BANK_LED,
19 .nranges = 1,
20 .range = (struct ab5500_reg_range[]) {
21 {
22 .first = 0x00,
23 .last = 0x0C,
24 .perm = AB5500_PERM_RW,
25 },
26 },
27 },
28 [AB5500_BANK_ADC] = {
29 .bankid = AB5500_BANK_ADC,
30 .nranges = 6,
31 .range = (struct ab5500_reg_range[]) {
32 {
33 .first = 0x1F,
34 .last = 0x22,
35 .perm = AB5500_PERM_RO,
36 },
37 {
38 .first = 0x23,
39 .last = 0x24,
40 .perm = AB5500_PERM_RW,
41 },
42 {
43 .first = 0x26,
44 .last = 0x2D,
45 .perm = AB5500_PERM_RO,
46 },
47 {
48 .first = 0x2F,
49 .last = 0x34,
50 .perm = AB5500_PERM_RW,
51 },
52 {
53 .first = 0x37,
54 .last = 0x57,
55 .perm = AB5500_PERM_RW,
56 },
57 {
58 .first = 0x58,
59 .last = 0x58,
60 .perm = AB5500_PERM_RO,
61 },
62 },
63 },
64 [AB5500_BANK_RTC] = {
65 .bankid = AB5500_BANK_RTC,
66 .nranges = 2,
67 .range = (struct ab5500_reg_range[]) {
68 {
69 .first = 0x00,
70 .last = 0x04,
71 .perm = AB5500_PERM_RW,
72 },
73 {
74 .first = 0x06,
75 .last = 0x0C,
76 .perm = AB5500_PERM_RW,
77 },
78 },
79 },
80 [AB5500_BANK_STARTUP] = {
81 .bankid = AB5500_BANK_STARTUP,
82 .nranges = 12,
83 .range = (struct ab5500_reg_range[]) {
84 {
85 .first = 0x00,
86 .last = 0x01,
87 .perm = AB5500_PERM_RW,
88 },
89 {
90 .first = 0x1F,
91 .last = 0x1F,
92 .perm = AB5500_PERM_RW,
93 },
94 {
95 .first = 0x2E,
96 .last = 0x2E,
97 .perm = AB5500_PERM_RO,
98 },
99 {
100 .first = 0x2F,
101 .last = 0x30,
102 .perm = AB5500_PERM_RW,
103 },
104 {
105 .first = 0x50,
106 .last = 0x51,
107 .perm = AB5500_PERM_RW,
108 },
109 {
110 .first = 0x60,
111 .last = 0x61,
112 .perm = AB5500_PERM_RW,
113 },
114 {
115 .first = 0x66,
116 .last = 0x8A,
117 .perm = AB5500_PERM_RW,
118 },
119 {
120 .first = 0x8C,
121 .last = 0x96,
122 .perm = AB5500_PERM_RW,
123 },
124 {
125 .first = 0xAA,
126 .last = 0xB4,
127 .perm = AB5500_PERM_RW,
128 },
129 {
130 .first = 0xB7,
131 .last = 0xBF,
132 .perm = AB5500_PERM_RW,
133 },
134 {
135 .first = 0xC1,
136 .last = 0xCA,
137 .perm = AB5500_PERM_RW,
138 },
139 {
140 .first = 0xD3,
141 .last = 0xE0,
142 .perm = AB5500_PERM_RW,
143 },
144 },
145 },
146 [AB5500_BANK_DBI_ECI] = {
147 .bankid = AB5500_BANK_DBI_ECI,
148 .nranges = 3,
149 .range = (struct ab5500_reg_range[]) {
150 {
151 .first = 0x00,
152 .last = 0x07,
153 .perm = AB5500_PERM_RW,
154 },
155 {
156 .first = 0x10,
157 .last = 0x10,
158 .perm = AB5500_PERM_RW,
159 },
160 {
161 .first = 0x13,
162 .last = 0x13,
163 .perm = AB5500_PERM_RW,
164 },
165 },
166 },
167 [AB5500_BANK_CHG] = {
168 .bankid = AB5500_BANK_CHG,
169 .nranges = 2,
170 .range = (struct ab5500_reg_range[]) {
171 {
172 .first = 0x11,
173 .last = 0x11,
174 .perm = AB5500_PERM_RO,
175 },
176 {
177 .first = 0x12,
178 .last = 0x1B,
179 .perm = AB5500_PERM_RW,
180 },
181 },
182 },
183 [AB5500_BANK_FG_BATTCOM_ACC] = {
184 .bankid = AB5500_BANK_FG_BATTCOM_ACC,
185 .nranges = 2,
186 .range = (struct ab5500_reg_range[]) {
187 {
188 .first = 0x00,
189 .last = 0x0B,
190 .perm = AB5500_PERM_RO,
191 },
192 {
193 .first = 0x0C,
194 .last = 0x10,
195 .perm = AB5500_PERM_RW,
196 },
197 },
198 },
199 [AB5500_BANK_USB] = {
200 .bankid = AB5500_BANK_USB,
201 .nranges = 12,
202 .range = (struct ab5500_reg_range[]) {
203 {
204 .first = 0x01,
205 .last = 0x01,
206 .perm = AB5500_PERM_RW,
207 },
208 {
209 .first = 0x80,
210 .last = 0x83,
211 .perm = AB5500_PERM_RW,
212 },
213 {
214 .first = 0x87,
215 .last = 0x8A,
216 .perm = AB5500_PERM_RW,
217 },
218 {
219 .first = 0x8B,
220 .last = 0x8B,
221 .perm = AB5500_PERM_RO,
222 },
223 {
224 .first = 0x91,
225 .last = 0x92,
226 .perm = AB5500_PERM_RO,
227 },
228 {
229 .first = 0x93,
230 .last = 0x93,
231 .perm = AB5500_PERM_RW,
232 },
233 {
234 .first = 0x94,
235 .last = 0x94,
236 .perm = AB5500_PERM_RO,
237 },
238 {
239 .first = 0xA8,
240 .last = 0xB0,
241 .perm = AB5500_PERM_RO,
242 },
243 {
244 .first = 0xB2,
245 .last = 0xB2,
246 .perm = AB5500_PERM_RO,
247 },
248 {
249 .first = 0xB4,
250 .last = 0xBC,
251 .perm = AB5500_PERM_RO,
252 },
253 {
254 .first = 0xBF,
255 .last = 0xBF,
256 .perm = AB5500_PERM_RO,
257 },
258 {
259 .first = 0xC1,
260 .last = 0xC5,
261 .perm = AB5500_PERM_RO,
262 },
263 },
264 },
265 [AB5500_BANK_IT] = {
266 .bankid = AB5500_BANK_IT,
267 .nranges = 4,
268 .range = (struct ab5500_reg_range[]) {
269 {
270 .first = 0x00,
271 .last = 0x02,
272 .perm = AB5500_PERM_RO,
273 },
274 {
275 .first = 0x20,
276 .last = 0x36,
277 .perm = AB5500_PERM_RO,
278 },
279 {
280 .first = 0x40,
281 .last = 0x56,
282 .perm = AB5500_PERM_RO,
283 },
284 {
285 .first = 0x60,
286 .last = 0x76,
287 .perm = AB5500_PERM_RO,
288 },
289 },
290 },
291 [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
292 .bankid = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST,
293 .nranges = 7,
294 .range = (struct ab5500_reg_range[]) {
295 {
296 .first = 0x02,
297 .last = 0x02,
298 .perm = AB5500_PERM_RW,
299 },
300 {
301 .first = 0x12,
302 .last = 0x12,
303 .perm = AB5500_PERM_RW,
304 },
305 {
306 .first = 0x30,
307 .last = 0x34,
308 .perm = AB5500_PERM_RW,
309 },
310 {
311 .first = 0x40,
312 .last = 0x44,
313 .perm = AB5500_PERM_RW,
314 },
315 {
316 .first = 0x50,
317 .last = 0x54,
318 .perm = AB5500_PERM_RW,
319 },
320 {
321 .first = 0x60,
322 .last = 0x64,
323 .perm = AB5500_PERM_RW,
324 },
325 {
326 .first = 0x70,
327 .last = 0x74,
328 .perm = AB5500_PERM_RW,
329 },
330 },
331 },
332 [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
333 .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
334 .nranges = 13,
335 .range = (struct ab5500_reg_range[]) {
336 {
337 .first = 0x01,
338 .last = 0x01,
339 .perm = AB5500_PERM_RW,
340 },
341 {
342 .first = 0x02,
343 .last = 0x02,
344 .perm = AB5500_PERM_RO,
345 },
346 {
347 .first = 0x0D,
348 .last = 0x0F,
349 .perm = AB5500_PERM_RW,
350 },
351 {
352 .first = 0x1C,
353 .last = 0x1C,
354 .perm = AB5500_PERM_RW,
355 },
356 {
357 .first = 0x1E,
358 .last = 0x1E,
359 .perm = AB5500_PERM_RW,
360 },
361 {
362 .first = 0x20,
363 .last = 0x21,
364 .perm = AB5500_PERM_RW,
365 },
366 {
367 .first = 0x25,
368 .last = 0x25,
369 .perm = AB5500_PERM_RW,
370 },
371 {
372 .first = 0x28,
373 .last = 0x2A,
374 .perm = AB5500_PERM_RW,
375 },
376 {
377 .first = 0x30,
378 .last = 0x33,
379 .perm = AB5500_PERM_RW,
380 },
381 {
382 .first = 0x40,
383 .last = 0x43,
384 .perm = AB5500_PERM_RW,
385 },
386 {
387 .first = 0x50,
388 .last = 0x53,
389 .perm = AB5500_PERM_RW,
390 },
391 {
392 .first = 0x60,
393 .last = 0x63,
394 .perm = AB5500_PERM_RW,
395 },
396 {
397 .first = 0x70,
398 .last = 0x73,
399 .perm = AB5500_PERM_RW,
400 },
401 },
402 },
403 [AB5500_BANK_VIBRA] = {
404 .bankid = AB5500_BANK_VIBRA,
405 .nranges = 2,
406 .range = (struct ab5500_reg_range[]) {
407 {
408 .first = 0x10,
409 .last = 0x13,
410 .perm = AB5500_PERM_RW,
411 },
412 {
413 .first = 0xFE,
414 .last = 0xFE,
415 .perm = AB5500_PERM_RW,
416 },
417 },
418 },
419 [AB5500_BANK_AUDIO_HEADSETUSB] = {
420 .bankid = AB5500_BANK_AUDIO_HEADSETUSB,
421 .nranges = 2,
422 .range = (struct ab5500_reg_range[]) {
423 {
424 .first = 0x00,
425 .last = 0x48,
426 .perm = AB5500_PERM_RW,
427 },
428 {
429 .first = 0xEB,
430 .last = 0xFB,
431 .perm = AB5500_PERM_RW,
432 },
433 },
434 },
435 [AB5500_BANK_SIM_USBSIM] = {
436 .bankid = AB5500_BANK_SIM_USBSIM,
437 .nranges = 1,
438 .range = (struct ab5500_reg_range[]) {
439 {
440 .first = 0x13,
441 .last = 0x19,
442 .perm = AB5500_PERM_RW,
443 },
444 },
445 },
446 [AB5500_BANK_VDENC] = {
447 .bankid = AB5500_BANK_VDENC,
448 .nranges = 12,
449 .range = (struct ab5500_reg_range[]) {
450 {
451 .first = 0x00,
452 .last = 0x08,
453 .perm = AB5500_PERM_RW,
454 },
455 {
456 .first = 0x09,
457 .last = 0x09,
458 .perm = AB5500_PERM_RO,
459 },
460 {
461 .first = 0x0A,
462 .last = 0x12,
463 .perm = AB5500_PERM_RW,
464 },
465 {
466 .first = 0x15,
467 .last = 0x19,
468 .perm = AB5500_PERM_RW,
469 },
470 {
471 .first = 0x1B,
472 .last = 0x21,
473 .perm = AB5500_PERM_RW,
474 },
475 {
476 .first = 0x27,
477 .last = 0x2C,
478 .perm = AB5500_PERM_RW,
479 },
480 {
481 .first = 0x41,
482 .last = 0x41,
483 .perm = AB5500_PERM_RW,
484 },
485 {
486 .first = 0x45,
487 .last = 0x5B,
488 .perm = AB5500_PERM_RW,
489 },
490 {
491 .first = 0x5D,
492 .last = 0x5D,
493 .perm = AB5500_PERM_RW,
494 },
495 {
496 .first = 0x69,
497 .last = 0x69,
498 .perm = AB5500_PERM_RW,
499 },
500 {
501 .first = 0x6C,
502 .last = 0x6D,
503 .perm = AB5500_PERM_RW,
504 },
505 {
506 .first = 0x80,
507 .last = 0x81,
508 .perm = AB5500_PERM_RW,
509 },
510 },
511 },
512};
513
514static int ab5500_registers_print(struct seq_file *s, void *p)
515{
516 struct ab5500 *ab = s->private;
517 unsigned int i;
518 u8 bank = (u8)ab->debug_bank;
519
520 seq_printf(s, "ab5500 register values:\n");
521 for (bank = 0; bank < AB5500_NUM_BANKS; bank++) {
522 seq_printf(s, " bank %u, %s (0x%x):\n", bank,
523 bankinfo[bank].name,
524 bankinfo[bank].slave_addr);
525 for (i = 0; i < ab5500_reg_ranges[bank].nranges; i++) {
526 u8 reg;
527 int err;
528
529 for (reg = ab5500_reg_ranges[bank].range[i].first;
530 reg <= ab5500_reg_ranges[bank].range[i].last;
531 reg++) {
532 u8 value;
533
534 err = ab5500_get_register_interruptible_raw(ab,
535 bank, reg,
536 &value);
537 if (err < 0) {
538 dev_err(ab->dev, "get_reg failed %d"
539 "bank 0x%x reg 0x%x\n",
540 err, bank, reg);
541 return err;
542 }
543
544 err = seq_printf(s, "[%d/0x%02X]: 0x%02X\n",
545 bank, reg, value);
546 if (err < 0) {
547 dev_err(ab->dev,
548 "seq_printf overflow\n");
549 /*
550 * Error is not returned here since
551 * the output is wanted in any case
552 */
553 return 0;
554 }
555 }
556 }
557 }
558 return 0;
559}
560
561static int ab5500_registers_open(struct inode *inode, struct file *file)
562{
563 return single_open(file, ab5500_registers_print, inode->i_private);
564}
565
566static const struct file_operations ab5500_registers_fops = {
567 .open = ab5500_registers_open,
568 .read = seq_read,
569 .llseek = seq_lseek,
570 .release = single_release,
571 .owner = THIS_MODULE,
572};
573
574static int ab5500_bank_print(struct seq_file *s, void *p)
575{
576 struct ab5500 *ab = s->private;
577
578 seq_printf(s, "%d\n", ab->debug_bank);
579 return 0;
580}
581
582static int ab5500_bank_open(struct inode *inode, struct file *file)
583{
584 return single_open(file, ab5500_bank_print, inode->i_private);
585}
586
587static ssize_t ab5500_bank_write(struct file *file,
588 const char __user *user_buf,
589 size_t count, loff_t *ppos)
590{
591 struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
592 char buf[32];
593 int buf_size;
594 unsigned long user_bank;
595 int err;
596
597 /* Get userspace string and assure termination */
598 buf_size = min(count, (sizeof(buf) - 1));
599 if (copy_from_user(buf, user_buf, buf_size))
600 return -EFAULT;
601 buf[buf_size] = 0;
602
603 err = strict_strtoul(buf, 0, &user_bank);
604 if (err)
605 return -EINVAL;
606
607 if (user_bank >= AB5500_NUM_BANKS) {
608 dev_err(ab->dev,
609 "debugfs error input > number of banks\n");
610 return -EINVAL;
611 }
612
613 ab->debug_bank = user_bank;
614
615 return buf_size;
616}
617
618static int ab5500_address_print(struct seq_file *s, void *p)
619{
620 struct ab5500 *ab = s->private;
621
622 seq_printf(s, "0x%02X\n", ab->debug_address);
623 return 0;
624}
625
626static int ab5500_address_open(struct inode *inode, struct file *file)
627{
628 return single_open(file, ab5500_address_print, inode->i_private);
629}
630
631static ssize_t ab5500_address_write(struct file *file,
632 const char __user *user_buf,
633 size_t count, loff_t *ppos)
634{
635 struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
636 char buf[32];
637 int buf_size;
638 unsigned long user_address;
639 int err;
640
641 /* Get userspace string and assure termination */
642 buf_size = min(count, (sizeof(buf) - 1));
643 if (copy_from_user(buf, user_buf, buf_size))
644 return -EFAULT;
645 buf[buf_size] = 0;
646
647 err = strict_strtoul(buf, 0, &user_address);
648 if (err)
649 return -EINVAL;
650 if (user_address > 0xff) {
651 dev_err(ab->dev,
652 "debugfs error input > 0xff\n");
653 return -EINVAL;
654 }
655 ab->debug_address = user_address;
656 return buf_size;
657}
658
659static int ab5500_val_print(struct seq_file *s, void *p)
660{
661 struct ab5500 *ab = s->private;
662 int err;
663 u8 regvalue;
664
665 err = ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank,
666 (u8)ab->debug_address, &regvalue);
667 if (err) {
668 dev_err(ab->dev, "get_reg failed %d, bank 0x%x"
669 ", reg 0x%x\n", err, ab->debug_bank,
670 ab->debug_address);
671 return -EINVAL;
672 }
673 seq_printf(s, "0x%02X\n", regvalue);
674
675 return 0;
676}
677
678static int ab5500_val_open(struct inode *inode, struct file *file)
679{
680 return single_open(file, ab5500_val_print, inode->i_private);
681}
682
683static ssize_t ab5500_val_write(struct file *file,
684 const char __user *user_buf,
685 size_t count, loff_t *ppos)
686{
687 struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
688 char buf[32];
689 int buf_size;
690 unsigned long user_val;
691 int err;
692 u8 regvalue;
693
694 /* Get userspace string and assure termination */
695 buf_size = min(count, (sizeof(buf)-1));
696 if (copy_from_user(buf, user_buf, buf_size))
697 return -EFAULT;
698 buf[buf_size] = 0;
699
700 err = strict_strtoul(buf, 0, &user_val);
701 if (err)
702 return -EINVAL;
703 if (user_val > 0xff) {
704 dev_err(ab->dev,
705 "debugfs error input > 0xff\n");
706 return -EINVAL;
707 }
708 err = ab5500_mask_and_set_register_interruptible_raw(
709 ab, (u8)ab->debug_bank,
710 (u8)ab->debug_address, 0xFF, (u8)user_val);
711 if (err)
712 return -EINVAL;
713
714 ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank,
715 (u8)ab->debug_address, &regvalue);
716 if (err)
717 return -EINVAL;
718
719 return buf_size;
720}
721
722static const struct file_operations ab5500_bank_fops = {
723 .open = ab5500_bank_open,
724 .write = ab5500_bank_write,
725 .read = seq_read,
726 .llseek = seq_lseek,
727 .release = single_release,
728 .owner = THIS_MODULE,
729};
730
731static const struct file_operations ab5500_address_fops = {
732 .open = ab5500_address_open,
733 .write = ab5500_address_write,
734 .read = seq_read,
735 .llseek = seq_lseek,
736 .release = single_release,
737 .owner = THIS_MODULE,
738};
739
740static const struct file_operations ab5500_val_fops = {
741 .open = ab5500_val_open,
742 .write = ab5500_val_write,
743 .read = seq_read,
744 .llseek = seq_lseek,
745 .release = single_release,
746 .owner = THIS_MODULE,
747};
748
749static struct dentry *ab5500_dir;
750static struct dentry *ab5500_reg_file;
751static struct dentry *ab5500_bank_file;
752static struct dentry *ab5500_address_file;
753static struct dentry *ab5500_val_file;
754
755void __init ab5500_setup_debugfs(struct ab5500 *ab)
756{
757 ab->debug_bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP;
758 ab->debug_address = AB5500_CHIP_ID;
759
760 ab5500_dir = debugfs_create_dir("ab5500", NULL);
761 if (!ab5500_dir)
762 goto exit_no_debugfs;
763
764 ab5500_reg_file = debugfs_create_file("all-bank-registers",
765 S_IRUGO, ab5500_dir, ab, &ab5500_registers_fops);
766 if (!ab5500_reg_file)
767 goto exit_destroy_dir;
768
769 ab5500_bank_file = debugfs_create_file("register-bank",
770 (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_bank_fops);
771 if (!ab5500_bank_file)
772 goto exit_destroy_reg;
773
774 ab5500_address_file = debugfs_create_file("register-address",
775 (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_address_fops);
776 if (!ab5500_address_file)
777 goto exit_destroy_bank;
778
779 ab5500_val_file = debugfs_create_file("register-value",
780 (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_val_fops);
781 if (!ab5500_val_file)
782 goto exit_destroy_address;
783
784 return;
785
786exit_destroy_address:
787 debugfs_remove(ab5500_address_file);
788exit_destroy_bank:
789 debugfs_remove(ab5500_bank_file);
790exit_destroy_reg:
791 debugfs_remove(ab5500_reg_file);
792exit_destroy_dir:
793 debugfs_remove(ab5500_dir);
794exit_no_debugfs:
795 dev_err(ab->dev, "failed to create debugfs entries.\n");
796 return;
797}
798
799void __exit ab5500_remove_debugfs(void)
800{
801 debugfs_remove(ab5500_val_file);
802 debugfs_remove(ab5500_address_file);
803 debugfs_remove(ab5500_bank_file);
804 debugfs_remove(ab5500_reg_file);
805 debugfs_remove(ab5500_dir);
806}
diff --git a/drivers/mfd/ab5500-debugfs.h b/drivers/mfd/ab5500-debugfs.h
new file mode 100644
index 000000000000..7330a9b6afa6
--- /dev/null
+++ b/drivers/mfd/ab5500-debugfs.h
@@ -0,0 +1,22 @@
1/*
2 * Copyright (C) 2011 ST-Ericsson
3 * License terms: GNU General Public License (GPL) version 2
4 * Debugfs interface to the AB5500 core driver
5 */
6
7#ifdef CONFIG_DEBUG_FS
8
9void ab5500_setup_debugfs(struct ab5500 *ab);
10void ab5500_remove_debugfs(void);
11
12#else /* !CONFIG_DEBUG_FS */
13
14static inline void ab5500_setup_debugfs(struct ab5500 *ab)
15{
16}
17
18static inline void ab5500_remove_debugfs(void)
19{
20}
21
22#endif