You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'mfd-3.6-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
Pull MFD bits from Samuel Ortiz: "We have support for a few new drivers: - Samsung s2mps11 - Wolfson Microelectronics wm5102 and wm5110 - Marvell 88PM800 and 88PM805 - TI twl6041 We also have our regular driver improvements: - Device tree and IRQ domain support for STE AB8500 - Regmap and devm_* API conversion for TI tps6586x - Device tree support for Samsung max77686 - devm_* API conversion for STE AB3100 Besides that, quite a lot of fixing and cleanup for mc13xxx, tps65910, tps65090, da9052 and twl-core." Fix up mostly trivial conflicts, with the exception of drivers/usb/host/ehci-omap.c in particular, which had some re-organization of the reset sequence (commit1a49e2ac96: "EHCI: centralize controller initialization") that clashed with commit2761a63945("mfd: USB: Fix the omap-usb EHCI ULPI PHY reset fix issues"). In particular, commit2761a63945moved the usb_add_hcd() to the *middle* of the reset sequence, which clashes fairly badly with the reset sequence re-organization (although it could have been done inside the new omap_ehci_init() function). I left that part of commit2761a63945just undone. * tag 'mfd-3.6-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (110 commits) mfd: Ensure AB8500 platform data is passed through db8500-prcmu to MFD Core mfd: Arizone core should select MFD_CORE mfd: Fix arizona-irq.c build by selecting REGMAP_IRQ mfd: Add debug trace on entering and leaving arizone runtime suspend mfd: Correct tps65090 cell names mfd: Remove gpio support from tps6586x core driver ARM: tegra: defconfig: Enable tps6586x gpio gpio: tps6586x: Add gpio support through platform driver mfd: Cache tps6586x register through regmap mfd: Use regmap for tps6586x register access. mfd: Use devm managed resources for tps6586x input: Add onkey support for 88PM80X PMIC mfd: Add support for twl6041 mfd: Fix twl6040 revision information mfd: Matches should be NULL when populate anatop child devices input: ab8500-ponkey: Create AB8500 domain IRQ mapping mfd: Add missing out of memory check for pcf50633 Documentation: Describe the AB8500 Device Tree bindings mfd: Add tps65910 32-kHz-crystal-input init mfd: Drop modifying mc13xxx driver's id_table in probe ...
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
* AB8500 Multi-Functional Device (MFD)
|
||||
|
||||
Required parent device properties:
|
||||
- compatible : contains "stericsson,ab8500";
|
||||
- interrupts : contains the IRQ line for the AB8500
|
||||
- interrupt-controller : describes the AB8500 as an Interrupt Controller (has its own domain)
|
||||
- #interrupt-cells : should be 2, for 2-cell format
|
||||
- The first cell is the AB8500 local IRQ number
|
||||
- The second cell is used to specify optional parameters
|
||||
- bits[3:0] trigger type and level flags:
|
||||
1 = low-to-high edge triggered
|
||||
2 = high-to-low edge triggered
|
||||
4 = active high level-sensitive
|
||||
8 = active low level-sensitive
|
||||
|
||||
Optional parent device properties:
|
||||
- reg : contains the PRCMU mailbox address for the AB8500 i2c port
|
||||
|
||||
The AB8500 consists of a large and varied group of sub-devices:
|
||||
|
||||
Device IRQ Names Supply Names Description
|
||||
------ --------- ------------ -----------
|
||||
ab8500-bm : : : Battery Manager
|
||||
ab8500-btemp : : : Battery Temperature
|
||||
ab8500-charger : : : Battery Charger
|
||||
ab8500-fg : : : Fuel Gauge
|
||||
ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter
|
||||
SW_CONV_END : :
|
||||
ab8500-gpio : : : GPIO Controller
|
||||
ab8500-ponkey : ONKEY_DBF : : Power-on Key
|
||||
ONKEY_DBR : :
|
||||
ab8500-pwm : : : Pulse Width Modulator
|
||||
ab8500-regulator : : : Regulators
|
||||
ab8500-rtc : 60S : : Real Time Clock
|
||||
: ALARM : :
|
||||
ab8500-sysctrl : : : System Control
|
||||
ab8500-usb : ID_WAKEUP_R : vddulpivio18 : Universal Serial Bus
|
||||
: ID_WAKEUP_F : v-ape :
|
||||
: VBUS_DET_F : musb_1v8 :
|
||||
: VBUS_DET_R : :
|
||||
: USB_LINK_STATUS : :
|
||||
: USB_ADP_PROBE_PLUG : :
|
||||
: USB_ADP_PROBE_UNPLUG : :
|
||||
|
||||
Required child device properties:
|
||||
- compatible : "stericsson,ab8500-[bm|btemp|charger|fg|gpadc|gpio|ponkey|
|
||||
pwm|regulator|rtc|sysctrl|usb]";
|
||||
|
||||
Optional child device properties:
|
||||
- interrupts : contains the device IRQ(s) using the 2-cell format (see above)
|
||||
- interrupt-names : contains names of IRQ resource in the order in which they were
|
||||
supplied in the interrupts property
|
||||
- <supply_name>-supply : contains a phandle to the regulator supply node in Device Tree
|
||||
|
||||
ab8500@5 {
|
||||
compatible = "stericsson,ab8500";
|
||||
reg = <5>; /* mailbox 5 is i2c */
|
||||
interrupts = <0 40 0x4>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
ab8500-rtc {
|
||||
compatible = "stericsson,ab8500-rtc";
|
||||
interrupts = <17 0x4
|
||||
18 0x4>;
|
||||
interrupt-names = "60S", "ALARM";
|
||||
};
|
||||
|
||||
ab8500-gpadc {
|
||||
compatible = "stericsson,ab8500-gpadc";
|
||||
interrupts = <32 0x4
|
||||
39 0x4>;
|
||||
interrupt-names = "HW_CONV_END", "SW_CONV_END";
|
||||
vddadc-supply = <&ab8500_ldo_tvout_reg>;
|
||||
};
|
||||
|
||||
ab8500-usb {
|
||||
compatible = "stericsson,ab8500-usb";
|
||||
interrupts = < 90 0x4
|
||||
96 0x4
|
||||
14 0x4
|
||||
15 0x4
|
||||
79 0x4
|
||||
74 0x4
|
||||
75 0x4>;
|
||||
interrupt-names = "ID_WAKEUP_R",
|
||||
"ID_WAKEUP_F",
|
||||
"VBUS_DET_F",
|
||||
"VBUS_DET_R",
|
||||
"USB_LINK_STATUS",
|
||||
"USB_ADP_PROBE_PLUG",
|
||||
"USB_ADP_PROBE_UNPLUG";
|
||||
vddulpivio18-supply = <&ab8500_ldo_initcore_reg>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
musb_1v8-supply = <&db8500_vsmps2_reg>;
|
||||
};
|
||||
|
||||
ab8500-ponkey {
|
||||
compatible = "stericsson,ab8500-ponkey";
|
||||
interrupts = <6 0x4
|
||||
7 0x4>;
|
||||
interrupt-names = "ONKEY_DBF", "ONKEY_DBR";
|
||||
};
|
||||
|
||||
ab8500-sysctrl {
|
||||
compatible = "stericsson,ab8500-sysctrl";
|
||||
};
|
||||
|
||||
ab8500-pwm {
|
||||
compatible = "stericsson,ab8500-pwm";
|
||||
};
|
||||
|
||||
ab8500-regulators {
|
||||
compatible = "stericsson,ab8500-regulator";
|
||||
|
||||
ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
|
||||
/*
|
||||
* See: Documentation/devicetree/bindings/regulator/regulator.txt
|
||||
* for more information on regulators
|
||||
*/
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
Maxim MAX77686 multi-function device
|
||||
|
||||
MAX77686 is a Mulitifunction device with PMIC, RTC and Charger on chip. It is
|
||||
interfaced to host controller using i2c interface. PMIC and Charger submodules
|
||||
are addressed using same i2c slave address whereas RTC submodule uses
|
||||
different i2c slave address,presently for which we are statically creating i2c
|
||||
client while probing.This document describes the binding for mfd device and
|
||||
PMIC submodule.
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be "maxim,max77686";
|
||||
- reg : Specifies the i2c slave address of PMIC block.
|
||||
- interrupts : This i2c device has an IRQ line connected to the main SoC.
|
||||
- interrupt-parent : The parent interrupt controller.
|
||||
|
||||
Optional node:
|
||||
- voltage-regulators : The regulators of max77686 have to be instantiated
|
||||
under subnode named "voltage-regulators" using the following format.
|
||||
|
||||
regulator_name {
|
||||
regulator-compatible = LDOn/BUCKn
|
||||
standard regulator constraints....
|
||||
};
|
||||
refer Documentation/devicetree/bindings/regulator/regulator.txt
|
||||
|
||||
The regulator-compatible property of regulator should initialized with string
|
||||
to get matched with their hardware counterparts as follow:
|
||||
|
||||
-LDOn : for LDOs, where n can lie in range 1 to 26.
|
||||
example: LDO1, LDO2, LDO26.
|
||||
-BUCKn : for BUCKs, where n can lie in range 1 to 9.
|
||||
example: BUCK1, BUCK5, BUCK9.
|
||||
|
||||
Example:
|
||||
|
||||
max77686@09 {
|
||||
compatible = "maxim,max77686";
|
||||
interrupt-parent = <&wakeup_eint>;
|
||||
interrupts = <26 0>;
|
||||
reg = <0x09>;
|
||||
|
||||
voltage-regulators {
|
||||
ldo11_reg {
|
||||
regulator-compatible = "LDO11";
|
||||
regulator-name = "vdd_ldo11";
|
||||
regulator-min-microvolt = <1900000>;
|
||||
regulator-max-microvolt = <1900000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
buck1_reg {
|
||||
regulator-compatible = "BUCK1";
|
||||
regulator-name = "vdd_mif";
|
||||
regulator-min-microvolt = <950000>;
|
||||
regulator-max-microvolt = <1300000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
}
|
||||
@@ -81,7 +81,7 @@ Example:
|
||||
|
||||
ti,vmbch-threshold = 0;
|
||||
ti,vmbch2-threshold = 0;
|
||||
|
||||
ti,en-ck32k-xtal;
|
||||
ti,en-gpio-sleep = <0 0 1 0 0 0 0 0 0>;
|
||||
|
||||
vcc1-supply = <®_parent>;
|
||||
|
||||
@@ -6,7 +6,7 @@ They are connected ot the host processor via i2c for commands, McPDM for audio
|
||||
data and commands.
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be "ti,twl6040";
|
||||
- compatible : "ti,twl6040" for twl6040, "ti,twl6041" for twl6041
|
||||
- reg: must be 0x4b for i2c address
|
||||
- interrupts: twl6040 has one interrupt line connecteded to the main SoC
|
||||
- interrupt-parent: The parent interrupt controller
|
||||
|
||||
+10
@@ -5912,6 +5912,16 @@ L: linux-fbdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/video/s3c-fb.c
|
||||
|
||||
SAMSUNG MULTIFUNCTION DEVICE DRIVERS
|
||||
M: Sangbeom Kim <sbkim73@samsung.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/mfd/sec*.c
|
||||
F: drivers/regulator/s2m*.c
|
||||
F: drivers/regulator/s5m*.c
|
||||
F: drivers/rtc/rtc-sec.c
|
||||
F: include/linux/mfd/samsung/
|
||||
|
||||
SERIAL DRIVERS
|
||||
M: Alan Cox <alan@linux.intel.com>
|
||||
L: linux-serial@vger.kernel.org
|
||||
|
||||
@@ -106,6 +106,7 @@ CONFIG_I2C_TEGRA=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_TEGRA=y
|
||||
CONFIG_GPIO_TPS65910=y
|
||||
CONFIG_GPIO_TPS6586X=y
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
CONFIG_BATTERY_SBS=y
|
||||
CONFIG_SENSORS_LM90=y
|
||||
|
||||
@@ -1066,12 +1066,8 @@ static struct platform_device nuri_max8903_device = {
|
||||
static void __init nuri_power_init(void)
|
||||
{
|
||||
int gpio;
|
||||
int irq_base = IRQ_GPIO_END + 1;
|
||||
int ta_en = 0;
|
||||
|
||||
nuri_max8997_pdata.irq_base = irq_base;
|
||||
irq_base += MAX8997_IRQ_NR;
|
||||
|
||||
gpio = EXYNOS4_GPX0(7);
|
||||
gpio_request(gpio, "AP_PMIC_IRQ");
|
||||
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
|
||||
|
||||
@@ -426,7 +426,6 @@ static struct max8997_platform_data __initdata origen_max8997_pdata = {
|
||||
.buck1_gpiodvs = false,
|
||||
.buck2_gpiodvs = false,
|
||||
.buck5_gpiodvs = false,
|
||||
.irq_base = IRQ_GPIO_END + 1,
|
||||
|
||||
.ignore_gpiodvs_side_effect = true,
|
||||
.buck125_default_idx = 0x0,
|
||||
|
||||
@@ -211,24 +211,6 @@ static struct ab8500_platform_data ab8500_platdata = {
|
||||
.codec = &ab8500_codec_pdata,
|
||||
};
|
||||
|
||||
static struct resource ab8500_resources[] = {
|
||||
[0] = {
|
||||
.start = IRQ_DB8500_AB8500,
|
||||
.end = IRQ_DB8500_AB8500,
|
||||
.flags = IORESOURCE_IRQ
|
||||
}
|
||||
};
|
||||
|
||||
struct platform_device ab8500_device = {
|
||||
.name = "ab8500-core",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &ab8500_platdata,
|
||||
},
|
||||
.num_resources = 1,
|
||||
.resource = ab8500_resources,
|
||||
};
|
||||
|
||||
/*
|
||||
* TPS61052
|
||||
*/
|
||||
@@ -443,7 +425,6 @@ static struct hash_platform_data u8500_hash1_platform_data = {
|
||||
/* add any platform devices here - TODO */
|
||||
static struct platform_device *mop500_platform_devs[] __initdata = {
|
||||
&mop500_gpio_keys_device,
|
||||
&ab8500_device,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
@@ -605,7 +586,6 @@ static struct platform_device *snowball_platform_devs[] __initdata = {
|
||||
&snowball_led_dev,
|
||||
&snowball_key_dev,
|
||||
&snowball_sbnet_dev,
|
||||
&ab8500_device,
|
||||
};
|
||||
|
||||
static void __init mop500_init_machine(void)
|
||||
@@ -617,9 +597,8 @@ static void __init mop500_init_machine(void)
|
||||
mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
|
||||
|
||||
mop500_pinmaps_init();
|
||||
parent = u8500_init_devices();
|
||||
parent = u8500_init_devices(&ab8500_platdata);
|
||||
|
||||
/* FIXME: parent of ab8500 should be prcmu */
|
||||
for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
|
||||
mop500_platform_devs[i]->dev.parent = parent;
|
||||
|
||||
@@ -652,7 +631,7 @@ static void __init snowball_init_machine(void)
|
||||
int i;
|
||||
|
||||
snowball_pinmaps_init();
|
||||
parent = u8500_init_devices();
|
||||
parent = u8500_init_devices(&ab8500_platdata);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++)
|
||||
snowball_platform_devs[i]->dev.parent = parent;
|
||||
@@ -684,7 +663,7 @@ static void __init hrefv60_init_machine(void)
|
||||
mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
|
||||
|
||||
hrefv60_pinmaps_init();
|
||||
parent = u8500_init_devices();
|
||||
parent = u8500_init_devices(&ab8500_platdata);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
|
||||
mop500_platform_devs[i]->dev.parent = parent;
|
||||
@@ -785,9 +764,6 @@ static const struct of_device_id u8500_local_bus_nodes[] = {
|
||||
/* only create devices below soc node */
|
||||
{ .compatible = "stericsson,db8500", },
|
||||
{ .compatible = "stericsson,db8500-prcmu", },
|
||||
{ .compatible = "stericsson,db8500-prcmu-regulator", },
|
||||
{ .compatible = "stericsson,ab8500", },
|
||||
{ .compatible = "stericsson,ab8500-regulator", },
|
||||
{ .compatible = "simple-bus"},
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mfd/abx500/ab8500.h>
|
||||
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/pmu.h>
|
||||
@@ -115,7 +116,7 @@ static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct arm_pmu_platdata db8500_pmu_platdata = {
|
||||
struct arm_pmu_platdata db8500_pmu_platdata = {
|
||||
.handle_irq = db8500_pmu_handler,
|
||||
};
|
||||
|
||||
@@ -206,7 +207,7 @@ static struct device * __init db8500_soc_device_init(void)
|
||||
/*
|
||||
* This function is called from the board init
|
||||
*/
|
||||
struct device * __init u8500_init_devices(void)
|
||||
struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500)
|
||||
{
|
||||
struct device *parent;
|
||||
int i;
|
||||
@@ -223,6 +224,8 @@ struct device * __init u8500_init_devices(void)
|
||||
for (i = 0; i < ARRAY_SIZE(platform_devs); i++)
|
||||
platform_devs[i]->dev.parent = parent;
|
||||
|
||||
db8500_prcmu_device.dev.platform_data = ab8500;
|
||||
|
||||
platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
|
||||
|
||||
return parent;
|
||||
|
||||
@@ -13,11 +13,12 @@
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mfd/abx500/ab8500.h>
|
||||
|
||||
void __init ux500_map_io(void);
|
||||
extern void __init u8500_map_io(void);
|
||||
|
||||
extern struct device * __init u8500_init_devices(void);
|
||||
extern struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500);
|
||||
|
||||
extern void __init ux500_init_irq(void);
|
||||
extern void __init ux500_init_late(void);
|
||||
|
||||
@@ -33,7 +33,7 @@ config EXTCON_MAX77693
|
||||
|
||||
config EXTCON_MAX8997
|
||||
tristate "MAX8997 EXTCON Support"
|
||||
depends on MFD_MAX8997
|
||||
depends on MFD_MAX8997 && IRQ_DOMAIN
|
||||
help
|
||||
If you say yes here you get support for the MUIC device of
|
||||
Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/mfd/max8997.h>
|
||||
#include <linux/mfd/max8997-private.h>
|
||||
#include <linux/extcon.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
#define DEV_NAME "max8997-muic"
|
||||
|
||||
@@ -77,6 +78,7 @@
|
||||
struct max8997_muic_irq {
|
||||
unsigned int irq;
|
||||
const char *name;
|
||||
unsigned int virq;
|
||||
};
|
||||
|
||||
static struct max8997_muic_irq muic_irqs[] = {
|
||||
@@ -343,12 +345,10 @@ static void max8997_muic_irq_work(struct work_struct *work)
|
||||
{
|
||||
struct max8997_muic_info *info = container_of(work,
|
||||
struct max8997_muic_info, irq_work);
|
||||
struct max8997_dev *max8997 = i2c_get_clientdata(info->muic);
|
||||
u8 status[2];
|
||||
u8 adc, chg_type;
|
||||
|
||||
int irq_type = info->irq - max8997->irq_base;
|
||||
int ret;
|
||||
int irq_type = 0;
|
||||
int i, ret;
|
||||
|
||||
mutex_lock(&info->mutex);
|
||||
|
||||
@@ -363,6 +363,10 @@ static void max8997_muic_irq_work(struct work_struct *work)
|
||||
dev_dbg(info->dev, "%s: STATUS1:0x%x, 2:0x%x\n", __func__,
|
||||
status[0], status[1]);
|
||||
|
||||
for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++)
|
||||
if (info->irq == muic_irqs[i].virq)
|
||||
irq_type = muic_irqs[i].irq;
|
||||
|
||||
switch (irq_type) {
|
||||
case MAX8997_MUICIRQ_ADC:
|
||||
adc = status[0] & STATUS1_ADC_MASK;
|
||||
@@ -448,11 +452,15 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
|
||||
struct max8997_muic_irq *muic_irq = &muic_irqs[i];
|
||||
int virq = 0;
|
||||
|
||||
ret = request_threaded_irq(pdata->irq_base + muic_irq->irq,
|
||||
NULL, max8997_muic_irq_handler,
|
||||
0, muic_irq->name,
|
||||
info);
|
||||
virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq);
|
||||
if (!virq)
|
||||
goto err_irq;
|
||||
muic_irq->virq = virq;
|
||||
|
||||
ret = request_threaded_irq(virq, NULL,max8997_muic_irq_handler,
|
||||
0, muic_irq->name, info);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed: irq request (IRQ: %d,"
|
||||
@@ -496,7 +504,7 @@ err_extcon:
|
||||
kfree(info->edev);
|
||||
err_irq:
|
||||
while (--i >= 0)
|
||||
free_irq(pdata->irq_base + muic_irqs[i].irq, info);
|
||||
free_irq(muic_irqs[i].virq, info);
|
||||
kfree(info);
|
||||
err_kfree:
|
||||
return ret;
|
||||
@@ -505,11 +513,10 @@ err_kfree:
|
||||
static int __devexit max8997_muic_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct max8997_muic_info *info = platform_get_drvdata(pdev);
|
||||
struct max8997_dev *max8997 = i2c_get_clientdata(info->muic);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
|
||||
free_irq(max8997->irq_base + muic_irqs[i].irq, info);
|
||||
free_irq(muic_irqs[i].virq, info);
|
||||
cancel_work_sync(&info->irq_work);
|
||||
|
||||
extcon_dev_unregister(info->edev);
|
||||
|
||||
@@ -597,6 +597,13 @@ config GPIO_AB8500
|
||||
help
|
||||
Select this to enable the AB8500 IC GPIO driver
|
||||
|
||||
config GPIO_TPS6586X
|
||||
bool "TPS6586X GPIO"
|
||||
depends on MFD_TPS6586X
|
||||
help
|
||||
Select this option to enable GPIO driver for the TPS6586X
|
||||
chip family.
|
||||
|
||||
config GPIO_TPS65910
|
||||
bool "TPS65910 GPIO"
|
||||
depends on MFD_TPS65910
|
||||
|
||||
@@ -63,6 +63,7 @@ obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
|
||||
obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o
|
||||
obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o
|
||||
obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o
|
||||
obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o
|
||||
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
|
||||
obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
|
||||
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* TI TPS6586x GPIO driver
|
||||
*
|
||||
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
|
||||
* Author: Laxman dewangan <ldewangan@nvidia.com>
|
||||
*
|
||||
* Based on tps6586x.c
|
||||
* Copyright (c) 2010 CompuLab Ltd.
|
||||
* Mike Rapoport <mike@compulab.co.il>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/tps6586x.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/* GPIO control registers */
|
||||
#define TPS6586X_GPIOSET1 0x5d
|
||||
#define TPS6586X_GPIOSET2 0x5e
|
||||
|
||||
struct tps6586x_gpio {
|
||||
struct gpio_chip gpio_chip;
|
||||
struct device *parent;
|
||||
};
|
||||
|
||||
static inline struct tps6586x_gpio *to_tps6586x_gpio(struct gpio_chip *chip)
|
||||
{
|
||||
return container_of(chip, struct tps6586x_gpio, gpio_chip);
|
||||
}
|
||||
|
||||
static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct tps6586x_gpio *tps6586x_gpio = to_tps6586x_gpio(gc);
|
||||
uint8_t val;
|
||||
int ret;
|
||||
|
||||
ret = tps6586x_read(tps6586x_gpio->parent, TPS6586X_GPIOSET2, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return !!(val & (1 << offset));
|
||||
}
|
||||
|
||||
static void tps6586x_gpio_set(struct gpio_chip *gc, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct tps6586x_gpio *tps6586x_gpio = to_tps6586x_gpio(gc);
|
||||
|
||||
tps6586x_update(tps6586x_gpio->parent, TPS6586X_GPIOSET2,
|
||||
value << offset, 1 << offset);
|
||||
}
|
||||
|
||||
static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct tps6586x_gpio *tps6586x_gpio = to_tps6586x_gpio(gc);
|
||||
uint8_t val, mask;
|
||||
|
||||
tps6586x_gpio_set(gc, offset, value);
|
||||
|
||||
val = 0x1 << (offset * 2);
|
||||
mask = 0x3 << (offset * 2);
|
||||
|
||||
return tps6586x_update(tps6586x_gpio->parent, TPS6586X_GPIOSET1,
|
||||
val, mask);
|
||||
}
|
||||
|
||||
static int __devinit tps6586x_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps6586x_platform_data *pdata;
|
||||
struct tps6586x_gpio *tps6586x_gpio;
|
||||
int ret;
|
||||
|
||||
pdata = dev_get_platdata(pdev->dev.parent);
|
||||
tps6586x_gpio = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*tps6586x_gpio), GFP_KERNEL);
|
||||
if (!tps6586x_gpio) {
|
||||
dev_err(&pdev->dev, "Could not allocate tps6586x_gpio\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tps6586x_gpio->parent = pdev->dev.parent;
|
||||
|
||||
tps6586x_gpio->gpio_chip.owner = THIS_MODULE;
|
||||
tps6586x_gpio->gpio_chip.label = pdev->name;
|
||||
tps6586x_gpio->gpio_chip.dev = &pdev->dev;
|
||||
tps6586x_gpio->gpio_chip.ngpio = 4;
|
||||
tps6586x_gpio->gpio_chip.can_sleep = 1;
|
||||
|
||||
/* FIXME: add handling of GPIOs as dedicated inputs */
|
||||
tps6586x_gpio->gpio_chip.direction_output = tps6586x_gpio_output;
|
||||
tps6586x_gpio->gpio_chip.set = tps6586x_gpio_set;
|
||||
tps6586x_gpio->gpio_chip.get = tps6586x_gpio_get;
|
||||
|
||||
#ifdef CONFIG_OF_GPIO
|
||||
tps6586x_gpio->gpio_chip.of_node = pdev->dev.parent->of_node;
|
||||
#endif
|
||||
if (pdata && pdata->gpio_base)
|
||||
tps6586x_gpio->gpio_chip.base = pdata->gpio_base;
|
||||
else
|
||||
tps6586x_gpio->gpio_chip.base = -1;
|
||||
|
||||
ret = gpiochip_add(&tps6586x_gpio->gpio_chip);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, tps6586x_gpio);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit tps6586x_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps6586x_gpio *tps6586x_gpio = platform_get_drvdata(pdev);
|
||||
|
||||
return gpiochip_remove(&tps6586x_gpio->gpio_chip);
|
||||
}
|
||||
|
||||
static struct platform_driver tps6586x_gpio_driver = {
|
||||
.driver.name = "tps6586x-gpio",
|
||||
.driver.owner = THIS_MODULE,
|
||||
.probe = tps6586x_gpio_probe,
|
||||
.remove = __devexit_p(tps6586x_gpio_remove),
|
||||
};
|
||||
|
||||
static int __init tps6586x_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&tps6586x_gpio_driver);
|
||||
}
|
||||
subsys_initcall(tps6586x_gpio_init);
|
||||
|
||||
static void __exit tps6586x_gpio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tps6586x_gpio_driver);
|
||||
}
|
||||
module_exit(tps6586x_gpio_exit);
|
||||
|
||||
MODULE_ALIAS("platform:tps6586x-gpio");
|
||||
MODULE_DESCRIPTION("GPIO interface for TPS6586X PMIC");
|
||||
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Marvell 88PM80x ONKEY driver
|
||||
*
|
||||
* Copyright (C) 2012 Marvell International Ltd.
|
||||
* Haojian Zhuang <haojian.zhuang@marvell.com>
|
||||
* Qiao Zhou <zhouqiao@marvell.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file "COPYING" in the main directory of this
|
||||
* archive for more details.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/mfd/88pm80x.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define PM800_LONG_ONKEY_EN (1 << 0)
|
||||
#define PM800_LONG_KEY_DELAY (8) /* 1 .. 16 seconds */
|
||||
#define PM800_LONKEY_PRESS_TIME ((PM800_LONG_KEY_DELAY-1) << 4)
|
||||
#define PM800_LONKEY_PRESS_TIME_MASK (0xF0)
|
||||
#define PM800_SW_PDOWN (1 << 5)
|
||||
|
||||
struct pm80x_onkey_info {
|
||||
struct input_dev *idev;
|
||||
struct pm80x_chip *pm80x;
|
||||
struct regmap *map;
|
||||
int irq;
|
||||
};
|
||||
|
||||
/* 88PM80x gives us an interrupt when ONKEY is held */
|
||||
static irqreturn_t pm80x_onkey_handler(int irq, void *data)
|
||||
{
|
||||
struct pm80x_onkey_info *info = data;
|
||||
int ret = 0;
|
||||
unsigned int val;
|
||||
|
||||
ret = regmap_read(info->map, PM800_STATUS_1, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(info->idev->dev.parent, "failed to read status: %d\n", ret);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
val &= PM800_ONKEY_STS1;
|
||||
|
||||
input_report_key(info->idev, KEY_POWER, val);
|
||||
input_sync(info->idev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(pm80x_onkey_pm_ops, pm80x_dev_suspend,
|
||||
pm80x_dev_resume);
|
||||
|
||||
static int __devinit pm80x_onkey_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct pm80x_onkey_info *info;
|
||||
int err;
|
||||
|
||||
info = kzalloc(sizeof(struct pm80x_onkey_info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
info->pm80x = chip;
|
||||
|
||||
info->irq = platform_get_irq(pdev, 0);
|
||||
if (info->irq < 0) {
|
||||
dev_err(&pdev->dev, "No IRQ resource!\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
info->map = info->pm80x->regmap;
|
||||
if (!info->map) {
|
||||
dev_err(&pdev->dev, "no regmap!\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
info->idev = input_allocate_device();
|
||||
if (!info->idev) {
|
||||
dev_err(&pdev->dev, "Failed to allocate input dev\n");
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
info->idev->name = "88pm80x_on";
|
||||
info->idev->phys = "88pm80x_on/input0";
|
||||
info->idev->id.bustype = BUS_I2C;
|
||||
info->idev->dev.parent = &pdev->dev;
|
||||
info->idev->evbit[0] = BIT_MASK(EV_KEY);
|
||||
__set_bit(KEY_POWER, info->idev->keybit);
|
||||
|
||||
err = pm80x_request_irq(info->pm80x, info->irq, pm80x_onkey_handler,
|
||||
IRQF_ONESHOT, "onkey", info);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "Failed to request IRQ: #%d: %d\n",
|
||||
info->irq, err);
|
||||
goto out_reg;
|
||||
}
|
||||
|
||||
err = input_register_device(info->idev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Can't register input device: %d\n", err);
|
||||
goto out_irq;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, info);
|
||||
|
||||
/* Enable long onkey detection */
|
||||
regmap_update_bits(info->map, PM800_RTC_MISC4, PM800_LONG_ONKEY_EN,
|
||||
PM800_LONG_ONKEY_EN);
|
||||
/* Set 8-second interval */
|
||||
regmap_update_bits(info->map, PM800_RTC_MISC3,
|
||||
PM800_LONKEY_PRESS_TIME_MASK,
|
||||
PM800_LONKEY_PRESS_TIME);
|
||||
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
return 0;
|
||||
|
||||
out_irq:
|
||||
pm80x_free_irq(info->pm80x, info->irq, info);
|
||||
out_reg:
|
||||
input_free_device(info->idev);
|
||||
out:
|
||||
kfree(info);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit pm80x_onkey_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct pm80x_onkey_info *info = platform_get_drvdata(pdev);
|
||||
|
||||
device_init_wakeup(&pdev->dev, 0);
|
||||
pm80x_free_irq(info->pm80x, info->irq, info);
|
||||
input_unregister_device(info->idev);
|
||||
kfree(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver pm80x_onkey_driver = {
|
||||
.driver = {
|
||||
.name = "88pm80x-onkey",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &pm80x_onkey_pm_ops,
|
||||
},
|
||||
.probe = pm80x_onkey_probe,
|
||||
.remove = __devexit_p(pm80x_onkey_remove),
|
||||
};
|
||||
|
||||
module_platform_driver(pm80x_onkey_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Marvell 88PM80x ONKEY driver");
|
||||
MODULE_AUTHOR("Qiao Zhou <zhouqiao@marvell.com>");
|
||||
MODULE_ALIAS("platform:88pm80x-onkey");
|
||||
@@ -22,6 +22,16 @@ config INPUT_88PM860X_ONKEY
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called 88pm860x_onkey.
|
||||
|
||||
config INPUT_88PM80X_ONKEY
|
||||
tristate "88PM80x ONKEY support"
|
||||
depends on MFD_88PM800
|
||||
help
|
||||
Support the ONKEY of Marvell 88PM80x PMICs as an input device
|
||||
reporting power button status.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called 88pm80x_onkey.
|
||||
|
||||
config INPUT_AB8500_PONKEY
|
||||
tristate "AB8500 Pon (PowerOn) Key"
|
||||
depends on AB8500_CORE
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o
|
||||
obj-$(CONFIG_INPUT_88PM80X_ONKEY) += 88pm80x_onkey.o
|
||||
obj-$(CONFIG_INPUT_AB8500_PONKEY) += ab8500-ponkey.o
|
||||
obj-$(CONFIG_INPUT_AD714X) += ad714x.o
|
||||
obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o
|
||||
|
||||
@@ -74,8 +74,8 @@ static int __devinit ab8500_ponkey_probe(struct platform_device *pdev)
|
||||
|
||||
ponkey->idev = input;
|
||||
ponkey->ab8500 = ab8500;
|
||||
ponkey->irq_dbf = irq_dbf;
|
||||
ponkey->irq_dbr = irq_dbr;
|
||||
ponkey->irq_dbf = ab8500_irq_get_virq(ab8500, irq_dbf);
|
||||
ponkey->irq_dbr = ab8500_irq_get_virq(ab8500, irq_dbr);
|
||||
|
||||
input->name = "AB8500 POn(PowerOn) Key";
|
||||
input->dev.parent = &pdev->dev;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user