diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-24 20:00:58 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-24 20:00:58 -0800 |
commit | ab7826595e9ec51a51f622c5fc91e2f59440481a (patch) | |
tree | 34241b399fa7a12c260e06e6c1c31bc69d46e1e3 /drivers/mfd | |
parent | 21fbd5809ad126b949206d78e0a0e07ec872ea11 (diff) | |
parent | ff7109fa632654eaef657186f2942f5b679023d6 (diff) |
Merge tag 'mfd-3.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
Pull MFS updates from Samuel Ortiz:
"This is the MFD pull request for the 3.9 merge window.
No new drivers this time, but a bunch of fairly big cleanups:
- Roger Quadros worked on a OMAP USBHS and TLL platform data
consolidation, OMAP5 support and clock management code cleanup.
- The first step of a major sync for the ab8500 driver from Lee
Jones. In particular, the debugfs and the sysct interfaces got
extended and improved.
- Peter Ujfalusi sent a nice patchset for cleaning and fixing the
twl-core driver, with a much needed module id lookup code
improvement.
- The regular wm5102 and arizona cleanups and fixes from Mark Brown.
- Laxman Dewangan extended the palmas APIs in order to implement the
palmas GPIO and rt drivers.
- Laxman also added DT support for the tps65090 driver.
- The Intel SCH and ICH drivers got a couple fixes from Aaron Sierra
and Darren Hart.
- Linus Walleij patchset for the ab8500 driver allowed ab8500 and
ab9540 based devices to switch to the new abx500 pin-ctrl driver.
- The max8925 now has device tree and irqdomain support thanks to
Qing Xu.
- The recently added rtsx driver got a few cleanups and fixes for a
better card detection code path and now also supports the RTS5227
chipset, thanks to Wei Wang and Roger Tseng."
* tag 'mfd-3.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (109 commits)
mfd: lpc_ich: Use devres API to allocate private data
mfd: lpc_ich: Add Device IDs for Intel Wellsburg PCH
mfd: lpc_sch: Accomodate partial population of the MFD devices
mfd: da9052-i2c: Staticize da9052_i2c_fix()
mfd: syscon: Fix sparse warning
mfd: twl-core: Fix kernel panic on boot
mfd: rtsx: Fix issue that booting OS with SD card inserted
mfd: ab8500: Fix compile error
mfd: Add missing GENERIC_HARDIRQS dependecies
Documentation: Add docs for max8925 dt
mfd: max8925: Add dts
mfd: max8925: Support dt for backlight
mfd: max8925: Fix onkey driver irq base
mfd: max8925: Fix mfd device register failure
mfd: max8925: Add irqdomain for dt
mfd: vexpress: Allow vexpress-sysreg to self-initialise
mfd: rtsx: Support RTS5227
mfd: rtsx: Implement driving adjustment to device-dependent callbacks
mfd: vexpress: Add pseudo-GPIO based LEDs
mfd: ab8500: Rename ab8500 to abx500 for hwmon driver
...
Diffstat (limited to 'drivers/mfd')
33 files changed, 2941 insertions, 997 deletions
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index 391e23e6a64..582bda54352 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -531,7 +531,7 @@ static int pm800_probe(struct i2c_client *client, ret = device_800_init(chip, pdata); if (ret) { dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); - goto err_800_init; + goto err_subchip_alloc; } ret = pm800_pages_init(chip); @@ -546,10 +546,8 @@ static int pm800_probe(struct i2c_client *client, err_page_init: mfd_remove_devices(chip->dev); device_irq_exit_800(chip); -err_800_init: - devm_kfree(&client->dev, subchip); err_subchip_alloc: - pm80x_deinit(client); + pm80x_deinit(); out_init: return ret; } @@ -562,9 +560,7 @@ static int pm800_remove(struct i2c_client *client) device_irq_exit_800(chip); pm800_pages_exit(chip); - devm_kfree(&client->dev, chip->subchip); - - pm80x_deinit(client); + pm80x_deinit(); return 0; } diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index e671230be2b..65d7ac099b2 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -257,7 +257,7 @@ static int pm805_probe(struct i2c_client *client, pdata->plat_config(chip, pdata); err_805_init: - pm80x_deinit(client); + pm80x_deinit(); out_init: return ret; } @@ -269,7 +269,7 @@ static int pm805_remove(struct i2c_client *client) mfd_remove_devices(chip->dev); device_irq_exit_805(chip); - pm80x_deinit(client); + pm80x_deinit(); return 0; } diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c index 1adb355d86d..f736a46eb8c 100644 --- a/drivers/mfd/88pm80x.c +++ b/drivers/mfd/88pm80x.c @@ -48,14 +48,12 @@ int pm80x_init(struct i2c_client *client, ret = PTR_ERR(map); dev_err(&client->dev, "Failed to allocate register map: %d\n", ret); - goto err_regmap_init; + return ret; } chip->id = id->driver_data; - if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805) { - ret = -EINVAL; - goto err_chip_id; - } + if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805) + return -EINVAL; chip->client = client; chip->regmap = map; @@ -82,19 +80,11 @@ int pm80x_init(struct i2c_client *client, } return 0; - -err_chip_id: - regmap_exit(map); -err_regmap_init: - devm_kfree(&client->dev, chip); - return ret; } EXPORT_SYMBOL_GPL(pm80x_init); -int pm80x_deinit(struct i2c_client *client) +int pm80x_deinit(void) { - struct pm80x_chip *chip = i2c_get_clientdata(client); - /* * workaround: clear the dependency between pm800 and pm805. * would remove it after HW chip fixes the issue. @@ -103,10 +93,6 @@ int pm80x_deinit(struct i2c_client *client) g_pm80x_chip->companion = NULL; else g_pm80x_chip = NULL; - - regmap_exit(chip->regmap); - devm_kfree(&client->dev, chip); - return 0; } EXPORT_SYMBOL_GPL(pm80x_deinit); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index ff553babf45..671f5b171c7 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -65,7 +65,7 @@ config MFD_SM501_GPIO config MFD_RTSX_PCI tristate "Support for Realtek PCI-E card reader" - depends on PCI + depends on PCI && GENERIC_HARDIRQS select MFD_CORE help This supports for Realtek PCI-Express card reader including rts5209, @@ -95,7 +95,7 @@ config MFD_DM355EVM_MSP config MFD_TI_SSP tristate "TI Sequencer Serial Port support" - depends on ARCH_DAVINCI_TNETV107X + depends on ARCH_DAVINCI_TNETV107X && GENERIC_HARDIRQS select MFD_CORE ---help--- Say Y here if you want support for the Sequencer Serial Port @@ -109,6 +109,7 @@ config MFD_TI_AM335X_TSCADC select MFD_CORE select REGMAP select REGMAP_MMIO + depends on GENERIC_HARDIRQS help If you say yes here you get support for Texas Instruments series of Touch Screen /ADC chips. @@ -126,6 +127,7 @@ config HTC_EGPIO config HTC_PASIC3 tristate "HTC PASIC3 LED/DS1WM chip support" select MFD_CORE + depends on GENERIC_HARDIRQS help This core driver provides register access for the LED/DS1WM chips labeled "AIC2" and "AIC3", found on HTC Blueangel and @@ -157,6 +159,7 @@ config MFD_LM3533 depends on I2C select MFD_CORE select REGMAP_I2C + depends on GENERIC_HARDIRQS help Say yes here to enable support for National Semiconductor / TI LM3533 Lighting Power chips. @@ -171,6 +174,7 @@ config TPS6105X select REGULATOR select MFD_CORE select REGULATOR_FIXED_VOLTAGE + depends on GENERIC_HARDIRQS help This option enables a driver for the TP61050/TPS61052 high-power "white LED driver". This boost converter is @@ -193,7 +197,7 @@ config TPS65010 config TPS6507X tristate "TPS6507x Power Management / Touch Screen chips" select MFD_CORE - depends on I2C + depends on I2C && GENERIC_HARDIRQS help If you say yes here you get support for the TPS6507x series of Power Management / Touch Screen chips. These include voltage @@ -204,7 +208,7 @@ config TPS6507X config MFD_TPS65217 tristate "TPS65217 Power Management / White LED chips" - depends on I2C + depends on I2C && GENERIC_HARDIRQS select MFD_CORE select REGMAP_I2C help @@ -234,7 +238,7 @@ config MFD_TPS6586X config MFD_TPS65910 bool "TPS65910 Power Management chip" - depends on I2C=y && GPIOLIB + depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS select MFD_CORE select REGMAP_I2C select REGMAP_IRQ @@ -251,7 +255,7 @@ config MFD_TPS65912_I2C bool "TPS65912 Power Management chip with I2C" select MFD_CORE select MFD_TPS65912 - depends on I2C=y && GPIOLIB + depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS help If you say yes here you get support for the TPS65912 series of PM chips with I2C interface. @@ -260,7 +264,7 @@ config MFD_TPS65912_SPI bool "TPS65912 Power Management chip with SPI" select MFD_CORE select MFD_TPS65912 - depends on SPI_MASTER && GPIOLIB + depends on SPI_MASTER && GPIOLIB && GENERIC_HARDIRQS help If you say yes here you get support for the TPS65912 series of PM chips with SPI interface. @@ -330,13 +334,13 @@ config TWL4030_POWER config MFD_TWL4030_AUDIO bool - depends on TWL4030_CORE + depends on TWL4030_CORE && GENERIC_HARDIRQS select MFD_CORE default n config TWL6040_CORE bool "Support for TWL6040 audio codec" - depends on I2C=y + depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE select REGMAP_I2C select REGMAP_IRQ @@ -405,7 +409,7 @@ config MFD_TMIO config MFD_T7L66XB bool "Support Toshiba T7L66XB" - depends on ARM && HAVE_CLK + depends on ARM && HAVE_CLK && GENERIC_HARDIRQS select MFD_CORE select MFD_TMIO help @@ -413,7 +417,7 @@ config MFD_T7L66XB config MFD_SMSC bool "Support for the SMSC ECE1099 series chips" - depends on I2C=y + depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE select REGMAP_I2C help @@ -460,7 +464,7 @@ config MFD_DA9052_SPI select REGMAP_SPI select REGMAP_IRQ select PMIC_DA9052 - depends on SPI_MASTER=y + depends on SPI_MASTER=y && GENERIC_HARDIRQS help Support for the Dialog Semiconductor DA9052 PMIC when controlled using SPI. This driver provides common support @@ -472,7 +476,7 @@ config MFD_DA9052_I2C select REGMAP_I2C select REGMAP_IRQ select PMIC_DA9052 - depends on I2C=y + depends on I2C=y && GENERIC_HARDIRQS help Support for the Dialog Semiconductor DA9052 PMIC when controlled using I2C. This driver provides common support @@ -485,7 +489,7 @@ config MFD_DA9055 select REGMAP_IRQ select PMIC_DA9055 select MFD_CORE - depends on I2C=y + depends on I2C=y && GENERIC_HARDIRQS help Say yes here for support of Dialog Semiconductor DA9055. This is a Power Management IC. This driver provides common support for @@ -508,7 +512,7 @@ config PMIC_ADP5520 config MFD_LP8788 bool "Texas Instruments LP8788 Power Management Unit Driver" - depends on I2C=y + depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE select REGMAP_I2C select IRQ_DOMAIN @@ -611,7 +615,7 @@ config MFD_ARIZONA_I2C select MFD_ARIZONA select MFD_CORE select REGMAP_I2C - depends on I2C + depends on I2C && GENERIC_HARDIRQS help Support for the Wolfson Microelectronics Arizona platform audio SoC core functionality controlled via I2C. @@ -621,7 +625,7 @@ config MFD_ARIZONA_SPI select MFD_ARIZONA select MFD_CORE select REGMAP_SPI - depends on SPI_MASTER + depends on SPI_MASTER && GENERIC_HARDIRQS help Support for the Wolfson Microelectronics Arizona platform audio SoC core functionality controlled via I2C. @@ -641,7 +645,7 @@ config MFD_WM5110 config MFD_WM8400 bool "Support Wolfson Microelectronics WM8400" select MFD_CORE - depends on I2C=y + depends on I2C=y && GENERIC_HARDIRQS select REGMAP_I2C help Support for the Wolfson Microelecronics WM8400 PMIC and audio @@ -785,7 +789,7 @@ config MFD_MC13783 config MFD_MC13XXX tristate - depends on SPI_MASTER || I2C + depends on (SPI_MASTER || I2C) && GENERIC_HARDIRQS select MFD_CORE select MFD_MC13783 help @@ -796,7 +800,7 @@ config MFD_MC13XXX config MFD_MC13XXX_SPI tristate "Freescale MC13783 and MC13892 SPI interface" - depends on SPI_MASTER + depends on SPI_MASTER && GENERIC_HARDIRQS select REGMAP_SPI select MFD_MC13XXX help @@ -804,7 +808,7 @@ config MFD_MC13XXX_SPI config MFD_MC13XXX_I2C tristate "Freescale MC13892 I2C interface" - depends on I2C + depends on I2C && GENERIC_HARDIRQS select REGMAP_I2C select MFD_MC13XXX help @@ -822,7 +826,7 @@ config ABX500_CORE config AB3100_CORE bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions" - depends on I2C=y && ABX500_CORE + depends on I2C=y && ABX500_CORE && GENERIC_HARDIRQS select MFD_CORE default y if ARCH_U300 help @@ -909,7 +913,7 @@ config MFD_TIMBERDALE config LPC_SCH tristate "Intel SCH LPC" - depends on PCI + depends on PCI && GENERIC_HARDIRQS select MFD_CORE help LPC bridge function of the Intel SCH provides support for @@ -917,7 +921,7 @@ config LPC_SCH config LPC_ICH tristate "Intel ICH LPC" - depends on PCI + depends on PCI && GENERIC_HARDIRQS select MFD_CORE help The LPC bridge function of the Intel ICH provides support for @@ -928,7 +932,7 @@ config LPC_ICH config MFD_RDC321X tristate "Support for RDC-R321x southbridge" select MFD_CORE - depends on PCI + depends on PCI && GENERIC_HARDIRQS help Say yes here if you want to have support for the RDC R-321x SoC southbridge which provides access to GPIOs and Watchdog using the @@ -937,7 +941,7 @@ config MFD_RDC321X config MFD_JANZ_CMODIO tristate "Support for Janz CMOD-IO PCI MODULbus Carrier Board" select MFD_CORE - depends on PCI + depends on PCI && GENERIC_HARDIRQS help This is the core driver for the Janz CMOD-IO PCI MODULbus carrier board. This device is a PCI to MODULbus bridge which may @@ -955,7 +959,7 @@ config MFD_JZ4740_ADC config MFD_VX855 tristate "Support for VIA VX855/VX875 integrated south bridge" - depends on PCI + depends on PCI && GENERIC_HARDIRQS select MFD_CORE help Say yes here to enable support for various functions of the @@ -964,7 +968,7 @@ config MFD_VX855 config MFD_WL1273_CORE tristate "Support for TI WL1273 FM radio." - depends on I2C + depends on I2C && GENERIC_HARDIRQS select MFD_CORE default n help @@ -1028,7 +1032,7 @@ config MFD_TPS65090 config MFD_AAT2870_CORE bool "Support for the AnalogicTech AAT2870" select MFD_CORE - depends on I2C=y && GPIOLIB + depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS help If you say yes here you get support for the AAT2870. This driver provides common support for accessing the device, @@ -1060,7 +1064,7 @@ config MFD_RC5T583 config MFD_STA2X11 bool "STA2X11 multi function device support" - depends on STA2X11 + depends on STA2X11 && GENERIC_HARDIRQS select MFD_CORE select REGMAP_MMIO @@ -1077,7 +1081,7 @@ config MFD_PALMAS select MFD_CORE select REGMAP_I2C select REGMAP_IRQ - depends on I2C=y + depends on I2C=y && GENERIC_HARDIRQS help If you say yes here you get support for the Palmas series of PMIC chips from Texas Instruments. @@ -1085,7 +1089,7 @@ config MFD_PALMAS config MFD_VIPERBOARD tristate "Support for Nano River Technologies Viperboard" select MFD_CORE - depends on USB + depends on USB && GENERIC_HARDIRQS default n help Say yes here if you want support for Nano River Technologies @@ -1099,7 +1103,7 @@ config MFD_VIPERBOARD config MFD_RETU tristate "Support for Retu multi-function device" select MFD_CORE - depends on I2C + depends on I2C && GENERIC_HARDIRQS select REGMAP_IRQ help Retu is a multi-function device found on Nokia Internet Tablets @@ -1110,7 +1114,7 @@ config MFD_AS3711 select MFD_CORE select REGMAP_I2C select REGMAP_IRQ - depends on I2C=y + depends on I2C=y && GENERIC_HARDIRQS help Support for the AS3711 PMIC from AMS diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8b977f8045a..b90409c2366 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -9,7 +9,7 @@ obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o obj-$(CONFIG_MFD_SM501) += sm501.o obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o -rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o +rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 8b5d685ab98..7c84ced2e01 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -320,6 +320,7 @@ static struct abx500_ops ab8500_ops = { .mask_and_set_register = ab8500_mask_and_set_register, .event_registers_startup_state_get = NULL, .startup_irq_enabled = NULL, + .dump_all_banks = ab8500_dump_all_banks, }; static void ab8500_irq_lock(struct irq_data *data) @@ -368,16 +369,48 @@ static void ab8500_irq_mask(struct irq_data *data) int mask = 1 << (offset % 8); ab8500->mask[index] |= mask; + + /* The AB8500 GPIOs have two interrupts each (rising & falling). */ + if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) + ab8500->mask[index + 2] |= mask; + if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) + ab8500->mask[index + 1] |= mask; + if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) + /* Here the falling IRQ is one bit lower */ + ab8500->mask[index] |= (mask << 1); } static void ab8500_irq_unmask(struct irq_data *data) { struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); + unsigned int type = irqd_get_trigger_type(data); int offset = data->hwirq; int index = offset / 8; int mask = 1 << (offset % 8); - ab8500->mask[index] &= ~mask; + if (type & IRQ_TYPE_EDGE_RISING) + ab8500->mask[index] &= ~mask; + + /* The AB8500 GPIOs have two interrupts each (rising & falling). */ + if (type & IRQ_TYPE_EDGE_FALLING) { + if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) + ab8500->mask[index + 2] &= ~mask; + else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) + ab8500->mask[index + 1] &= ~mask; + else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) + /* Here the falling IRQ is one bit lower */ + ab8500->mask[index] &= ~(mask << 1); + else + ab8500->mask[index] &= ~mask; + } else { + /* Satisfies the case where type is not set. */ + ab8500->mask[index] &= ~mask; + } +} + +static int ab8500_irq_set_type(struct irq_data *data, unsigned int type) +{ + return 0; } static struct irq_chip ab8500_irq_chip = { @@ -387,6 +420,7 @@ static struct irq_chip ab8500_irq_chip = { .irq_mask = ab8500_irq_mask, .irq_disable = ab8500_irq_mask, .irq_unmask = ab8500_irq_unmask, + .irq_set_type = ab8500_irq_set_type, }; static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, @@ -411,6 +445,19 @@ static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, line = (i << 3) + int_bit; latch_val &= ~(1 << int_bit); + /* + * This handles the falling edge hwirqs from the GPIO + * lines. Route them back to the line registered for the + * rising IRQ, as this is merely a flag for the same IRQ + * in linux terms. + */ + if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F) + line -= 16; + if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F) + line -= 8; + if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F) + line += 1; + handle_nested_irq(ab8500->irq_base + line); } while (latch_val); @@ -521,6 +568,7 @@ static irqreturn_t ab8500_irq(int irq, void *dev) int virq = ab8500_irq_get_virq(ab8500, line); handle_nested_irq(virq); + ab8500_debug_register_interrupt(line); value &= ~(1 << bit); } while (value); @@ -929,7 +977,7 @@ static struct resource ab8505_iddet_resources[] = { static struct resource ab8500_temp_resources[] = { { - .name = "AB8500_TEMP_WARM", + .name = "ABX500_TEMP_WARM", .start = AB8500_INT_TEMP_WARM, .end = AB8500_INT_TEMP_WARM, .flags = IORESOURCE_IRQ, @@ -1005,8 +1053,8 @@ static struct mfd_cell abx500_common_devs[] = { .of_compatible = "stericsson,ab8500-denc", }, { - .name = "ab8500-temp", - .of_compatible = "stericsson,ab8500-temp", + .name = "abx500-temp", + .of_compatible = "stericsson,abx500-temp", .num_resources = ARRAY_SIZE(ab8500_temp_resources), .resources = ab8500_temp_resources, }, @@ -1049,7 +1097,7 @@ static struct mfd_cell ab8500_bm_devs[] = { static struct mfd_cell ab8500_devs[] = { { - .name = "ab8500-gpio", + .name = "pinctrl-ab8500", .of_compatible = "stericsson,ab8500-gpio", }, { @@ -1066,7 +1114,8 @@ static struct mfd_cell ab8500_devs[] = { static struct mfd_cell ab9540_devs[] = { { - .name = "ab8500-gpio", + .name = "pinctrl-ab9540", + .of_compatible = "stericsson,ab9540-gpio", }, { .name = "ab9540-usb", diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 5a8e707bc03..45fe3c50eb0 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -4,6 +4,72 @@ * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson. * License Terms: GNU General Public License v2 */ +/* + * AB8500 register access + * ====================== + * + * read: + * # echo BANK > <debugfs>/ab8500/register-bank + * # echo ADDR > <debugfs>/ab8500/register-address + * # cat <debugfs>/ab8500/register-value + * + * write: + * # echo BANK > <debugfs>/ab8500/register-bank + * # echo ADDR > <debugfs>/ab8500/register-address + * # echo VALUE > <debugfs>/ab8500/register-value + * + * read all registers from a bank: + * # echo BANK > <debugfs>/ab8500/register-bank + * # cat <debugfs>/ab8500/all-bank-register + * + * BANK target AB8500 register bank + * ADDR target AB8500 register address + * VALUE decimal or 0x-prefixed hexadecimal + * + * + * User Space notification on AB8500 IRQ + * ===================================== + * + * Allows user space entity to be notified when target AB8500 IRQ occurs. + * When subscribed, a sysfs entry is created in ab8500.i2c platform device. + * One can pool this file to get target IRQ occurence information. + * + * subscribe to an AB8500 IRQ: + * # echo IRQ > <debugfs>/ab8500/irq-subscribe + * + * unsubscribe from an AB8500 IRQ: + * # echo IRQ > <debugfs>/ab8500/irq-unsubscribe + * + * + * AB8500 register formated read/write access + * ========================================== + * + * Read: read data, data>>SHIFT, data&=MASK, output data + * [0xABCDEF98] shift=12 mask=0xFFF => 0x00000CDE + * Write: read data, data &= ~(MASK<<SHIFT), data |= (VALUE<<SHIFT), write data + * [0xABCDEF98] shift=12 mask=0xFFF value=0x123 => [0xAB123F98] + * + * Usage: + * # echo "CMD [OPTIONS] BANK ADRESS [VALUE]" > $debugfs/ab8500/hwreg + * + * CMD read read access + * write write access + * + * BANK target reg bank + * ADDRESS target reg address + * VALUE (write) value to be updated + * + * OPTIONS + * -d|-dec (read) output in decimal + * -h|-hexa (read) output in 0x-hexa (default) + * -l|-w|-b 32bit (default), 16bit or 8bit reg access + * -m|-mask MASK 0x-hexa mask (default 0xFFFFFFFF) + * -s|-shift SHIFT bit shift value (read:left, write:right) + * -o|-offset OFFSET address offset to add to ADDRESS value + * + * Warning: bit shift operation is applied to bit-mask. + * Warning: bit shift direction depends on read or right command. + */ #include <linux/seq_file.h> #include <linux/uaccess.h> @@ -11,13 +77,30 @@ #include <linux/module.h> #include <linux/debugfs.h> #include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/kobject.h> +#include <linux/slab.h> #include <linux/mfd/abx500.h> #include <linux/mfd/abx500/ab8500.h> +#include <linux/mfd/abx500/ab8500-gpadc.h> + +#ifdef CONFIG_DEBUG_FS +#include <linux/string.h> +#include <linux/ctype.h> +#endif static u32 debug_bank; static u32 debug_address; +static int irq_first; +static int irq_last; +static u32 *irq_count; +static int num_irqs; + +static struct device_attribute **dev_attr; +static char **event_name; + /** * struct ab8500_reg_range * @first: the first address of the range @@ -42,15 +125,35 @@ struct ab8500_prcmu_ranges { const struct ab8500_reg_range *range; }; +/* hwreg- "mask" and "shift" entries ressources */ +struct hwreg_cfg { + u32 bank; /* target bank */ + u32 addr; /* target address */ + uint fmt; /* format */ + uint mask; /* read/write mask, applied before any bit shift */ + int shift; /* bit shift (read:right shift, write:left shift */ +}; +/* fmt bit #0: 0=hexa, 1=dec */ +#define REG_FMT_DEC(c) ((c)->fmt & 0x1) +#define REG_FMT_HEX(c) (!REG_FMT_DEC(c)) + +static struct hwreg_cfg hwreg_cfg = { + .addr = 0, /* default: invalid phys addr */ + .fmt = 0, /* default: 32bit access, hex output */ + .mask = 0xFFFFFFFF, /* default: no mask */ + .shift = 0, /* default: no bit shift */ +}; + #define AB8500_NAME_STRING "ab8500" -#define AB8500_NUM_BANKS 22 +#define AB8500_ADC_NAME_STRING "gpadc" +#define AB8500_NUM_BANKS 24 #define AB8500_REV_REG 0x80 static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { [0x0] = { .num_ranges = 0, - .range = 0, + .range = NULL, }, [AB8500_SYS_CTRL1_BLOCK] = { .num_ranges = 3, @@ -215,7 +318,7 @@ static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { }, }, [AB8500_CHARGER] = { - .num_ranges = 8, + .num_ranges = 9, .range = (struct ab8500_reg_range[]) { { .first = 0x00, @@ -249,6 +352,10 @@ static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { .first = 0xC0, .last = 0xC2, }, + { + .first = 0xf5, + .last = 0xf6, + }, }, }, [AB8500_GAS_GAUGE] = { @@ -268,6 +375,24 @@ static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { }, }, }, + [AB8500_DEVELOPMENT] = { + .num_ranges = 1, + .range = (struct ab8500_reg_range[]) { + { + .first = 0x00, + .last = 0x00, + }, + }, + }, + [AB8500_DEBUG] = { + .num_ranges = 1, + .range = (struct ab8500_reg_range[]) { + { + .first = 0x05, + .last = 0x07, + }, + }, + }, [AB8500_AUDIO] = { .num_ranges = 1, .range = (struct ab8500_reg_range[]) { @@ -354,15 +479,30 @@ static struc |