Merge tag 'mfd-next-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 16 Nov 2017 17:15:57 +0000 (09:15 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 16 Nov 2017 17:15:57 +0000 (09:15 -0800)
Pull MFD updates from Lee Jones:
 "New drivers:
   - Add support for Cherry Trail Dollar Cove TI PMIC
   - Add support for Add Spreadtrum SC27xx series PMICs

  New device support:
   - Add support Regulator to axp20x

  New functionality:
   - Add DT support; aspeed-scu sc27xx-pmic
   - Add power saving support; rts5249

  Fix-ups:
   - DT clean-up/rework; tps65217, max77693, iproc-cdru, iproc-mhb, tps65218
   - Staticise/constify; stw481x
   - Use new succinct IRQ API; fsl-imx25-tsadc
   - Kconfig fix-ups; MFD_TPS65218
   - Identify SPI method; lpc_ich
   - Use managed resources (devm_*) calls; ssbi
   - Remove unused/obsolete code/documentation; mc13xxx

  Bug fixes:
   - Fix typo in MAINTAINERS
   - Fix error handling; mxs-lradc
   - Clean-up IRQs on .remove; fsl-imx25-tsadc"

* tag 'mfd-next-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (21 commits)
  dt-bindings: mfd: mc13xxx: Remove obsolete property
  mfd: axp20x: Add axp20x-regulator cell for AXP813
  mfd: Add Spreadtrum SC27xx series PMICs driver
  dt-bindings: mfd: Add Spreadtrum SC27xx PMIC documentation
  mfd: ssbi: Use devm_of_platform_populate()
  mfd: fsl-imx25: Clean up irq settings during removal
  mfd: mxs-lradc: Fix error handling in mxs_lradc_probe()
  mfd: lpc_ich: Avoton/Rangeley uses SPI_BYT method
  mfd: tps65218: Introduce dependency on CONFIG_OF
  mfd: tps65218: Correct the config description
  MAINTAINERS: Fix Dialog search term for watchdog binding file
  mfd: fsl-imx25: Set irq handler and data in one go
  mfd: rts5249: Add support for RTS5250S power saving
  ACPI / PMIC: Add opregion driver for Intel Dollar Cove TI PMIC
  mfd: Add support for Cherry Trail Dollar Cove TI PMIC
  syscon: dt-bindings: Add binding document for iProc MHB block
  syscon: dt-bindings: Add binding doc for Broadcom iProc CDRU
  mfd: max77693: Add muic of_compatible in mfd_cell
  mfd: stw481x: Make three arrays static const, reduces object code size
  mfd: tps65217: Introduce dependency on CONFIG_OF
  ...

30 files changed:
Documentation/devicetree/bindings/mfd/aspeed-scu.txt
Documentation/devicetree/bindings/mfd/brcm,iproc-cdru.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/brcm,iproc-mhb.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/max77693.txt
Documentation/devicetree/bindings/mfd/mc13xxx.txt
Documentation/devicetree/bindings/mfd/sprd,sc27xx-pmic.txt [new file with mode: 0644]
MAINTAINERS
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/pmic/intel_pmic_chtdc_ti.c [new file with mode: 0644]
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/axp20x.c
drivers/mfd/fsl-imx25-tsadc.c
drivers/mfd/intel_soc_pmic_chtdc_ti.c [new file with mode: 0644]
drivers/mfd/lpc_ich.c
drivers/mfd/max77693.c
drivers/mfd/mxs-lradc.c
drivers/mfd/rts5249.c
drivers/mfd/rtsx_pcr.c
drivers/mfd/rtsx_pcr.h
drivers/mfd/sprd-sc27xx-spi.c [new file with mode: 0644]
drivers/mfd/ssbi.c
drivers/mfd/stw481x.c
drivers/mfd/tps65217.c
drivers/mfd/tps65218.c
drivers/regulator/tps65217-regulator.c
drivers/video/backlight/tps65217_bl.c
include/linux/mfd/rtsx_pci.h
include/linux/mfd/tps65217.h

index 4fc5b83726d6c6a6e90e971f9480f6851983d83d..ce8cf0ec6279a5ccc8aece96e4c85cc2aab46776 100644 (file)
@@ -9,10 +9,16 @@ Required properties:
                "aspeed,g5-scu", "syscon", "simple-mfd"
 
 - reg:         contains the offset and length of the SCU memory region
+- #clock-cells: should be set to <1> - the system controller is also a
+       clock provider
+- #reset-cells: should be set to <1> - the system controller is also a
+       reset line provider
 
 Example:
 
 syscon: syscon@1e6e2000 {
        compatible = "aspeed,ast2400-scu", "syscon", "simple-mfd";
        reg = <0x1e6e2000 0x1a8>;
+       #clock-cells = <1>;
+       #reset-cells = <1>;
 };
diff --git a/Documentation/devicetree/bindings/mfd/brcm,iproc-cdru.txt b/Documentation/devicetree/bindings/mfd/brcm,iproc-cdru.txt
new file mode 100644 (file)
index 0000000..82f82e0
--- /dev/null
@@ -0,0 +1,16 @@
+Broadcom iProc Chip Device Resource Unit (CDRU)
+
+Various Broadcom iProc SoCs have a set of registers that provide various
+chip specific device and resource configurations. This node allows access to
+these CDRU registers via syscon.
+
+Required properties:
+- compatible: should contain:
+               "brcm,sr-cdru", "syscon" for Stingray
+- reg: base address and range of the CDRU registers
+
+Example:
+       cdru: syscon@6641d000 {
+               compatible = "brcm,sr-cdru", "syscon";
+               reg = <0 0x6641d000 0 0x400>;
+       };
diff --git a/Documentation/devicetree/bindings/mfd/brcm,iproc-mhb.txt b/Documentation/devicetree/bindings/mfd/brcm,iproc-mhb.txt
new file mode 100644 (file)
index 0000000..4421e97
--- /dev/null
@@ -0,0 +1,18 @@
+Broadcom iProc Multi Host Bridge (MHB)
+
+Certain Broadcom iProc SoCs have a multi host bridge (MHB) block that controls
+the connection and configuration of 1) internal PCIe serdes; 2) PCIe endpoint
+interface; 3) access to the Nitro (network processing) engine
+
+This node allows access to these MHB registers via syscon.
+
+Required properties:
+- compatible: should contain:
+               "brcm,sr-mhb", "syscon" for Stingray
+- reg: base address and range of the MHB registers
+
+Example:
+       mhb: syscon@60401000 {
+               compatible = "brcm,sr-mhb", "syscon";
+               reg = <0 0x60401000 0 0x38c>;
+       };
index 6a1ae3a2b77f978d33515cb2bf5c08cecd44cc4d..e6754974a74594b8c969441fec6b08019b2c2167 100644 (file)
@@ -127,6 +127,12 @@ Required properties for the LED child node:
 Optional properties for the LED child node:
 - label : see Documentation/devicetree/bindings/leds/common.txt
 
+Optional nodes:
+- max77693-muic :
+       Node used only by extcon consumers.
+       Required properties:
+               - compatible : "maxim,max77693-muic"
+
 Example:
 #include <dt-bindings/leds/common.h>
 
index 39ba4146769deb9ab3549a0789bbb340e693e7ca..ac235fe385fc296e371fab835170c9e0b14a7ae1 100644 (file)
@@ -113,7 +113,6 @@ MC13892 regulators:
 Examples:
 
 ecspi@70010000 { /* ECSPI1 */
-       fsl,spi-num-chipselects = <2>;
        cs-gpios = <&gpio4 24 0>, /* GPIO4_24 */
                   <&gpio4 25 0>; /* GPIO4_25 */
 
diff --git a/Documentation/devicetree/bindings/mfd/sprd,sc27xx-pmic.txt b/Documentation/devicetree/bindings/mfd/sprd,sc27xx-pmic.txt
new file mode 100644 (file)
index 0000000..21b9a89
--- /dev/null
@@ -0,0 +1,40 @@
+Spreadtrum SC27xx Power Management Integrated Circuit (PMIC)
+
+The Spreadtrum SC27xx series PMICs contain SC2720, SC2721, SC2723, SC2730
+and SC2731. The Spreadtrum PMIC belonging to SC27xx series integrates all
+mobile handset power management, audio codec, battery management and user
+interface support function in a single chip. It has 6 major functional
+blocks:
+- DCDCs to support CPU, memory.
+- LDOs to support both internal and external requirement.
+- Battery management system, such as charger, fuel gauge.
+- Audio codec.
+- User interface function, such as indicator, flash LED and so on.
+- IC level interface, such as power on/off control, RTC and typec and so on.
+
+Required properties:
+- compatible: Should be one of the following:
+       "sprd,sc2720"
+       "sprd,sc2721"
+       "sprd,sc2723"
+       "sprd,sc2730"
+       "sprd,sc2731"
+- reg: The address of the device chip select, should be 0.
+- spi-max-frequency: Typically set to 26000000.
+- 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 PMIC IRQ, must be 2.
+- #address-cells: Child device offset number of cells, must be 1.
+- #size-cells: Child device size number of cells, must be 0.
+
+Example:
+pmic@0 {
+       compatible = "sprd,sc2731";
+       reg = <0>;
+       spi-max-frequency = <26000000>;
+       interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+       interrupt-controller;
+       #interrupt-cells = <2>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+};
index 7f9c4f3fc9419d1b199ac2ffd4575077738ac8f4..fa9c49c594a1c5152a5d35a19204c29eee3b51a7 100644 (file)
@@ -4146,7 +4146,7 @@ F:        Documentation/devicetree/bindings/mfd/da90*.txt
 F:     Documentation/devicetree/bindings/input/da90??-onkey.txt
 F:     Documentation/devicetree/bindings/thermal/da90??-thermal.txt
 F:     Documentation/devicetree/bindings/regulator/da92*.txt
-F:     Documentation/devicetree/bindings/watchdog/da92??-wdt.txt
+F:     Documentation/devicetree/bindings/watchdog/da90??-wdt.txt
 F:     Documentation/devicetree/bindings/sound/da[79]*.txt
 F:     drivers/gpio/gpio-da90??.c
 F:     drivers/hwmon/da90??-hwmon.c
index 91477d5ab422c4795b56abffe1075f3c35e40b76..46505396869e615e17809d06ecac974798c39e51 100644 (file)
@@ -527,6 +527,12 @@ config CHT_WC_PMIC_OPREGION
        help
          This config adds ACPI operation region support for CHT Whiskey Cove PMIC.
 
+config CHT_DC_TI_PMIC_OPREGION
+       bool "ACPI operation region support for Dollar Cove TI PMIC"
+       depends on INTEL_SOC_PMIC_CHTDC_TI
+       help
+         This config adds ACPI operation region support for Dollar Cove TI PMIC.
+
 endif
 
 config ACPI_CONFIGFS
index 31c15d84a8d03811358cc4f0b9a40509694c10bc..41954a601989368894256b561a26e5823ce8a155 100644 (file)
@@ -106,6 +106,7 @@ obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
 obj-$(CONFIG_BXT_WC_PMIC_OPREGION) += pmic/intel_pmic_bxtwc.o
 obj-$(CONFIG_CHT_WC_PMIC_OPREGION) += pmic/intel_pmic_chtwc.o
+obj-$(CONFIG_CHT_DC_TI_PMIC_OPREGION) += pmic/intel_pmic_chtdc_ti.o
 
 obj-$(CONFIG_ACPI_CONFIGFS)    += acpi_configfs.o
 
diff --git a/drivers/acpi/pmic/intel_pmic_chtdc_ti.c b/drivers/acpi/pmic/intel_pmic_chtdc_ti.c
new file mode 100644 (file)
index 0000000..109c1e9
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Dollar Cove TI PMIC operation region driver
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ * Rewritten and cleaned up
+ * Copyright (C) 2017 Takashi Iwai <tiwai@suse.de>
+ */
+
+#include <linux/acpi.h>
+#include <linux/init.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include <linux/platform_device.h>
+#include "intel_pmic.h"
+
+/* registers stored in 16bit BE (high:low, total 10bit) */
+#define CHTDC_TI_VBAT          0x54
+#define CHTDC_TI_DIETEMP       0x56
+#define CHTDC_TI_BPTHERM       0x58
+#define CHTDC_TI_GPADC         0x5a
+
+static struct pmic_table chtdc_ti_power_table[] = {
+       { .address = 0x00, .reg = 0x41 },
+       { .address = 0x04, .reg = 0x42 },
+       { .address = 0x08, .reg = 0x43 },
+       { .address = 0x0c, .reg = 0x45 },
+       { .address = 0x10, .reg = 0x46 },
+       { .address = 0x14, .reg = 0x47 },
+       { .address = 0x18, .reg = 0x48 },
+       { .address = 0x1c, .reg = 0x49 },
+       { .address = 0x20, .reg = 0x4a },
+       { .address = 0x24, .reg = 0x4b },
+       { .address = 0x28, .reg = 0x4c },
+       { .address = 0x2c, .reg = 0x4d },
+       { .address = 0x30, .reg = 0x4e },
+};
+
+static struct pmic_table chtdc_ti_thermal_table[] = {
+       {
+               .address = 0x00,
+               .reg = CHTDC_TI_GPADC
+       },
+       {
+               .address = 0x0c,
+               .reg = CHTDC_TI_GPADC
+       },
+       /* TMP2 -> SYSTEMP */
+       {
+               .address = 0x18,
+               .reg = CHTDC_TI_GPADC
+       },
+       /* TMP3 -> BPTHERM */
+       {
+               .address = 0x24,
+               .reg = CHTDC_TI_BPTHERM
+       },
+       {
+               .address = 0x30,
+               .reg = CHTDC_TI_GPADC
+       },
+       /* TMP5 -> DIETEMP */
+       {
+               .address = 0x3c,
+               .reg = CHTDC_TI_DIETEMP
+       },
+};
+
+static int chtdc_ti_pmic_get_power(struct regmap *regmap, int reg, int bit,
+                                  u64 *value)
+{
+       int data;
+
+       if (regmap_read(regmap, reg, &data))
+               return -EIO;
+
+       *value = data & 1;
+       return 0;
+}
+
+static int chtdc_ti_pmic_update_power(struct regmap *regmap, int reg, int bit,
+                                     bool on)
+{
+       return regmap_update_bits(regmap, reg, 1, on);
+}
+
+static int chtdc_ti_pmic_get_raw_temp(struct regmap *regmap, int reg)
+{
+       u8 buf[2];
+
+       if (regmap_bulk_read(regmap, reg, buf, 2))
+               return -EIO;
+
+       /* stored in big-endian */
+       return ((buf[0] & 0x03) << 8) | buf[1];
+}
+
+static struct intel_pmic_opregion_data chtdc_ti_pmic_opregion_data = {
+       .get_power = chtdc_ti_pmic_get_power,
+       .update_power = chtdc_ti_pmic_update_power,
+       .get_raw_temp = chtdc_ti_pmic_get_raw_temp,
+       .power_table = chtdc_ti_power_table,
+       .power_table_count = ARRAY_SIZE(chtdc_ti_power_table),
+       .thermal_table = chtdc_ti_thermal_table,
+       .thermal_table_count = ARRAY_SIZE(chtdc_ti_thermal_table),
+};
+
+static int chtdc_ti_pmic_opregion_probe(struct platform_device *pdev)
+{
+       struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
+       int err;
+
+       err = intel_pmic_install_opregion_handler(&pdev->dev,
+                       ACPI_HANDLE(pdev->dev.parent), pmic->regmap,
+                       &chtdc_ti_pmic_opregion_data);
+       if (err < 0)
+               return err;
+
+       /* Re-enumerate devices depending on PMIC */
+       acpi_walk_dep_device_list(ACPI_HANDLE(pdev->dev.parent));
+       return 0;
+}
+
+static const struct platform_device_id chtdc_ti_pmic_opregion_id_table[] = {
+       { .name = "chtdc_ti_region" },
+       {},
+};
+
+static struct platform_driver chtdc_ti_pmic_opregion_driver = {
+       .probe = chtdc_ti_pmic_opregion_probe,
+       .driver = {
+               .name = "cht_dollar_cove_ti_pmic",
+       },
+       .id_table = chtdc_ti_pmic_opregion_id_table,
+};
+module_platform_driver(chtdc_ti_pmic_opregion_driver);
+
+MODULE_DESCRIPTION("Dollar Cove TI PMIC opregion driver");
+MODULE_LICENSE("GPL v2");
index ac5ad6d0837c982de9c3f9e3520d643636eedc81..1d20a800e96795cd2bf1b9303f7bd2fa1d284b03 100644 (file)
@@ -510,6 +510,19 @@ config INTEL_SOC_PMIC_CHTWC
          available before any devices using it are probed. This option also
          causes the designware-i2c driver to be builtin for the same reason.
 
+config INTEL_SOC_PMIC_CHTDC_TI
+       tristate "Support for Intel Cherry Trail Dollar Cove TI PMIC"
+       depends on GPIOLIB
+       depends on I2C
+       depends on ACPI
+       depends on X86
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       help
+         Select this option for supporting Dollar Cove (TI version) PMIC
+         device that is found on some Intel Cherry Trail systems.
+
 config MFD_INTEL_LPSS
        tristate
        select COMMON_CLK
@@ -1057,6 +1070,22 @@ config MFD_SMSC
         To compile this driver as a module, choose M here: the
         module will be called smsc.
 
+config MFD_SC27XX_PMIC
+       tristate "Spreadtrum SC27xx PMICs"
+       depends on ARCH_SPRD || COMPILE_TEST
+       depends on SPI_MASTER
+       select MFD_CORE
+       select REGMAP_SPI
+       select REGMAP_IRQ
+       help
+         This enables support for the Spreadtrum SC27xx PMICs with SPI
+         interface. The SC27xx series PMICs integrate power management,
+         audio codec, battery management and user interface support
+         function (such as RTC, Typec, indicator and so on) in a single chip.
+
+         This driver provides common support for accessing the SC27xx PMICs,
+         and it also adds the irq_chip parts for handling the PMIC chip events.
+
 config ABX500_CORE
        bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions"
        default y if ARCH_U300 || ARCH_U8500 || COMPILE_TEST
@@ -1338,7 +1367,7 @@ config MFD_TPS65090
 
 config MFD_TPS65217
        tristate "TI TPS65217 Power Management / White LED chips"
-       depends on I2C
+       depends on I2C && OF
        select MFD_CORE
        select REGMAP_I2C
        select IRQ_DOMAIN
@@ -1400,7 +1429,7 @@ config MFD_TI_LP87565
 
 config MFD_TPS65218
        tristate "TI TPS65218 Power Management chips"
-       depends on I2C
+       depends on I2C && OF
        select MFD_CORE
        select REGMAP_I2C
        select REGMAP_IRQ
@@ -1408,8 +1437,7 @@ config MFD_TPS65218
          If you say yes here you get support for the TPS65218 series of
          Power Management chips.
          These include voltage regulators, gpio and other features
-         that are often used in portable devices. Only regulator
-         component is currently supported.
+         that are often used in portable devices.
 
          This driver can also be built as a module.  If so, the module
          will be called tps65218.
index 0235e6766bc13e070d9c07b39582159787853908..d9474ade32e6693fd7a3e5adb583eb2f3366c5cb 100644 (file)
@@ -220,6 +220,7 @@ intel-soc-pmic-objs         := intel_soc_pmic_core.o intel_soc_pmic_crc.o
 obj-$(CONFIG_INTEL_SOC_PMIC)   += intel-soc-pmic.o
 obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC)     += intel_soc_pmic_bxtwc.o
 obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC)     += intel_soc_pmic_chtwc.o
+obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI)  += intel_soc_pmic_chtdc_ti.o
 obj-$(CONFIG_MFD_MT6397)       += mt6397-core.o
 
 obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
@@ -228,3 +229,4 @@ obj-$(CONFIG_MFD_SUN4I_GPADC)       += sun4i-gpadc.o
 obj-$(CONFIG_MFD_STM32_LPTIMER)        += stm32-lptimer.o
 obj-$(CONFIG_MFD_STM32_TIMERS)         += stm32-timers.o
 obj-$(CONFIG_MFD_MXS_LRADC)     += mxs-lradc.o
+obj-$(CONFIG_MFD_SC27XX_PMIC)  += sprd-sc27xx-spi.o
index 336de66ca408079f841e4277f7db499e8e2b7e11..2468b431bb22038cd051d0002983445f907cd364 100644 (file)
@@ -876,6 +876,8 @@ static struct mfd_cell axp813_cells[] = {
                .name                   = "axp221-pek",
                .num_resources          = ARRAY_SIZE(axp803_pek_resources),
                .resources              = axp803_pek_resources,
+       }, {
+               .name                   = "axp20x-regulator",
        }
 };
 
index b3767c3141e58a0fd9af028ced1ad13f67726c77..dbb85caaafede157127b52f33333ad851c9b5183 100644 (file)
@@ -84,8 +84,7 @@ static int mx25_tsadc_setup_irq(struct platform_device *pdev,
                return -ENOMEM;
        }
 
-       irq_set_chained_handler(irq, mx25_tsadc_irq_handler);
-       irq_set_handler_data(irq, tsadc);
+       irq_set_chained_handler_and_data(irq, mx25_tsadc_irq_handler, tsadc);
 
        return 0;
 }
@@ -180,6 +179,19 @@ static int mx25_tsadc_probe(struct platform_device *pdev)
        return devm_of_platform_populate(dev);
 }
 
+static int mx25_tsadc_remove(struct platform_device *pdev)
+{
+       struct mx25_tsadc *tsadc = platform_get_drvdata(pdev);
+       int irq = platform_get_irq(pdev, 0);
+
+       if (irq) {
+               irq_set_chained_handler_and_data(irq, NULL, NULL);
+               irq_domain_remove(tsadc->domain);
+       }
+
+       return 0;
+}
+
 static const struct of_device_id mx25_tsadc_ids[] = {
        { .compatible = "fsl,imx25-tsadc" },
        { /* Sentinel */ }
@@ -192,6 +204,7 @@ static struct platform_driver mx25_tsadc_driver = {
                .of_match_table = of_match_ptr(mx25_tsadc_ids),
        },
        .probe = mx25_tsadc_probe,
+       .remove = mx25_tsadc_remove,
 };
 module_platform_driver(mx25_tsadc_driver);
 
diff --git a/drivers/mfd/intel_soc_pmic_chtdc_ti.c b/drivers/mfd/intel_soc_pmic_chtdc_ti.c
new file mode 100644 (file)
index 0000000..861277c
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Device access for Dollar Cove TI PMIC
+ *
+ * Copyright (c) 2014, Intel Corporation.
+ *   Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
+ *
+ * Cleanup and forward-ported
+ *   Copyright (c) 2017 Takashi Iwai <tiwai@suse.de>
+ *
+ * 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.
+ */
+
+#include <linux/acpi.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#define CHTDC_TI_IRQLVL1       0x01
+#define CHTDC_TI_MASK_IRQLVL1  0x02
+
+/* Level 1 IRQs */
+enum {
+       CHTDC_TI_PWRBTN = 0,    /* power button */
+       CHTDC_TI_DIETMPWARN,    /* thermal */
+       CHTDC_TI_ADCCMPL,       /* ADC */
+       /* No IRQ 3 */
+       CHTDC_TI_VBATLOW = 4,   /* battery */
+       CHTDC_TI_VBUSDET,       /* power source */
+       /* No IRQ 6 */
+       CHTDC_TI_CCEOCAL = 7,   /* battery */
+};
+
+static struct resource power_button_resources[] = {
+       DEFINE_RES_IRQ(CHTDC_TI_PWRBTN),
+};
+
+static struct resource thermal_resources[] = {
+       DEFINE_RES_IRQ(CHTDC_TI_DIETMPWARN),
+};
+
+static struct resource adc_resources[] = {
+       DEFINE_RES_IRQ(CHTDC_TI_ADCCMPL),
+};
+
+static struct resource pwrsrc_resources[] = {
+       DEFINE_RES_IRQ(CHTDC_TI_VBUSDET),
+};
+
+static struct resource battery_resources[] = {
+       DEFINE_RES_IRQ(CHTDC_TI_VBATLOW),
+       DEFINE_RES_IRQ(CHTDC_TI_CCEOCAL),
+};
+
+static struct mfd_cell chtdc_ti_dev[] = {
+       {
+               .name = "chtdc_ti_pwrbtn",
+               .num_resources = ARRAY_SIZE(power_button_resources),
+               .resources = power_button_resources,
+       }, {
+               .name = "chtdc_ti_adc",
+               .num_resources = ARRAY_SIZE(adc_resources),
+               .resources = adc_resources,
+       }, {
+               .name = "chtdc_ti_thermal",
+               .num_resources = ARRAY_SIZE(thermal_resources),
+               .resources = thermal_resources,
+       }, {
+               .name = "chtdc_ti_pwrsrc",
+               .num_resources = ARRAY_SIZE(pwrsrc_resources),
+               .resources = pwrsrc_resources,
+       }, {
+               .name = "chtdc_ti_battery",
+               .num_resources = ARRAY_SIZE(battery_resources),
+               .resources = battery_resources,
+       },
+       {       .name = "chtdc_ti_region", },
+};
+
+static const struct regmap_config chtdc_ti_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = 128,
+       .cache_type = REGCACHE_NONE,
+};
+
+static const struct regmap_irq chtdc_ti_irqs[] = {
+       REGMAP_IRQ_REG(CHTDC_TI_PWRBTN, 0, BIT(CHTDC_TI_PWRBTN)),
+       REGMAP_IRQ_REG(CHTDC_TI_DIETMPWARN, 0, BIT(CHTDC_TI_DIETMPWARN)),
+       REGMAP_IRQ_REG(CHTDC_TI_ADCCMPL, 0, BIT(CHTDC_TI_ADCCMPL)),
+       REGMAP_IRQ_REG(CHTDC_TI_VBATLOW, 0, BIT(CHTDC_TI_VBATLOW)),
+       REGMAP_IRQ_REG(CHTDC_TI_VBUSDET, 0, BIT(CHTDC_TI_VBUSDET)),
+       REGMAP_IRQ_REG(CHTDC_TI_CCEOCAL, 0, BIT(CHTDC_TI_CCEOCAL)),
+};
+
+static const struct regmap_irq_chip chtdc_ti_irq_chip = {
+       .name = KBUILD_MODNAME,
+       .irqs = chtdc_ti_irqs,
+       .num_irqs = ARRAY_SIZE(chtdc_ti_irqs),
+       .num_regs = 1,
+       .status_base = CHTDC_TI_IRQLVL1,
+       .mask_base = CHTDC_TI_MASK_IRQLVL1,
+       .ack_base = CHTDC_TI_IRQLVL1,
+};
+
+static int chtdc_ti_probe(struct i2c_client *i2c)
+{
+       struct device *dev = &i2c->dev;
+       struct intel_soc_pmic *pmic;
+       int ret;
+
+       pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
+       if (!pmic)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, pmic);
+
+       pmic->regmap = devm_regmap_init_i2c(i2c, &chtdc_ti_regmap_config);
+       if (IS_ERR(pmic->regmap))
+               return PTR_ERR(pmic->regmap);
+       pmic->irq = i2c->irq;
+
+       ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq,
+                                      IRQF_ONESHOT, 0,
+                                      &chtdc_ti_irq_chip,
+                                      &pmic->irq_chip_data);
+       if (ret)
+               return ret;
+
+       return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, chtdc_ti_dev,
+                                   ARRAY_SIZE(chtdc_ti_dev), NULL, 0,
+                                   regmap_irq_get_domain(pmic->irq_chip_data));
+}
+
+static void chtdc_ti_shutdown(struct i2c_client *i2c)
+{
+       struct intel_soc_pmic *pmic = i2c_get_clientdata(i2c);
+
+       disable_irq(pmic->irq);
+}
+
+static int __maybe_unused chtdc_ti_suspend(struct device *dev)
+{
+       struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+       disable_irq(pmic->irq);
+
+       return 0;
+}
+
+static int __maybe_unused chtdc_ti_resume(struct device *dev)
+{
+       struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+       enable_irq(pmic->irq);
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(chtdc_ti_pm_ops, chtdc_ti_suspend, chtdc_ti_resume);
+
+static const struct acpi_device_id chtdc_ti_acpi_ids[] = {
+       { "INT33F5" },
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, chtdc_ti_acpi_ids);
+
+static struct i2c_driver chtdc_ti_i2c_driver = {
+       .driver = {
+               .name = "intel_soc_pmic_chtdc_ti",
+               .pm = &chtdc_ti_pm_ops,
+               .acpi_match_table = chtdc_ti_acpi_ids,
+       },
+       .probe_new = chtdc_ti_probe,
+       .shutdown = chtdc_ti_shutdown,
+};
+module_i2c_driver(chtdc_ti_i2c_driver);
+
+MODULE_DESCRIPTION("I2C driver for Intel SoC Dollar Cove TI PMIC");
+MODULE_LICENSE("GPL v2");
index 450ae36645aa29099c5a318995287df9bbc6c1d4..cf1120abbf521f4c819ff2ab0318cdfaf86515e9 100644 (file)
@@ -522,6 +522,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
                .name = "Avoton SoC",
                .iTCO_version = 3,
                .gpio_version = AVOTON_GPIO,
+               .spi_type = INTEL_SPI_BYT,
        },
        [LPC_BAYTRAIL] = {
                .name = "Bay Trail SoC",
index 662ae0d9e33497e2eac861de437386009315a335..1c05ea0cba6152f79abd61a4e3d3bf1c7d791c6f 100644 (file)
@@ -48,7 +48,10 @@ static const struct mfd_cell max77693_devs[] = {
                .name = "max77693-charger",
                .of_compatible = "maxim,max77693-charger",
        },
-       { .name = "max77693-muic", },
+       {
+               .name = "max77693-muic",
+               .of_compatible = "maxim,max77693-muic",
+       },
        {
                .name = "max77693-haptic",
                .of_compatible = "maxim,max77693-haptic",
index 630bd19b2c0a57949853d89cdcead69ded46c095..98e732a7ae96f02b3d0b7f825a9bd3e3a3931cbe 100644 (file)
@@ -196,8 +196,10 @@ static int mxs_lradc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, lradc);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENOMEM;
+       if (!res) {
+               ret = -ENOMEM;
+               goto err_clk;
+       }
 
        switch (lradc->soc) {
        case IMX23_LRADC:
index 40f8bb14fc59720906a6ad4d2e65edc0b5c40d4e..7fcf37ba922c704f50f6c24b056f97eac5c19382 100644 (file)
@@ -103,8 +103,64 @@ static void rtsx_base_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
        rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
 }
 
+static void rts5249_init_from_cfg(struct rtsx_pcr *pcr)
+{
+       struct rtsx_cr_option *option = &(pcr->option);
+       u32 lval;
+
+       if (CHK_PCI_PID(pcr, PID_524A))
+               rtsx_pci_read_config_dword(pcr,
+                       PCR_ASPM_SETTING_REG1, &lval);
+       else
+               rtsx_pci_read_config_dword(pcr,
+                       PCR_ASPM_SETTING_REG2, &lval);
+
+       if (lval & ASPM_L1_1_EN_MASK)
+               rtsx_set_dev_flag(pcr, ASPM_L1_1_EN);
+
+       if (lval & ASPM_L1_2_EN_MASK)
+               rtsx_set_dev_flag(pcr, ASPM_L1_2_EN);
+
+       if (lval & PM_L1_1_EN_MASK)
+               rtsx_set_dev_flag(pcr, PM_L1_1_EN);
+
+       if (lval & PM_L1_2_EN_MASK)
+               rtsx_set_dev_flag(pcr, PM_L1_2_EN);
+
+       if (option->ltr_en) {
+               u16 val;
+
+               pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &val);
+               if (val & PCI_EXP_DEVCTL2_LTR_EN) {
+                       option->ltr_enabled = true;
+                       option->ltr_active = true;
+                       rtsx_set_ltr_latency(pcr, option->ltr_active_latency);
+               } else {
+                       option->ltr_enabled = false;
+               }
+       }
+}
+
+static int rts5249_init_from_hw(struct rtsx_pcr *pcr)
+{
+       struct rtsx_cr_option *option = &(pcr->option);
+
+       if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
+                               | PM_L1_1_EN | PM_L1_2_EN))
+               option->force_clkreq_0 = false;
+       else
+               option->force_clkreq_0 = true;
+
+       return 0;
+}
+
 static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
 {
+       struct rtsx_cr_option *option = &(pcr->option);
+
+       rts5249_init_from_cfg(pcr);
+       rts5249_init_from_hw(pcr);
+
        rtsx_pci_init_cmd(pcr);
 
        /* Rest L1SUB Config */
@@ -125,7 +181,18 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
        else
                rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0x80);
 
-       return rtsx_pci_send_cmd(pcr, 100);
+       /*
+        * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
+        * to drive low, and we forcibly request clock.
+        */
+       if (option->force_clkreq_0)
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,
+                       FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
+       else
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,
+                       FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
+
+       return rtsx_pci_send_cmd(pcr, CMD_TIMEOUT_DEF);
 }
 
 static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
@@ -285,6 +352,31 @@ static int rtsx_base_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
        return rtsx_pci_send_cmd(pcr, 100);
 }
 
+static void rts5249_set_aspm(struct rtsx_pcr *pcr, bool enable)
+{
+       struct rtsx_cr_option *option = &pcr->option;
+       u8 val = 0;
+
+       if (pcr->aspm_enabled == enable)
+               return;
+
+       if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) {
+               if (enable)
+                       val = pcr->aspm_en;
+               rtsx_pci_update_cfg_byte(pcr,
+                       pcr->pcie_cap + PCI_EXP_LNKCTL,
+                       ASPM_MASK_NEG, val);
+       } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) {
+               u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0;
+
+               if (!enable)
+                       val = FORCE_ASPM_CTL0;
+               rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val);
+       }
+
+       pcr->aspm_enabled = enable;
+}
+
 static const struct pcr_ops rts5249_pcr_ops = {
        .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
        .extra_init_hw = rts5249_extra_init_hw,
@@ -297,6 +389,7 @@ static const struct pcr_ops rts5249_pcr_ops = {
        .card_power_off = rtsx_base_card_power_off,
        .switch_output_voltage = rtsx_base_switch_output_voltage,
        .force_power_down = rtsx_base_force_power_down,
+       .set_aspm = rts5249_set_aspm,
 };
 
 /* SD Pull Control Enable:
@@ -353,6 +446,8 @@ static const u32 rts5249_ms_pull_ctl_disable_tbl[] = {
 
 void rts5249_init_params(struct rtsx_pcr *pcr)
 {
+       struct rtsx_cr_option *option = &(pcr->option);
+
        pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
        pcr->num_slots = 2;
        pcr->ops = &rts5249_pcr_ops;
@@ -372,6 +467,20 @@ void rts5249_init_params(struct rtsx_pcr *pcr)
        pcr->ms_pull_ctl_disable_tbl = rts5249_ms_pull_ctl_disable_tbl;
 
        pcr->reg_pm_ctrl3 = PM_CTRL3;
+
+       option->dev_flags = (LTR_L1SS_PWR_GATE_CHECK_CARD_EN
+                               | LTR_L1SS_PWR_GATE_EN);
+       option->ltr_en = true;
+
+       /* Init latency of active, idle, L1OFF to 60us, 300us, 3ms */
+       option->ltr_active_latency = LTR_ACTIVE_LATENCY_DEF;
+       option->ltr_idle_latency = LTR_IDLE_LATENCY_DEF;
+       option->ltr_l1off_latency = LTR_L1OFF_LATENCY_DEF;
+       option->dev_aspm_mode = DEV_ASPM_DYNAMIC;
+       option->l1_snooze_delay = L1_SNOOZE_DELAY_DEF;
+       option->ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5249_DEF;
+       option->ltr_l1off_snooze_sspwrgate =
+               LTR_L1OFF_SNOOZE_SSPWRGATE_5249_DEF;
 }
 
 static int rts524a_write_phy(struct rtsx_pcr *pcr, u8 addr, u16 val)
@@ -459,6 +568,40 @@ static int rts524a_extra_init_hw(struct rtsx_pcr *pcr)
        return 0;
 }
 
+static void rts5250_set_l1off_cfg_sub_d0(struct rtsx_pcr *pcr, int active)
+{
+       struct rtsx_cr_option *option = &(pcr->option);
+
+       u32 interrupt = rtsx_pci_readl(pcr, RTSX_BIPR);
+       int card_exist = (interrupt & SD_EXIST) | (interrupt & MS_EXIST);
+       int aspm_L1_1, aspm_L1_2;
+       u8 val = 0;
+
+       aspm_L1_1 = rtsx_check_dev_flag(pcr, ASPM_L1_1_EN);
+       aspm_L1_2 = rtsx_check_dev_flag(pcr, ASPM_L1_2_EN);
+
+       if (active) {
+               /* Run, latency: 60us */
+               if (aspm_L1_1)
+                       val = option->ltr_l1off_snooze_sspwrgate;
+       } else {
+               /* L1off, latency: 300us */
+               if (aspm_L1_2)
+                       val = option->ltr_l1off_sspwrgate;
+       }
+
+       if (aspm_L1_1 || aspm_L1_2) {
+               if (rtsx_check_dev_flag(pcr,
+                                       LTR_L1SS_PWR_GATE_CHECK_CARD_EN)) {
+                       if (card_exist)
+                               val &= ~L1OFF_MBIAS2_EN_5250;
+                       else
+                               val |= L1OFF_MBIAS2_EN_5250;
+               }
+       }
+       rtsx_set_l1off_sub(pcr, val);
+}
+
 static const struct pcr_ops rts524a_pcr_ops = {
        .write_phy = rts524a_write_phy,
        .read_phy = rts524a_read_phy,
@@ -473,11 +616,16 @@ static const struct pcr_ops rts524a_pcr_ops = {
        .card_power_off = rtsx_base_card_power_off,
        .switch_output_voltage = rtsx_base_switch_output_voltage,
        .force_power_down = rtsx_base_force_power_down,
+       .set_l1off_cfg_sub_d0 = rts5250_set_l1off_cfg_sub_d0,
+       .set_aspm = rts5249_set_aspm,
 };
 
 void rts524a_init_params(struct rtsx_pcr *pcr)
 {
        rts5249_init_params(pcr);
+       pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF;
+       pcr->option.ltr_l1off_snooze_sspwrgate =
+               LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF;
 
        pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3;
        pcr->ops = &rts524a_pcr_ops;
@@ -576,11 +724,16 @@ static const struct pcr_ops rts525a_pcr_ops = {
        .card_power_off = rtsx_base_card_power_off,
        .switch_output_voltage = rts525a_switch_output_voltage,
        .force_power_down = rtsx_base_force_power_down,
+       .set_l1off_cfg_sub_d0 = rts5250_set_l1off_cfg_sub_d0,
+       .set_aspm = rts5249_set_aspm,
 };
 
 void rts525a_init_params(struct rtsx_pcr *pcr)
 {
        rts5249_init_params(pcr);
+       pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF;
+       pcr->option.ltr_l1off_snooze_sspwrgate =
+               LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF;
 
        pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3;
        pcr->ops = &rts525a_pcr_ops;
index 3cf69e5c570354fe50bdd534c099728096c054e0..590fb9aad77d9a690d6948d61715f04af0a43cd9 100644 (file)
@@ -79,6 +79,96 @@ static inline void rtsx_pci_disable_aspm(struct rtsx_pcr *pcr)
                0xFC, 0);
 }
 
+int rtsx_comm_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency)
+{
+       rtsx_pci_write_register(pcr, MSGTXDATA0,
+                               MASK_8_BIT_DEF, (u8) (latency & 0xFF));
+       rtsx_pci_write_register(pcr, MSGTXDATA1,
+                               MASK_8_BIT_DEF, (u8)((latency >> 8) & 0xFF));
+       rtsx_pci_write_register(pcr, MSGTXDATA2,
+                               MASK_8_BIT_DEF, (u8)((latency >> 16) & 0xFF));
+       rtsx_pci_write_register(pcr, MSGTXDATA3,
+                               MASK_8_BIT_DEF, (u8)((latency >> 24) & 0xFF));
+       rtsx_pci_write_register(pcr, LTR_CTL, LTR_TX_EN_MASK |
+               LTR_LATENCY_MODE_MASK, LTR_TX_EN_1 | LTR_LATENCY_MODE_SW);
+
+       return 0;
+}
+
+int rtsx_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency)
+{
+       if (pcr->ops->set_ltr_latency)
+               return pcr->ops->set_ltr_latency(pcr, latency);
+       else
+               return rtsx_comm_set_ltr_latency(pcr, latency);
+}
+
+static void rtsx_comm_set_aspm(struct rtsx_pcr *pcr, bool enable)
+{
+       struct rtsx_cr_option *option = &pcr->option;
+
+       if (pcr->aspm_enabled == enable)
+               return;
+
+       if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) {
+               if (enable)
+                       rtsx_pci_enable_aspm(pcr);
+               else
+                       rtsx_pci_disable_aspm(pcr);
+       } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) {
+               u8 mask = FORCE_ASPM_VAL_MASK;
+               u8 val = 0;
+
+               if (enable)
+                       val = pcr->aspm_en;
+               rtsx_pci_write_register(pcr, ASPM_FORCE_CTL,  mask, val);
+       }
+
+       pcr->aspm_enabled = enable;
+}
+
+static void rtsx_disable_aspm(struct rtsx_pcr *pcr)
+{
+       if (pcr->ops->set_aspm)
+               pcr->ops->set_aspm(pcr, false);
+       else
+               rtsx_comm_set_aspm(pcr, false);
+}
+
+int rtsx_set_l1off_sub(struct rtsx_pcr *pcr, u8 val)
+{
+       rtsx_pci_write_register(pcr, L1SUB_CONFIG3, 0xFF, val);
+
+       return 0;
+}
+
+void rtsx_set_l1off_sub_cfg_d0(struct rtsx_pcr *pcr, int active)
+{
+       if (pcr->ops->set_l1off_cfg_sub_d0)
+               pcr->ops->set_l1off_cfg_sub_d0(pcr, active);
+}
+
+static void rtsx_comm_pm_full_on(struct rtsx_pcr *pcr)
+{
+       struct rtsx_cr_option *option = &pcr->option;
+
+       rtsx_disable_aspm(pcr);
+
+       if (option->ltr_enabled)
+               rtsx_set_ltr_latency(pcr, option->ltr_active_latency);
+
+       if (rtsx_check_dev_flag(pcr, LTR_L1SS_PWR_GATE_EN))
+               rtsx_set_l1off_sub_cfg_d0(pcr, 1);
+}
+
+void rtsx_pm_full_on(struct rtsx_pcr *pcr)
+{
+       if (pcr->ops->full_on)
+               pcr->ops->full_on(pcr);
+       else
+               rtsx_comm_pm_full_on(pcr);
+}
+
 void rtsx_pci_start_run(struct rtsx_pcr *pcr)
 {
        /* If pci device removed, don't queue idle work any more */
@@ -89,9 +179,7 @@ void rtsx_pci_start_run(struct rtsx_pcr *pcr)
                pcr->state = PDEV_STAT_RUN;
                if (pcr->ops->enable_auto_blink)
                        pcr->ops->enable_auto_blink(pcr);
-
-               if (pcr->aspm_en)
-                       rtsx_pci_disable_aspm(pcr);
+               rtsx_pm_full_on(pcr);
        }
 
        mod_delayed_work(system_wq, &pcr->idle_work, msecs_to_jiffies(200));
@@ -958,6 +1046,41 @@ static int rtsx_pci_acquire_irq(struct rtsx_pcr *pcr)
        return 0;
 }
 
+static void rtsx_enable_aspm(struct rtsx_pcr *pcr)
+{
+       if (pcr->ops->set_aspm)
+               pcr->ops->set_aspm(pcr, true);
+       else
+               rtsx_comm_set_aspm(pcr, true);
+}
+
+static void rtsx_comm_pm_power_saving(struct rtsx_pcr *pcr)
+{
+       struct rtsx_cr_option *option = &pcr->option;
+
+       if (option->ltr_enabled) {
+               u32 latency = option->ltr_l1off_latency;
+
+               if (rtsx_check_dev_flag(pcr, L1_SNOOZE_TEST_EN))
+                       mdelay(option->l1_snooze_delay);
+
+               rtsx_set_ltr_latency(pcr, latency);
+       }
+
+       if (rtsx_check_dev_flag(pcr, LTR_L1SS_PWR_GATE_EN))
+               rtsx_set_l1off_sub_cfg_d0(pcr, 0);
+
+       rtsx_enable_aspm(pcr);
+}
+
+void rtsx_pm_power_saving(struct rtsx_pcr *pcr)
+{
+       if (pcr->ops->power_saving)
+               pcr->ops->power_saving(pcr);
+       else
+               rtsx_comm_pm_power_saving(pcr);
+}
+
 static void rtsx_pci_idle_work(struct work_struct *work)
 {
        struct delayed_work *dwork = to_delayed_work(work);
@@ -974,8 +1097,7 @@ static void rtsx_pci_idle_work(struct work_struct *work)
        if (pcr->ops->turn_off_led)
                pcr->ops->turn_off_led(pcr);
 
-       if (pcr->aspm_en)
-               rtsx_pci_enable_aspm(pcr);
+       rtsx_pm_power_saving(pcr);
 
        mutex_unlock(&pcr->pcr_mutex);
 }
@@ -1063,6 +1185,16 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
        if (err < 0)
                return err;
 
+       switch (PCI_PID(pcr)) {
+       case PID_5250:
+       case PID_524A:
+       case PID_525A:
+               rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 1, 1);
+               break;
+       default:
+               break;
+       }
+
        /* Enable clk_request_n to enable clock power management */
        rtsx_pci_write_config_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL + 1, 1);
        /* Enter L1 when host tx idle */
index 931d1ae3ce32b726d015cf5de5b9aa820da40ff6..ec784e04fe203d1f5ca242df16f522ee709219c2 100644 (file)
 #define RTS524A_PME_FORCE_CTL          0xFF78
 #define RTS524A_PM_CTRL3               0xFF7E
 
+#define LTR_ACTIVE_LATENCY_DEF         0x883C
+#define LTR_IDLE_LATENCY_DEF           0x892C
+#define LTR_L1OFF_LATENCY_DEF          0x9003
+#define L1_SNOOZE_DELAY_DEF            1
+#define LTR_L1OFF_SSPWRGATE_5249_DEF           0xAF
+#define LTR_L1OFF_SSPWRGATE_5250_DEF           0xFF
+#define LTR_L1OFF_SNOOZE_SSPWRGATE_5249_DEF    0xAC
+#define LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF    0xF8
+#define CMD_TIMEOUT_DEF                100
+#define ASPM_MASK_NEG          0xFC
+#define MASK_8_BIT_DEF         0xFF
+
 int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val);
 int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val);
 
@@ -85,5 +97,7 @@ do {                                                                  \
 
 /* generic operations */
 int rtsx_gops_pm_reset(struct rtsx_pcr *pcr);
+int rtsx_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency);
+int rtsx_set_l1off_sub(struct rtsx_pcr *pcr, u8 val);
 
 #endif
diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c
new file mode 100644 (file)
index 0000000..56a4782
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2017 Spreadtrum Communications Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/core.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#define SPRD_PMIC_INT_MASK_STATUS      0x0
+#define SPRD_PMIC_INT_RAW_STATUS       0x4
+#define SPRD_PMIC_INT_EN               0x8
+
+#define SPRD_SC2731_IRQ_BASE           0x140
+#define SPRD_SC2731_IRQ_NUMS           16
+
+struct sprd_pmic {
+       struct regmap *regmap;
+       struct device *dev;
+       struct regmap_irq *irqs;
+       struct regmap_irq_chip irq_chip;
+       struct regmap_irq_chip_data *irq_data;
+       int irq;
+};
+
+struct sprd_pmic_data {
+       u32 irq_base;
+       u32 num_irqs;
+};
+
+/*
+ * Since different PMICs of SC27xx series can have different interrupt
+ * base address and irq number, we should save irq number and irq base
+ * in the device data structure.
+ */
+static const struct sprd_pmic_data sc2731_data = {
+       .irq_base = SPRD_SC2731_IRQ_BASE,
+       .num_irqs = SPRD_SC2731_IRQ_NUMS,
+};
+
+static const struct mfd_cell sprd_pmic_devs[] = {
+       {
+               .name = "sc27xx-wdt",
+               .of_compatible = "sprd,sc27xx-wdt",
+       }, {
+               .name = "sc27xx-rtc",
+               .of_compatible = "sprd,sc27xx-rtc",
+       }, {
+               .name = "sc27xx-charger",
+               .of_compatible = "sprd,sc27xx-charger",
+       }, {
+               .name = "sc27xx-chg-timer",
+               .of_compatible = "sprd,sc27xx-chg-timer",
+       }, {
+               .name = "sc27xx-fast-chg",
+               .of_compatible = "sprd,sc27xx-fast-chg",
+       }, {
+               .name = "sc27xx-chg-wdt",
+               .of_compatible = "sprd,sc27xx-chg-wdt",
+       }, {
+               .name = "sc27xx-typec",
+               .of_compatible = "sprd,sc27xx-typec",
+       }, {
+               .name = "sc27xx-flash",
+               .of_compatible = "sprd,sc27xx-flash",
+       }, {
+               .name = "sc27xx-eic",
+               .of_compatible = "sprd,sc27xx-eic",
+       }, {
+               .name = "sc27xx-efuse",
+               .of_compatible = "sprd,sc27xx-efuse",
+       }, {
+               .name = "sc27xx-thermal",
+               .of_compatible = "sprd,sc27xx-thermal",
+       }, {
+               .name = "sc27xx-adc",
+               .of_compatible = "sprd,sc27xx-adc",
+       }, {
+               .name = "sc27xx-audio-codec",
+               .of_compatible = "sprd,sc27xx-audio-codec",
+       }, {
+               .name = "sc27xx-regulator",
+               .of_compatible = "sprd,sc27xx-regulator",
+       }, {
+               .name = "sc27xx-vibrator",
+               .of_compatible = "sprd,sc27xx-vibrator",
+       }, {
+               .name = "sc27xx-keypad-led",
+               .of_compatible = "sprd,sc27xx-keypad-led",
+       }, {
+               .name = "sc27xx-bltc",
+               .of_compatible = "sprd,sc27xx-bltc",
+       }, {
+               .name = "sc27xx-fgu",
+               .of_compatible = "sprd,sc27xx-fgu",
+       }, {
+               .name = "sc27xx-7sreset",
+               .of_compatible = "sprd,sc27xx-7sreset",
+       }, {
+               .name = "sc27xx-poweroff",
+               .of_compatible = "sprd,sc27xx-poweroff",
+       },
+};
+
+static int sprd_pmic_spi_write(void *context, const void *data, size_t count)
+{
+       struct device *dev = context;
+       struct spi_device *spi = to_spi_device(dev);
+
+       return spi_write(spi, data, count);
+}
+
+static int sprd_pmic_spi_read(void *context,
+                             const void *reg, size_t reg_size,
+                             void *val, size_t val_size)
+{
+       struct device *dev = context;
+       struct spi_device *spi = to_spi_device(dev);
+       u32 rx_buf[2] = { 0 };
+       int ret;
+
+       /* Now we only support one PMIC register to read every time. */
+       if (reg_size != sizeof(u32) || val_size != sizeof(u32))
+               return -EINVAL;
+
+       /* Copy address to read from into first element of SPI buffer. */
+       memcpy(rx_buf, reg, sizeof(u32));
+       ret = spi_read(spi, rx_buf, 1);
+       if (ret < 0)
+               return ret;
+
+       memcpy(val, rx_buf, val_size);
+       return 0;
+}
+
+static struct regmap_bus sprd_pmic_regmap = {
+       .write = sprd_pmic_spi_write,
+       .read = sprd_pmic_spi_read,
+       .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+       .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+static const struct regmap_config sprd_pmic_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+       .max_register = 0xffff,
+};
+
+static int sprd_pmic_probe(struct spi_device *spi)
+{
+       struct sprd_pmic *ddata;
+       const struct sprd_pmic_data *pdata;
+       int ret, i;
+
+       pdata = of_device_get_match_data(&spi->dev);
+       if (!pdata) {
+               dev_err(&spi->dev, "No matching driver data found\n");
+               return -EINVAL;
+       }
+
+       ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
+       if (!ddata)
+               return -ENOMEM;
+
+       ddata->regmap = devm_regmap_init(&spi->dev, &sprd_pmic_regmap,
+                                        &spi->dev, &sprd_pmic_config);
+       if (IS_ERR(ddata->regmap)) {
+               ret = PTR_ERR(ddata->regmap);
+               dev_err(&spi->dev, "Failed to allocate register map %d\n", ret);
+               return ret;
+       }
+
+       spi_set_drvdata(spi, ddata);
+       ddata->dev = &spi->dev;
+       ddata->irq = spi->irq;
+
+       ddata->irq_chip.name = dev_name(&spi->dev);
+       ddata->irq_chip.status_base =
+               pdata->irq_base + SPRD_PMIC_INT_MASK_STATUS;
+       ddata->irq_chip.mask_base = pdata->irq_base + SPRD_PMIC_INT_EN;
+       ddata->irq_chip.ack_base = 0;
+       ddata->irq_chip.num_regs = 1;
+       ddata->irq_chip.num_irqs = pdata->num_irqs;
+       ddata->irq_chip.mask_invert = true;
+
+       ddata->irqs = devm_kzalloc(&spi->dev, sizeof(struct regmap_irq) *
+                                  pdata->num_irqs, GFP_KERNEL);
+       if (!ddata->irqs)
+               return -ENOMEM;
+
+       ddata->irq_chip.irqs = ddata->irqs;
+       for (i = 0; i < pdata->num_irqs; i++) {
+               ddata->irqs[i].reg_offset = i / pdata->num_irqs;
+               ddata->irqs[i].mask = BIT(i % pdata->num_irqs);
+       }
+
+       ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq,
+                                      IRQF_ONESHOT | IRQF_NO_SUSPEND, 0,
+                                      &ddata->irq_chip, &ddata->irq_data);
+       if (ret) {
+               dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret);
+               return ret;
+       }
+
+       ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO,
+                                  sprd_pmic_devs, ARRAY_SIZE(sprd_pmic_devs),
+                                  NULL, 0,
+                                  regmap_irq_get_domain(ddata->irq_data));
+       if (ret) {
+               dev_err(&spi->dev, "Failed to register device %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct of_device_id sprd_pmic_match[] = {
+       { .compatible = "sprd,sc2731", .data = &sc2731_data },
+       {},
+};
+MODULE_DEVICE_TABLE(of, sprd_pmic_match);
+
+static struct spi_driver sprd_pmic_driver = {
+       .driver = {
+               .name = "sc27xx-pmic",
+               .bus = &spi_bus_type,
+               .of_match_table = sprd_pmic_match,
+       },
+       .probe = sprd_pmic_probe,
+};
+
+static int __init sprd_pmic_init(void)
+{
+       return spi_register_driver(&sprd_pmic_driver);
+}
+subsys_initcall(sprd_pmic_init);
+
+static void __exit sprd_pmic_exit(void)
+{
+       spi_unregister_driver(&sprd_pmic_driver);
+}
+module_exit(sprd_pmic_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Spreadtrum SC27xx PMICs driver");
+MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>");
index 27986f641f7dbddabaa2cfdeca42c3ac038ba219..36b96fee4ce60c2ba4199413319064917eb1d390 100644 (file)
@@ -314,7 +314,7 @@ static int ssbi_probe(struct platform_device *pdev)
 
        spin_lock_init(&ssbi->lock);
 
-       return of_platform_populate(np, NULL, NULL, &pdev->dev);
+       return devm_of_platform_populate(&pdev->dev);
 }
 
 static const struct of_device_id ssbi_match_table[] = {
index ab949eaca6ad82edee77c443efb220c6a81b8a23..3cc80956260e4d180fd0b840cf8b680e400124b2 100644 (file)
@@ -72,10 +72,12 @@ static int stw481x_get_pctl_reg(struct stw481x *stw481x, u8 reg)
 static int stw481x_startup(struct stw481x *stw481x)
 {
        /* Voltages multiplied by 100 */
-       u8 vcore_val[] = { 100, 105, 110, 115, 120, 122, 124, 126, 128,
-                          130, 132, 134, 136, 138, 140, 145 };
-       u8 vpll_val[] = { 105, 120, 130, 180 };
-       u8 vaux_val[] = { 15, 18, 25, 28 };
+       static const u8 vcore_val[] = {
+               100, 105, 110, 115, 120, 122, 124, 126, 128,
+               130, 132, 134, 136, 138, 140, 145
+       };
+       static const u8 vpll_val[] = { 105, 120, 130, 180 };
+       static const u8 vaux_val[] = { 15, 18, 25, 28 };
        u8 vcore;
        u8 vcore_slp;
        u8 vpll;
index f769c7d4e335ac20da4db26ae5d7eb024d0b9987..7566ce4457a0167073826881954aec491fca6c34 100644 (file)
@@ -311,37 +311,20 @@ static const struct regmap_config tps65217_regmap_config = {
 };
 
 static const struct of_device_id tps65217_of_match[] = {
-       { .compatible = "ti,tps65217", .data = (void *)TPS65217 },
+       { .compatible = "ti,tps65217"},
        { /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, tps65217_of_match);
 
-static int tps65217_probe(struct i2c_client *client,
-                               const struct i2c_device_id *ids)
+static int tps65217_probe(struct i2c_client *client)
 {
        struct tps65217 *tps;
        unsigned int version;
-       unsigned long chip_id = ids->driver_data;
-       const struct of_device_id *match;
        bool status_off = false;
        int ret;
 
-       if (client->dev.of_node) {
-               match = of_match_device(tps65217_of_match, &client->dev);
-               if (!match) {
-                       dev_err(&client->dev,
-                               "Failed to find matching dt id\n");
-                       return -EINVAL;
-               }
-               chip_id = (unsigned long)match->data;
-               status_off = of_property_read_bool(client->dev.of_node,
-                                       "ti,pmic-shutdown-controller");
-       }
-
-       if (!chip_id) {
-               dev_err(&client->dev, "id is null.\n");
-               return -ENODEV;
-       }
+       status_off = of_property_read_bool(client->dev.of_node,
+                                          "ti,pmic-shutdown-controller");
 
        tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
        if (!tps)
@@ -349,7 +332,6 @@ static int tps65217_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, tps);
        tps->dev = &client->dev;
-       tps->id = chip_id;
 
        tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config);
        if (IS_ERR(tps->regmap)) {
@@ -430,7 +412,7 @@ static struct i2c_driver tps65217_driver = {
                .of_match_table = tps65217_of_match,
        },
        .id_table       = tps65217_id_table,
-       .probe          = tps65217_probe,
+       .probe_new      = tps65217_probe,
        .remove         = tps65217_remove,
 };
 
index 13834a0d28172fe5334f0385571fafb34cc21248..910f569ff77c1b7313c4c03c6d3a57b92f6c73b4 100644 (file)
@@ -215,17 +215,9 @@ static int tps65218_probe(struct i2c_client *client,
                                const struct i2c_device_id *ids)
 {
        struct tps65218 *tps;
-       const struct of_device_id *match;
        int ret;
        unsigned int chipid;
 
-       match = of_match_device(of_tps65218_match_table, &client->dev);
-       if (!match) {
-               dev_err(&client->dev,
-                       "Failed to find matching dt id\n");
-               return -EINVAL;
-       }
-
        tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
        if (!tps)
                return -ENOMEM;
index 5324dc9e6d6e67d763f4f65c9532fe39f2fd0a0c..7b12e880d1eae0d4f332119d82e510a643dc89e5 100644 (file)
@@ -228,11 +228,6 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
        int i, ret;
        unsigned int val;
 
-       if (tps65217_chip_id(tps) != TPS65217) {
-               dev_err(&pdev->dev, "Invalid tps chip version\n");
-               return -ENODEV;
-       }
-
        /* Allocate memory for strobes */
        tps->strobes = devm_kzalloc(&pdev->dev, sizeof(u8) *
                                    TPS65217_NUM_REGULATOR, GFP_KERNEL);
index fd524ad860a57bd4ac11166eeef278ef306358a4..5ce8791f45231b7547379a937c569bc64e875878 100644 (file)
@@ -275,17 +275,9 @@ static int tps65217_bl_probe(struct platform_device *pdev)
        struct tps65217_bl_pdata *pdata;
        struct backlight_properties bl_props;
 
-       if (tps->dev->of_node) {
-               pdata = tps65217_bl_parse_dt(pdev);
-               if (IS_ERR(pdata))
-                       return PTR_ERR(pdata);
-       } else {
-               pdata = dev_get_platdata(&pdev->dev);
-               if (!pdata) {
-                       dev_err(&pdev->dev, "no platform data provided\n");
-                       return -EINVAL;
-               }
-       }
+       pdata = tps65217_bl_parse_dt(pdev);
+       if (IS_ERR(pdata))
+               return PTR_ERR(pdata);
 
        tps65217_bl = devm_kzalloc(&pdev->dev, sizeof(*tps65217_bl),
                                GFP_KERNEL);
index 7815d8db7eca5a6b8f3b4fc7411f200d55b0e19c..a2a1318a3d0c8be0a1fb3d1a08fcf671ff9d8bee 100644 (file)
 #define MSGTXDATA3                     0xFE47
 #define MSGTXCTL                       0xFE48
 #define LTR_CTL                                0xFE4A
+#define LTR_TX_EN_MASK         BIT(7)
+#define LTR_TX_EN_1                    BIT(7)
+#define LTR_TX_EN_0                    0
+#define LTR_LATENCY_MODE_MASK          BIT(6)
+#define LTR_LATENCY_MODE_HW            0
+#define LTR_LATENCY_MODE_SW            BIT(6)
 #define OBFF_CFG                       0xFE4C
 
 #define CDRESUMECTL                    0xFE52
 #define L1SUB_CONFIG2                  0xFE8E
 #define   L1SUB_AUTO_CFG               0x02
 #define L1SUB_CONFIG3                  0xFE8F
+#define   L1OFF_MBIAS2_EN_5250         BIT(7)
 
 #define DUMMY_REG_RESET_0              0xFE90
 
 #define AUTOLOAD_CFG_BASE              0xFF00
 #define PETXCFG                                0xFF03
+#define FORCE_CLKREQ_DELINK_MASK       BIT(7)
+#define FORCE_CLKREQ_LOW       0x80
+#define FORCE_CLKREQ_HIGH      0x00
 
 #define PM_CTRL1                       0xFF44
 #define   CD_RESUME_EN_MASK            0xF0
 #define   PHY_DIG1E_RX_EN_KEEP         0x0001
 #define PHY_DUM_REG                    0x1F
 
+#define PCR_ASPM_SETTING_REG1          0x160
+#define PCR_ASPM_SETTING_REG2          0x168
+
 #define PCR_SETTING_REG1               0x724
 #define PCR_SETTING_REG2               0x814
 #define PCR_SETTING_REG3               0x747
@@ -877,14 +890,79 @@ struct pcr_ops {
        int             (*conv_clk_and_div_n)(int clk, int dir);
        void            (*fetch_vendor_settings)(struct rtsx_pcr *pcr);
        void            (*force_power_down)(struct rtsx_pcr *pcr, u8 pm_state);
+
+       void (*set_aspm)(struct rtsx_pcr *pcr, bool enable);
+       int (*set_ltr_latency)(struct rtsx_pcr *pcr, u32 latency);
+       int (*set_l1off_sub)(struct rtsx_pcr *pcr, u8 val);
+       void (*set_l1off_cfg_sub_d0)(struct rtsx_pcr *pcr, int active);
+       void (*full_on)(struct rtsx_pcr *pcr);
+       void (*power_saving)(struct rtsx_pcr *pcr);
 };
 
 enum PDEV_STAT  {PDEV_STAT_IDLE, PDEV_STAT_RUN};
 
+#define ASPM_L1_1_EN_MASK              BIT(3)
+#define ASPM_L1_2_EN_MASK              BIT(2)
+#define PM_L1_1_EN_MASK                BIT(1)
+#define PM_L1_2_EN_MASK                BIT(0)
+
+#define ASPM_L1_1_EN                   BIT(0)
+#define ASPM_L1_2_EN                   BIT(1)
+#define PM_L1_1_EN                             BIT(2)
+#define PM_L1_2_EN                             BIT(3)
+#define LTR_L1SS_PWR_GATE_EN   BIT(4)
+#define L1_SNOOZE_TEST_EN              BIT(5)
+#define LTR_L1SS_PWR_GATE_CHECK_CARD_EN        BIT(6)
+
+enum dev_aspm_mode {
+       DEV_ASPM_DISABLE = 0,
+       DEV_ASPM_DYNAMIC,
+       DEV_ASPM_BACKDOOR,
+       DEV_ASPM_STATIC,
+};
+
+/*
+ * struct rtsx_cr_option  - card reader option
+ * @dev_flags: device flags
+ * @force_clkreq_0: force clock request
+ * @ltr_en: enable ltr mode flag
+ * @ltr_enabled: ltr mode in configure space flag
+ * @ltr_active: ltr mode status
+ * @ltr_active_latency: ltr mode active latency
+ * @ltr_idle_latency: ltr mode idle latency
+ * @ltr_l1off_latency: ltr mode l1off latency
+ * @dev_aspm_mode: device aspm mode
+ * @l1_snooze_delay: l1 snooze delay
+ * @ltr_l1off_sspwrgate: ltr l1off sspwrgate
+ * @ltr_l1off_snooze_sspwrgate: ltr l1off snooze sspwrgate
+ */
+struct rtsx_cr_option {
+       u32 dev_flags;
+       bool force_clkreq_0;
+       bool ltr_en;
+       bool ltr_enabled;
+       bool ltr_active;
+       u32 ltr_active_latency;
+       u32 ltr_idle_latency;
+       u32 ltr_l1off_latency;
+       enum dev_aspm_mode dev_aspm_mode;
+       u32 l1_snooze_delay;
+       u8 ltr_l1off_sspwrgate;
+       u8 ltr_l1off_snooze_sspwrgate;
+};
+
+#define rtsx_set_dev_flag(cr, flag) \
+       ((cr)->option.dev_flags |= (flag))
+#define rtsx_clear_dev_flag(cr, flag) \
+       ((cr)->option.dev_flags &= ~(flag))
+#define rtsx_check_dev_flag(cr, flag) \
+       ((cr)->option.dev_flags & (flag))
+
 struct rtsx_pcr {
        struct pci_dev                  *pci;
        unsigned int                    id;
        int                             pcie_cap;
+       struct rtsx_cr_option   option;
 
        /* pci resources */
        unsigned long                   addr;
@@ -941,6 +1019,7 @@ struct rtsx_pcr {
        u8                              card_drive_sel;
 #define ASPM_L1_EN                     0x02
        u8                              aspm_en;
+       bool                            aspm_enabled;
 
 #define PCR_MS_PMOS                    (1 << 0)
 #define PCR_REVERSE_SOCKET             (1 << 1)
@@ -965,6 +1044,11 @@ struct rtsx_pcr {
        u8                              dma_error_count;
 };
 
+#define PID_524A       0x524A
+#define PID_5249               0x5249
+#define PID_5250               0x5250
+#define PID_525A       0x525A
+
 #define CHK_PCI_PID(pcr, pid)          ((pcr)->pci->device == (pid))
 #define PCI_VID(pcr)                   ((pcr)->pci->vendor)
 #define PCI_PID(pcr)                   ((pcr)->pci->device)
index eac285756b37a918c1bfb11845b2a160f559618f..b5dd108421c8d876b7e55f7f85a17f77b0c37416 100644 (file)
@@ -263,7 +263,6 @@ struct tps65217_board {
 struct tps65217 {
        struct device *dev;
        struct tps65217_board *pdata;
-       unsigned long id;
        struct regulator_desc desc[TPS65217_NUM_REGULATOR];
        struct regmap *regmap;
        u8 *strobes;
@@ -278,11 +277,6 @@ static inline struct tps65217 *dev_to_tps65217(struct device *dev)
        return dev_get_drvdata(dev);
 }
 
-static inline unsigned long tps65217_chip_id(struct tps65217 *tps65217)
-{
-       return tps65217->id;
-}
-
 int tps65217_reg_read(struct tps65217 *tps, unsigned int reg,
                                        unsigned int *val);
 int tps65217_reg_write(struct tps65217 *tps, unsigned int reg,