Merge (most of) tag 'mfd-next-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd

Pull MFD updates from Lee Jones:
 "New Drivers:
   - Intel Cherry Trail Whiskey Cove PMIC
   - TI LP87565 PMIC

  New Device Support:
   - Add support for Cannonlake to intel-lpss-pci
   - Add support for Simatic IOT2000 to intel_quark_i2c_gpio

  New Functionality:
   - Add Regulator support (axp20x)

  Fix-ups:
   - Rework IRQ handling (intel_soc_pmic_bxtwc, rtsx_pcr, cros_ec)
   - Remove unused/unwelcome code (ipaq-micro, wm831x-core, da9062-core)
   - Provide deregistration on unbind (rn5t618)
   - Rework DT code/documentation (arizona)
   - Constify things (fsl-imx25-tsadc)
   - MAINTAINERS updates (DA9062/61)
   - Kconfig configuration adaptions (INTEL_SOC_PMIC, MFD_AXP20X_I2C)
   - Switch to DMI matching (intel_quark_i2c_gpio)
   - Provide an appropriate level of error checking (wm831x-{i2c,spi},
     twl4030-irq, tc6393xb)
   - Make use of devm_* (resource handling) calls (intel_soc_pmic_bxtwc,
     stm32-timers, atmel-flexcom, cros_ec, fsl-imx25-tsadc,
     exynos-lpass, palmas, qcom-spmi-pmic, smsc-ece1099,
     motorola-cpcap)"

[ Skipped the last commit in that series that added eight thousand
  lines of pointless repeated register definitions.  - Linus ]

* tag 'mfd-next-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (38 commits)
  mfd: Add LP87565 PMIC support
  mfd: cros_ec: Free IRQ on exit
  dt-bindings: vendor-prefixes: Add arctic to vendor prefix
  mfd: da9061: Fix to remove BBAT_CONT register from chip model
  mfd: da9061: Fix to remove BBAT_CONT register from chip model
  mfd: axp20x-i2c: Document that this must be builtin on x86
  mfd: Add Cherry Trail Whiskey Cove PMIC driver
  mfd: tc6393xb: Handle return value of clk_prepare_enable
  mfd: intel_quark_i2c_gpio: Add support for SIMATIC IOT2000 platform
  mfd: intel_quark_i2c_gpio: Use dmi_system_id table for retrieving frequency
  mfd: motorola-cpcap: Use devm_of_platform_populate()
  mfd: smsc-ece: Use devm_of_platform_populate()
  mfd: qcom-spmi-pmic: Use devm_of_platform_populate()
  mfd: palmas: Use devm_of_platform_populate()
  mfd: exynos: Use devm_of_platform_populate()
  mfd: fsl-imx25: Use devm_of_platform_populate()
  mfd: cros_ec: Use devm_of_platform_populate()
  mfd: atmel: Use devm_of_platform_populate()
  mfd: stm32-timers: Use devm_of_platform_populate()
  mfd: intel_soc_pmic: Select designware i2c-bus driver
  ...
This commit is contained in:
Linus Torvalds
2017-07-07 13:30:05 -07:00
37 changed files with 987 additions and 185 deletions
@@ -30,7 +30,8 @@ Required properties:
- gpio-controller : Indicates this device is a GPIO controller.
- #gpio-cells : Must be 2. The first cell is the pin number and the
second cell is used to specify optional parameters (currently unused).
second cell is used to specify optional parameters, see ../gpio/gpio.txt
for details.
- AVDD-supply, DBVDD1-supply, CPVDD-supply : Power supplies for the device,
as covered in Documentation/devicetree/bindings/regulator/regulator.txt
@@ -0,0 +1,43 @@
TI LP87565 PMIC MFD driver
Required properties:
- compatible: "ti,lp87565", "ti,lp87565-q1"
- reg: I2C slave address.
- gpio-controller: Marks the device node as a GPIO Controller.
- #gpio-cells: Should be two. The first cell is the pin number and
the second cell is used to specify flags.
See ../gpio/gpio.txt for more information.
- xxx-in-supply: Phandle to parent supply node of each regulator
populated under regulators node. xxx should match
the supply_name populated in driver.
Example:
lp87565_pmic: pmic@60 {
compatible = "ti,lp87565-q1";
reg = <0x60>;
gpio-controller;
#gpio-cells = <2>;
buck10-in-supply = <&vsys_3v3>;
buck23-in-supply = <&vsys_3v3>;
regulators: regulators {
buck10_reg: buck10 {
/* VDD_MPU */
regulator-name = "buck10";
regulator-min-microvolt = <850000>;
regulator-max-microvolt = <1250000>;
regulator-always-on;
regulator-boot-on;
};
buck23_reg: buck23 {
/* VDD_GPU */
regulator-name = "buck23";
regulator-min-microvolt = <850000>;
regulator-max-microvolt = <1250000>;
regulator-boot-on;
regulator-always-on;
};
};
};
@@ -29,6 +29,7 @@ andestech Andes Technology Corporation
apm Applied Micro Circuits Corporation (APM)
aptina Aptina Imaging
arasan Arasan Chip Systems
arctic Arctic Sand
aries Aries Embedded GmbH
arm ARM Ltd.
armadeus ARMadeus Systems SARL
+4
View File
@@ -4048,7 +4048,10 @@ W: http://www.dialog-semiconductor.com/products
S: Supported
F: Documentation/hwmon/da90??
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/sound/da[79]*.txt
F: drivers/gpio/gpio-da90??.c
F: drivers/hwmon/da90??-hwmon.c
@@ -4063,6 +4066,7 @@ F: drivers/power/supply/da9052-battery.c
F: drivers/power/supply/da91??-*.c
F: drivers/regulator/da903x.c
F: drivers/regulator/da9???-regulator.[ch]
F: drivers/thermal/da90??-thermal.c
F: drivers/rtc/rtc-da90??.c
F: drivers/video/backlight/da90??_bl.c
F: drivers/watchdog/da90??_wdt.c
+13 -1
View File
@@ -428,7 +428,7 @@ static int wcove_gpio_probe(struct platform_device *pdev)
if (!wg)
return -ENOMEM;
wg->regmap_irq_chip = pmic->irq_chip_data_level2;
wg->regmap_irq_chip = pmic->irq_chip_data;
platform_set_drvdata(pdev, wg);
@@ -476,6 +476,18 @@ static int wcove_gpio_probe(struct platform_device *pdev)
gpiochip_set_nested_irqchip(&wg->chip, &wcove_irqchip, virq);
/* Enable GPIO0 interrupts */
ret = regmap_update_bits(wg->regmap, IRQ_MASK_BASE, GPIO_IRQ0_MASK,
0x00);
if (ret)
return ret;
/* Enable GPIO1 interrupts */
ret = regmap_update_bits(wg->regmap, IRQ_MASK_BASE + 1, GPIO_IRQ1_MASK,
0x00);
if (ret)
return ret;
return 0;
}
+42 -2
View File
@@ -160,6 +160,11 @@ config MFD_AXP20X_I2C
components like regulators or the PEK (Power Enable Key) under the
corresponding menus.
Note on x86 this provides an ACPI OpRegion, so this must be 'y'
(builtin) and not a module, as the OpRegion must be available as
soon as possible. For the same reason the I2C bus driver options
I2C_DESIGNWARE_PLATFORM and I2C_DESIGNWARE_BAYTRAIL must be 'y' too.
config MFD_AXP20X_RSB
tristate "X-Powers AXP series PMICs with RSB"
select MFD_AXP20X
@@ -448,17 +453,22 @@ config LPC_SCH
config INTEL_SOC_PMIC
bool "Support for Crystal Cove PMIC"
depends on GPIOLIB
depends on I2C=y
depends on HAS_IOMEM && I2C=y && GPIOLIB && COMMON_CLK
depends on X86 || COMPILE_TEST
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
select I2C_DESIGNWARE_PLATFORM if ACPI
help
Select this option to enable support for Crystal Cove PMIC
on some Intel SoC systems. The PMIC provides ADC, GPIO,
thermal, charger and related power management functions
on these systems.
This option is a bool as it provides an ACPI OpRegion which must be
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_BXTWC
tristate "Support for Intel Broxton Whiskey Cove PMIC"
depends on INTEL_PMC_IPC
@@ -470,6 +480,22 @@ config INTEL_SOC_PMIC_BXTWC
thermal, charger and related power management functions
on these systems.
config INTEL_SOC_PMIC_CHTWC
tristate "Support for Intel Cherry Trail Whiskey Cove PMIC"
depends on ACPI && HAS_IOMEM && I2C=y && COMMON_CLK
depends on X86 || COMPILE_TEST
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
select I2C_DESIGNWARE_PLATFORM
help
Select this option to enable support for the Intel Cherry Trail
Whiskey Cove PMIC found on some Intel Cherry Trail systems.
This option is a bool as it provides an ACPI OpRegion which must be
available before any devices using it are probed. This option also
causes the designware-i2c driver to be builtin for the same reason.
config MFD_INTEL_LPSS
tristate
select COMMON_CLK
@@ -1325,6 +1351,20 @@ config MFD_TI_LP873X
This driver can also be built as a module. If so, the module
will be called lp873x.
config MFD_TI_LP87565
tristate "TI LP87565 Power Management IC"
depends on I2C && OF
select MFD_CORE
select REGMAP_I2C
help
If you say yes here then you get support for the LP87565 series of
Power Management Integrated Circuits (PMIC).
These include voltage regulators, thermal protection, configurable
General Purpose Outputs (GPO) that are used in portable devices.
This driver can also be built as a module. If so, the module
will be called lp87565.
config MFD_TPS65218
tristate "TI TPS65218 Power Management chips"
depends on I2C
+2
View File
@@ -25,6 +25,7 @@ obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o
obj-$(CONFIG_MFD_TI_LP873X) += lp873x.o
obj-$(CONFIG_MFD_TI_LP87565) += lp87565.o
obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o
obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
@@ -214,6 +215,7 @@ obj-$(CONFIG_MFD_SKY81452) += sky81452.o
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_MFD_MT6397) += mt6397-core.o
obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
+1 -1
View File
@@ -80,7 +80,7 @@ static int atmel_flexcom_probe(struct platform_device *pdev)
clk_disable_unprepare(clk);
return of_platform_populate(np, NULL, NULL, &pdev->dev);
return devm_of_platform_populate(&pdev->dev);
}
static const struct of_device_id atmel_flexcom_of_match[] = {
+2 -1
View File
@@ -848,7 +848,8 @@ static struct mfd_cell axp803_cells[] = {
.name = "axp20x-pek",
.num_resources = ARRAY_SIZE(axp803_pek_resources),
.resources = axp803_pek_resources,
}
},
{ .name = "axp20x-regulator" },
};
static struct mfd_cell axp806_cells[] = {
+4 -1
View File
@@ -147,7 +147,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
}
if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
err = of_platform_populate(dev->of_node, NULL, NULL, dev);
err = devm_of_platform_populate(dev);
if (err) {
mfd_remove_devices(dev);
dev_err(dev, "Failed to register sub-devices\n");
@@ -183,6 +183,9 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
cros_ec_acpi_remove_gpe_handler();
if (ec_dev->irq)
free_irq(ec_dev->irq, ec_dev);
return 0;
}
EXPORT_SYMBOL(cros_ec_remove);
-12
View File
@@ -428,9 +428,6 @@ static const struct regmap_range da9061_aa_readable_ranges[] = {
}, {
.range_min = DA9062AA_VLDO1_B,
.range_max = DA9062AA_VLDO4_B,
}, {
.range_min = DA9062AA_BBAT_CONT,
.range_max = DA9062AA_BBAT_CONT,
}, {
.range_min = DA9062AA_INTERFACE,
.range_max = DA9062AA_CONFIG_E,
@@ -513,9 +510,6 @@ static const struct regmap_range da9061_aa_writeable_ranges[] = {
}, {
.range_min = DA9062AA_VLDO1_B,
.range_max = DA9062AA_VLDO4_B,
}, {
.range_min = DA9062AA_BBAT_CONT,
.range_max = DA9062AA_BBAT_CONT,
}, {
.range_min = DA9062AA_GP_ID_0,
.range_max = DA9062AA_GP_ID_19,
@@ -650,9 +644,6 @@ static const struct regmap_range da9062_aa_readable_ranges[] = {
}, {
.range_min = DA9062AA_VLDO1_B,
.range_max = DA9062AA_VLDO4_B,
}, {
.range_min = DA9062AA_BBAT_CONT,
.range_max = DA9062AA_BBAT_CONT,
}, {
.range_min = DA9062AA_INTERFACE,
.range_max = DA9062AA_CONFIG_E,
@@ -729,9 +720,6 @@ static const struct regmap_range da9062_aa_writeable_ranges[] = {
}, {
.range_min = DA9062AA_VLDO1_B,
.range_max = DA9062AA_VLDO4_B,
}, {
.range_min = DA9062AA_BBAT_CONT,
.range_max = DA9062AA_BBAT_CONT,
}, {
.range_min = DA9062AA_GP_ID_0,
.range_max = DA9062AA_GP_ID_19,
+1 -1
View File
@@ -138,7 +138,7 @@ static int exynos_lpass_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
exynos_lpass_enable(lpass);
return of_platform_populate(dev->of_node, NULL, NULL, dev);
return devm_of_platform_populate(dev);
}
static int exynos_lpass_remove(struct platform_device *pdev)
+2 -5
View File
@@ -59,7 +59,7 @@ static int mx25_tsadc_domain_map(struct irq_domain *d, unsigned int irq,
return 0;
}
static struct irq_domain_ops mx25_tsadc_domain_ops = {
static const struct irq_domain_ops mx25_tsadc_domain_ops = {
.map = mx25_tsadc_domain_map,
.xlate = irq_domain_xlate_onecell,
};
@@ -129,7 +129,6 @@ static void mx25_tsadc_setup_clk(struct platform_device *pdev,
static int mx25_tsadc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct mx25_tsadc *tsadc;
struct resource *res;
int ret;
@@ -178,9 +177,7 @@ static int mx25_tsadc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, tsadc);
of_platform_populate(np, NULL, NULL, dev);
return 0;
return devm_of_platform_populate(dev);
}
static const struct of_device_id mx25_tsadc_ids[] = {
+24
View File
@@ -201,6 +201,19 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x9d64), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9d65), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9d66), (kernel_ulong_t)&spt_uart_info },
/* CNL-LP */
{ PCI_VDEVICE(INTEL, 0x9da8), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x9da9), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x9daa), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x9dab), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x9dfb), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x9dc5), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9dc6), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9dc7), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x9de8), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9de9), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9dea), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9deb), (kernel_ulong_t)&spt_i2c_info },
/* SPT-H */
{ PCI_VDEVICE(INTEL, 0xa127), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa128), (kernel_ulong_t)&spt_uart_info },
@@ -219,6 +232,17 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0xa2e2), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa2e3), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa2e6), (kernel_ulong_t)&spt_uart_info },
/* CNL-H */
{ PCI_VDEVICE(INTEL, 0xa328), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa329), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa32a), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0xa32b), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0xa37b), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0xa347), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa368), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa369), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa36a), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa36b), (kernel_ulong_t)&spt_i2c_info },
{ }
};
MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids);
+29 -20
View File
@@ -58,19 +58,34 @@ struct intel_quark_mfd {
struct clk_lookup *i2c_clk_lookup;
};
struct i2c_mode_info {
const char *name;
unsigned int i2c_scl_freq;
};
static const struct i2c_mode_info platform_i2c_mode_info[] = {
static const struct dmi_system_id dmi_platform_info[] = {
{
.name = "Galileo",
.i2c_scl_freq = 100000,
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_NAME, "Galileo"),
},
.driver_data = (void *)100000,
},
{
.name = "GalileoGen2",
.i2c_scl_freq = 400000,
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"),
},
.driver_data = (void *)400000,
},
{
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
"6ES7647-0AA00-0YA2"),
},
.driver_data = (void *)400000,
},
{
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
"6ES7647-0AA00-1YA2"),
},
.driver_data = (void *)400000,
},
{}
};
@@ -160,8 +175,7 @@ static void intel_quark_unregister_i2c_clk(struct device *dev)
static int intel_quark_i2c_setup(struct pci_dev *pdev, struct mfd_cell *cell)
{
const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
const struct i2c_mode_info *info;
const struct dmi_system_id *dmi_id;
struct dw_i2c_platform_data *pdata;
struct resource *res = (struct resource *)cell->resources;
struct device *dev = &pdev->dev;
@@ -181,14 +195,9 @@ static int intel_quark_i2c_setup(struct pci_dev *pdev, struct mfd_cell *cell)
/* Normal mode by default */
pdata->i2c_scl_freq = 100000;
if (board_name) {
for (info = platform_i2c_mode_info; info->name; info++) {
if (!strcmp(board_name, info->name)) {
pdata->i2c_scl_freq = info->i2c_scl_freq;
break;
}
}
}
dmi_id = dmi_first_match(dmi_platform_info);
if (dmi_id)
pdata->i2c_scl_freq = (uintptr_t)dmi_id->driver_data;
cell->platform_data = pdata;
cell->pdata_size = sizeof(*pdata);
+158 -78
View File
@@ -82,20 +82,26 @@ enum bxtwc_irqs {
BXTWC_PWRBTN_IRQ,
};
enum bxtwc_irqs_level2 {
/* Level 2 */
BXTWC_THRM0_IRQ = 0,
BXTWC_THRM1_IRQ,
BXTWC_THRM2_IRQ,
BXTWC_BCU_IRQ,
BXTWC_ADC_IRQ,
BXTWC_USBC_IRQ,
enum bxtwc_irqs_bcu {
BXTWC_BCU_IRQ = 0,
};
enum bxtwc_irqs_adc {
BXTWC_ADC_IRQ = 0,
};
enum bxtwc_irqs_chgr {
BXTWC_USBC_IRQ = 0,
BXTWC_CHGR0_IRQ,
BXTWC_CHGR1_IRQ,
BXTWC_GPIO0_IRQ,
BXTWC_GPIO1_IRQ,
BXTWC_CRIT_IRQ,
BXTWC_TMU_IRQ,
};
enum bxtwc_irqs_tmu {
BXTWC_TMU_IRQ = 0,
};
enum bxtwc_irqs_crit {
BXTWC_CRIT_IRQ = 0,
};
static const struct regmap_irq bxtwc_regmap_irqs[] = {
@@ -110,24 +116,28 @@ static const struct regmap_irq bxtwc_regmap_irqs[] = {
REGMAP_IRQ_REG(BXTWC_PWRBTN_IRQ, 1, 0x03),
};
static const struct regmap_irq bxtwc_regmap_irqs_level2[] = {
REGMAP_IRQ_REG(BXTWC_THRM0_IRQ, 0, 0xff),
REGMAP_IRQ_REG(BXTWC_THRM1_IRQ, 1, 0xbf),
REGMAP_IRQ_REG(BXTWC_THRM2_IRQ, 2, 0xff),
REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 3, 0x1f),
REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 4, 0xff),
REGMAP_IRQ_REG(BXTWC_USBC_IRQ, 5, BIT(5)),
REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x1f),
REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 6, 0x1f),
REGMAP_IRQ_REG(BXTWC_GPIO0_IRQ, 7, 0xff),
REGMAP_IRQ_REG(BXTWC_GPIO1_IRQ, 8, 0x3f),
REGMAP_IRQ_REG(BXTWC_CRIT_IRQ, 9, 0x03),
static const struct regmap_irq bxtwc_regmap_irqs_bcu[] = {
REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 0, 0x1f),
};
static const struct regmap_irq bxtwc_regmap_irqs_adc[] = {
REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 0, 0xff),
};
static const struct regmap_irq bxtwc_regmap_irqs_chgr[] = {
REGMAP_IRQ_REG(BXTWC_USBC_IRQ, 0, BIT(5)),
REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 0, 0x1f),
REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 1, 0x1f),
};
static const struct regmap_irq bxtwc_regmap_irqs_tmu[] = {
REGMAP_IRQ_REG(BXTWC_TMU_IRQ, 0, 0x06),
};
static const struct regmap_irq bxtwc_regmap_irqs_crit[] = {
REGMAP_IRQ_REG(BXTWC_CRIT_IRQ, 0, 0x03),
};
static struct regmap_irq_chip bxtwc_regmap_irq_chip = {
.name = "bxtwc_irq_chip",
.status_base = BXTWC_IRQLVL1,
@@ -137,15 +147,6 @@ static struct regmap_irq_chip bxtwc_regmap_irq_chip = {
.num_regs = 2,
};
static struct regmap_irq_chip bxtwc_regmap_irq_chip_level2 = {
.name = "bxtwc_irq_chip_level2",
.status_base = BXTWC_THRM0IRQ,
.mask_base = BXTWC_MTHRM0IRQ,
.irqs = bxtwc_regmap_irqs_level2,
.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_level2),
.num_regs = 10,
};
static struct regmap_irq_chip bxtwc_regmap_irq_chip_tmu = {
.name = "bxtwc_irq_chip_tmu",
.status_base = BXTWC_TMUIRQ,
@@ -155,9 +156,44 @@ static struct regmap_irq_chip bxtwc_regmap_irq_chip_tmu = {
.num_regs = 1,
};
static struct regmap_irq_chip bxtwc_regmap_irq_chip_bcu = {
.name = "bxtwc_irq_chip_bcu",
.status_base = BXTWC_BCUIRQ,
.mask_base = BXTWC_MBCUIRQ,
.irqs = bxtwc_regmap_irqs_bcu,
.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_bcu),
.num_regs = 1,
};
static struct regmap_irq_chip bxtwc_regmap_irq_chip_adc = {
.name = "bxtwc_irq_chip_adc",
.status_base = BXTWC_ADCIRQ,
.mask_base = BXTWC_MADCIRQ,
.irqs = bxtwc_regmap_irqs_adc,
.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_adc),
.num_regs = 1,
};
static struct regmap_irq_chip bxtwc_regmap_irq_chip_chgr = {
.name = "bxtwc_irq_chip_chgr",
.status_base = BXTWC_CHGR0IRQ,
.mask_base = BXTWC_MCHGR0IRQ,
.irqs = bxtwc_regmap_irqs_chgr,
.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_chgr),
.num_regs = 2,
};
static struct regmap_irq_chip bxtwc_regmap_irq_chip_crit = {
.name = "bxtwc_irq_chip_crit",
.status_base = BXTWC_CRITIRQ,
.mask_base = BXTWC_MCRITIRQ,
.irqs = bxtwc_regmap_irqs_crit,
.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_crit),
.num_regs = 1,
};
static struct resource gpio_resources[] = {
DEFINE_RES_IRQ_NAMED(BXTWC_GPIO0_IRQ, "GPIO0"),
DEFINE_RES_IRQ_NAMED(BXTWC_GPIO1_IRQ, "GPIO1"),
DEFINE_RES_IRQ_NAMED(BXTWC_GPIO_LVL1_IRQ, "GPIO"),
};
static struct resource adc_resources[] = {
@@ -174,9 +210,7 @@ static struct resource charger_resources[] = {
};
static struct resource thermal_resources[] = {
DEFINE_RES_IRQ(BXTWC_THRM0_IRQ),
DEFINE_RES_IRQ(BXTWC_THRM1_IRQ),
DEFINE_RES_IRQ(BXTWC_THRM2_IRQ),
DEFINE_RES_IRQ(BXTWC_THRM_LVL1_IRQ),
};
static struct resource bcu_resources[] = {
@@ -367,6 +401,26 @@ static const struct regmap_config bxtwc_regmap_config = {
.reg_read = regmap_ipc_byte_reg_read,
};
static int bxtwc_add_chained_irq_chip(struct intel_soc_pmic *pmic,
struct regmap_irq_chip_data *pdata,
int pirq, int irq_flags,
const struct regmap_irq_chip *chip,
struct regmap_irq_chip_data **data)
{
int irq;
irq = regmap_irq_get_virq(pdata, pirq);
if (irq < 0) {
dev_err(pmic->dev,
"Failed to get parent vIRQ(%d) for chip %s, ret:%d\n",
pirq, chip->name, irq);
return irq;
}
return devm_regmap_add_irq_chip(pmic->dev, pmic->regmap, irq, irq_flags,
0, chip, data);
}
static int bxtwc_probe(struct platform_device *pdev)
{
int ret;
@@ -409,45 +463,88 @@ static int bxtwc_probe(struct platform_device *pdev)
return ret;
}
ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
IRQF_ONESHOT | IRQF_SHARED,
0, &bxtwc_regmap_irq_chip,
&pmic->irq_chip_data);
ret = devm_regmap_add_irq_chip(&pdev->dev, pmic->regmap, pmic->irq,
IRQF_ONESHOT | IRQF_SHARED,
0, &bxtwc_regmap_irq_chip,
&pmic->irq_chip_data);
if (ret) {
dev_err(&pdev->dev, "Failed to add IRQ chip\n");
return ret;
}
ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
IRQF_ONESHOT | IRQF_SHARED,
0, &bxtwc_regmap_irq_chip_level2,
&pmic->irq_chip_data_level2);
if (ret) {
dev_err(&pdev->dev, "Failed to add secondary IRQ chip\n");
goto err_irq_chip_level2;
}
ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
IRQF_ONESHOT | IRQF_SHARED,
0, &bxtwc_regmap_irq_chip_tmu,
&pmic->irq_chip_data_tmu);
ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
BXTWC_TMU_LVL1_IRQ,
IRQF_ONESHOT,
&bxtwc_regmap_irq_chip_tmu,
&pmic->irq_chip_data_tmu);
if (ret) {
dev_err(&pdev->dev, "Failed to add TMU IRQ chip\n");
goto err_irq_chip_tmu;
return ret;
}
ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, bxt_wc_dev,
ARRAY_SIZE(bxt_wc_dev), NULL, 0,
NULL);
/* Add chained IRQ handler for BCU IRQs */
ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
BXTWC_BCU_LVL1_IRQ,
IRQF_ONESHOT,
&bxtwc_regmap_irq_chip_bcu,
&pmic->irq_chip_data_bcu);
if (ret) {
dev_err(&pdev->dev, "Failed to add BUC IRQ chip\n");
return ret;
}
/* Add chained IRQ handler for ADC IRQs */
ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
BXTWC_ADC_LVL1_IRQ,
IRQF_ONESHOT,
&bxtwc_regmap_irq_chip_adc,
&pmic->irq_chip_data_adc);
if (ret) {
dev_err(&pdev->dev, "Failed to add ADC IRQ chip\n");
return ret;
}
/* Add chained IRQ handler for CHGR IRQs */
ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
BXTWC_CHGR_LVL1_IRQ,
IRQF_ONESHOT,
&bxtwc_regmap_irq_chip_chgr,
&pmic->irq_chip_data_chgr);
if (ret) {
dev_err(&pdev->dev, "Failed to add CHGR IRQ chip\n");
return ret;
}
/* Add chained IRQ handler for CRIT IRQs */
ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
BXTWC_CRIT_LVL1_IRQ,
IRQF_ONESHOT,
&bxtwc_regmap_irq_chip_crit,
&pmic->irq_chip_data_crit);
if (ret) {
dev_err(&pdev->dev, "Failed to add CRIT IRQ chip\n");
return ret;
}
ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, bxt_wc_dev,
ARRAY_SIZE(bxt_wc_dev), NULL, 0, NULL);
if (ret) {
dev_err(&pdev->dev, "Failed to add devices\n");
goto err_mfd;
return ret;
}
ret = sysfs_create_group(&pdev->dev.kobj, &bxtwc_group);
if (ret) {
dev_err(&pdev->dev, "Failed to create sysfs group %d\n", ret);
goto err_sysfs;
return ret;
}
/*
@@ -461,28 +558,11 @@ static int bxtwc_probe(struct platform_device *pdev)
BXTWC_MIRQLVL1_MCHGR, 0);
return 0;
err_sysfs:
mfd_remove_devices(&pdev->dev);
err_mfd:
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_tmu);
err_irq_chip_tmu:
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2);
err_irq_chip_level2:
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
return ret;
}
static int bxtwc_remove(struct platform_device *pdev)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(&pdev->dev);
sysfs_remove_group(&pdev->dev.kobj, &bxtwc_group);
mfd_remove_devices(&pdev->dev);
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2);
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_tmu);
return 0;
}
+230
View File
@@ -0,0 +1,230 @@
/*
* MFD core driver for Intel Cherrytrail Whiskey Cove PMIC
*
* Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
*
* Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
* Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
*
* 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/delay.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/mfd/intel_soc_pmic.h>
#include <linux/regmap.h>
/* PMIC device registers */
#define REG_OFFSET_MASK GENMASK(7, 0)
#define REG_ADDR_MASK GENMASK(15, 8)
#define REG_ADDR_SHIFT 8
#define CHT_WC_IRQLVL1 0x6e02
#define CHT_WC_IRQLVL1_MASK 0x6e0e
/* Whiskey Cove PMIC share same ACPI ID between different platforms */
#define CHT_WC_HRV 3
/* Level 1 IRQs (level 2 IRQs are handled in the child device drivers) */
enum {
CHT_WC_PWRSRC_IRQ = 0,
CHT_WC_THRM_IRQ,
CHT_WC_BCU_IRQ,
CHT_WC_ADC_IRQ,
CHT_WC_EXT_CHGR_IRQ,
CHT_WC_GPIO_IRQ,
/* There is no irq 6 */
CHT_WC_CRIT_IRQ = 7,
};
static struct resource cht_wc_pwrsrc_resources[] = {
DEFINE_RES_IRQ(CHT_WC_PWRSRC_IRQ),
};
static struct resource cht_wc_ext_charger_resources[] = {
DEFINE_RES_IRQ(CHT_WC_EXT_CHGR_IRQ),
};
static struct mfd_cell cht_wc_dev[] = {
{
.name = "cht_wcove_pwrsrc",
.num_resources = ARRAY_SIZE(cht_wc_pwrsrc_resources),
.resources = cht_wc_pwrsrc_resources,
}, {
.name = "cht_wcove_ext_chgr",
.num_resources = ARRAY_SIZE(cht_wc_ext_charger_resources),
.resources = cht_wc_ext_charger_resources,
},
{ .name = "cht_wcove_region", },
};
/*
* The CHT Whiskey Cove covers multiple I2C addresses, with a 1 Byte
* register address space per I2C address, so we use 16 bit register
* addresses where the high 8 bits contain the I2C client address.
*/
static int cht_wc_byte_reg_read(void *context, unsigned int reg,
unsigned int *val)
{
struct i2c_client *client = context;
int ret, orig_addr = client->addr;
if (!(reg & REG_ADDR_MASK)) {
dev_err(&client->dev, "Error I2C address not specified\n");
return -EINVAL;
}
client->addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
ret = i2c_smbus_read_byte_data(client, reg & REG_OFFSET_MASK);
client->addr = orig_addr;
if (ret < 0)
return ret;
*val = ret;
return 0;
}
static int cht_wc_byte_reg_write(void *context, unsigned int reg,
unsigned int val)
{
struct i2c_client *client = context;
int ret, orig_addr = client->addr;
if (!(reg & REG_ADDR_MASK)) {
dev_err(&client->dev, "Error I2C address not specified\n");
return -EINVAL;
}
client->addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
ret = i2c_smbus_write_byte_data(client, reg & REG_OFFSET_MASK, val);
client->addr = orig_addr;
return ret;
}
static const struct regmap_config cht_wc_regmap_cfg = {
.reg_bits = 16,
.val_bits = 8,
.reg_write = cht_wc_byte_reg_write,
.reg_read = cht_wc_byte_reg_read,
};
static const struct regmap_irq cht_wc_regmap_irqs[] = {
REGMAP_IRQ_REG(CHT_WC_PWRSRC_IRQ, 0, BIT(CHT_WC_PWRSRC_IRQ)),
REGMAP_IRQ_REG(CHT_WC_THRM_IRQ, 0, BIT(CHT_WC_THRM_IRQ)),
REGMAP_IRQ_REG(CHT_WC_BCU_IRQ, 0, BIT(CHT_WC_BCU_IRQ)),
REGMAP_IRQ_REG(CHT_WC_ADC_IRQ, 0, BIT(CHT_WC_ADC_IRQ)),
REGMAP_IRQ_REG(CHT_WC_EXT_CHGR_IRQ, 0, BIT(CHT_WC_EXT_CHGR_IRQ)),
REGMAP_IRQ_REG(CHT_WC_GPIO_IRQ, 0, BIT(CHT_WC_GPIO_IRQ)),
REGMAP_IRQ_REG(CHT_WC_CRIT_IRQ, 0, BIT(CHT_WC_CRIT_IRQ)),
};
static const struct regmap_irq_chip cht_wc_regmap_irq_chip = {
.name = "cht_wc_irq_chip",
.status_base = CHT_WC_IRQLVL1,
.mask_base = CHT_WC_IRQLVL1_MASK,
.irqs = cht_wc_regmap_irqs,
.num_irqs = ARRAY_SIZE(cht_wc_regmap_irqs),
.num_regs = 1,
};
static int cht_wc_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct intel_soc_pmic *pmic;
acpi_status status;
unsigned long long hrv;
int ret;
status = acpi_evaluate_integer(ACPI_HANDLE(dev), "_HRV", NULL, &hrv);
if (ACPI_FAILURE(status)) {
dev_err(dev, "Failed to get PMIC hardware revision\n");
return -ENODEV;
}
if (hrv != CHT_WC_HRV) {
dev_err(dev, "Invalid PMIC hardware revision: %llu\n", hrv);
return -ENODEV;
}
if (client->irq < 0) {
dev_err(dev, "Invalid IRQ\n");
return -EINVAL;
}
pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic)
return -ENOMEM;
pmic->irq = client->irq;
pmic->dev = dev;
i2c_set_clientdata(client, pmic);
pmic->regmap = devm_regmap_init(dev, NULL, client, &cht_wc_regmap_cfg);
if (IS_ERR(pmic->regmap))
return PTR_ERR(pmic->regmap);
ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq,
IRQF_ONESHOT | IRQF_SHARED, 0,
&cht_wc_regmap_irq_chip,
&pmic->irq_chip_data);
if (ret)
return ret;
return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
cht_wc_dev, ARRAY_SIZE(cht_wc_dev), NULL, 0,
regmap_irq_get_domain(pmic->irq_chip_data));
}
static void cht_wc_shutdown(struct i2c_client *client)
{
struct intel_soc_pmic *pmic = i2c_get_clientdata(client);
disable_irq(pmic->irq);
}
static int __maybe_unused cht_wc_suspend(struct device *dev)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
disable_irq(pmic->irq);
return 0;
}
static int __maybe_unused cht_wc_resume(struct device *dev)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
enable_irq(pmic->irq);
return 0;
}
static SIMPLE_DEV_PM_OPS(cht_wc_pm_ops, cht_wc_suspend, cht_wc_resume);
static const struct i2c_device_id cht_wc_i2c_id[] = {
{ }
};
static const struct acpi_device_id cht_wc_acpi_ids[] = {
{ "INT34D3", },
{ }
};
static struct i2c_driver cht_wc_driver = {
.driver = {
.name = "CHT Whiskey Cove PMIC",
.pm = &cht_wc_pm_ops,
.acpi_match_table = cht_wc_acpi_ids,
},
.probe_new = cht_wc_probe,
.shutdown = cht_wc_shutdown,
.id_table = cht_wc_i2c_id,
};
builtin_i2c_driver(cht_wc_driver);
-5
View File
@@ -53,8 +53,6 @@ static void ipaq_micro_trigger_tx(struct ipaq_micro *micro)
tx->buf[bp++] = checksum;
tx->len = bp;
tx->index = 0;
print_hex_dump_debug("data: ", DUMP_PREFIX_OFFSET, 16, 1,
tx->buf, tx->len, true);
/* Enable interrupt */
val = readl(micro->base + UTCR3);
@@ -281,9 +279,6 @@ static void __init ipaq_micro_eeprom_dump(struct ipaq_micro *micro)
dev_info(micro->dev, "RAM size: %u KiB\n", ipaq_micro_to_u16(dump+92));
dev_info(micro->dev, "screen: %u x %u\n",
ipaq_micro_to_u16(dump+94), ipaq_micro_to_u16(dump+96));
print_hex_dump_debug("eeprom: ", DUMP_PREFIX_OFFSET, 16, 1,
dump, 256, true);
}
static void micro_tx_chars(struct ipaq_micro *micro)
+100
View File
@@ -0,0 +1,100 @@
/*
* Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
*
* Author: Keerthy <j-keerthy@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*/
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/mfd/lp87565.h>
static const struct regmap_config lp87565_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = LP87565_REG_MAX,
};
static const struct mfd_cell lp87565_cells[] = {
{ .name = "lp87565-q1-regulator", },
{ .name = "lp87565-q1-gpio", },
};
static const struct of_device_id of_lp87565_match_table[] = {
{ .compatible = "ti,lp87565", },
{
.compatible = "ti,lp87565-q1",
.data = (void *)LP87565_DEVICE_TYPE_LP87565_Q1,
},
{}
};
MODULE_DEVICE_TABLE(of, of_lp87565_match_table);
static int lp87565_probe(struct i2c_client *client,
const struct i2c_device_id *ids)
{
struct lp87565 *lp87565;
const struct of_device_id *of_id;
int ret;
unsigned int otpid;
lp87565 = devm_kzalloc(&client->dev, sizeof(*lp87565), GFP_KERNEL);
if (!lp87565)
return -ENOMEM;
lp87565->dev = &client->dev;
lp87565->regmap = devm_regmap_init_i2c(client, &lp87565_regmap_config);
if (IS_ERR(lp87565->regmap)) {
ret = PTR_ERR(lp87565->regmap);
dev_err(lp87565->dev,
"Failed to initialize register map: %d\n", ret);
return ret;
}
ret = regmap_read(lp87565->regmap, LP87565_REG_OTP_REV, &otpid);
if (ret) {
dev_err(lp87565->dev, "Failed to read OTP ID\n");
return ret;
}
lp87565->rev = otpid & LP87565_OTP_REV_OTP_ID;
of_id = of_match_device(of_lp87565_match_table, &client->dev);
if (of_id)
lp87565->dev_type = (enum lp87565_device_type)of_id->data;
i2c_set_clientdata(client, lp87565);
ret = mfd_add_devices(lp87565->dev, PLATFORM_DEVID_AUTO, lp87565_cells,
ARRAY_SIZE(lp87565_cells), NULL, 0, NULL);
return ret;
}
static const struct i2c_device_id lp87565_id_table[] = {
{ "lp87565-q1", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, lp87565_id_table);
static struct i2c_driver lp87565_driver = {
.driver = {
.name = "lp87565",
.of_match_table = of_lp87565_match_table,
},
.probe = lp87565_probe,
.id_table = lp87565_id_table,
};
module_i2c_driver(lp87565_driver);
MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
MODULE_DESCRIPTION("lp87565 chip family Multi-Function Device driver");
MODULE_LICENSE("GPL v2");
+1 -12
View File
@@ -260,17 +260,7 @@ static int cpcap_probe(struct spi_device *spi)
if (ret)
return ret;
return of_platform_populate(spi->dev.of_node, NULL, NULL,
&cpcap->spi->dev);
}
static int cpcap_remove(struct spi_device *pdev)
{
struct cpcap_ddata *cpcap = spi_get_drvdata(pdev);
of_platform_depopulate(&cpcap->spi->dev);
return 0;
return devm_of_platform_populate(&cpcap->spi->dev);
}
static struct spi_driver cpcap_driver = {
@@ -279,7 +269,6 @@ static struct spi_driver cpcap_driver = {
.of_match_table = cpcap_of_match,
},
.probe = cpcap_probe,
.remove = cpcap_remove,
};
module_spi_driver(cpcap_driver);

Some files were not shown because too many files have changed in this diff Show More