forked from Minki/linux
- 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 -----BEGIN PGP SIGNATURE----- iQIcBAABCAAGBQJaDaBsAAoJEFGvii+H/HdhfGUP/itBfs94YdkUeDFyWzfbg6ib X1t+3mXhPQiVAt91EBwl6JD7FQgdqoB/g4pNf937bFQ+Rm8Sd4R/a5J1KQ8Zta4H QaMmlhi6Fy5NWh2gmjuC3KoGOeXz9zAaaDH3SeAs98XCN55Akf6Tt1Us2Wp9VHkq PoMfwZXlqb4KggvEaraQS4QvTVXuKIoq49LmqUMxBhInMwoT9qwiI/PSWDfirzQk TLA3LOEjLpRKZQuHR+kovQOU2wnwmiOhBFuVuaYixPqDYFvm3/2KtuPKW79KzQPX vsi7/x4ShPB55extHPhuoRkjbp/7gvZQS2iW5NufJfrcu3m1kEnu5DLAB6e+4SHs ZE52MviFrCFoAXyXRvHBdzqgGKEzq2Jhlse4j+HRXVLOzIW8PzVM4MkZvfVFcqYx 4BQuxdM6+oUGAqeKlmydaMTng8o/UfRainQ1dIGAblk5DCR+SHxqt582f9qyLAhT 55OMFJG/bQ4cW86EXWtp+8DUA4Aoz5ZIJ+C5IrYKOA2ScQo//imoH5Hz1PH1m91O GebDdw7AijGLbSqXSu4aRfFe9+Whyo2387A+1Zd9zdfLyiOQ1n5ty6ClRsCfDJ8P K4ONmZL7H5n8I8j3eyivn+k1MelIdfG0hB8YS0NnYvR3pR9AY1NWCgO0f4rfyU9o whyvIqg22EepnbEJjjFv =LAK+ -----END PGP SIGNATURE----- Merge tag 'mfd-next-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd 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 ...
This commit is contained in:
commit
d3092e4e99
@ -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>;
|
||||
};
|
||||
|
16
Documentation/devicetree/bindings/mfd/brcm,iproc-cdru.txt
Normal file
16
Documentation/devicetree/bindings/mfd/brcm,iproc-cdru.txt
Normal file
@ -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>;
|
||||
};
|
18
Documentation/devicetree/bindings/mfd/brcm,iproc-mhb.txt
Normal file
18
Documentation/devicetree/bindings/mfd/brcm,iproc-mhb.txt
Normal file
@ -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>;
|
||||
};
|
@ -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>
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
40
Documentation/devicetree/bindings/mfd/sprd,sc27xx-pmic.txt
Normal file
40
Documentation/devicetree/bindings/mfd/sprd,sc27xx-pmic.txt
Normal file
@ -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>;
|
||||
};
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
137
drivers/acpi/pmic/intel_pmic_chtdc_ti.c
Normal file
137
drivers/acpi/pmic/intel_pmic_chtdc_ti.c
Normal file
@ -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");
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
184
drivers/mfd/intel_soc_pmic_chtdc_ti.c
Normal file
184
drivers/mfd/intel_soc_pmic_chtdc_ti.c
Normal file
@ -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");
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -32,6 +32,18 @@
|
||||
#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
|
||||
|
259
drivers/mfd/sprd-sc27xx-spi.c
Normal file
259
drivers/mfd/sprd-sc27xx-spi.c
Normal file
@ -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>");
|
@ -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[] = {
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -574,6 +574,12 @@
|
||||
#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
|
||||
@ -617,11 +623,15 @@
|
||||
#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
|
||||
@ -845,6 +855,9 @@
|
||||
#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)
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user