summaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-04-28 15:59:13 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2021-04-28 15:59:13 -0700
commit71a5cc28e88b0db69c3f83d4061ad4cc684af09f (patch)
tree3cc40d902e7cba992c27c946f69ef65fc7d2a807 /drivers/mfd
parentbe18cd1fcae2ed7db58d92d20733dfa8aa0a5173 (diff)
parentf9386c91574fe6da9f4fca9a47734816b0db0019 (diff)
downloadlinux-71a5cc28e88b0db69c3f83d4061ad4cc684af09f.tar.gz
linux-71a5cc28e88b0db69c3f83d4061ad4cc684af09f.tar.bz2
linux-71a5cc28e88b0db69c3f83d4061ad4cc684af09f.zip
Merge tag 'mfd-next-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones: "Core Framework: - Add support for Software Nodes to MFD Core - Remove support for Device Properties from MFD Core - Use standard APIs in MFD Core New Drivers: - Add support for ROHM BD9576MUF and BD9573MUF PMICs - Add support for Netronix Embedded Controller, PWM and RTC - Add support for Actions Semi ATC260x PMICs and OnKey New Device Support: - Add support for DG1 PCIe Graphics Card to Intel PMT - Add support for ROHM BD71815 PMIC to ROHM BD71828 - Add support for Tolino Shine 2 HD to Netronix Embedded Controller - Add support for AX10 BMC Secure Updates to Intel M10 BMC Removed Device Support: - Remove Arizona Extcon support from MFD - Remove ST-E AB8500 Power Supply code from MFD - Remove AB3100 altogether New Functionality: - Add support for SMBus and I2C modes to Dialog DA9063 - Switch to using Software Nodes in Intel (various) New/converted Device Tree bindings: - rohm bd71815-pmic, rohm bd9576-pmic, netronix ntxec, actions atc260x, ricoh rn5t618, qcom pm8xxx - Fix-ups: - Fix error handling/path; intel_pmt - Simplify code; rohm-bd718x7, ab8500-core, intel-m10-bmc - Trivial clean-ups (reordering, spelling); rohm-generic, rn5t618, max8997 - Use correct data-type; db8500-prcmu - Remove superfluous code; lp87565, intel_quark_i2c_gpi, lpc_sch, twl - Use generic APIs/defines; lm3533-core, intel_quark_i2c_gpio - Regmap related fix-ups; intel-m10-bmc, sec-core - Reorder resource freeing during remove; intel_quark_i2c_gpio - Make table indexing more robust; intel_quark_i2c_gpio - Fix reference imbalances; arizona-irq - Staticify and (un)constify things; arizona-spi, stmpe, ene-kb3930, intel-lpss-acpi, intel-lpss-pci, atc260x-i2c, intel_quark_i2c_gpio Bug Fixes: - Fix incorrect (register) values; intel-m10-bmc - Kconfig related fixes; ABX500_CORE - Do not clear the Auto Reload Register; stm32-timers" * tag 'mfd-next-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (84 commits) mfd: intel-m10-bmc: Add support for MAX10 BMC Secure Updates Revert "mfd: max8997: Add of_compatible to Extcon and Charger mfd_cell" mfd: twl: Remove unused inline function twl4030charger_usb_en() dt-bindings: mfd: Convert pm8xxx bindings to yaml dt-bindings: mfd: Add compatible for pmk8350 rtc i2c: designware: Get rid of legacy platform data mfd: intel_quark_i2c_gpio: Convert I²C to use software nodes mfd: lpc_sch: Partially revert "Add support for Intel Quark X1000" mfd: arizona: Fix rumtime PM imbalance on error mfd: max8997: Replace 8998 with 8997 mfd: core: Use acpi_find_child_device() for child devices lookup mfd: intel_quark_i2c_gpio: Don't play dirty trick with const mfd: intel_quark_i2c_gpio: Enable MSI interrupt mfd: intel_quark_i2c_gpio: Reuse BAR definitions for MFD cell indexing mfd: ntxec: Support for EC in Tolino Shine 2 HD mfd: stm32-timers: Avoid clearing auto reload register mfd: intel_quark_i2c_gpio: Replace I²C speeds with descriptive definitions mfd: intel_quark_i2c_gpio: Remove unused struct device member mfd: intel_quark_i2c_gpio: Unregister resources in reversed order mfd: Kconfig: ABX500_CORE should depend on ARCH_U8500 ...
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Kconfig82
-rw-r--r--drivers/mfd/Makefile7
-rw-r--r--drivers/mfd/ab3100-core.c929
-rw-r--r--drivers/mfd/ab3100-otp.c240
-rw-r--r--drivers/mfd/ab8500-core.c20
-rw-r--r--drivers/mfd/arizona-core.c20
-rw-r--r--drivers/mfd/arizona-irq.c2
-rw-r--r--drivers/mfd/arizona-spi.c4
-rw-r--r--drivers/mfd/atc260x-core.c310
-rw-r--r--drivers/mfd/atc260x-i2c.c64
-rw-r--r--drivers/mfd/da9063-i2c.c10
-rw-r--r--drivers/mfd/ene-kb3930.c2
-rw-r--r--drivers/mfd/intel-lpss-acpi.c32
-rw-r--r--drivers/mfd/intel-lpss-pci.c46
-rw-r--r--drivers/mfd/intel-lpss.c2
-rw-r--r--drivers/mfd/intel-lpss.h4
-rw-r--r--drivers/mfd/intel-m10-bmc.c30
-rw-r--r--drivers/mfd/intel_quark_i2c_gpio.c112
-rw-r--r--drivers/mfd/lm3533-core.c2
-rw-r--r--drivers/mfd/lpc_sch.c32
-rw-r--r--drivers/mfd/max8997.c4
-rw-r--r--drivers/mfd/mfd-core.c29
-rw-r--r--drivers/mfd/ntxec.c271
-rw-r--r--drivers/mfd/rn5t618.c3
-rw-r--r--drivers/mfd/rohm-bd71828.c486
-rw-r--r--drivers/mfd/rohm-bd718x7.c43
-rw-r--r--drivers/mfd/rohm-bd9576.c189
-rw-r--r--drivers/mfd/sec-core.c14
-rw-r--r--drivers/mfd/stm32-timers.c7
-rw-r--r--drivers/mfd/stmpe.c14
30 files changed, 1468 insertions, 1542 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 2ce9edb90901..5c7f2b100191 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -967,6 +967,17 @@ config MFD_VIPERBOARD
You need to select the mfd cell drivers separately.
The drivers do not support all features the board exposes.
+config MFD_NTXEC
+ tristate "Netronix embedded controller (EC)"
+ depends on OF || COMPILE_TEST
+ depends on I2C
+ select REGMAP_I2C
+ select MFD_CORE
+ help
+ Say yes here if you want to support the embedded controller found in
+ certain e-book readers designed by the original design manufacturer
+ Netronix.
+
config MFD_RETU
tristate "Nokia Retu and Tahvo multi-function device"
select MFD_CORE
@@ -1224,7 +1235,8 @@ config MFD_SC27XX_PMIC
config ABX500_CORE
bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions"
- default y if ARCH_U300 || ARCH_U8500 || COMPILE_TEST
+ depends on ARCH_U8500 || COMPILE_TEST
+ default y if ARCH_U8500
help
Say yes here if you have the ABX500 Mixed Signal IC family
chips. This core driver expose register access functions.
@@ -1232,30 +1244,6 @@ config ABX500_CORE
remain unchanged when IC changes. Binding of the functions to
actual register access is done by the IC core driver.
-config AB3100_CORE
- bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions"
- depends on I2C=y && ABX500_CORE
- select MFD_CORE
- default y if ARCH_U300
- help
- Select this to enable the AB3100 Mixed Signal IC core
- functionality. This connects to a AB3100 on the I2C bus
- and expose a number of symbols needed for dependent devices
- to read and write registers and subscribe to events from
- this multi-functional IC. This is needed to use other features
- of the AB3100 such as battery-backed RTC, charging control,
- LEDs, vibrator, system power and temperature, power management
- and ALSA sound.
-
-config AB3100_OTP
- tristate "ST-Ericsson AB3100 OTP functions"
- depends on AB3100_CORE
- default y if AB3100_CORE
- help
- Select this to enable the AB3100 Mixed Signal IC OTP (one-time
- programmable memory) support. This exposes a sysfs file to read
- out OTP values.
-
config AB8500_CORE
bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
depends on ABX500_CORE && MFD_DB8500_PRCMU
@@ -1975,19 +1963,31 @@ config MFD_ROHM_BD70528
charger.
config MFD_ROHM_BD71828
- tristate "ROHM BD71828 Power Management IC"
+ tristate "ROHM BD71828 and BD71815 Power Management IC"
depends on I2C=y
depends on OF
select REGMAP_I2C
select REGMAP_IRQ
select MFD_CORE
help
- Select this option to get support for the ROHM BD71828 Power
- Management IC. BD71828GW is a single-chip power management IC for
- battery-powered portable devices. The IC integrates 7 buck
- converters, 7 LDOs, and a 1500 mA single-cell linear charger.
- Also included is a Coulomb counter, a real-time clock (RTC), and
- a 32.768 kHz clock gate.
+ Select this option to get support for the ROHM BD71828 and BD71815
+ Power Management ICs. BD71828GW and BD71815AGW are single-chip power
+ management ICs mainly for battery-powered portable devices.
+ The BD71828 integrates 7 buck converters and 7 LDOs. The BD71815
+ has 5 bucks, 7 LDOs, and a boost for driving LEDs. Both ICs provide
+ also a single-cell linear charger, a Coulomb counter, a real-time
+ clock (RTC), GPIOs and a 32.768 kHz clock gate.
+
+config MFD_ROHM_BD957XMUF
+ tristate "ROHM BD9576MUF and BD9573MUF Power Management ICs"
+ depends on I2C=y
+ depends on OF
+ select REGMAP_I2C
+ select MFD_CORE
+ help
+ Select this option to get support for the ROHM BD9576MUF and
+ BD9573MUF Power Management ICs. BD9576 and BD9573 are primarily
+ designed to be used to power R-Car series processors.
config MFD_STM32_LPTIMER
tristate "Support for STM32 Low-Power Timer"
@@ -2055,6 +2055,24 @@ config MFD_WCD934X
This driver provides common support WCD934x audio codec and its
associated Pin Controller, Soundwire Controller and Audio codec.
+config MFD_ATC260X
+ tristate
+ select MFD_CORE
+ select REGMAP
+ select REGMAP_IRQ
+
+config MFD_ATC260X_I2C
+ tristate "Actions Semi ATC260x PMICs with I2C"
+ select MFD_ATC260X
+ select REGMAP_I2C
+ depends on I2C
+ help
+ Support for the Actions Semi ATC260x PMICs controlled via I2C.
+
+ This driver provides common support for accessing the ATC2603C
+ and ATC2609A chip variants, additional drivers must be enabled
+ in order to use the functionality of the device.
+
config MFD_KHADAS_MCU
tristate "Support for Khadas System control Microcontroller"
depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 834f5463af28..4f6d2b8a5f76 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -178,8 +178,6 @@ obj-$(CONFIG_MFD_PCF50633) += pcf50633.o
obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
obj-$(CONFIG_ABX500_CORE) += abx500-core.o
-obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
-obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o
obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
# ab8500-core need to come after db8500-prcmu (which provides the channel)
@@ -218,6 +216,7 @@ obj-$(CONFIG_MFD_INTEL_PMC_BXT) += intel_pmc_bxt.o
obj-$(CONFIG_MFD_INTEL_PMT) += intel_pmt.o
obj-$(CONFIG_MFD_PALMAS) += palmas.o
obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o
+obj-$(CONFIG_MFD_NTXEC) += ntxec.o
obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
obj-$(CONFIG_MFD_RK808) += rk808.o
obj-$(CONFIG_MFD_RN5T618) += rn5t618.o
@@ -261,6 +260,7 @@ obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o
obj-$(CONFIG_MFD_ROHM_BD70528) += rohm-bd70528.o
obj-$(CONFIG_MFD_ROHM_BD71828) += rohm-bd71828.o
obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
+obj-$(CONFIG_MFD_ROHM_BD957XMUF) += rohm-bd9576.o
obj-$(CONFIG_MFD_STMFX) += stmfx.o
obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o
obj-$(CONFIG_MFD_ACER_A500_EC) += acer-ec-a500.o
@@ -268,3 +268,6 @@ obj-$(CONFIG_MFD_ACER_A500_EC) += acer-ec-a500.o
obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o
obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o
obj-$(CONFIG_MFD_INTEL_M10_BMC) += intel-m10-bmc.o
+
+obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o
+obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
deleted file mode 100644
index ee71ae04b5e6..000000000000
--- a/drivers/mfd/ab3100-core.c
+++ /dev/null
@@ -1,929 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2007-2010 ST-Ericsson
- * Low-level core for exclusive access to the AB3100 IC on the I2C bus
- * and some basic chip-configuration.
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- */
-
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/list.h>
-#include <linux/notifier.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/random.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/ab3100.h>
-#include <linux/mfd/abx500.h>
-
-/* These are the only registers inside AB3100 used in this main file */
-
-/* Interrupt event registers */
-#define AB3100_EVENTA1 0x21
-#define AB3100_EVENTA2 0x22
-#define AB3100_EVENTA3 0x23
-
-/* AB3100 DAC converter registers */
-#define AB3100_DIS 0x00
-#define AB3100_D0C 0x01
-#define AB3100_D1C 0x02
-#define AB3100_D2C 0x03
-#define AB3100_D3C 0x04
-
-/* Chip ID register */
-#define AB3100_CID 0x20
-
-/* AB3100 interrupt registers */
-#define AB3100_IMRA1 0x24
-#define AB3100_IMRA2 0x25
-#define AB3100_IMRA3 0x26
-#define AB3100_IMRB1 0x2B
-#define AB3100_IMRB2 0x2C
-#define AB3100_IMRB3 0x2D
-
-/* System Power Monitoring and control registers */
-#define AB3100_MCA 0x2E
-#define AB3100_MCB 0x2F
-
-/* SIM power up */
-#define AB3100_SUP 0x50
-
-/*
- * I2C communication
- *
- * The AB3100 is usually assigned address 0x48 (7-bit)
- * The chip is defined in the platform i2c_board_data section.
- */
-static int ab3100_get_chip_id(struct device *dev)
-{
- struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
-
- return (int)ab3100->chip_id;
-}
-
-static int ab3100_set_register_interruptible(struct ab3100 *ab3100,
- u8 reg, u8 regval)
-{
- u8 regandval[2] = {reg, regval};
- int err;
-
- err = mutex_lock_interruptible(&ab3100->access_mutex);
- if (err)
- return err;
-
- /*
- * A two-byte write message with the first byte containing the register
- * number and the second byte containing the value to be written
- * effectively sets a register in the AB3100.
- */
- err = i2c_master_send(ab3100->i2c_client, regandval, 2);
- if (err < 0) {
- dev_err(ab3100->dev,
- "write error (write register): %d\n",
- err);
- } else if (err != 2) {
- dev_err(ab3100->dev,
- "write error (write register)\n"
- " %d bytes transferred (expected 2)\n",
- err);
- err = -EIO;
- } else {
- /* All is well */
- err = 0;
- }
- mutex_unlock(&ab3100->access_mutex);
- return err;
-}
-
-static int set_register_interruptible(struct device *dev,
- u8 bank, u8 reg, u8 value)
-{
- struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
-
- return ab3100_set_register_interruptible(ab3100, reg, value);
-}
-
-/*
- * The test registers exist at an I2C bus address up one
- * from the ordinary base. They are not supposed to be used
- * in production code, but sometimes you have to do that
- * anyway. It's currently only used from this file so declare
- * it static and do not export.
- */
-static int ab3100_set_test_register_interruptible(struct ab3100 *ab3100,
- u8 reg, u8 regval)
-{
- u8 regandval[2] = {reg, regval};
- int err;
-
- err = mutex_lock_interruptible(&ab3100->access_mutex);
- if (err)
- return err;
-
- err = i2c_master_send(ab3100->testreg_client, regandval, 2);
- if (err < 0) {
- dev_err(ab3100->dev,
- "write error (write test register): %d\n",
- err);
- } else if (err != 2) {
- dev_err(ab3100->dev,
- "write error (write test register)\n"
- " %d bytes transferred (expected 2)\n",
- err);
- err = -EIO;
- } else {
- /* All is well */
- err = 0;
- }
- mutex_unlock(&ab3100->access_mutex);
-
- return err;
-}
-
-static int ab3100_get_register_interruptible(struct ab3100 *ab3100,
- u8 reg, u8 *regval)
-{
- int err;
-
- err = mutex_lock_interruptible(&ab3100->access_mutex);
- if (err)
- return err;
-
- /*
- * AB3100 require an I2C "stop" command between each message, else
- * it will not work. The only way of achieveing this with the
- * message transport layer is to send the read and write messages
- * separately.
- */
- err = i2c_master_send(ab3100->i2c_client, &reg, 1);
- if (err < 0) {
- dev_err(ab3100->dev,
- "write error (send register address): %d\n",
- err);
- goto get_reg_out_unlock;
- } else if (err != 1) {
- dev_err(ab3100->dev,
- "write error (send register address)\n"
- " %d bytes transferred (expected 1)\n",
- err);
- err = -EIO;
- goto get_reg_out_unlock;
- } else {
- /* All is well */
- err = 0;
- }
-
- err = i2c_master_recv(ab3100->i2c_client, regval, 1);
- if (err < 0) {
- dev_err(ab3100->dev,
- "write error (read register): %d\n",
- err);
- goto get_reg_out_unlock;
- } else if (err != 1) {
- dev_err(ab3100->dev,
- "write error (read register)\n"
- " %d bytes transferred (expected 1)\n",
- err);
- err = -EIO;
- goto get_reg_out_unlock;
- } else {
- /* All is well */
- err = 0;
- }
-
- get_reg_out_unlock:
- mutex_unlock(&ab3100->access_mutex);
- return err;
-}
-
-static int get_register_interruptible(struct device *dev, u8 bank, u8 reg,
- u8 *value)
-{
- struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
-
- return ab3100_get_register_interruptible(ab3100, reg, value);
-}
-
-static int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
- u8 first_reg, u8 *regvals, u8 numregs)
-{
- int err;
-
- if (ab3100->chip_id == 0xa0 ||
- ab3100->chip_id == 0xa1)
- /* These don't support paged reads */
- return -EIO;
-
- err = mutex_lock_interruptible(&ab3100->access_mutex);
- if (err)
- return err;
-
- /*
- * Paged read also require an I2C "stop" command.
- */
- err = i2c_master_send(ab3100->i2c_client, &first_reg, 1);
- if (err < 0) {
- dev_err(ab3100->dev,
- "write error (send first register address): %d\n",
- err);
- goto get_reg_page_out_unlock;
- } else if (err != 1) {
- dev_err(ab3100->dev,
- "write error (send first register address)\n"
- " %d bytes transferred (expected 1)\n",
- err);
- err = -EIO;
- goto get_reg_page_out_unlock;
- }
-
- err = i2c_master_recv(ab3100->i2c_client, regvals, numregs);
- if (err < 0) {
- dev_err(ab3100->dev,
- "write error (read register page): %d\n",
- err);
- goto get_reg_page_out_unlock;
- } else if (err != numregs) {
- dev_err(ab3100->dev,
- "write error (read register page)\n"
- " %d bytes transferred (expected %d)\n",
- err, numregs);
- err = -EIO;
- goto get_reg_page_out_unlock;
- }
-
- /* All is well */
- err = 0;
-
- get_reg_page_out_unlock:
- mutex_unlock(&ab3100->access_mutex);
- return err;
-}
-
-static int get_register_page_interruptible(struct device *dev, u8 bank,
- u8 first_reg, u8 *regvals, u8 numregs)
-{
- struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
-
- return ab3100_get_register_page_interruptible(ab3100,
- first_reg, regvals, numregs);
-}
-
-static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
- u8 reg, u8 andmask, u8 ormask)
-{
- u8 regandval[2] = {reg, 0};
- int err;
-
- err = mutex_lock_interruptible(&ab3100->access_mutex);
- if (err)
- return err;
-
- /* First read out the target register */
- err = i2c_master_send(ab3100->i2c_client, &reg, 1);
- if (err < 0) {
- dev_err(ab3100->dev,
- "write error (maskset send address): %d\n",
- err);
- goto get_maskset_unlock;
- } else if (err != 1) {
- dev_err(ab3100->dev,
- "write error (maskset send address)\n"
- " %d bytes transferred (expected 1)\n",
- err);
- err = -EIO;
- goto get_maskset_unlock;
- }
-
- err = i2c_master_recv(ab3100->i2c_client, &regandval[1], 1);
- if (err < 0) {
- dev_err(ab3100->dev,
- "write error (maskset read register): %d\n",
- err);
- goto get_maskset_unlock;
- } else if (err != 1) {
- dev_err(ab3100->dev,
- "write error (maskset read register)\n"
- " %d bytes transferred (expected 1)\n",
- err);
- err = -EIO;
- goto get_maskset_unlock;
- }
-
- /* Modify the register */
- regandval[1] &= andmask;
- regandval[1] |= ormask;
-
- /* Write the register */
- err = i2c_master_send(ab3100->i2c_client, regandval, 2);
- if (err < 0) {
- dev_err(ab3100->dev,
- "write error (write register): %d\n",
- err);
- goto get_maskset_unlock;
- } else if (err != 2) {
- dev_err(ab3100->dev,
- "write error (write register)\n"
- " %d bytes transferred (expected 2)\n",
- err);
- err = -EIO;
- goto get_maskset_unlock;
- }
-
- /* All is well */
- err = 0;
-
- get_maskset_unlock:
- mutex_unlock(&ab3100->access_mutex);
- return err;
-}
-
-static int mask_and_set_register_interruptible(struct device *dev, u8 bank,
- u8 reg, u8 bitmask, u8 bitvalues)
-{
- struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
-
- return ab3100_mask_and_set_register_interruptible(ab3100,
- reg, bitmask, (bitmask & bitvalues));
-}
-
-/*
- * Register a simple callback for handling any AB3100 events.
- */
-int ab3100_event_register(struct ab3100 *ab3100,
- struct notifier_block *nb)
-{
- return blocking_notifier_chain_register(&ab3100->event_subscribers,
- nb);
-}
-EXPORT_SYMBOL(ab3100_event_register);
-
-/*
- * Remove a previously registered callback.
- */
-int ab3100_event_unregister(struct ab3100 *ab3100,
- struct notifier_block *nb)
-{
- return blocking_notifier_chain_unregister(&ab3100->event_subscribers,
- nb);
-}
-EXPORT_SYMBOL(ab3100_event_unregister);
-
-
-static int ab3100_event_registers_startup_state_get(struct device *dev,
- u8 *event)
-{
- struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
-
- if (!ab3100->startup_events_read)
- return -EAGAIN; /* Try again later */
- memcpy(event, ab3100->startup_events, 3);
-
- return 0;
-}
-
-static struct abx500_ops ab3100_ops = {
- .get_chip_id = ab3100_get_chip_id,
- .set_register = set_register_interruptible,
- .get_register = get_register_interruptible,
- .get_register_page = get_register_page_interruptible,
- .set_register_page = NULL,
- .mask_and_set_register = mask_and_set_register_interruptible,
- .event_registers_startup_state_get =
- ab3100_event_registers_startup_state_get,
- .startup_irq_enabled = NULL,
-};
-
-/*
- * This is a threaded interrupt handler so we can make some
- * I2C calls etc.
- */
-static irqreturn_t ab3100_irq_handler(int irq, void *data)
-{
- struct ab3100 *ab3100 = data;
- u8 event_regs[3];
- u32 fatevent;
- int err;
-
- err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1,
- event_regs, 3);
- if (err)
- goto err_event;
-
- fatevent = (event_regs[0] << 16) |
- (event_regs[1] << 8) |
- event_regs[2];
-
- if (!ab3100->startup_events_read) {
- ab3100->startup_events[0] = event_regs[0];
- ab3100->startup_events[1] = event_regs[1];
- ab3100->startup_events[2] = event_regs[2];
- ab3100->startup_events_read = true;
- }
- /*
- * The notified parties will have to mask out the events
- * they're interested in and react to them. They will be
- * notified on all events, then they use the fatevent value
- * to determine if they're interested.
- */
- blocking_notifier_call_chain(&ab3100->event_subscribers,
- fatevent, NULL);
-
- dev_dbg(ab3100->dev,
- "IRQ Event: 0x%08x\n", fatevent);
-
- return IRQ_HANDLED;
-
- err_event:
- dev_dbg(ab3100->dev,
- "error reading event status\n");
- return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_DEBUG_FS
-/*
- * Some debugfs entries only exposed if we're using debug
- */
-static int ab3100_registers_print(struct seq_file *s, void *p)
-{
- struct ab3100 *ab3100 = s->private;
- u8 value;
- u8 reg;
-
- seq_puts(s, "AB3100 registers:\n");
-
- for (reg = 0; reg < 0xff; reg++) {
- ab3100_get_register_interruptible(ab3100, reg, &value);
- seq_printf(s, "[0x%x]: 0x%x\n", reg, value);
- }
- return 0;
-}
-
-static int ab3100_registers_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab3100_registers_print, inode->i_private);
-}
-
-static const struct file_operations ab3100_registers_fops = {
- .open = ab3100_registers_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-struct ab3100_get_set_reg_priv {
- struct ab3100 *ab3100;
- bool mode;
-};
-
-static ssize_t ab3100_get_set_reg(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ab3100_get_set_reg_priv *priv = file->private_data;
- struct ab3100 *ab3100 = priv->ab3100;
- char buf[32];
- ssize_t buf_size;
- int regp;
- u8 user_reg;
- int err;
- int i = 0;
-
- /* Get userspace string and assure termination */
- buf_size = min((ssize_t)count, (ssize_t)(sizeof(buf)-1));
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- buf[buf_size] = 0;
-
- /*
- * The idea is here to parse a string which is either
- * "0xnn" for reading a register, or "0xaa 0xbb" for
- * writing 0xbb to the register 0xaa. First move past
- * whitespace and then begin to parse the register.
- */
- while ((i < buf_size) && (buf[i] == ' '))
- i++;
- regp = i;
-
- /*
- * Advance pointer to end of string then terminate
- * the register string. This is needed to satisfy
- * the kstrtou8() function.
- */
- while ((i < buf_size) && (buf[i] != ' '))
- i++;
- buf[i] = '\0';
-
- err = kstrtou8(&buf[regp], 16, &user_reg);
- if (err)
- return err;
-
- /* Either we read or we write a register here */
- if (!priv->mode) {
- /* Reading */
- u8 regvalue;
-
- ab3100_get_register_interruptible(ab3100, user_reg, &regvalue);
-
- dev_info(ab3100->dev,
- "debug read AB3100 reg[0x%02x]: 0x%02x\n",
- user_reg, regvalue);
- } else {
- int valp;
- u8 user_value;
- u8 regvalue;
-
- /*
- * Writing, we need some value to write to
- * the register so keep parsing the string
- * from userspace.
- */
- i++;
- while ((i < buf_size) && (buf[i] == ' '))
- i++;
- valp = i;
- while ((i < buf_size) && (buf[i] != ' '))
- i++;
- buf[i] = '\0';
-
- err = kstrtou8(&buf[valp], 16, &user_value);
- if (err)
- return err;
-
- ab3100_set_register_interruptible(ab3100, user_reg, user_value);
- ab3100_get_register_interruptible(ab3100, user_reg, &regvalue);
-
- dev_info(ab3100->dev,
- "debug write reg[0x%02x]\n"
- " with 0x%02x, after readback: 0x%02x\n",
- user_reg, user_value, regvalue);
- }
- return buf_size;
-}
-
-static const struct file_operations ab3100_get_set_reg_fops = {
- .open = simple_open,
- .write = ab3100_get_set_reg,
- .llseek = noop_llseek,
-};
-
-static struct ab3100_get_set_reg_priv ab3100_get_priv;
-static struct ab3100_get_set_reg_priv ab3100_set_priv;
-
-static void ab3100_setup_debugfs(struct ab3100 *ab3100)
-{
- struct dentry *ab3100_dir;
-
- ab3100_dir = debugfs_create_dir("ab3100", NULL);
-
- debugfs_create_file("registers", S_IRUGO, ab3100_dir, ab3100,
- &ab3100_registers_fops);
-
- ab3100_get_priv.ab3100 = ab3100;
- ab3100_get_priv.mode = false;
- debugfs_create_file("get_reg", S_IWUSR, ab3100_dir, &ab3100_get_priv,
- &ab3100_get_set_reg_fops);
-
- ab3100_set_priv.ab3100 = ab3100;
- ab3100_set_priv.mode = true;
- debugfs_create_file("set_reg", S_IWUSR, ab3100_dir, &ab3100_set_priv,
- &ab3100_get_set_reg_fops);
-}
-#else
-static inline void ab3100_setup_debugfs(struct ab3100 *ab3100)
-{
-}
-#endif
-
-/*
- * Basic set-up, datastructure creation/destruction and I2C interface.
- * This sets up a default config in the AB3100 chip so that it
- * will work as expected.
- */
-
-struct ab3100_init_setting {
- u8 abreg;
- u8 setting;
-};
-
-static const struct ab3100_init_setting ab3100_init_settings[] = {
- {
- .abreg = AB3100_MCA,
- .setting = 0x01
- }, {
- .abreg = AB3100_MCB,
- .setting = 0x30
- }, {
- .abreg = AB3100_IMRA1,
- .setting = 0x00
- }, {
- .abreg = AB3100_IMRA2,
- .setting = 0xFF
- }, {
- .abreg = AB3100_IMRA3,
- .setting = 0x01
- }, {
- .abreg = AB3100_IMRB1,
- .setting = 0xBF
- }, {
- .abreg = AB3100_IMRB2,
- .setting = 0xFF
- }, {
- .abreg = AB3100_IMRB3,
- .setting = 0xFF
- }, {
- .abreg = AB3100_SUP,
- .setting = 0x00
- }, {
- .abreg = AB3100_DIS,
- .setting = 0xF0
- }, {
- .abreg = AB3100_D0C,
- .setting = 0x00
- }, {
- .abreg = AB3100_D1C,
- .setting = 0x00
- }, {
- .abreg = AB3100_D2C,
- .setting = 0x00
- }, {
- .abreg = AB3100_D3C,
- .setting = 0x00