mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 19:51:31 -04:00
MFD changes for 3.5
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
iQIcBAABAgAGBQJPw2QKAAoJEIqAPN1PVmxKfv8P/2L5d38tc3+9wYuGI1l+k7Mz
xQt2PdAx/kHQGTjLE1DSoeOD6dn4aodFbPaTcsLsU9Eo4IiJnT68b8adr/bqYHKU
Cod6NSPJMaBxLBJZxXsA7nY69Z6O5SMjXxEQsiDc24gaP0jjwaeY35KJSfMug8nF
DA6rvEpchkF8QXzBmkO2t2/uPYr1YWqDZQkauLDnLRG01JnGXFz5ajv9N5pYhiFt
QyYtheg8yEnfwnQ6AlmRtGK75jZRVmrj0kOzRjE9UL7ZwtzswWJes+RE3tlgk89m
JQ7KASRmmqLpvcVJ9fG9SlGX//yBO6OEp5Km06RTxgmt0XftBDVqBTjk1EG2tfMR
SR0NIz6gJ0twKAe6U0d+5HMYalOU45H5ha9e3vCqZ8vl9JfmM95RS+TmWbGcRIqj
04Y5x3I4zq6e9D0u+211BeuRfzkQiefwWJmdPpn0oac3u5LeYbRj/aQ85fqwJWzG
f99D9VU5xgfFHPAtL3SLFiwgd9yOiMBar6eeIva+okDyOW3KaEUzs8Y4dgDyvYcg
IU//JGK51vLVmI5kXtGCwYkgRLF/Y7WKZ8TwypT+SY6iv6tPQVvApOZljq7RC9GI
mXx2z2slA90jlg3TlEFZfxr1WqbZ3TCbonU1riLeMEtkiXUpLtmKC8gbhOqfGvvn
Nzgt+YqRJXafZdELb/S+
=Rh0r
-----END PGP SIGNATURE-----
Merge tag 'mfd-3.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
Pull MFD changes from Samuel Ortiz:
"Besides the usual cleanups, this one brings:
* Support for 5 new chipsets: Intel's ICH LPC and SCH Centerton,
ST-E's STAX211, Samsung's MAX77693 and TI's LM3533.
* Device tree support for the twl6040, tps65910, da9502 and ab8500
drivers.
* Fairly big tps56910, ab8500 and db8500 updates.
* i2c support for mc13xxx.
* Our regular update for the wm8xxx driver from Mark."
Fix up various conflicts with other trees, largely due to ab5500 removal
etc.
* tag 'mfd-3.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (106 commits)
mfd: Fix build break of max77693 by adding REGMAP_I2C option
mfd: Fix twl6040 build failure
mfd: Fix max77693 build failure
mfd: ab8500-core should depend on MFD_DB8500_PRCMU
gpio: tps65910: dt: process gpio specific device node info
mfd: Remove the parsing of dt info for tps65910 gpio
mfd: Save device node parsed platform data for tps65910 sub devices
mfd: Add r_select to lm3533 platform data
gpio: Add Intel Centerton support to gpio-sch
mfd: Emulate active low IRQs as well as active high IRQs for wm831x
mfd: Mark two lm3533 zone registers as volatile
mfd: Fix return type of lm533 attribute is_visible
mfd: Enable Device Tree support in the ab8500-pwm driver
mfd: Enable Device Tree support in the ab8500-sysctrl driver
mfd: Add support for Device Tree to twl6040
mfd: Register the twl6040 child for the ASoC codec unconditionally
mfd: Allocate twl6040 IRQ numbers dynamically
mfd: twl6040 code cleanup in interrupt initialization part
mfd: Enable ab8500-gpadc driver for Device Tree
mfd: Prevent unassigned pointer from being used in ab8500-gpadc driver
...
This commit is contained in:
commit
4b78147468
94 changed files with 6799 additions and 1750 deletions
|
|
@ -167,6 +167,14 @@ config GPIO_PXA
|
|||
help
|
||||
Say yes here to support the PXA GPIO device
|
||||
|
||||
config GPIO_STA2X11
|
||||
bool "STA2x11/ConneXt GPIO support"
|
||||
depends on MFD_STA2X11
|
||||
select GENERIC_IRQ_CHIP
|
||||
help
|
||||
Say yes here to support the STA2x11/ConneXt GPIO device.
|
||||
The GPIO module has 128 GPIO pins with alternate functions.
|
||||
|
||||
config GPIO_XILINX
|
||||
bool "Xilinx GPIO support"
|
||||
depends on PPC_OF || MICROBLAZE
|
||||
|
|
@ -180,13 +188,13 @@ config GPIO_VR41XX
|
|||
Say yes here to support the NEC VR4100 series General-purpose I/O Uint
|
||||
|
||||
config GPIO_SCH
|
||||
tristate "Intel SCH/TunnelCreek GPIO"
|
||||
tristate "Intel SCH/TunnelCreek/Centerton GPIO"
|
||||
depends on PCI && X86
|
||||
select MFD_CORE
|
||||
select LPC_SCH
|
||||
help
|
||||
Say yes here to support GPIO interface on Intel Poulsbo SCH
|
||||
or Intel Tunnel Creek processor.
|
||||
Say yes here to support GPIO interface on Intel Poulsbo SCH,
|
||||
Intel Tunnel Creek processor or Intel Centerton processor.
|
||||
The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
|
||||
powered by the core power rail and are turned off during sleep
|
||||
modes (S3 and higher). The remaining four GPIOs are powered by
|
||||
|
|
@ -195,6 +203,22 @@ config GPIO_SCH
|
|||
system from the Suspend-to-RAM state.
|
||||
The Intel Tunnel Creek processor has 5 GPIOs powered by the
|
||||
core power rail and 9 from suspend power supply.
|
||||
The Intel Centerton processor has a total of 30 GPIO pins.
|
||||
Twenty-one are powered by the core power rail and 9 from the
|
||||
suspend power supply.
|
||||
|
||||
config GPIO_ICH
|
||||
tristate "Intel ICH GPIO"
|
||||
depends on PCI && X86
|
||||
select MFD_CORE
|
||||
select LPC_ICH
|
||||
help
|
||||
Say yes here to support the GPIO functionality of a number of Intel
|
||||
ICH-based chipsets. Currently supported devices: ICH6, ICH7, ICH8
|
||||
ICH9, ICH10, Series 5/3400 (eg Ibex Peak), Series 6/C200 (eg
|
||||
Cougar Point), NM10 (Tiger Point), and 3100 (Whitmore Lake).
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config GPIO_VX855
|
||||
tristate "VIA VX855/VX875 GPIO"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o
|
|||
obj-$(CONFIG_GPIO_EM) += gpio-em.o
|
||||
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
|
||||
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
|
||||
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
|
||||
obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
|
||||
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
|
||||
obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
|
||||
|
|
@ -51,6 +52,7 @@ obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o
|
|||
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
|
||||
obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
|
||||
obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o
|
||||
obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o
|
||||
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
|
||||
obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
|
||||
obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
|
||||
|
|
|
|||
419
drivers/gpio/gpio-ich.c
Normal file
419
drivers/gpio/gpio-ich.c
Normal file
|
|
@ -0,0 +1,419 @@
|
|||
/*
|
||||
* Intel ICH6-10, Series 5 and 6 GPIO driver
|
||||
*
|
||||
* Copyright (C) 2010 Extreme Engineering Solutions.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/lpc_ich.h>
|
||||
|
||||
#define DRV_NAME "gpio_ich"
|
||||
|
||||
/*
|
||||
* GPIO register offsets in GPIO I/O space.
|
||||
* Each chunk of 32 GPIOs is manipulated via its own USE_SELx, IO_SELx, and
|
||||
* LVLx registers. Logic in the read/write functions takes a register and
|
||||
* an absolute bit number and determines the proper register offset and bit
|
||||
* number in that register. For example, to read the value of GPIO bit 50
|
||||
* the code would access offset ichx_regs[2(=GPIO_LVL)][1(=50/32)],
|
||||
* bit 18 (50%32).
|
||||
*/
|
||||
enum GPIO_REG {
|
||||
GPIO_USE_SEL = 0,
|
||||
GPIO_IO_SEL,
|
||||
GPIO_LVL,
|
||||
};
|
||||
|
||||
static const u8 ichx_regs[3][3] = {
|
||||
{0x00, 0x30, 0x40}, /* USE_SEL[1-3] offsets */
|
||||
{0x04, 0x34, 0x44}, /* IO_SEL[1-3] offsets */
|
||||
{0x0c, 0x38, 0x48}, /* LVL[1-3] offsets */
|
||||
};
|
||||
|
||||
#define ICHX_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start)
|
||||
#define ICHX_READ(reg, base_res) inl((reg) + (base_res)->start)
|
||||
|
||||
struct ichx_desc {
|
||||
/* Max GPIO pins the chipset can have */
|
||||
uint ngpio;
|
||||
|
||||
/* Whether the chipset has GPIO in GPE0_STS in the PM IO region */
|
||||
bool uses_gpe0;
|
||||
|
||||
/* USE_SEL is bogus on some chipsets, eg 3100 */
|
||||
u32 use_sel_ignore[3];
|
||||
|
||||
/* Some chipsets have quirks, let these use their own request/get */
|
||||
int (*request)(struct gpio_chip *chip, unsigned offset);
|
||||
int (*get)(struct gpio_chip *chip, unsigned offset);
|
||||
};
|
||||
|
||||
static struct {
|
||||
spinlock_t lock;
|
||||
struct platform_device *dev;
|
||||
struct gpio_chip chip;
|
||||
struct resource *gpio_base; /* GPIO IO base */
|
||||
struct resource *pm_base; /* Power Mangagment IO base */
|
||||
struct ichx_desc *desc; /* Pointer to chipset-specific description */
|
||||
u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */
|
||||
} ichx_priv;
|
||||
|
||||
static int modparam_gpiobase = -1; /* dynamic */
|
||||
module_param_named(gpiobase, modparam_gpiobase, int, 0444);
|
||||
MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, "
|
||||
"which is the default.");
|
||||
|
||||
static int ichx_write_bit(int reg, unsigned nr, int val, int verify)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 data, tmp;
|
||||
int reg_nr = nr / 32;
|
||||
int bit = nr & 0x1f;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&ichx_priv.lock, flags);
|
||||
|
||||
data = ICHX_READ(ichx_regs[reg][reg_nr], ichx_priv.gpio_base);
|
||||
if (val)
|
||||
data |= 1 << bit;
|
||||
else
|
||||
data &= ~(1 << bit);
|
||||
ICHX_WRITE(data, ichx_regs[reg][reg_nr], ichx_priv.gpio_base);
|
||||
tmp = ICHX_READ(ichx_regs[reg][reg_nr], ichx_priv.gpio_base);
|
||||
if (verify && data != tmp)
|
||||
ret = -EPERM;
|
||||
|
||||
spin_unlock_irqrestore(&ichx_priv.lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ichx_read_bit(int reg, unsigned nr)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 data;
|
||||
int reg_nr = nr / 32;
|
||||
int bit = nr & 0x1f;
|
||||
|
||||
spin_lock_irqsave(&ichx_priv.lock, flags);
|
||||
|
||||
data = ICHX_READ(ichx_regs[reg][reg_nr], ichx_priv.gpio_base);
|
||||
|
||||
spin_unlock_irqrestore(&ichx_priv.lock, flags);
|
||||
|
||||
return data & (1 << bit) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
|
||||
{
|
||||
/*
|
||||
* Try setting pin as an input and verify it worked since many pins
|
||||
* are output-only.
|
||||
*/
|
||||
if (ichx_write_bit(GPIO_IO_SEL, nr, 1, 1))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
|
||||
int val)
|
||||
{
|
||||
/* Set GPIO output value. */
|
||||
ichx_write_bit(GPIO_LVL, nr, val, 0);
|
||||
|
||||
/*
|
||||
* Try setting pin as an output and verify it worked since many pins
|
||||
* are input-only.
|
||||
*/
|
||||
if (ichx_write_bit(GPIO_IO_SEL, nr, 0, 1))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr)
|
||||
{
|
||||
return ichx_read_bit(GPIO_LVL, nr);
|
||||
}
|
||||
|
||||
static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 data;
|
||||
|
||||
/*
|
||||
* GPI 0 - 15 need to be read from the power management registers on
|
||||
* a ICH6/3100 bridge.
|
||||
*/
|
||||
if (nr < 16) {
|
||||
if (!ichx_priv.pm_base)
|
||||
return -ENXIO;
|
||||
|
||||
spin_lock_irqsave(&ichx_priv.lock, flags);
|
||||
|
||||
/* GPI 0 - 15 are latched, write 1 to clear*/
|
||||
ICHX_WRITE(1 << (16 + nr), 0, ichx_priv.pm_base);
|
||||
data = ICHX_READ(0, ichx_priv.pm_base);
|
||||
|
||||
spin_unlock_irqrestore(&ichx_priv.lock, flags);
|
||||
|
||||
return (data >> 16) & (1 << nr) ? 1 : 0;
|
||||
} else {
|
||||
return ichx_gpio_get(chip, nr);
|
||||
}
|
||||
}
|
||||
|
||||
static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr)
|
||||
{
|
||||
/*
|
||||
* Note we assume the BIOS properly set a bridge's USE value. Some
|
||||
* chips (eg Intel 3100) have bogus USE values though, so first see if
|
||||
* the chipset's USE value can be trusted for this specific bit.
|
||||
* If it can't be trusted, assume that the pin can be used as a GPIO.
|
||||
*/
|
||||
if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f)))
|
||||
return 1;
|
||||
|
||||
return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
static int ich6_gpio_request(struct gpio_chip *chip, unsigned nr)
|
||||
{
|
||||
/*
|
||||
* Fixups for bits 16 and 17 are necessary on the Intel ICH6/3100
|
||||
* bridge as they are controlled by USE register bits 0 and 1. See
|
||||
* "Table 704 GPIO_USE_SEL1 register" in the i3100 datasheet for
|
||||
* additional info.
|
||||
*/
|
||||
if (nr == 16 || nr == 17)
|
||||
nr -= 16;
|
||||
|
||||
return ichx_gpio_request(chip, nr);
|
||||
}
|
||||
|
||||
static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val)
|
||||
{
|
||||
ichx_write_bit(GPIO_LVL, nr, val, 0);
|
||||
}
|
||||
|
||||
static void __devinit ichx_gpiolib_setup(struct gpio_chip *chip)
|
||||
{
|
||||
chip->owner = THIS_MODULE;
|
||||
chip->label = DRV_NAME;
|
||||
chip->dev = &ichx_priv.dev->dev;
|
||||
|
||||
/* Allow chip-specific overrides of request()/get() */
|
||||
chip->request = ichx_priv.desc->request ?
|
||||
ichx_priv.desc->request : ichx_gpio_request;
|
||||
chip->get = ichx_priv.desc->get ?
|
||||
ichx_priv.desc->get : ichx_gpio_get;
|
||||
|
||||
chip->set = ichx_gpio_set;
|
||||
chip->direction_input = ichx_gpio_direction_input;
|
||||
chip->direction_output = ichx_gpio_direction_output;
|
||||
chip->base = modparam_gpiobase;
|
||||
chip->ngpio = ichx_priv.desc->ngpio;
|
||||
chip->can_sleep = 0;
|
||||
chip->dbg_show = NULL;
|
||||
}
|
||||
|
||||
/* ICH6-based, 631xesb-based */
|
||||
static struct ichx_desc ich6_desc = {
|
||||
/* Bridges using the ICH6 controller need fixups for GPIO 0 - 17 */
|
||||
.request = ich6_gpio_request,
|
||||
.get = ich6_gpio_get,
|
||||
|
||||
/* GPIO 0-15 are read in the GPE0_STS PM register */
|
||||
.uses_gpe0 = true,
|
||||
|
||||
.ngpio = 50,
|
||||
};
|
||||
|
||||
/* Intel 3100 */
|
||||
static struct ichx_desc i3100_desc = {
|
||||
/*
|
||||
* Bits 16,17, 20 of USE_SEL and bit 16 of USE_SEL2 always read 0 on
|
||||
* the Intel 3100. See "Table 712. GPIO Summary Table" of 3100
|
||||
* Datasheet for more info.
|
||||
*/
|
||||
.use_sel_ignore = {0x00130000, 0x00010000, 0x0},
|
||||
|
||||
/* The 3100 needs fixups for GPIO 0 - 17 */
|
||||
.request = ich6_gpio_request,
|
||||
.get = ich6_gpio_get,
|
||||
|
||||
/* GPIO 0-15 are read in the GPE0_STS PM register */
|
||||
.uses_gpe0 = true,
|
||||
|
||||
.ngpio = 50,
|
||||
};
|
||||
|
||||
/* ICH7 and ICH8-based */
|
||||
static struct ichx_desc ich7_desc = {
|
||||
.ngpio = 50,
|
||||
};
|
||||
|
||||
/* ICH9-based */
|
||||
static struct ichx_desc ich9_desc = {
|
||||
.ngpio = 61,
|
||||
};
|
||||
|
||||
/* ICH10-based - Consumer/corporate versions have different amount of GPIO */
|
||||
static struct ichx_desc ich10_cons_desc = {
|
||||
.ngpio = 61,
|
||||
};
|
||||
static struct ichx_desc ich10_corp_desc = {
|
||||
.ngpio = 72,
|
||||
};
|
||||
|
||||
/* Intel 5 series, 6 series, 3400 series, and C200 series */
|
||||
static struct ichx_desc intel5_desc = {
|
||||
.ngpio = 76,
|
||||
};
|
||||
|
||||
static int __devinit ichx_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res_base, *res_pm;
|
||||
int err;
|
||||
struct lpc_ich_info *ich_info = pdev->dev.platform_data;
|
||||
|
||||
if (!ich_info)
|
||||
return -ENODEV;
|
||||
|
||||
ichx_priv.dev = pdev;
|
||||
|
||||
switch (ich_info->gpio_version) {
|
||||
case ICH_I3100_GPIO:
|
||||
ichx_priv.desc = &i3100_desc;
|
||||
break;
|
||||
case ICH_V5_GPIO:
|
||||
ichx_priv.desc = &intel5_desc;
|
||||
break;
|
||||
case ICH_V6_GPIO:
|
||||
ichx_priv.desc = &ich6_desc;
|
||||
break;
|
||||
case ICH_V7_GPIO:
|
||||
ichx_priv.desc = &ich7_desc;
|
||||
break;
|
||||
case ICH_V9_GPIO:
|
||||
ichx_priv.desc = &ich9_desc;
|
||||
break;
|
||||
case ICH_V10CORP_GPIO:
|
||||
ichx_priv.desc = &ich10_corp_desc;
|
||||
break;
|
||||
case ICH_V10CONS_GPIO:
|
||||
ichx_priv.desc = &ich10_cons_desc;
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO);
|
||||
if (!res_base || !res_base->start || !res_base->end)
|
||||
return -ENODEV;
|
||||
|
||||
if (!request_region(res_base->start, resource_size(res_base),
|
||||
pdev->name))
|
||||
return -EBUSY;
|
||||
|
||||
ichx_priv.gpio_base = res_base;
|
||||
|
||||
/*
|
||||
* If necessary, determine the I/O address of ACPI/power management
|
||||
* registers which are needed to read the the GPE0 register for GPI pins
|
||||
* 0 - 15 on some chipsets.
|
||||
*/
|
||||
if (!ichx_priv.desc->uses_gpe0)
|
||||
goto init;
|
||||
|
||||
res_pm = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPE0);
|
||||
if (!res_pm) {
|
||||
pr_warn("ACPI BAR is unavailable, GPI 0 - 15 unavailable\n");
|
||||
goto init;
|
||||
}
|
||||
|
||||
if (!request_region(res_pm->start, resource_size(res_pm),
|
||||
pdev->name)) {
|
||||
pr_warn("ACPI BAR is busy, GPI 0 - 15 unavailable\n");
|
||||
goto init;
|
||||
}
|
||||
|
||||
ichx_priv.pm_base = res_pm;
|
||||
|
||||
init:
|
||||
ichx_gpiolib_setup(&ichx_priv.chip);
|
||||
err = gpiochip_add(&ichx_priv.chip);
|
||||
if (err) {
|
||||
pr_err("Failed to register GPIOs\n");
|
||||
goto add_err;
|
||||
}
|
||||
|
||||
pr_info("GPIO from %d to %d on %s\n", ichx_priv.chip.base,
|
||||
ichx_priv.chip.base + ichx_priv.chip.ngpio - 1, DRV_NAME);
|
||||
|
||||
return 0;
|
||||
|
||||
add_err:
|
||||
release_region(ichx_priv.gpio_base->start,
|
||||
resource_size(ichx_priv.gpio_base));
|
||||
if (ichx_priv.pm_base)
|
||||
release_region(ichx_priv.pm_base->start,
|
||||
resource_size(ichx_priv.pm_base));
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit ichx_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = gpiochip_remove(&ichx_priv.chip);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "%s failed, %d\n",
|
||||
"gpiochip_remove()", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
release_region(ichx_priv.gpio_base->start,
|
||||
resource_size(ichx_priv.gpio_base));
|
||||
if (ichx_priv.pm_base)
|
||||
release_region(ichx_priv.pm_base->start,
|
||||
resource_size(ichx_priv.pm_base));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ichx_gpio_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = DRV_NAME,
|
||||
},
|
||||
.probe = ichx_gpio_probe,
|
||||
.remove = __devexit_p(ichx_gpio_remove),
|
||||
};
|
||||
|
||||
module_platform_driver(ichx_gpio_driver);
|
||||
|
||||
MODULE_AUTHOR("Peter Tyser <[email protected]>");
|
||||
MODULE_DESCRIPTION("GPIO interface for Intel ICH series");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:"DRV_NAME);
|
||||
|
|
@ -232,6 +232,14 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev)
|
|||
sch_gpio_resume.ngpio = 9;
|
||||
break;
|
||||
|
||||
case PCI_DEVICE_ID_INTEL_CENTERTON_ILB:
|
||||
sch_gpio_core.base = 0;
|
||||
sch_gpio_core.ngpio = 21;
|
||||
|
||||
sch_gpio_resume.base = 21;
|
||||
sch_gpio_resume.ngpio = 9;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
|||
435
drivers/gpio/gpio-sta2x11.c
Normal file
435
drivers/gpio/gpio-sta2x11.c
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
/*
|
||||
* STMicroelectronics ConneXt (STA2X11) GPIO driver
|
||||
*
|
||||
* Copyright 2012 ST Microelectronics (Alessandro Rubini)
|
||||
* Based on gpio-ml-ioh.c, Copyright 2010 OKI Semiconductors Ltd.
|
||||
* Also based on previous sta2x11 work, Copyright 2011 Wind River Systems, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/sta2x11-mfd.h>
|
||||
|
||||
struct gsta_regs {
|
||||
u32 dat; /* 0x00 */
|
||||
u32 dats;
|
||||
u32 datc;
|
||||
u32 pdis;
|
||||
u32 dir; /* 0x10 */
|
||||
u32 dirs;
|
||||
u32 dirc;
|
||||
u32 unused_1c;
|
||||
u32 afsela; /* 0x20 */
|
||||
u32 unused_24[7];
|
||||
u32 rimsc; /* 0x40 */
|
||||
u32 fimsc;
|
||||
u32 is;
|
||||
u32 ic;
|
||||
};
|
||||
|
||||
struct gsta_gpio {
|
||||
spinlock_t lock;
|
||||
struct device *dev;
|
||||
void __iomem *reg_base;
|
||||
struct gsta_regs __iomem *regs[GSTA_NR_BLOCKS];
|
||||
struct gpio_chip gpio;
|
||||
int irq_base;
|
||||
/* FIXME: save the whole config here (AF, ...) */
|
||||
unsigned irq_type[GSTA_NR_GPIO];
|
||||
};
|
||||
|
||||
static inline struct gsta_regs __iomem *__regs(struct gsta_gpio *chip, int nr)
|
||||
{
|
||||
return chip->regs[nr / GSTA_GPIO_PER_BLOCK];
|
||||
}
|
||||
|
||||
static inline u32 __bit(int nr)
|
||||
{
|
||||
return 1U << (nr % GSTA_GPIO_PER_BLOCK);
|
||||
}
|
||||
|
||||
/*
|
||||
* gpio methods
|
||||
*/
|
||||
|
||||
static void gsta_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
|
||||
{
|
||||
struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio);
|
||||
struct gsta_regs __iomem *regs = __regs(chip, nr);
|
||||
u32 bit = __bit(nr);
|
||||
|
||||
if (val)
|
||||
writel(bit, ®s->dats);
|
||||
else
|
||||
writel(bit, ®s->datc);
|
||||
}
|
||||
|
||||
static int gsta_gpio_get(struct gpio_chip *gpio, unsigned nr)
|
||||
{
|
||||
struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio);
|
||||
struct gsta_regs __iomem *regs = __regs(chip, nr);
|
||||
u32 bit = __bit(nr);
|
||||
|
||||
return readl(®s->dat) & bit;
|
||||
}
|
||||
|
||||
static int gsta_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
|
||||
int val)
|
||||
{
|
||||
struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio);
|
||||
struct gsta_regs __iomem *regs = __regs(chip, nr);
|
||||
u32 bit = __bit(nr);
|
||||
|
||||
writel(bit, ®s->dirs);
|
||||
/* Data register after direction, otherwise pullup/down is selected */
|
||||
if (val)
|
||||
writel(bit, ®s->dats);
|
||||
else
|
||||
writel(bit, ®s->datc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gsta_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
|
||||
{
|
||||
struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio);
|
||||
struct gsta_regs __iomem *regs = __regs(chip, nr);
|
||||
u32 bit = __bit(nr);
|
||||
|
||||
writel(bit, ®s->dirc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gsta_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
|
||||
{
|
||||
struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio);
|
||||
return chip->irq_base + offset;
|
||||
}
|
||||
|
||||
static void gsta_gpio_setup(struct gsta_gpio *chip) /* called from probe */
|
||||
{
|
||||
struct gpio_chip *gpio = &chip->gpio;
|
||||
|
||||
/*
|
||||
* ARCH_NR_GPIOS is currently 256 and dynamic allocation starts
|
||||
* from the end. However, for compatibility, we need the first
|
||||
* ConneXt device to start from gpio 0: it's the main chipset
|
||||
* on most boards so documents and drivers assume gpio0..gpio127
|
||||
*/
|
||||
static int gpio_base;
|
||||
|
||||
gpio->label = dev_name(chip->dev);
|
||||
gpio->owner = THIS_MODULE;
|
||||
gpio->direction_input = gsta_gpio_direction_input;
|
||||
gpio->get = gsta_gpio_get;
|
||||
gpio->direction_output = gsta_gpio_direction_output;
|
||||
gpio->set = gsta_gpio_set;
|
||||
gpio->dbg_show = NULL;
|
||||
gpio->base = gpio_base;
|
||||
gpio->ngpio = GSTA_NR_GPIO;
|
||||
gpio->can_sleep = 0;
|
||||
gpio->to_irq = gsta_gpio_to_irq;
|
||||
|
||||
/*
|
||||
* After the first device, turn to dynamic gpio numbers.
|
||||
* For example, with ARCH_NR_GPIOS = 256 we can fit two cards
|
||||
*/
|
||||
if (!gpio_base)
|
||||
gpio_base = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special method: alternate functions and pullup/pulldown. This is only
|
||||
* invoked on startup to configure gpio's according to platform data.
|
||||
* FIXME : this functionality shall be managed (and exported to other drivers)
|
||||
* via the pin control subsystem.
|
||||
*/
|
||||
static void gsta_set_config(struct gsta_gpio *chip, int nr, unsigned cfg)
|
||||
{
|
||||
struct gsta_regs __iomem *regs = __regs(chip, nr);
|
||||
unsigned long flags;
|
||||
u32 bit = __bit(nr);
|
||||
u32 val;
|
||||
int err = 0;
|
||||
|
||||
pr_info("%s: %p %i %i\n", __func__, chip, nr, cfg);
|
||||
|
||||
if (cfg == PINMUX_TYPE_NONE)
|
||||
return;
|
||||
|
||||
/* Alternate function or not? */
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
val = readl(®s->afsela);
|
||||
if (cfg == PINMUX_TYPE_FUNCTION)
|
||||
val |= bit;
|
||||
else
|
||||
val &= ~bit;
|
||||
writel(val | bit, ®s->afsela);
|
||||
if (cfg == PINMUX_TYPE_FUNCTION) {
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* not alternate function: set details */
|
||||
switch (cfg) {
|
||||
case PINMUX_TYPE_OUTPUT_LOW:
|
||||
writel(bit, ®s->dirs);
|
||||
writel(bit, ®s->datc);
|
||||
break;
|
||||
case PINMUX_TYPE_OUTPUT_HIGH:
|
||||
writel(bit, ®s->dirs);
|
||||
writel(bit, ®s->dats);
|
||||
break;
|
||||
case PINMUX_TYPE_INPUT:
|
||||
writel(bit, ®s->dirc);
|
||||
val = readl(®s->pdis) | bit;
|
||||
writel(val, ®s->pdis);
|
||||
break;
|
||||
case PINMUX_TYPE_INPUT_PULLUP:
|
||||
writel(bit, ®s->dirc);
|
||||
val = readl(®s->pdis) & ~bit;
|
||||
writel(val, ®s->pdis);
|
||||
writel(bit, ®s->dats);
|
||||
break;
|
||||
case PINMUX_TYPE_INPUT_PULLDOWN:
|
||||
writel(bit, ®s->dirc);
|
||||
val = readl(®s->pdis) & ~bit;
|
||||
writel(val, ®s->pdis);
|
||||
writel(bit, ®s->datc);
|
||||
break;
|
||||
default:
|
||||
err = 1;
|
||||
}
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
if (err)
|
||||
pr_err("%s: chip %p, pin %i, cfg %i is invalid\n",
|
||||
__func__, chip, nr, cfg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Irq methods
|
||||
*/
|
||||
|
||||
static void gsta_irq_disable(struct irq_data *data)
|
||||
{
|
||||
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
|
||||
struct gsta_gpio *chip = gc->private;
|
||||
int nr = data->irq - chip->irq_base;
|
||||
struct gsta_regs __iomem *regs = __regs(chip, nr);
|
||||
u32 bit = __bit(nr);
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
if (chip->irq_type[nr] & IRQ_TYPE_EDGE_RISING) {
|
||||
val = readl(®s->rimsc) & ~bit;
|
||||
writel(val, ®s->rimsc);
|
||||
}
|
||||
if (chip->irq_type[nr] & IRQ_TYPE_EDGE_FALLING) {
|
||||
val = readl(®s->fimsc) & ~bit;
|
||||
writel(val, ®s->fimsc);
|
||||
}
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
static void gsta_irq_enable(struct irq_data *data)
|
||||
{
|
||||
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
|
||||
struct gsta_gpio *chip = gc->private;
|
||||
int nr = data->irq - chip->irq_base;
|
||||
struct gsta_regs __iomem *regs = __regs(chip, nr);
|
||||
u32 bit = __bit(nr);
|
||||
u32 val;
|
||||
int type;
|
||||
unsigned long flags;
|
||||
|
||||
type = chip->irq_type[nr];
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
val = readl(®s->rimsc);
|
||||
if (type & IRQ_TYPE_EDGE_RISING)
|
||||
writel(val | bit, ®s->rimsc);
|
||||
else
|
||||
writel(val & ~bit, ®s->rimsc);
|
||||
val = readl(®s->rimsc);
|
||||
if (type & IRQ_TYPE_EDGE_FALLING)
|
||||
writel(val | bit, ®s->fimsc);
|
||||
else
|
||||
writel(val & ~bit, ®s->fimsc);
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
static int gsta_irq_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||
struct gsta_gpio *chip = gc->private;
|
||||
int nr = d->irq - chip->irq_base;
|
||||
|
||||
/* We only support edge interrupts */
|
||||
if (!(type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))) {
|
||||
pr_debug("%s: unsupported type 0x%x\n", __func__, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
chip->irq_type[nr] = type; /* used for enable/disable */
|
||||
|
||||
gsta_irq_enable(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t gsta_gpio_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct gsta_gpio *chip = dev_id;
|
||||
struct gsta_regs __iomem *regs;
|
||||
u32 is;
|
||||
int i, nr, base;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
for (i = 0; i < GSTA_NR_BLOCKS; i++) {
|
||||
regs = chip->regs[i];
|
||||
base = chip->irq_base + i * GSTA_GPIO_PER_BLOCK;
|
||||
while ((is = readl(®s->is))) {
|
||||
nr = __ffs(is);
|
||||
irq = base + nr;
|
||||
generic_handle_irq(irq);
|
||||
writel(1 << nr, ®s->ic);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devinit void gsta_alloc_irq_chip(struct gsta_gpio *chip)
|
||||
{
|
||||
struct irq_chip_generic *gc;
|
||||
struct irq_chip_type *ct;
|
||||
|
||||
gc = irq_alloc_generic_chip(KBUILD_MODNAME, 1, chip->irq_base,
|
||||
chip->reg_base, handle_simple_irq);
|
||||
gc->private = chip;
|
||||
ct = gc->chip_types;
|
||||
|
||||
ct->chip.irq_set_type = gsta_irq_type;
|
||||
ct->chip.irq_disable = gsta_irq_disable;
|
||||
ct->chip.irq_enable = gsta_irq_enable;
|
||||
|
||||
/* FIXME: this makes at most 32 interrupts. Request 0 by now */
|
||||
irq_setup_generic_chip(gc, 0 /* IRQ_MSK(GSTA_GPIO_PER_BLOCK) */, 0,
|
||||
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
|
||||
|
||||
/* Set up all all 128 interrupts: code from setup_generic_chip */
|
||||
{
|
||||
struct irq_chip_type *ct = gc->chip_types;
|
||||
int i, j;
|
||||
for (j = 0; j < GSTA_NR_GPIO; j++) {
|
||||
i = chip->irq_base + j;
|
||||
irq_set_chip_and_handler(i, &ct->chip, ct->handler);
|
||||
irq_set_chip_data(i, gc);
|
||||
irq_modify_status(i, IRQ_NOREQUEST | IRQ_NOPROBE, 0);
|
||||
}
|
||||
gc->irq_cnt = i - gc->irq_base;
|
||||
}
|
||||
}
|
||||
|
||||
/* The platform device used here is instantiated by the MFD device */
|
||||
static int __devinit gsta_probe(struct platform_device *dev)
|
||||
{
|
||||
int i, err;
|
||||
struct pci_dev *pdev;
|
||||
struct sta2x11_gpio_pdata *gpio_pdata;
|
||||
struct gsta_gpio *chip;
|
||||
struct resource *res;
|
||||
|
||||
pdev = *(struct pci_dev **)(dev->dev.platform_data);
|
||||
gpio_pdata = dev_get_platdata(&pdev->dev);
|
||||
|
||||
if (gpio_pdata == NULL)
|
||||
dev_err(&dev->dev, "no gpio config\n");
|
||||
pr_debug("gpio config: %p\n", gpio_pdata);
|
||||
|
||||
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
|
||||
chip = devm_kzalloc(&dev->dev, sizeof(*chip), GFP_KERNEL);
|
||||
chip->dev = &dev->dev;
|
||||
chip->reg_base = devm_request_and_ioremap(&dev->dev, res);
|
||||
|
||||
for (i = 0; i < GSTA_NR_BLOCKS; i++) {
|
||||
chip->regs[i] = chip->reg_base + i * 4096;
|
||||
/* disable all irqs */
|
||||
writel(0, &chip->regs[i]->rimsc);
|
||||
writel(0, &chip->regs[i]->fimsc);
|
||||
writel(~0, &chip->regs[i]->ic);
|
||||
}
|
||||
spin_lock_init(&chip->lock);
|
||||
gsta_gpio_setup(chip);
|
||||
for (i = 0; i < GSTA_NR_GPIO; i++)
|
||||
gsta_set_config(chip, i, gpio_pdata->pinconfig[i]);
|
||||
|
||||
/* 384 was used in previous code: be compatible for other drivers */
|
||||
err = irq_alloc_descs(-1, 384, GSTA_NR_GPIO, NUMA_NO_NODE);
|
||||
if (err < 0) {
|
||||
dev_warn(&dev->dev, "sta2x11 gpio: Can't get irq base (%i)\n",
|
||||
-err);
|
||||
return err;
|
||||
}
|
||||
chip->irq_base = err;
|
||||
gsta_alloc_irq_chip(chip);
|
||||
|
||||
err = request_irq(pdev->irq, gsta_gpio_handler,
|
||||
IRQF_SHARED, KBUILD_MODNAME, chip);
|
||||
if (err < 0) {
|
||||
dev_err(&dev->dev, "sta2x11 gpio: Can't request irq (%i)\n",
|
||||
-err);
|
||||
goto err_free_descs;
|
||||
}
|
||||
|
||||
err = gpiochip_add(&chip->gpio);
|
||||
if (err < 0) {
|
||||
dev_err(&dev->dev, "sta2x11 gpio: Can't register (%i)\n",
|
||||
-err);
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
platform_set_drvdata(dev, chip);
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
free_irq(pdev->irq, chip);
|
||||
err_free_descs:
|
||||
irq_free_descs(chip->irq_base, GSTA_NR_GPIO);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct platform_driver sta2x11_gpio_platform_driver = {
|
||||
.driver = {
|
||||
.name = "sta2x11-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = gsta_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(sta2x11_gpio_platform_driver);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("sta2x11_gpio GPIO driver");
|
||||
|
|
@ -18,14 +18,27 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/tps65910.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
struct tps65910_gpio {
|
||||
struct gpio_chip gpio_chip;
|
||||
struct tps65910 *tps65910;
|
||||
};
|
||||
|
||||
static inline struct tps65910_gpio *to_tps65910_gpio(struct gpio_chip *chip)
|
||||
{
|
||||
return container_of(chip, struct tps65910_gpio, gpio_chip);
|
||||
}
|
||||
|
||||
static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
|
||||
uint8_t val;
|
||||
struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
|
||||
struct tps65910 *tps65910 = tps65910_gpio->tps65910;
|
||||
unsigned int val;
|
||||
|
||||
tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val);
|
||||
tps65910_reg_read(tps65910, TPS65910_GPIO0 + offset, &val);
|
||||
|
||||
if (val & GPIO_STS_MASK)
|
||||
return 1;
|
||||
|
|
@ -36,83 +49,170 @@ static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
|
|||
static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
|
||||
struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
|
||||
struct tps65910 *tps65910 = tps65910_gpio->tps65910;
|
||||
|
||||
if (value)
|
||||
tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
|
||||
tps65910_reg_set_bits(tps65910, TPS65910_GPIO0 + offset,
|
||||
GPIO_SET_MASK);
|
||||
else
|
||||
tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
|
||||
tps65910_reg_clear_bits(tps65910, TPS65910_GPIO0 + offset,
|
||||
GPIO_SET_MASK);
|
||||
}
|
||||
|
||||
static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
|
||||
struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
|
||||
struct tps65910 *tps65910 = tps65910_gpio->tps65910;
|
||||
|
||||
/* Set the initial value */
|
||||
tps65910_gpio_set(gc, offset, value);
|
||||
|
||||
return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
|
||||
return tps65910_reg_set_bits(tps65910, TPS65910_GPIO0 + offset,
|
||||
GPIO_CFG_MASK);
|
||||
}
|
||||
|
||||
static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
|
||||
struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
|
||||
struct tps65910 *tps65910 = tps65910_gpio->tps65910;
|
||||
|
||||
return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
|
||||
return tps65910_reg_clear_bits(tps65910, TPS65910_GPIO0 + offset,
|
||||
GPIO_CFG_MASK);
|
||||
}
|
||||
|
||||
void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
|
||||
#ifdef CONFIG_OF
|
||||
static struct tps65910_board *tps65910_parse_dt_for_gpio(struct device *dev,
|
||||
struct tps65910 *tps65910, int chip_ngpio)
|
||||
{
|
||||
struct tps65910_board *tps65910_board = tps65910->of_plat_data;
|
||||
unsigned int prop_array[TPS6591X_MAX_NUM_GPIO];
|
||||
int ngpio = min(chip_ngpio, TPS6591X_MAX_NUM_GPIO);
|
||||
int ret;
|
||||
struct tps65910_board *board_data;
|
||||
int idx;
|
||||
|
||||
if (!gpio_base)
|
||||
return;
|
||||
tps65910_board->gpio_base = -1;
|
||||
ret = of_property_read_u32_array(tps65910->dev->of_node,
|
||||
"ti,en-gpio-sleep", prop_array, ngpio);
|
||||
if (ret < 0) {
|
||||
dev_dbg(dev, "ti,en-gpio-sleep not specified\n");
|
||||
return tps65910_board;
|
||||
}
|
||||
|
||||
tps65910->gpio.owner = THIS_MODULE;
|
||||
tps65910->gpio.label = tps65910->i2c_client->name;
|
||||
tps65910->gpio.dev = tps65910->dev;
|
||||
tps65910->gpio.base = gpio_base;
|
||||
for (idx = 0; idx < ngpio; idx++)
|
||||
tps65910_board->en_gpio_sleep[idx] = (prop_array[idx] != 0);
|
||||
|
||||
return tps65910_board;
|
||||
}
|
||||
#else
|
||||
static struct tps65910_board *tps65910_parse_dt_for_gpio(struct device *dev,
|
||||
struct tps65910 *tps65910, int chip_ngpio)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __devinit tps65910_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
|
||||
struct tps65910_gpio *tps65910_gpio;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
tps65910_gpio = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*tps65910_gpio), GFP_KERNEL);
|
||||
if (!tps65910_gpio) {
|
||||
dev_err(&pdev->dev, "Could not allocate tps65910_gpio\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tps65910_gpio->tps65910 = tps65910;
|
||||
|
||||
tps65910_gpio->gpio_chip.owner = THIS_MODULE;
|
||||
tps65910_gpio->gpio_chip.label = tps65910->i2c_client->name;
|
||||
|
||||
switch(tps65910_chip_id(tps65910)) {
|
||||
case TPS65910:
|
||||
tps65910->gpio.ngpio = TPS65910_NUM_GPIO;
|
||||
tps65910_gpio->gpio_chip.ngpio = TPS65910_NUM_GPIO;
|
||||
break;
|
||||
case TPS65911:
|
||||
tps65910->gpio.ngpio = TPS65911_NUM_GPIO;
|
||||
tps65910_gpio->gpio_chip.ngpio = TPS65911_NUM_GPIO;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
tps65910->gpio.can_sleep = 1;
|
||||
tps65910_gpio->gpio_chip.can_sleep = 1;
|
||||
tps65910_gpio->gpio_chip.direction_input = tps65910_gpio_input;
|
||||
tps65910_gpio->gpio_chip.direction_output = tps65910_gpio_output;
|
||||
tps65910_gpio->gpio_chip.set = tps65910_gpio_set;
|
||||
tps65910_gpio->gpio_chip.get = tps65910_gpio_get;
|
||||
tps65910_gpio->gpio_chip.dev = &pdev->dev;
|
||||
if (pdata && pdata->gpio_base)
|
||||
tps65910_gpio->gpio_chip.base = pdata->gpio_base;
|
||||
else
|
||||
tps65910_gpio->gpio_chip.base = -1;
|
||||
|
||||
tps65910->gpio.direction_input = tps65910_gpio_input;
|
||||
tps65910->gpio.direction_output = tps65910_gpio_output;
|
||||
tps65910->gpio.set = tps65910_gpio_set;
|
||||
tps65910->gpio.get = tps65910_gpio_get;
|
||||
if (!pdata && tps65910->dev->of_node)
|
||||
pdata = tps65910_parse_dt_for_gpio(&pdev->dev, tps65910,
|
||||
tps65910_gpio->gpio_chip.ngpio);
|
||||
|
||||
/* Configure sleep control for gpios */
|
||||
board_data = dev_get_platdata(tps65910->dev);
|
||||
if (board_data) {
|
||||
int i;
|
||||
for (i = 0; i < tps65910->gpio.ngpio; ++i) {
|
||||
if (board_data->en_gpio_sleep[i]) {
|
||||
ret = tps65910_set_bits(tps65910,
|
||||
TPS65910_GPIO0 + i, GPIO_SLEEP_MASK);
|
||||
if (ret < 0)
|
||||
dev_warn(tps65910->dev,
|
||||
"GPIO Sleep setting failed\n");
|
||||
}
|
||||
}
|
||||
if (!pdata)
|
||||
goto skip_init;
|
||||
|
||||
/* Configure sleep control for gpios if provided */
|
||||
for (i = 0; i < tps65910_gpio->gpio_chip.ngpio; ++i) {
|
||||
if (!pdata->en_gpio_sleep[i])
|
||||
continue;
|
||||
|
||||
ret = tps65910_reg_set_bits(tps65910,
|
||||
TPS65910_GPIO0 + i, GPIO_SLEEP_MASK);
|
||||
if (ret < 0)
|
||||
dev_warn(tps65910->dev,
|
||||
"GPIO Sleep setting failed with err %d\n", ret);
|
||||
}
|
||||
|
||||
ret = gpiochip_add(&tps65910->gpio);
|
||||
skip_init:
|
||||
ret = gpiochip_add(&tps65910_gpio->gpio_chip);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret);
|
||||
platform_set_drvdata(pdev, tps65910_gpio);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit tps65910_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65910_gpio *tps65910_gpio = platform_get_drvdata(pdev);
|
||||
|
||||
return gpiochip_remove(&tps65910_gpio->gpio_chip);
|
||||
}
|
||||
|
||||
static struct platform_driver tps65910_gpio_driver = {
|
||||
.driver.name = "tps65910-gpio",
|
||||
.driver.owner = THIS_MODULE,
|
||||
.probe = tps65910_gpio_probe,
|
||||
.remove = __devexit_p(tps65910_gpio_remove),
|
||||
};
|
||||
|
||||
static int __init tps65910_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&tps65910_gpio_driver);
|
||||
}
|
||||
subsys_initcall(tps65910_gpio_init);
|
||||
|
||||
static void __exit tps65910_gpio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tps65910_gpio_driver);
|
||||
}
|
||||
module_exit(tps65910_gpio_exit);
|
||||
|
||||
MODULE_AUTHOR("Graeme Gregory <[email protected]>");
|
||||
MODULE_AUTHOR("Jorge Eduardo Candelaria [email protected]>");
|
||||
MODULE_DESCRIPTION("GPIO interface for TPS65910/TPS6511 PMICs");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:tps65910-gpio");
|
||||
|
|
|
|||
|
|
@ -102,10 +102,8 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
|||
struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
|
||||
struct wm831x *wm831x = wm831x_gpio->wm831x;
|
||||
|
||||
if (!wm831x->irq_base)
|
||||
return -EINVAL;
|
||||
|
||||
return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset;
|
||||
return irq_create_mapping(wm831x->irq_domain,
|
||||
WM831X_IRQ_GPIO_1 + offset);
|
||||
}
|
||||
|
||||
static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
|
||||
|
|
|
|||
Loading…
Reference in a new issue