]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'mfd/for-mfd-next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 11 Feb 2016 01:36:38 +0000 (12:36 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 11 Feb 2016 01:36:38 +0000 (12:36 +1100)
13 files changed:
Documentation/devicetree/bindings/mfd/tps65086.txt [new file with mode: 0644]
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/ab8500-core.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/intel-lpss-pci.c
drivers/mfd/intel-lpss.c
drivers/mfd/lpc_ich.c
drivers/mfd/syscon.c
drivers/mfd/tps65010.c
drivers/mfd/tps65086.c [new file with mode: 0644]
include/linux/mfd/core.h
include/linux/mfd/tps65086.h [new file with mode: 0644]

diff --git a/Documentation/devicetree/bindings/mfd/tps65086.txt b/Documentation/devicetree/bindings/mfd/tps65086.txt
new file mode 100644 (file)
index 0000000..d370561
--- /dev/null
@@ -0,0 +1,55 @@
+* TPS65086 Power Management Integrated Circuit (PMIC) bindings
+
+Required properties:
+ - compatible          : Should be "ti,tps65086".
+ - reg                 : I2C slave address.
+ - interrupt-parent    : Phandle to the parent interrupt controller.
+ - interrupts          : The interrupt line the device is connected to.
+ - interrupt-controller        : Marks the device node as an interrupt controller.
+ - #interrupt-cells    : The number of cells to describe an IRQ, should be 2.
+                           The first cell is the IRQ number.
+                           The second cell is the flags, encoded as trigger
+                           masks from ../interrupt-controller/interrupts.txt.
+ - gpio-controller      : Marks the device node as a GPIO Controller.
+ - #gpio-cells          : Should be two.  The first cell is the pin number and
+                            the second cell is used to specify flags.
+                            See ../gpio/gpio.txt for more information.
+ - regulators:          : List of child nodes that specify the regulator
+                            initialization data. Child nodes must be named
+                            after their hardware counterparts: buck[1-6],
+                            ldoa[1-3], swa1, swb[1-2], and vtt. Each child
+                            node is defined using the standard binding for
+                            regulators and the optional regulator properties
+                            defined below.
+
+Optional regulator properties:
+ - ti,regulator-step-size-25mv : This is applicable for buck[1,2,6], set this
+                                   if the regulator is factory set with a 25mv
+                                   step voltage mapping.
+ - ti,regulator-decay          : This is applicable for buck[1-6], set this if
+                                   the output needs to decay, default is for
+                                   the output to slew down.
+
+Example:
+
+       pmic: tps65086@5e {
+               compatible = "ti,tps65086";
+               reg = <0x5e>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               regulators {
+                       buck1 {
+                               regulator-name = "vcc1";
+                               regulator-min-microvolt = <1600000>;
+                               regulator-max-microvolt = <1600000>;
+                               regulator-boot-on;
+                               ti,regulator-decay;
+                               ti,regulator-step-size-25mv;
+                       };
+               };
+       };
index 9ca66de0c1c1770f4630c35a93c81adfdcee4883..1b8668a4a26d9045680c8b31ecf02011fff766c3 100644 (file)
@@ -203,7 +203,7 @@ config MFD_DA9062
        select MFD_CORE
        select REGMAP_I2C
        select REGMAP_IRQ
-       depends on I2C=y
+       depends on I2C
        help
          Say yes here for support for the Dialog Semiconductor DA9062 PMIC.
          This includes the I2C driver and core APIs.
@@ -215,7 +215,7 @@ config MFD_DA9063
        select MFD_CORE
        select REGMAP_I2C
        select REGMAP_IRQ
-       depends on I2C=y
+       depends on I2C
        help
          Say yes here for support for the Dialog Semiconductor DA9063 PMIC.
          This includes the I2C driver and core APIs.
@@ -224,7 +224,7 @@ config MFD_DA9063
 
 config MFD_DA9150
        tristate "Dialog Semiconductor DA9150 Charger Fuel-Gauge chip"
-       depends on I2C=y
+       depends on I2C
        select MFD_CORE
        select REGMAP_I2C
        select REGMAP_IRQ
@@ -445,7 +445,7 @@ config MFD_KEMPLD
 
 config MFD_88PM800
        tristate "Marvell 88PM800"
-       depends on I2C=y
+       depends on I2C
        select REGMAP_I2C
        select REGMAP_IRQ
        select MFD_CORE
@@ -457,7 +457,7 @@ config MFD_88PM800
 
 config MFD_88PM805
        tristate "Marvell 88PM805"
-       depends on I2C=y
+       depends on I2C
        select REGMAP_I2C
        select REGMAP_IRQ
        select MFD_CORE
@@ -538,7 +538,7 @@ config MFD_MAX77843
 config MFD_MAX8907
        tristate "Maxim Semiconductor MAX8907 PMIC Support"
        select MFD_CORE
-       depends on I2C=y
+       depends on I2C
        select REGMAP_I2C
        select REGMAP_IRQ
        help
@@ -743,7 +743,7 @@ config MFD_RTSX_PCI
 
 config MFD_RT5033
        tristate "Richtek RT5033 Power Management IC"
-       depends on I2C=y
+       depends on I2C
        select MFD_CORE
        select REGMAP_I2C
        select REGMAP_IRQ
@@ -1106,6 +1106,19 @@ config TPS6507X
          This driver can also be built as a module.  If so, the module
          will be called tps6507x.
 
+config MFD_TPS65086
+       tristate "TI TPS65086 Power Management Integrated Chips (PMICs)"
+       select REGMAP
+       select REGMAP_IRQ
+       select REGMAP_I2C
+       depends on I2C
+       help
+         If you say yes here you get support for the TPS65086 series of
+         Power Management chips.
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the
+         functionality of the device.
+
 config TPS65911_COMPARATOR
        tristate
 
index 0f230a6103f866e88213ea5315e18e64ca2fb31b..06801aa9d8dcdf5d36061cc519b3187cae2d6da2 100644 (file)
@@ -70,6 +70,7 @@ obj-$(CONFIG_MFD_WM8994)      += wm8994.o
 obj-$(CONFIG_TPS6105X)         += tps6105x.o
 obj-$(CONFIG_TPS65010)         += tps65010.o
 obj-$(CONFIG_TPS6507X)         += tps6507x.o
+obj-$(CONFIG_MFD_TPS65086)     += tps65086.o
 obj-$(CONFIG_MFD_TPS65217)     += tps65217.o
 obj-$(CONFIG_MFD_TPS65218)     += tps65218.o
 obj-$(CONFIG_MFD_TPS65910)     += tps65910.o
index f3d689176fc2229f5dd1be64af2014af798dac60..c03a86ee64e67957971d39ca5de993340a3b493f 100644 (file)
@@ -634,79 +634,41 @@ static const struct mfd_cell ab8500_bm_devs[] = {
 
 static const struct mfd_cell ab8500_devs[] = {
 #ifdef CONFIG_DEBUG_FS
-       {
-               .name = "ab8500-debug",
-               .of_compatible = "stericsson,ab8500-debug",
-       },
+       OF_MFD_CELL("ab8500-debug",
+                   NULL, NULL, 0, "stericsson,ab8500-debug"),
 #endif
-       {
-               .name = "ab8500-sysctrl",
-               .of_compatible = "stericsson,ab8500-sysctrl",
-       },
-       {
-               .name = "ab8500-ext-regulator",
-               .of_compatible = "stericsson,ab8500-ext-regulator",
-       },
-       {
-               .name = "ab8500-regulator",
-               .of_compatible = "stericsson,ab8500-regulator",
-       },
-       {
-               .name = "abx500-clk",
-               .of_compatible = "stericsson,abx500-clk",
-       },
-       {
-               .name = "ab8500-gpadc",
-               .of_compatible = "stericsson,ab8500-gpadc",
-       },
-       {
-               .name = "ab8500-rtc",
-               .of_compatible = "stericsson,ab8500-rtc",
-       },
-       {
-               .name = "ab8500-acc-det",
-               .of_compatible = "stericsson,ab8500-acc-det",
-       },
-       {
-
-               .name = "ab8500-poweron-key",
-               .of_compatible = "stericsson,ab8500-poweron-key",
-       },
-       {
-               .name = "ab8500-pwm",
-               .of_compatible = "stericsson,ab8500-pwm",
-               .id = 1,
-       },
-       {
-               .name = "ab8500-pwm",
-               .of_compatible = "stericsson,ab8500-pwm",
-               .id = 2,
-       },
-       {
-               .name = "ab8500-pwm",
-               .of_compatible = "stericsson,ab8500-pwm",
-               .id = 3,
-       },
-       {
-               .name = "ab8500-denc",
-               .of_compatible = "stericsson,ab8500-denc",
-       },
-       {
-               .name = "pinctrl-ab8500",
-               .of_compatible = "stericsson,ab8500-gpio",
-       },
-       {
-               .name = "abx500-temp",
-               .of_compatible = "stericsson,abx500-temp",
-       },
-       {
-               .name = "ab8500-usb",
-               .of_compatible = "stericsson,ab8500-usb",
-       },
-       {
-               .name = "ab8500-codec",
-               .of_compatible = "stericsson,ab8500-codec",
-       },
+       OF_MFD_CELL("ab8500-sysctrl",
+                   NULL, NULL, 0, "stericsson,ab8500-sysctrl"),
+       OF_MFD_CELL("ab8500-ext-regulator",
+                   NULL, NULL, 0, "stericsson,ab8500-ext-regulator"),
+       OF_MFD_CELL("ab8500-regulator",
+                   NULL, NULL, 0, "stericsson,ab8500-regulator"),
+       OF_MFD_CELL("abx500-clk",
+                   NULL, NULL, 0, "stericsson,abx500-clk"),
+       OF_MFD_CELL("ab8500-gpadc",
+                   NULL, NULL, 0, "stericsson,ab8500-gpadc"),
+       OF_MFD_CELL("ab8500-rtc",
+                   NULL, NULL, 0, "stericsson,ab8500-rtc"),
+       OF_MFD_CELL("ab8500-acc-det",
+                   NULL, NULL, 0, "stericsson,ab8500-acc-det"),
+       OF_MFD_CELL("ab8500-poweron-key",
+                   NULL, NULL, 0, "stericsson,ab8500-poweron-key"),
+       OF_MFD_CELL("ab8500-pwm",
+                   NULL, NULL, 1, "stericsson,ab8500-pwm"),
+       OF_MFD_CELL("ab8500-pwm",
+                   NULL, NULL, 2, "stericsson,ab8500-pwm"),
+       OF_MFD_CELL("ab8500-pwm",
+                   NULL, NULL, 3, "stericsson,ab8500-pwm"),
+       OF_MFD_CELL("ab8500-denc",
+                   NULL, NULL, 0, "stericsson,ab8500-denc"),
+       OF_MFD_CELL("pinctrl-ab8500",
+                   NULL, NULL, 0, "stericsson,ab8500-gpio"),
+       OF_MFD_CELL("abx500-temp",
+                   NULL, NULL, 0, "stericsson,abx500-temp"),
+       OF_MFD_CELL("ab8500-usb",
+                   NULL, NULL, 0, "stericsson,ab8500-usb"),
+       OF_MFD_CELL("ab8500-codec",
+                   NULL, NULL, 0, "stericsson,ab8500-codec"),
 };
 
 static const struct mfd_cell ab9540_devs[] = {
index 12099b09a9a71ee5f49e61608b24734e42ca58db..c0a86aeb173303fb6c07100137eddad6a2bcf68c 100644 (file)
@@ -739,20 +739,17 @@ int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
        if (!div && !requests[clkout])
                return -EINVAL;
 
-       switch (clkout) {
-       case 0:
+       if (clkout == 0) {
                div_mask = PRCM_CLKOCR_CLKODIV0_MASK;
                mask = (PRCM_CLKOCR_CLKODIV0_MASK | PRCM_CLKOCR_CLKOSEL0_MASK);
                bits = ((source << PRCM_CLKOCR_CLKOSEL0_SHIFT) |
                        (div << PRCM_CLKOCR_CLKODIV0_SHIFT));
-               break;
-       case 1:
+       } else {
                div_mask = PRCM_CLKOCR_CLKODIV1_MASK;
                mask = (PRCM_CLKOCR_CLKODIV1_MASK | PRCM_CLKOCR_CLKOSEL1_MASK |
                        PRCM_CLKOCR_CLK1TYPE);
                bits = ((source << PRCM_CLKOCR_CLKOSEL1_SHIFT) |
                        (div << PRCM_CLKOCR_CLKODIV1_SHIFT));
-               break;
        }
        bits &= mask;
 
index a7136c7ae9fb4b2ed4e51c54534f5f2a99cba8d2..afc7af92db9efcb02a58728a7aa48d25fc637df8 100644 (file)
@@ -112,7 +112,7 @@ static const struct intel_lpss_platform_info bxt_i2c_info = {
 };
 
 static const struct pci_device_id intel_lpss_pci_ids[] = {
-       /* BXT */
+       /* BXT A-Step */
        { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info },
        { PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info },
        { PCI_VDEVICE(INTEL, 0x0ab0), (kernel_ulong_t)&bxt_i2c_info },
@@ -128,6 +128,23 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
        { PCI_VDEVICE(INTEL, 0x0ac4), (kernel_ulong_t)&bxt_info },
        { PCI_VDEVICE(INTEL, 0x0ac6), (kernel_ulong_t)&bxt_info },
        { PCI_VDEVICE(INTEL, 0x0aee), (kernel_ulong_t)&bxt_uart_info },
+       /* BXT B-Step */
+       { PCI_VDEVICE(INTEL, 0x1aac), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x1aae), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x1ab0), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x1ab2), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x1ab4), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x1ab6), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x1ab8), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x1aba), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x1abc), (kernel_ulong_t)&bxt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x1abe), (kernel_ulong_t)&bxt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x1ac0), (kernel_ulong_t)&bxt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x1ac2), (kernel_ulong_t)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x1ac4), (kernel_ulong_t)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x1ac6), (kernel_ulong_t)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x1aee), (kernel_ulong_t)&bxt_uart_info },
+
        /* APL */
        { PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&bxt_i2c_info },
        { PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&bxt_i2c_info },
index 1743788f1595671af62102f95979af1f61c5a14d..1bbbe877ba7e7c1702107fa062f208c089151f60 100644 (file)
@@ -453,6 +453,7 @@ int intel_lpss_probe(struct device *dev,
 err_remove_ltr:
        intel_lpss_debugfs_remove(lpss);
        intel_lpss_ltr_hide(lpss);
+       intel_lpss_unregister_clock(lpss);
 
 err_clk_register:
        ida_simple_remove(&intel_lpss_devid_ida, lpss->devid);
index bd3aa45783460e983add77ab46d32124f46c37a0..d5296bd3e88d85b40f15323f259b28943fb25c3f 100644 (file)
@@ -936,7 +936,10 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
 gpe0_done:
        /* Setup GPIO base register */
        pci_read_config_dword(dev, priv->gbase, &base_addr_cfg);
-       base_addr = base_addr_cfg & 0x0000ff80;
+
+       /* Clear the i/o flag */
+       base_addr = base_addr_cfg & ~BIT(0);
+
        if (!base_addr) {
                dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n");
                ret = -ENODEV;
index b7aabeefab07a2b44ab96b3e371de3d731c0b9cf..2f2225e845efe960a9904fefc1d16fc5cde6b081 100644 (file)
@@ -36,7 +36,7 @@ struct syscon {
        struct list_head list;
 };
 
-static struct regmap_config syscon_regmap_config = {
+static const struct regmap_config syscon_regmap_config = {
        .reg_bits = 32,
        .val_bits = 32,
        .reg_stride = 4,
@@ -50,6 +50,7 @@ static struct syscon *of_syscon_register(struct device_node *np)
        u32 reg_io_width;
        int ret;
        struct regmap_config syscon_config = syscon_regmap_config;
+       struct resource res;
 
        if (!of_device_is_compatible(np, "syscon"))
                return ERR_PTR(-EINVAL);
@@ -58,7 +59,12 @@ static struct syscon *of_syscon_register(struct device_node *np)
        if (!syscon)
                return ERR_PTR(-ENOMEM);
 
-       base = of_iomap(np, 0);
+       if (of_address_to_resource(np, 0, &res)) {
+               ret = -ENOMEM;
+               goto err_map;
+       }
+
+       base = ioremap(res.start, resource_size(&res));
        if (!base) {
                ret = -ENOMEM;
                goto err_map;
@@ -81,6 +87,7 @@ static struct syscon *of_syscon_register(struct device_node *np)
 
        syscon_config.reg_stride = reg_io_width;
        syscon_config.val_bits = reg_io_width * 8;
+       syscon_config.max_register = resource_size(&res) - reg_io_width;
 
        regmap = regmap_init_mmio(NULL, base, &syscon_config);
        if (IS_ERR(regmap)) {
@@ -192,6 +199,7 @@ static int syscon_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct syscon_platform_data *pdata = dev_get_platdata(dev);
        struct syscon *syscon;
+       struct regmap_config syscon_config = syscon_regmap_config;
        struct resource *res;
        void __iomem *base;
 
@@ -207,11 +215,10 @@ static int syscon_probe(struct platform_device *pdev)
        if (!base)
                return -ENOMEM;
 
-       syscon_regmap_config.max_register = res->end - res->start - 3;
+       syscon_config.max_register = res->end - res->start - 3;
        if (pdata)
-               syscon_regmap_config.name = pdata->label;
-       syscon->regmap = devm_regmap_init_mmio(dev, base,
-                                       &syscon_regmap_config);
+               syscon_config.name = pdata->label;
+       syscon->regmap = devm_regmap_init_mmio(dev, base, &syscon_config);
        if (IS_ERR(syscon->regmap)) {
                dev_err(dev, "regmap init failed\n");
                return PTR_ERR(syscon->regmap);
index 83e615ed100ae76bf4abd4740f1acb9cce9de862..495e4518fc2992ff1a757858611f7cf1f3c27b55 100644 (file)
@@ -1059,26 +1059,7 @@ EXPORT_SYMBOL(tps65013_set_low_pwr);
 
 static int __init tps_init(void)
 {
-       u32     tries = 3;
-       int     status = -ENODEV;
-
-       printk(KERN_INFO "%s: version %s\n", DRIVER_NAME, DRIVER_VERSION);
-
-       /* some boards have startup glitches */
-       while (tries--) {
-               status = i2c_add_driver(&tps65010_driver);
-               if (the_tps)
-                       break;
-               i2c_del_driver(&tps65010_driver);
-               if (!tries) {
-                       printk(KERN_ERR "%s: no chip?\n", DRIVER_NAME);
-                       return -ENODEV;
-               }
-               pr_debug("%s: re-probe ...\n", DRIVER_NAME);
-               msleep(10);
-       }
-
-       return status;
+       return i2c_add_driver(&tps65010_driver);
 }
 /* NOTE:  this MUST be initialized before the other parts of the system
  * that rely on it ... but after the i2c bus on which this relies.
diff --git a/drivers/mfd/tps65086.c b/drivers/mfd/tps65086.c
new file mode 100644 (file)
index 0000000..43119a6
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
+ *     Andrew F. Davis <afd@ti.com>
+ *
+ * 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 "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether expressed or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License version 2 for more details.
+ *
+ * Based on the TPS65912 driver
+ */
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+
+#include <linux/mfd/tps65086.h>
+
+static const struct mfd_cell tps65086_cells[] = {
+       { .name = "tps65086-regulator", },
+       { .name = "tps65086-gpio", },
+};
+
+static const struct regmap_range tps65086_yes_ranges[] = {
+       regmap_reg_range(TPS65086_IRQ, TPS65086_IRQ),
+       regmap_reg_range(TPS65086_PMICSTAT, TPS65086_SHUTDNSRC),
+       regmap_reg_range(TPS65086_GPOCTRL, TPS65086_GPOCTRL),
+       regmap_reg_range(TPS65086_PG_STATUS1, TPS65086_OC_STATUS),
+};
+
+static const struct regmap_access_table tps65086_volatile_table = {
+       .yes_ranges = tps65086_yes_ranges,
+       .n_yes_ranges = ARRAY_SIZE(tps65086_yes_ranges),
+};
+
+static const struct regmap_config tps65086_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .cache_type = REGCACHE_RBTREE,
+       .volatile_table = &tps65086_volatile_table,
+};
+
+static const struct regmap_irq tps65086_irqs[] = {
+       REGMAP_IRQ_REG(TPS65086_IRQ_DIETEMP, 0, TPS65086_IRQ_DIETEMP_MASK),
+       REGMAP_IRQ_REG(TPS65086_IRQ_SHUTDN, 0, TPS65086_IRQ_SHUTDN_MASK),
+       REGMAP_IRQ_REG(TPS65086_IRQ_FAULT, 0, TPS65086_IRQ_FAULT_MASK),
+};
+
+static struct regmap_irq_chip tps65086_irq_chip = {
+       .name = "tps65086",
+       .status_base = TPS65086_IRQ,
+       .mask_base = TPS65086_IRQ_MASK,
+       .ack_base = TPS65086_IRQ,
+       .init_ack_masked = true,
+       .num_regs = 1,
+       .irqs = tps65086_irqs,
+       .num_irqs = ARRAY_SIZE(tps65086_irqs),
+};
+
+static const struct of_device_id tps65086_of_match_table[] = {
+       { .compatible = "ti,tps65086", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, tps65086_of_match_table);
+
+static int tps65086_probe(struct i2c_client *client,
+                         const struct i2c_device_id *ids)
+{
+       struct tps65086 *tps;
+       unsigned int version;
+       int ret;
+
+       tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+       if (!tps)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, tps);
+       tps->dev = &client->dev;
+       tps->irq = client->irq;
+
+       tps->regmap = devm_regmap_init_i2c(client, &tps65086_regmap_config);
+       if (IS_ERR(tps->regmap)) {
+               dev_err(tps->dev, "Failed to initialize register map\n");
+               return PTR_ERR(tps->regmap);
+       }
+
+       ret = regmap_read(tps->regmap, TPS65086_DEVICEID, &version);
+       if (ret) {
+               dev_err(tps->dev, "Failed to read revision register\n");
+               return ret;
+       }
+
+       dev_info(tps->dev, "Device: TPS65086%01lX, OTP: %c, Rev: %ld\n",
+                (version & TPS65086_DEVICEID_PART_MASK),
+                (char)((version & TPS65086_DEVICEID_OTP_MASK) >> 4) + 'A',
+                (version & TPS65086_DEVICEID_REV_MASK) >> 6);
+
+       ret = regmap_add_irq_chip(tps->regmap, tps->irq, IRQF_ONESHOT, 0,
+                                 &tps65086_irq_chip, &tps->irq_data);
+       if (ret) {
+               dev_err(tps->dev, "Failed to register IRQ chip\n");
+               return ret;
+       }
+
+       ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65086_cells,
+                             ARRAY_SIZE(tps65086_cells), NULL, 0,
+                             regmap_irq_get_domain(tps->irq_data));
+       if (ret) {
+               regmap_del_irq_chip(tps->irq, tps->irq_data);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int tps65086_remove(struct i2c_client *client)
+{
+       struct tps65086 *tps = i2c_get_clientdata(client);
+
+       regmap_del_irq_chip(tps->irq, tps->irq_data);
+
+       return 0;
+}
+
+static const struct i2c_device_id tps65086_id_table[] = {
+       { "tps65086", 0 },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, tps65086_id_table);
+
+static struct i2c_driver tps65086_driver = {
+       .driver         = {
+               .name   = "tps65086",
+               .of_match_table = tps65086_of_match_table,
+       },
+       .probe          = tps65086_probe,
+       .remove         = tps65086_remove,
+       .id_table       = tps65086_id_table,
+};
+module_i2c_driver(tps65086_driver);
+
+MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
+MODULE_DESCRIPTION("TPS65086 PMIC Driver");
+MODULE_LICENSE("GPL v2");
index bc6f7e00fb3de33438759c6c88184b7385dc86b7..1a5a87f3cd38e5733f8c9a518d7389b889fc56bd 100644 (file)
 
 #include <linux/platform_device.h>
 
+#define MFD_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+#define MFD_CELL_ALL(_name, _res, _pdata, _id, _compat, _match)                \
+       {                                                               \
+               .name = (_name),                                        \
+               .resources = (_res),                                    \
+               .num_resources = MFD_ARRAY_SIZE((_res)),                \
+               .platform_data = (_pdata),                              \
+               .pdata_size = MFD_ARRAY_SIZE((_pdata)),                 \
+               .of_compatible = (_compat),                             \
+               .acpi_match = (_match),                                 \
+               .id = _id,                                              \
+       }
+
+#define OF_MFD_CELL(_name, _res, _pdata, _id, _compat)                 \
+               MFD_CELL_ALL(_name, _res, _pdata, _id, _compat, NULL)   \
+
+#define ACPI_MFD_CELL(_name, _res, _pdata, _id, _match)                        \
+               MFD_CELL_ALL(_name, _res, _pdata, _id, NULL, _match)    \
+
+#define MFD_CELL_BASIC(_name, _res, _pdata, _id)                       \
+               MFD_CELL_ALL(_name, _res, _pdata, _id, NULL, NULL)      \
+
+#define MFD_CELL_NAME(_name)                                           \
+               MFD_CELL_ALL(_name, NULL, NULL, 0, NULL, NULL)          \
+
 struct irq_domain;
 struct property_set;
 
diff --git a/include/linux/mfd/tps65086.h b/include/linux/mfd/tps65086.h
new file mode 100644 (file)
index 0000000..a228ae4
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
+ *     Andrew F. Davis <afd@ti.com>
+ *
+ * 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 "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether expressed or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License version 2 for more details.
+ *
+ * Based on the TPS65912 driver
+ */
+
+#ifndef __LINUX_MFD_TPS65086_H
+#define __LINUX_MFD_TPS65086_H
+
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+/* List of registers for TPS65086 */
+#define TPS65086_DEVICEID              0x01
+#define TPS65086_IRQ                   0x02
+#define TPS65086_IRQ_MASK              0x03
+#define TPS65086_PMICSTAT              0x04
+#define TPS65086_SHUTDNSRC             0x05
+#define TPS65086_BUCK1CTRL             0x20
+#define TPS65086_BUCK2CTRL             0x21
+#define TPS65086_BUCK3DECAY            0x22
+#define TPS65086_BUCK3VID              0x23
+#define TPS65086_BUCK3SLPCTRL          0x24
+#define TPS65086_BUCK4CTRL             0x25
+#define TPS65086_BUCK5CTRL             0x26
+#define TPS65086_BUCK6CTRL             0x27
+#define TPS65086_LDOA2CTRL             0x28
+#define TPS65086_LDOA3CTRL             0x29
+#define TPS65086_DISCHCTRL1            0x40
+#define TPS65086_DISCHCTRL2            0x41
+#define TPS65086_DISCHCTRL3            0x42
+#define TPS65086_PG_DELAY1             0x43
+#define TPS65086_FORCESHUTDN           0x91
+#define TPS65086_BUCK1SLPCTRL          0x92
+#define TPS65086_BUCK2SLPCTRL          0x93
+#define TPS65086_BUCK4VID              0x94
+#define TPS65086_BUCK4SLPVID           0x95
+#define TPS65086_BUCK5VID              0x96
+#define TPS65086_BUCK5SLPVID           0x97
+#define TPS65086_BUCK6VID              0x98
+#define TPS65086_BUCK6SLPVID           0x99
+#define TPS65086_LDOA2VID              0x9A
+#define TPS65086_LDOA3VID              0x9B
+#define TPS65086_BUCK123CTRL           0x9C
+#define TPS65086_PG_DELAY2             0x9D
+#define TPS65086_PIN_EN_MASK1          0x9E
+#define TPS65086_PIN_EN_MASK2          0x9F
+#define TPS65086_SWVTT_EN              0x9F
+#define TPS65086_PIN_EN_OVR1           0xA0
+#define TPS65086_PIN_EN_OVR2           0xA1
+#define TPS65086_GPOCTRL               0xA1
+#define TPS65086_PWR_FAULT_MASK1       0xA2
+#define TPS65086_PWR_FAULT_MASK2       0xA3
+#define TPS65086_GPO1PG_CTRL1          0xA4
+#define TPS65086_GPO1PG_CTRL2          0xA5
+#define TPS65086_GPO4PG_CTRL1          0xA6
+#define TPS65086_GPO4PG_CTRL2          0xA7
+#define TPS65086_GPO2PG_CTRL1          0xA8
+#define TPS65086_GPO2PG_CTRL2          0xA9
+#define TPS65086_GPO3PG_CTRL1          0xAA
+#define TPS65086_GPO3PG_CTRL2          0xAB
+#define TPS65086_LDOA1CTRL             0xAE
+#define TPS65086_PG_STATUS1            0xB0
+#define TPS65086_PG_STATUS2            0xB1
+#define TPS65086_PWR_FAULT_STATUS1     0xB2
+#define TPS65086_PWR_FAULT_STATUS2     0xB3
+#define TPS65086_TEMPCRIT              0xB4
+#define TPS65086_TEMPHOT               0xB5
+#define TPS65086_OC_STATUS             0xB6
+
+/* IRQ Register field definitions */
+#define TPS65086_IRQ_DIETEMP_MASK      BIT(0)
+#define TPS65086_IRQ_SHUTDN_MASK       BIT(3)
+#define TPS65086_IRQ_FAULT_MASK                BIT(7)
+
+/* DEVICEID Register field definitions */
+#define TPS65086_DEVICEID_PART_MASK    GENMASK(3, 0)
+#define TPS65086_DEVICEID_OTP_MASK     GENMASK(5, 4)
+#define TPS65086_DEVICEID_REV_MASK     GENMASK(7, 6)
+
+/* VID Masks */
+#define BUCK_VID_MASK                  GENMASK(7, 1)
+#define VDOA1_VID_MASK                 GENMASK(4, 1)
+#define VDOA23_VID_MASK                        GENMASK(3, 0)
+
+/* Define the TPS65086 IRQ numbers */
+enum tps65086_irqs {
+       TPS65086_IRQ_DIETEMP,
+       TPS65086_IRQ_SHUTDN,
+       TPS65086_IRQ_FAULT,
+};
+
+/**
+ * struct tps65086 - state holder for the tps65086 driver
+ *
+ * Device data may be used to access the TPS65086 chip
+ */
+struct tps65086 {
+       struct device *dev;
+       struct regmap *regmap;
+
+       /* IRQ Data */
+       int irq;
+       struct regmap_irq_chip_data *irq_data;
+};
+
+#endif /* __LINUX_MFD_TPS65086_H */