Merge tag 'mfd-next-4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones: "New Drivers - RK805 Power Management IC (PMIC) - ROHM BD9571MWV-M MFD Power Management IC (PMIC) - Texas Instruments TPS68470 Power Management IC (PMIC) & LEDs New Device Support: - Add support for HiSilicon Hi6421v530 to hi6421-pmic-core - Add support for X-Powers AXP806 to axp20x - Add support for X-Powers AXP813 to axp20x - Add support for Intel Sunrise Point LPSS to intel-lpss-pci New Functionality: - Amend API to provide register layout; atmel-smc Fix-ups: - DT re-work; omap, nokia - Header file location change {I2C => MFD}; dm355evm_msp, tps65010 - Fix chip ID formatting issue(s); rk808 - Optionally register touchscreen devices; da9052-core - Documentation improvements; twl-core - Constification; rtsx_pcr, ab8500-core, da9055-i2c, da9052-spi - Drop unnecessary static declaration; max8925-i2c - Kconfig changes (missing deps and remove module support) - Slim down oversized licence statement; hi6421-pmic-core - Use managed resources (devm_*); lp87565 - Supply proper error checking/handling; t7l66xb Bug Fixes: - Fix counter duplication issue; da9052-core - Fix potential NULL deference issue; max8998 - Leave SPI-NOR write-protection bit alone; lpc_ich - Ensure device is put into reset during suspend; intel-lpss - Correct register offset variable size; omap-usb-tll" * tag 'mfd-next-4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (61 commits) mfd: intel_soc_pmic: Differentiate between Bay and Cherry Trail CRC variants mfd: intel_soc_pmic: Export separate mfd-cell configs for BYT and CHT dt-bindings: mfd: Add bindings for ZII RAVE devices mfd: omap-usb-tll: Fix register offsets mfd: da9052: Constify spi_device_id mfd: intel-lpss: Put I2C and SPI controllers into reset state on suspend mfd: da9055: Constify i2c_device_id mfd: intel-lpss: Add missing PCI ID for Intel Sunrise Point LPSS devices mfd: t7l66xb: Handle return value of clk_prepare_enable mfd: Add ROHM BD9571MWV-M PMIC DT bindings mfd: intel_soc_pmic_chtwc: Turn Kconfig option into a bool mfd: lp87565: Convert to use devm_mfd_add_devices() mfd: Add support for TPS68470 device mfd: lpc_ich: Do not touch SPI-NOR write protection bit on Haswell/Broadwell mfd: syscon: atmel-smc: Add helper to retrieve register layout mfd: axp20x: Use correct platform device ID for many PEK dt-bindings: mfd: axp20x: Introduce bindings for AXP813 mfd: axp20x: Add support for AXP813 PMIC dt-bindings: mfd: axp20x: Add AXP806 to supported list of chips mfd: Add ROHM BD9571MWV-M MFD PMIC driver ...
This commit is contained in:
@@ -133,6 +133,20 @@ config MFD_BCM590XX
|
||||
help
|
||||
Support for the BCM590xx PMUs from Broadcom
|
||||
|
||||
config MFD_BD9571MWV
|
||||
tristate "ROHM BD9571MWV PMIC"
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
depends on I2C
|
||||
help
|
||||
Support for the ROHM BD9571MWV PMIC, which contains single
|
||||
voltage regulator, voltage sampling units, GPIO block and
|
||||
watchdog block.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called bd9571mwv.
|
||||
|
||||
config MFD_AC100
|
||||
tristate "X-Powers AC100"
|
||||
select MFD_CORE
|
||||
@@ -453,12 +467,12 @@ config LPC_SCH
|
||||
|
||||
config INTEL_SOC_PMIC
|
||||
bool "Support for Crystal Cove PMIC"
|
||||
depends on HAS_IOMEM && I2C=y && GPIOLIB && COMMON_CLK
|
||||
depends on ACPI && 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
|
||||
select I2C_DESIGNWARE_PLATFORM
|
||||
help
|
||||
Select this option to enable support for Crystal Cove PMIC
|
||||
on some Intel SoC systems. The PMIC provides ADC, GPIO,
|
||||
@@ -481,7 +495,7 @@ config INTEL_SOC_PMIC_BXTWC
|
||||
on these systems.
|
||||
|
||||
config INTEL_SOC_PMIC_CHTWC
|
||||
tristate "Support for Intel Cherry Trail Whiskey Cove PMIC"
|
||||
bool "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
|
||||
@@ -951,13 +965,13 @@ config MFD_RC5T583
|
||||
different functionality of the device.
|
||||
|
||||
config MFD_RK808
|
||||
tristate "Rockchip RK808/RK818 Power Management Chip"
|
||||
tristate "Rockchip RK805/RK808/RK818 Power Management Chip"
|
||||
depends on I2C && OF
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
help
|
||||
If you say yes here you get support for the RK808 and RK818
|
||||
If you say yes here you get support for the RK805, RK808 and RK818
|
||||
Power Management chips.
|
||||
This driver provides common support for accessing the device
|
||||
through I2C interface. The device supports multiple sub-devices
|
||||
@@ -1294,6 +1308,7 @@ config TPS6507X
|
||||
|
||||
config MFD_TPS65086
|
||||
tristate "TI TPS65086 Power Management Integrated Chips (PMICs)"
|
||||
select MFD_CORE
|
||||
select REGMAP
|
||||
select REGMAP_IRQ
|
||||
select REGMAP_I2C
|
||||
@@ -1337,6 +1352,24 @@ config MFD_TPS65217
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called tps65217.
|
||||
|
||||
config MFD_TPS68470
|
||||
bool "TI TPS68470 Power Management / LED chips"
|
||||
depends on ACPI && I2C=y
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select I2C_DESIGNWARE_PLATFORM
|
||||
help
|
||||
If you say yes here you get support for the TPS68470 series of
|
||||
Power Management / LED chips.
|
||||
|
||||
These include voltage regulators, LEDs and other features
|
||||
that are often used in portable devices.
|
||||
|
||||
This option is a bool as it provides an ACPI operation
|
||||
region, which must be available before any of the devices
|
||||
using this are probed. This option also configures the
|
||||
designware-i2c driver to be built-in, for the same reason.
|
||||
|
||||
config MFD_TI_LP873X
|
||||
tristate "TI LP873X Power Management IC"
|
||||
depends on I2C
|
||||
@@ -1723,6 +1756,20 @@ config MFD_STW481X
|
||||
in various ST Microelectronics and ST-Ericsson embedded
|
||||
Nomadik series.
|
||||
|
||||
config MFD_STM32_LPTIMER
|
||||
tristate "Support for STM32 Low-Power Timer"
|
||||
depends on (ARCH_STM32 && OF) || COMPILE_TEST
|
||||
select MFD_CORE
|
||||
select REGMAP
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
Select this option to enable STM32 Low-Power Timer driver
|
||||
used for PWM, IIO Trigger, IIO Encoder and Counter. Shared
|
||||
resources are also dealt with here.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called stm32-lptimer.
|
||||
|
||||
config MFD_STM32_TIMERS
|
||||
tristate "Support for STM32 Timers"
|
||||
depends on (ARCH_STM32 && OF) || COMPILE_TEST
|
||||
|
@@ -10,6 +10,7 @@ obj-$(CONFIG_MFD_ACT8945A) += act8945a.o
|
||||
obj-$(CONFIG_MFD_SM501) += sm501.o
|
||||
obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
|
||||
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
|
||||
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
|
||||
cros_ec_core-objs := cros_ec.o
|
||||
cros_ec_core-$(CONFIG_ACPI) += cros_ec_acpi_gpe.o
|
||||
obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o
|
||||
@@ -83,6 +84,7 @@ obj-$(CONFIG_MFD_TPS65910) += tps65910.o
|
||||
obj-$(CONFIG_MFD_TPS65912) += tps65912-core.o
|
||||
obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o
|
||||
obj-$(CONFIG_MFD_TPS65912_SPI) += tps65912-spi.o
|
||||
obj-$(CONFIG_MFD_TPS68470) += tps68470.o
|
||||
obj-$(CONFIG_MFD_TPS80031) += tps80031.o
|
||||
obj-$(CONFIG_MENELAUS) += menelaus.o
|
||||
|
||||
@@ -221,5 +223,6 @@ obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
|
||||
obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
|
||||
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
|
||||
|
@@ -1059,15 +1059,15 @@ static struct attribute *ab9540_sysfs_entries[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group ab8500_attr_group = {
|
||||
static const struct attribute_group ab8500_attr_group = {
|
||||
.attrs = ab8500_sysfs_entries,
|
||||
};
|
||||
|
||||
static struct attribute_group ab8505_attr_group = {
|
||||
static const struct attribute_group ab8505_attr_group = {
|
||||
.attrs = ab8505_sysfs_entries,
|
||||
};
|
||||
|
||||
static struct attribute_group ab9540_attr_group = {
|
||||
static const struct attribute_group ab9540_attr_group = {
|
||||
.attrs = ab9540_sysfs_entries,
|
||||
};
|
||||
|
||||
|
@@ -258,19 +258,21 @@ EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_apply);
|
||||
* atmel_hsmc_cs_conf_apply - apply an SMC CS conf
|
||||
* @regmap: the HSMC regmap
|
||||
* @cs: the CS id
|
||||
* @layout: the layout of registers
|
||||
* @conf the SMC CS conf to apply
|
||||
*
|
||||
* Applies an SMC CS configuration.
|
||||
* Only valid on post-sama5 SoCs.
|
||||
*/
|
||||
void atmel_hsmc_cs_conf_apply(struct regmap *regmap, int cs,
|
||||
const struct atmel_smc_cs_conf *conf)
|
||||
void atmel_hsmc_cs_conf_apply(struct regmap *regmap,
|
||||
const struct atmel_hsmc_reg_layout *layout,
|
||||
int cs, const struct atmel_smc_cs_conf *conf)
|
||||
{
|
||||
regmap_write(regmap, ATMEL_HSMC_SETUP(cs), conf->setup);
|
||||
regmap_write(regmap, ATMEL_HSMC_PULSE(cs), conf->pulse);
|
||||
regmap_write(regmap, ATMEL_HSMC_CYCLE(cs), conf->cycle);
|
||||
regmap_write(regmap, ATMEL_HSMC_TIMINGS(cs), conf->timings);
|
||||
regmap_write(regmap, ATMEL_HSMC_MODE(cs), conf->mode);
|
||||
regmap_write(regmap, ATMEL_HSMC_SETUP(layout, cs), conf->setup);
|
||||
regmap_write(regmap, ATMEL_HSMC_PULSE(layout, cs), conf->pulse);
|
||||
regmap_write(regmap, ATMEL_HSMC_CYCLE(layout, cs), conf->cycle);
|
||||
regmap_write(regmap, ATMEL_HSMC_TIMINGS(layout, cs), conf->timings);
|
||||
regmap_write(regmap, ATMEL_HSMC_MODE(layout, cs), conf->mode);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(atmel_hsmc_cs_conf_apply);
|
||||
|
||||
@@ -297,18 +299,55 @@ EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_get);
|
||||
* atmel_hsmc_cs_conf_get - retrieve the current SMC CS conf
|
||||
* @regmap: the HSMC regmap
|
||||
* @cs: the CS id
|
||||
* @layout: the layout of registers
|
||||
* @conf: the SMC CS conf object to store the current conf
|
||||
*
|
||||
* Retrieve the SMC CS configuration.
|
||||
* Only valid on post-sama5 SoCs.
|
||||
*/
|
||||
void atmel_hsmc_cs_conf_get(struct regmap *regmap, int cs,
|
||||
struct atmel_smc_cs_conf *conf)
|
||||
void atmel_hsmc_cs_conf_get(struct regmap *regmap,
|
||||
const struct atmel_hsmc_reg_layout *layout,
|
||||
int cs, struct atmel_smc_cs_conf *conf)
|
||||
{
|
||||
regmap_read(regmap, ATMEL_HSMC_SETUP(cs), &conf->setup);
|
||||
regmap_read(regmap, ATMEL_HSMC_PULSE(cs), &conf->pulse);
|
||||
regmap_read(regmap, ATMEL_HSMC_CYCLE(cs), &conf->cycle);
|
||||
regmap_read(regmap, ATMEL_HSMC_TIMINGS(cs), &conf->timings);
|
||||
regmap_read(regmap, ATMEL_HSMC_MODE(cs), &conf->mode);
|
||||
regmap_read(regmap, ATMEL_HSMC_SETUP(layout, cs), &conf->setup);
|
||||
regmap_read(regmap, ATMEL_HSMC_PULSE(layout, cs), &conf->pulse);
|
||||
regmap_read(regmap, ATMEL_HSMC_CYCLE(layout, cs), &conf->cycle);
|
||||
regmap_read(regmap, ATMEL_HSMC_TIMINGS(layout, cs), &conf->timings);
|
||||
regmap_read(regmap, ATMEL_HSMC_MODE(layout, cs), &conf->mode);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(atmel_hsmc_cs_conf_get);
|
||||
|
||||
static const struct atmel_hsmc_reg_layout sama5d3_reg_layout = {
|
||||
.timing_regs_offset = 0x600,
|
||||
};
|
||||
|
||||
static const struct atmel_hsmc_reg_layout sama5d2_reg_layout = {
|
||||
.timing_regs_offset = 0x700,
|
||||
};
|
||||
|
||||
static const struct of_device_id atmel_smc_ids[] = {
|
||||
{ .compatible = "atmel,at91sam9260-smc", .data = NULL },
|
||||
{ .compatible = "atmel,sama5d3-smc", .data = &sama5d3_reg_layout },
|
||||
{ .compatible = "atmel,sama5d2-smc", .data = &sama5d2_reg_layout },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
/**
|
||||
* atmel_hsmc_get_reg_layout - retrieve the layout of HSMC registers
|
||||
* @np: the HSMC regmap
|
||||
*
|
||||
* Retrieve the layout of HSMC registers.
|
||||
*
|
||||
* Returns NULL in case of SMC, a struct atmel_hsmc_reg_layout pointer
|
||||
* in HSMC case, otherwise ERR_PTR(-EINVAL).
|
||||
*/
|
||||
const struct atmel_hsmc_reg_layout *
|
||||
atmel_hsmc_get_reg_layout(struct device_node *np)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
|
||||
match = of_match_node(atmel_smc_ids, np);
|
||||
|
||||
return match ? match->data : ERR_PTR(-EINVAL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(atmel_hsmc_get_reg_layout);
|
||||
|
@@ -64,6 +64,7 @@ static const struct of_device_id axp20x_rsb_of_match[] = {
|
||||
{ .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
|
||||
{ .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
|
||||
{ .compatible = "x-powers,axp809", .data = (void *)AXP809_ID },
|
||||
{ .compatible = "x-powers,axp813", .data = (void *)AXP813_ID },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, axp20x_rsb_of_match);
|
||||
|
@@ -44,6 +44,7 @@ static const char * const axp20x_model_names[] = {
|
||||
"AXP803",
|
||||
"AXP806",
|
||||
"AXP809",
|
||||
"AXP813",
|
||||
};
|
||||
|
||||
static const struct regmap_range axp152_writeable_ranges[] = {
|
||||
@@ -676,7 +677,7 @@ static struct mfd_cell axp20x_cells[] = {
|
||||
|
||||
static struct mfd_cell axp221_cells[] = {
|
||||
{
|
||||
.name = "axp20x-pek",
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp22x_pek_resources),
|
||||
.resources = axp22x_pek_resources,
|
||||
}, {
|
||||
@@ -701,7 +702,7 @@ static struct mfd_cell axp221_cells[] = {
|
||||
|
||||
static struct mfd_cell axp223_cells[] = {
|
||||
{
|
||||
.name = "axp20x-pek",
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp22x_pek_resources),
|
||||
.resources = axp22x_pek_resources,
|
||||
}, {
|
||||
@@ -834,7 +835,7 @@ static struct mfd_cell axp288_cells[] = {
|
||||
.resources = axp288_fuel_gauge_resources,
|
||||
},
|
||||
{
|
||||
.name = "axp20x-pek",
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp288_power_button_resources),
|
||||
.resources = axp288_power_button_resources,
|
||||
},
|
||||
@@ -845,7 +846,7 @@ static struct mfd_cell axp288_cells[] = {
|
||||
|
||||
static struct mfd_cell axp803_cells[] = {
|
||||
{
|
||||
.name = "axp20x-pek",
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp803_pek_resources),
|
||||
.resources = axp803_pek_resources,
|
||||
},
|
||||
@@ -861,7 +862,7 @@ static struct mfd_cell axp806_cells[] = {
|
||||
|
||||
static struct mfd_cell axp809_cells[] = {
|
||||
{
|
||||
.name = "axp20x-pek",
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp809_pek_resources),
|
||||
.resources = axp809_pek_resources,
|
||||
}, {
|
||||
@@ -870,6 +871,14 @@ static struct mfd_cell axp809_cells[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell axp813_cells[] = {
|
||||
{
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp803_pek_resources),
|
||||
.resources = axp803_pek_resources,
|
||||
}
|
||||
};
|
||||
|
||||
static struct axp20x_dev *axp20x_pm_power_off;
|
||||
static void axp20x_power_off(void)
|
||||
{
|
||||
@@ -956,6 +965,19 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
|
||||
axp20x->regmap_cfg = &axp22x_regmap_config;
|
||||
axp20x->regmap_irq_chip = &axp809_regmap_irq_chip;
|
||||
break;
|
||||
case AXP813_ID:
|
||||
axp20x->nr_cells = ARRAY_SIZE(axp813_cells);
|
||||
axp20x->cells = axp813_cells;
|
||||
axp20x->regmap_cfg = &axp288_regmap_config;
|
||||
/*
|
||||
* The IRQ table given in the datasheet is incorrect.
|
||||
* In IRQ enable/status registers 1, there are separate
|
||||
* IRQs for ACIN and VBUS, instead of bits [7:5] being
|
||||
* the same as bits [4:2]. So it shares the same IRQs
|
||||
* as the AXP803, rather than the AXP288.
|
||||
*/
|
||||
axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
|
||||
return -EINVAL;
|
||||
|
230
drivers/mfd/bd9571mwv.c
Normal file
230
drivers/mfd/bd9571mwv.c
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* ROHM BD9571MWV-M MFD driver
|
||||
*
|
||||
* Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether expressed or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License version 2 for more details.
|
||||
*
|
||||
* Based on the TPS65086 driver
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/mfd/bd9571mwv.h>
|
||||
|
||||
static const struct mfd_cell bd9571mwv_cells[] = {
|
||||
{ .name = "bd9571mwv-regulator", },
|
||||
{ .name = "bd9571mwv-gpio", },
|
||||
};
|
||||
|
||||
static const struct regmap_range bd9571mwv_readable_yes_ranges[] = {
|
||||
regmap_reg_range(BD9571MWV_VENDOR_CODE, BD9571MWV_PRODUCT_REVISION),
|
||||
regmap_reg_range(BD9571MWV_AVS_SET_MONI, BD9571MWV_AVS_DVFS_VID(3)),
|
||||
regmap_reg_range(BD9571MWV_VD18_VID, BD9571MWV_VD33_VID),
|
||||
regmap_reg_range(BD9571MWV_DVFS_VINIT, BD9571MWV_DVFS_VINIT),
|
||||
regmap_reg_range(BD9571MWV_DVFS_SETVMAX, BD9571MWV_DVFS_MONIVDAC),
|
||||
regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
|
||||
regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INTMASK),
|
||||
regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table bd9571mwv_readable_table = {
|
||||
.yes_ranges = bd9571mwv_readable_yes_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(bd9571mwv_readable_yes_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range bd9571mwv_writable_yes_ranges[] = {
|
||||
regmap_reg_range(BD9571MWV_AVS_VD09_VID(0), BD9571MWV_AVS_VD09_VID(3)),
|
||||
regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_SETVID),
|
||||
regmap_reg_range(BD9571MWV_GPIO_DIR, BD9571MWV_GPIO_OUT),
|
||||
regmap_reg_range(BD9571MWV_GPIO_INT_SET, BD9571MWV_GPIO_INTMASK),
|
||||
regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table bd9571mwv_writable_table = {
|
||||
.yes_ranges = bd9571mwv_writable_yes_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(bd9571mwv_writable_yes_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range bd9571mwv_volatile_yes_ranges[] = {
|
||||
regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
|
||||
regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT),
|
||||
regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table bd9571mwv_volatile_table = {
|
||||
.yes_ranges = bd9571mwv_volatile_yes_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(bd9571mwv_volatile_yes_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_config bd9571mwv_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.rd_table = &bd9571mwv_readable_table,
|
||||
.wr_table = &bd9571mwv_writable_table,
|
||||
.volatile_table = &bd9571mwv_volatile_table,
|
||||
.max_register = 0xff,
|
||||
};
|
||||
|
||||
static const struct regmap_irq bd9571mwv_irqs[] = {
|
||||
REGMAP_IRQ_REG(BD9571MWV_IRQ_MD1, 0,
|
||||
BD9571MWV_INT_INTREQ_MD1_INT),
|
||||
REGMAP_IRQ_REG(BD9571MWV_IRQ_MD2_E1, 0,
|
||||
BD9571MWV_INT_INTREQ_MD2_E1_INT),
|
||||
REGMAP_IRQ_REG(BD9571MWV_IRQ_MD2_E2, 0,
|
||||
BD9571MWV_INT_INTREQ_MD2_E2_INT),
|
||||
REGMAP_IRQ_REG(BD9571MWV_IRQ_PROT_ERR, 0,
|
||||
BD9571MWV_INT_INTREQ_PROT_ERR_INT),
|
||||
REGMAP_IRQ_REG(BD9571MWV_IRQ_GP, 0,
|
||||
BD9571MWV_INT_INTREQ_GP_INT),
|
||||
REGMAP_IRQ_REG(BD9571MWV_IRQ_128H_OF, 0,
|
||||
BD9571MWV_INT_INTREQ_128H_OF_INT),
|
||||
REGMAP_IRQ_REG(BD9571MWV_IRQ_WDT_OF, 0,
|
||||
BD9571MWV_INT_INTREQ_WDT_OF_INT),
|
||||
REGMAP_IRQ_REG(BD9571MWV_IRQ_BKUP_TRG, 0,
|
||||
BD9571MWV_INT_INTREQ_BKUP_TRG_INT),
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip bd9571mwv_irq_chip = {
|
||||
.name = "bd9571mwv",
|
||||
.status_base = BD9571MWV_INT_INTREQ,
|
||||
.mask_base = BD9571MWV_INT_INTMASK,
|
||||
.ack_base = BD9571MWV_INT_INTREQ,
|
||||
.init_ack_masked = true,
|
||||
.num_regs = 1,
|
||||
.irqs = bd9571mwv_irqs,
|
||||
.num_irqs = ARRAY_SIZE(bd9571mwv_irqs),
|
||||
};
|
||||
|
||||
static int bd9571mwv_identify(struct bd9571mwv *bd)
|
||||
{
|
||||
struct device *dev = bd->dev;
|
||||
unsigned int value;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(bd->regmap, BD9571MWV_VENDOR_CODE, &value);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read vendor code register (ret=%i)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (value != BD9571MWV_VENDOR_CODE_VAL) {
|
||||
dev_err(dev, "Invalid vendor code ID %02x (expected %02x)\n",
|
||||
value, BD9571MWV_VENDOR_CODE_VAL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_read(bd->regmap, BD9571MWV_PRODUCT_CODE, &value);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read product code register (ret=%i)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (value != BD9571MWV_PRODUCT_CODE_VAL) {
|
||||
dev_err(dev, "Invalid product code ID %02x (expected %02x)\n",
|
||||
value, BD9571MWV_PRODUCT_CODE_VAL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_read(bd->regmap, BD9571MWV_PRODUCT_REVISION, &value);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read revision register (ret=%i)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(dev, "Device: BD9571MWV rev. %d\n", value & 0xff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd9571mwv_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *ids)
|
||||
{
|
||||
struct bd9571mwv *bd;
|
||||
int ret;
|
||||
|
||||
bd = devm_kzalloc(&client->dev, sizeof(*bd), GFP_KERNEL);
|
||||
if (!bd)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, bd);
|
||||
bd->dev = &client->dev;
|
||||
bd->irq = client->irq;
|
||||
|
||||
bd->regmap = devm_regmap_init_i2c(client, &bd9571mwv_regmap_config);
|
||||
if (IS_ERR(bd->regmap)) {
|
||||
dev_err(bd->dev, "Failed to initialize register map\n");
|
||||
return PTR_ERR(bd->regmap);
|
||||
}
|
||||
|
||||
ret = bd9571mwv_identify(bd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_add_irq_chip(bd->regmap, bd->irq, IRQF_ONESHOT, 0,
|
||||
&bd9571mwv_irq_chip, &bd->irq_data);
|
||||
if (ret) {
|
||||
dev_err(bd->dev, "Failed to register IRQ chip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mfd_add_devices(bd->dev, PLATFORM_DEVID_AUTO, bd9571mwv_cells,
|
||||
ARRAY_SIZE(bd9571mwv_cells), NULL, 0,
|
||||
regmap_irq_get_domain(bd->irq_data));
|
||||
if (ret) {
|
||||
regmap_del_irq_chip(bd->irq, bd->irq_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd9571mwv_remove(struct i2c_client *client)
|
||||
{
|
||||
struct bd9571mwv *bd = i2c_get_clientdata(client);
|
||||
|
||||
regmap_del_irq_chip(bd->irq, bd->irq_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id bd9571mwv_of_match_table[] = {
|
||||
{ .compatible = "rohm,bd9571mwv", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bd9571mwv_of_match_table);
|
||||
|
||||
static const struct i2c_device_id bd9571mwv_id_table[] = {
|
||||
{ "bd9571mwv", 0 },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bd9571mwv_id_table);
|
||||
|
||||
static struct i2c_driver bd9571mwv_driver = {
|
||||
.driver = {
|
||||
.name = "bd9571mwv",
|
||||
.of_match_table = bd9571mwv_of_match_table,
|
||||
},
|
||||
.probe = bd9571mwv_probe,
|
||||
.remove = bd9571mwv_remove,
|
||||
.id_table = bd9571mwv_id_table,
|
||||
};
|
||||
module_i2c_driver(bd9571mwv_driver);
|
||||
|
||||
MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>");
|
||||
MODULE_DESCRIPTION("BD9571MWV PMIC Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@@ -387,6 +387,8 @@ int da9052_adc_manual_read(struct da9052 *da9052, unsigned char channel)
|
||||
|
||||
mutex_lock(&da9052->auxadc_lock);
|
||||
|
||||
reinit_completion(&da9052->done);
|
||||
|
||||
/* Channel gets activated on enabling the Conversion bit */
|
||||
mux_sel = chan_mux[channel] | DA9052_ADC_MAN_MAN_CONV;
|
||||
|
||||
|
@@ -67,7 +67,7 @@ static int da9052_spi_remove(struct spi_device *spi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_device_id da9052_spi_id[] = {
|
||||
static const struct spi_device_id da9052_spi_id[] = {
|
||||
{"da9052", DA9052},
|
||||
{"da9053-aa", DA9053_AA},
|
||||
{"da9053-ba", DA9053_BA},
|
||||
|
@@ -62,7 +62,7 @@ static int da9055_i2c_remove(struct i2c_client *i2c)
|
||||
* purposes separate). As a result there are specific DA9055 ids for PMIC
|
||||
* and CODEC, which must be different to operate together.
|
||||
*/
|
||||
static struct i2c_device_id da9055_i2c_id[] = {
|
||||
static const struct i2c_device_id da9055_i2c_id[] = {
|
||||
{"da9055-pmic", 0},
|
||||
{ }
|
||||
};
|
||||
|
@@ -18,7 +18,7 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c/dm355evm_msp.h>
|
||||
#include <linux/mfd/dm355evm_msp.h>
|
||||
|
||||
|
||||
/*
|
||||
|
@@ -1,40 +1,35 @@
|
||||
/*
|
||||
* Device driver for Hi6421 IC
|
||||
* Device driver for Hi6421 PMIC
|
||||
*
|
||||
* Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd.
|
||||
* http://www.hisilicon.com
|
||||
* Copyright (c) <2013-2014> Linaro Ltd.
|
||||
* Copyright (c) <2013-2017> Linaro Ltd.
|
||||
* http://www.linaro.org
|
||||
*
|
||||
* Author: Guodong Xu <guodong.xu@linaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/hi6421-pmic.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/hi6421-pmic.h>
|
||||
|
||||
static const struct mfd_cell hi6421_devs[] = {
|
||||
{ .name = "hi6421-regulator", },
|
||||
};
|
||||
|
||||
static const struct mfd_cell hi6421v530_devs[] = {
|
||||
{ .name = "hi6421v530-regulator", },
|
||||
};
|
||||
|
||||
static const struct regmap_config hi6421_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
@@ -42,12 +37,33 @@ static const struct regmap_config hi6421_regmap_config = {
|
||||
.max_register = HI6421_REG_TO_BUS_ADDR(HI6421_REG_MAX),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_hi6421_pmic_match[] = {
|
||||
{
|
||||
.compatible = "hisilicon,hi6421-pmic",
|
||||
.data = (void *)HI6421
|
||||
},
|
||||
{
|
||||
.compatible = "hisilicon,hi6421v530-pmic",
|
||||
.data = (void *)HI6421_V530
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match);
|
||||
|
||||
static int hi6421_pmic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct hi6421_pmic *pmic;
|
||||
struct resource *res;
|
||||
const struct of_device_id *id;
|
||||
const struct mfd_cell *subdevs;
|
||||
enum hi6421_type type;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
int n_subdevs, ret;
|
||||
|
||||
id = of_match_device(of_hi6421_pmic_match, &pdev->dev);
|
||||
if (!id)
|
||||
return -EINVAL;
|
||||
type = (enum hi6421_type)id->data;
|
||||
|
||||
pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
|
||||
if (!pmic)
|
||||
@@ -61,41 +77,50 @@ static int hi6421_pmic_probe(struct platform_device *pdev)
|
||||
pmic->regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
|
||||
&hi6421_regmap_config);
|
||||
if (IS_ERR(pmic->regmap)) {
|
||||
dev_err(&pdev->dev,
|
||||
"regmap init failed: %ld\n", PTR_ERR(pmic->regmap));
|
||||
dev_err(&pdev->dev, "Failed to initialise Regmap: %ld\n",
|
||||
PTR_ERR(pmic->regmap));
|
||||
return PTR_ERR(pmic->regmap);
|
||||
}
|
||||
|
||||
/* set over-current protection debounce 8ms */
|
||||
regmap_update_bits(pmic->regmap, HI6421_OCP_DEB_CTRL_REG,
|
||||
platform_set_drvdata(pdev, pmic);
|
||||
|
||||
switch (type) {
|
||||
case HI6421:
|
||||
/* set over-current protection debounce 8ms */
|
||||
regmap_update_bits(pmic->regmap, HI6421_OCP_DEB_CTRL_REG,
|
||||
(HI6421_OCP_DEB_SEL_MASK
|
||||
| HI6421_OCP_EN_DEBOUNCE_MASK
|
||||
| HI6421_OCP_AUTO_STOP_MASK),
|
||||
(HI6421_OCP_DEB_SEL_8MS
|
||||
| HI6421_OCP_EN_DEBOUNCE_ENABLE));
|
||||
|
||||
platform_set_drvdata(pdev, pmic);
|
||||
subdevs = hi6421_devs;
|
||||
n_subdevs = ARRAY_SIZE(hi6421_devs);
|
||||
break;
|
||||
case HI6421_V530:
|
||||
subdevs = hi6421v530_devs;
|
||||
n_subdevs = ARRAY_SIZE(hi6421v530_devs);
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Unknown device type %d\n",
|
||||
(unsigned int)type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_mfd_add_devices(&pdev->dev, 0, hi6421_devs,
|
||||
ARRAY_SIZE(hi6421_devs), NULL, 0, NULL);
|
||||
ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
|
||||
subdevs, n_subdevs, NULL, 0, NULL);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "add mfd devices failed: %d\n", ret);
|
||||
dev_err(&pdev->dev, "Failed to add child devices: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_hi6421_pmic_match_tbl[] = {
|
||||
{ .compatible = "hisilicon,hi6421-pmic", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match_tbl);
|
||||
|
||||
static struct platform_driver hi6421_pmic_driver = {
|
||||
.driver = {
|
||||
.name = "hi6421_pmic",
|
||||
.of_match_table = of_hi6421_pmic_match_tbl,
|
||||
.name = "hi6421_pmic",
|
||||
.of_match_table = of_hi6421_pmic_match,
|
||||
},
|
||||
.probe = hi6421_pmic_probe,
|
||||
};
|
||||
|
@@ -221,6 +221,7 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0xa12a), (kernel_ulong_t)&spt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa160), (kernel_ulong_t)&spt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa161), (kernel_ulong_t)&spt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa162), (kernel_ulong_t)&spt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa166), (kernel_ulong_t)&spt_uart_info },
|
||||
/* KBL-H */
|
||||
{ PCI_VDEVICE(INTEL, 0xa2a7), (kernel_ulong_t)&spt_uart_info },
|
||||
|
@@ -502,6 +502,14 @@ int intel_lpss_suspend(struct device *dev)
|
||||
for (i = 0; i < LPSS_PRIV_REG_COUNT; i++)
|
||||
lpss->priv_ctx[i] = readl(lpss->priv + i * 4);
|
||||
|
||||
/*
|
||||
* If the device type is not UART, then put the controller into
|
||||
* reset. UART cannot be put into reset since S3/S0ix fail when
|
||||
* no_console_suspend flag is enabled.
|
||||
*/
|
||||
if (lpss->type != LPSS_DEV_UART)
|
||||
writel(0, lpss->priv + LPSS_PRIV_RESETS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_lpss_suspend);
|
||||
|
@@ -16,6 +16,7 @@
|
||||
* Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/i2c.h>
|
||||
@@ -28,6 +29,10 @@
|
||||
#include <linux/pwm.h>
|
||||
#include "intel_soc_pmic_core.h"
|
||||
|
||||
/* Crystal Cove PMIC shares same ACPI ID between different platforms */
|
||||
#define BYT_CRC_HRV 2
|
||||
#define CHT_CRC_HRV 3
|
||||
|
||||
/* Lookup table for the Panel Enable/Disable line as GPIO signals */
|
||||
static struct gpiod_lookup_table panel_gpio_table = {
|
||||
/* Intel GFX is consumer */
|
||||
@@ -48,16 +53,33 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
{
|
||||
struct device *dev = &i2c->dev;
|
||||
const struct acpi_device_id *id;
|
||||
struct intel_soc_pmic_config *config;
|
||||
struct intel_soc_pmic *pmic;
|
||||
unsigned long long hrv;
|
||||
acpi_status status;
|
||||
int ret;
|
||||
|
||||
id = acpi_match_device(dev->driver->acpi_match_table, dev);
|
||||
if (!id || !id->driver_data)
|
||||
/*
|
||||
* There are 2 different Crystal Cove PMICs a Bay Trail and Cherry
|
||||
* Trail version, use _HRV to differentiate between the 2.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
config = (struct intel_soc_pmic_config *)id->driver_data;
|
||||
switch (hrv) {
|
||||
case BYT_CRC_HRV:
|
||||
config = &intel_soc_pmic_config_byt_crc;
|
||||
break;
|
||||
case CHT_CRC_HRV:
|
||||
config = &intel_soc_pmic_config_cht_crc;
|
||||
break;
|
||||
default:
|
||||
dev_warn(dev, "Unknown hardware rev %llu, assuming BYT\n", hrv);
|
||||
config = &intel_soc_pmic_config_byt_crc;
|
||||
}
|
||||
|
||||
pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
|
||||
if (!pmic)
|
||||
@@ -157,7 +179,7 @@ MODULE_DEVICE_TABLE(i2c, intel_soc_pmic_i2c_id);
|
||||
|
||||
#if defined(CONFIG_ACPI)
|
||||
static const struct acpi_device_id intel_soc_pmic_acpi_match[] = {
|
||||
{"INT33FD", (kernel_ulong_t)&intel_soc_pmic_config_crc},
|
||||
{ "INT33FD" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, intel_soc_pmic_acpi_match);
|
||||
|
@@ -27,6 +27,7 @@ struct intel_soc_pmic_config {
|
||||
const struct regmap_irq_chip *irq_chip;
|
||||
};
|
||||
|
||||
extern struct intel_soc_pmic_config intel_soc_pmic_config_crc;
|
||||
extern struct intel_soc_pmic_config intel_soc_pmic_config_byt_crc;
|
||||
extern struct intel_soc_pmic_config intel_soc_pmic_config_cht_crc;
|
||||
|
||||
#endif /* __INTEL_SOC_PMIC_CORE_H__ */
|
||||
|
@@ -80,7 +80,7 @@ static struct resource bcu_resources[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell crystal_cove_dev[] = {
|
||||
static struct mfd_cell crystal_cove_byt_dev[] = {
|
||||
{
|
||||
.name = "crystal_cove_pwrsrc",
|
||||
.num_resources = ARRAY_SIZE(pwrsrc_resources),
|
||||
@@ -114,6 +114,17 @@ static struct mfd_cell crystal_cove_dev[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell crystal_cove_cht_dev[] = {
|
||||
{
|
||||
.name = "crystal_cove_gpio",
|
||||
.num_resources = ARRAY_SIZE(gpio_resources),
|
||||
.resources = gpio_resources,
|
||||
},
|
||||
{
|
||||
.name = "crystal_cove_pwm",
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_config crystal_cove_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
@@ -155,10 +166,18 @@ static const struct regmap_irq_chip crystal_cove_irq_chip = {
|
||||
.mask_base = CRYSTAL_COVE_REG_MIRQLVL1,
|
||||
};
|
||||
|
||||
struct intel_soc_pmic_config intel_soc_pmic_config_crc = {
|
||||
struct intel_soc_pmic_config intel_soc_pmic_config_byt_crc = {
|
||||
.irq_flags = IRQF_TRIGGER_RISING,
|
||||
.cell_dev = crystal_cove_dev,
|
||||
.n_cell_devs = ARRAY_SIZE(crystal_cove_dev),
|
||||
.cell_dev = crystal_cove_byt_dev,
|
||||
.n_cell_devs = ARRAY_SIZE(crystal_cove_byt_dev),
|
||||
.regmap_config = &crystal_cove_regmap_config,
|
||||
.irq_chip = &crystal_cove_irq_chip,
|
||||
};
|
||||
|
||||
struct intel_soc_pmic_config intel_soc_pmic_config_cht_crc = {
|
||||
.irq_flags = IRQF_TRIGGER_RISING,
|
||||
.cell_dev = crystal_cove_cht_dev,
|
||||
.n_cell_devs = ARRAY_SIZE(crystal_cove_cht_dev),
|
||||
.regmap_config = &crystal_cove_regmap_config,
|
||||
.irq_chip = &crystal_cove_irq_chip,
|
||||
};
|
||||
|
@@ -73,10 +73,9 @@ static int lp87565_probe(struct i2c_client *client,
|
||||
|
||||
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;
|
||||
return devm_mfd_add_devices(lp87565->dev, PLATFORM_DEVID_AUTO,
|
||||
lp87565_cells, ARRAY_SIZE(lp87565_cells),
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lp87565_id_table[] = {
|
||||
|
@@ -1119,17 +1119,7 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
|
||||
res->start = spi_base + SPIBASE_LPT;
|
||||
res->end = res->start + SPIBASE_LPT_SZ - 1;
|
||||
|
||||
/*
|
||||
* Try to make the flash chip writeable now by
|
||||
* setting BCR_WPD. It it fails we tell the driver
|
||||
* that it can only read the chip.
|
||||
*/
|
||||
pci_read_config_dword(dev, BCR, &bcr);
|
||||
if (!(bcr & BCR_WPD)) {
|
||||
bcr |= BCR_WPD;
|
||||
pci_write_config_dword(dev, BCR, bcr);
|
||||
pci_read_config_dword(dev, BCR, &bcr);
|
||||
}
|
||||
info->writeable = !!(bcr & BCR_WPD);
|
||||
}
|
||||
break;
|
||||
|
@@ -151,7 +151,7 @@ static int max8925_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max8925_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
static struct max8925_chip *chip;
|
||||
struct max8925_chip *chip;
|
||||
struct device_node *node = client->dev.of_node;
|
||||
|
||||
if (node && !pdata) {
|
||||
|
@@ -192,10 +192,8 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
|
||||
|
||||
if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
|
||||
pdata = max8998_i2c_parse_dt_pdata(&i2c->dev);
|
||||
if (IS_ERR(pdata)) {
|
||||
ret = PTR_ERR(pdata);
|
||||
goto err;
|
||||
}
|
||||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
}
|
||||
|
||||
i2c_set_clientdata(i2c, max8998);
|
||||
|
@@ -131,12 +131,12 @@ static inline u32 usbtll_read(void __iomem *base, u32 reg)
|
||||
return readl_relaxed(base + reg);
|
||||
}
|
||||
|
||||
static inline void usbtll_writeb(void __iomem *base, u8 reg, u8 val)
|
||||
static inline void usbtll_writeb(void __iomem *base, u32 reg, u8 val)
|
||||
{
|
||||
writeb_relaxed(val, base + reg);
|
||||
}
|
||||
|
||||
static inline u8 usbtll_readb(void __iomem *base, u8 reg)
|
||||
static inline u8 usbtll_readb(void __iomem *base, u32 reg)
|
||||
{
|
||||
return readb_relaxed(base + reg);
|
||||
}
|
||||
|
@@ -302,15 +302,23 @@ static int retu_remove(struct i2c_client *i2c)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id retu_id[] = {
|
||||
{ "retu-mfd", 0 },
|
||||
{ "tahvo-mfd", 0 },
|
||||
{ "retu", 0 },
|
||||
{ "tahvo", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, retu_id);
|
||||
|
||||
static const struct of_device_id retu_of_match[] = {
|
||||
{ .compatible = "nokia,retu" },
|
||||
{ .compatible = "nokia,tahvo" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, retu_of_match);
|
||||
|
||||
static struct i2c_driver retu_driver = {
|
||||
.driver = {
|
||||
.name = "retu-mfd",
|
||||
.of_match_table = retu_of_match,
|
||||
},
|
||||
.probe = retu_probe,
|
||||
.remove = retu_remove,
|
||||
|
@@ -70,6 +70,14 @@ static const struct regmap_config rk818_regmap_config = {
|
||||
.volatile_reg = rk808_is_volatile_reg,
|
||||
};
|
||||
|
||||
static const struct regmap_config rk805_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = RK805_OFF_SOURCE_REG,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.volatile_reg = rk808_is_volatile_reg,
|
||||
};
|
||||
|
||||
static const struct regmap_config rk808_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
@@ -86,6 +94,34 @@ static struct resource rtc_resources[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct resource rk805_key_resources[] = {
|
||||
{
|
||||
.start = RK805_IRQ_PWRON_FALL,
|
||||
.end = RK805_IRQ_PWRON_FALL,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = RK805_IRQ_PWRON_RISE,
|
||||
.end = RK805_IRQ_PWRON_RISE,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct mfd_cell rk805s[] = {
|
||||
{ .name = "rk808-clkout", },
|
||||
{ .name = "rk808-regulator", },
|
||||
{ .name = "rk805-pinctrl", },
|
||||
{
|
||||
.name = "rk808-rtc",
|
||||
.num_resources = ARRAY_SIZE(rtc_resources),
|
||||
.resources = &rtc_resources[0],
|
||||
},
|
||||
{ .name = "rk805-pwrkey",
|
||||
.num_resources = ARRAY_SIZE(rk805_key_resources),
|
||||
.resources = &rk805_key_resources[0],
|
||||
},
|
||||
};
|
||||
|
||||
static const struct mfd_cell rk808s[] = {
|
||||
{ .name = "rk808-clkout", },
|
||||
{ .name = "rk808-regulator", },
|
||||
@@ -106,6 +142,20 @@ static const struct mfd_cell rk818s[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct rk808_reg_data rk805_pre_init_reg[] = {
|
||||
{RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
|
||||
RK805_BUCK1_2_ILMAX_4000MA},
|
||||
{RK805_BUCK2_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
|
||||
RK805_BUCK1_2_ILMAX_4000MA},
|
||||
{RK805_BUCK3_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,
|
||||
RK805_BUCK3_ILMAX_3000MA},
|
||||
{RK805_BUCK4_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,
|
||||
RK805_BUCK4_ILMAX_3500MA},
|
||||
{RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA},
|
||||
{RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SLEEP_FUN},
|
||||
{RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C},
|
||||
};
|
||||
|
||||
static const struct rk808_reg_data rk808_pre_init_reg[] = {
|
||||
{ RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA },
|
||||
{ RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA },
|
||||
@@ -135,6 +185,41 @@ static const struct rk808_reg_data rk818_pre_init_reg[] = {
|
||||
VB_LO_SEL_3500MV },
|
||||
};
|
||||
|
||||
static const struct regmap_irq rk805_irqs[] = {
|
||||
[RK805_IRQ_PWRON_RISE] = {
|
||||
.mask = RK805_IRQ_PWRON_RISE_MSK,
|
||||
.reg_offset = 0,
|
||||
},
|
||||
[RK805_IRQ_VB_LOW] = {
|
||||
.mask = RK805_IRQ_VB_LOW_MSK,
|
||||
.reg_offset = 0,
|
||||
},
|
||||
[RK805_IRQ_PWRON] = {
|
||||
.mask = RK805_IRQ_PWRON_MSK,
|
||||
.reg_offset = 0,
|
||||
},
|
||||
[RK805_IRQ_PWRON_LP] = {
|
||||
.mask = RK805_IRQ_PWRON_LP_MSK,
|
||||
.reg_offset = 0,
|
||||
},
|
||||
[RK805_IRQ_HOTDIE] = {
|
||||
.mask = RK805_IRQ_HOTDIE_MSK,
|
||||
.reg_offset = 0,
|
||||
},
|
||||
[RK805_IRQ_RTC_ALARM] = {
|
||||
.mask = RK805_IRQ_RTC_ALARM_MSK,
|
||||
.reg_offset = 0,
|
||||
},
|
||||
[RK805_IRQ_RTC_PERIOD] = {
|
||||
.mask = RK805_IRQ_RTC_PERIOD_MSK,
|
||||
.reg_offset = 0,
|
||||
},
|
||||
[RK805_IRQ_PWRON_FALL] = {
|
||||
.mask = RK805_IRQ_PWRON_FALL_MSK,
|
||||
.reg_offset = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_irq rk808_irqs[] = {
|
||||
/* INT_STS */
|
||||
[RK808_IRQ_VOUT_LO] = {
|
||||
@@ -247,6 +332,17 @@ static const struct regmap_irq rk818_irqs[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip rk805_irq_chip = {
|
||||
.name = "rk805",
|
||||
.irqs = rk805_irqs,
|
||||
.num_irqs = ARRAY_SIZE(rk805_irqs),
|
||||
.num_regs = 1,
|
||||
.status_base = RK805_INT_STS_REG,
|
||||
.mask_base = RK805_INT_STS_MSK_REG,
|
||||
.ack_base = RK805_INT_STS_REG,
|
||||
.init_ack_masked = true,
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip rk808_irq_chip = {
|
||||
.name = "rk808",
|
||||
.irqs = rk808_irqs,
|
||||
@@ -272,6 +368,25 @@ static const struct regmap_irq_chip rk818_irq_chip = {
|
||||
};
|
||||
|
||||
static struct i2c_client *rk808_i2c_client;
|
||||
|
||||
static void rk805_device_shutdown(void)
|
||||
{
|
||||
int ret;
|
||||
struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
|
||||
|
||||
if (!rk808) {
|
||||
dev_warn(&rk808_i2c_client->dev,
|
||||
"have no rk805, so do nothing here\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(rk808->regmap,
|
||||
RK805_DEV_CTRL_REG,
|
||||
DEV_OFF, DEV_OFF);
|
||||
if (ret)
|
||||
dev_err(&rk808_i2c_client->dev, "power off error!\n");
|
||||
}
|
||||
|
||||
static void rk808_device_shutdown(void)
|
||||
{
|
||||
int ret;
|
||||
@@ -309,6 +424,7 @@ static void rk818_device_shutdown(void)
|
||||
}
|
||||
|
||||
static const struct of_device_id rk808_of_match[] = {
|
||||
{ .compatible = "rockchip,rk805" },
|
||||
{ .compatible = "rockchip,rk808" },
|
||||
{ .compatible = "rockchip,rk818" },
|
||||
{ },
|
||||
@@ -325,7 +441,7 @@ static int rk808_probe(struct i2c_client *client,
|
||||
void (*pm_pwroff_fn)(void);
|
||||
int nr_pre_init_regs;
|
||||
int nr_cells;
|
||||
int pm_off = 0;
|
||||
int pm_off = 0, msb, lsb;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
@@ -333,16 +449,34 @@ static int rk808_probe(struct i2c_client *client,
|
||||
if (!rk808)
|
||||
return -ENOMEM;
|
||||
|
||||
rk808->variant = i2c_smbus_read_word_data(client, RK808_ID_MSB);
|
||||
if (rk808->variant < 0) {
|
||||
dev_err(&client->dev, "Failed to read the chip id at 0x%02x\n",
|
||||
/* Read chip variant */
|
||||
msb = i2c_smbus_read_byte_data(client, RK808_ID_MSB);
|
||||
if (msb < 0) {
|
||||
dev_err(&client->dev, "failed to read the chip id at 0x%x\n",
|
||||
RK808_ID_MSB);
|
||||
return rk808->variant;
|
||||
return msb;
|
||||
}
|
||||
|
||||
dev_dbg(&client->dev, "Chip id: 0x%x\n", (unsigned int)rk808->variant);
|
||||
lsb = i2c_smbus_read_byte_data(client, RK808_ID_LSB);
|
||||
if (lsb < 0) {
|
||||
dev_err(&client->dev, "failed to read the chip id at 0x%x\n",
|
||||
RK808_ID_LSB);
|
||||
return lsb;
|
||||
}
|
||||
|
||||
rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
|
||||
dev_info(&client->dev, "chip id: 0x%x\n", (unsigned int)rk808->variant);
|
||||
|
||||
switch (rk808->variant) {
|
||||
case RK805_ID:
|
||||
rk808->regmap_cfg = &rk805_regmap_config;
|
||||
rk808->regmap_irq_chip = &rk805_irq_chip;
|
||||
pre_init_reg = rk805_pre_init_reg;
|
||||
nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg);
|
||||
cells = rk805s;
|
||||
nr_cells = ARRAY_SIZE(rk805s);
|
||||
pm_pwroff_fn = rk805_device_shutdown;
|
||||
break;
|
||||
case RK808_ID:
|
||||
rk808->regmap_cfg = &rk808_regmap_config;
|
||||
rk808->regmap_irq_chip = &rk808_irq_chip;
|
||||
@@ -435,6 +569,7 @@ static int rk808_remove(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id rk808_ids[] = {
|
||||
{ "rk805" },
|
||||
{ "rk808" },
|
||||
{ "rk818" },
|
||||
{ },
|
||||
|
@@ -644,7 +644,7 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
|
||||
{
|
||||
int err, clk;
|
||||
u8 n, clk_divider, mcu_cnt, div;
|
||||
u8 depth[] = {
|
||||
static const u8 depth[] = {
|
||||
[RTSX_SSC_DEPTH_4M] = SSC_DEPTH_4M,
|
||||
[RTSX_SSC_DEPTH_2M] = SSC_DEPTH_2M,
|
||||
[RTSX_SSC_DEPTH_1M] = SSC_DEPTH_1M,
|
||||
@@ -768,7 +768,7 @@ EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off);
|
||||
|
||||
int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card)
|
||||
{
|
||||
unsigned int cd_mask[] = {
|
||||
static const unsigned int cd_mask[] = {
|
||||
[RTSX_SD_CARD] = SD_EXIST,
|
||||
[RTSX_MS_CARD] = MS_EXIST
|
||||
};
|
||||
|
107
drivers/mfd/stm32-lptimer.c
Normal file
107
drivers/mfd/stm32-lptimer.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* STM32 Low-Power Timer parent driver.
|
||||
*
|
||||
* Copyright (C) STMicroelectronics 2017
|
||||
*
|
||||
* Author: Fabrice Gasnier <fabrice.gasnier@st.com>
|
||||
*
|
||||
* Inspired by Benjamin Gaignard's stm32-timers driver
|
||||
*
|
||||
* License terms: GNU General Public License (GPL), version 2
|
||||
*/
|
||||
|
||||
#include <linux/mfd/stm32-lptimer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#define STM32_LPTIM_MAX_REGISTER 0x3fc
|
||||
|
||||
static const struct regmap_config stm32_lptimer_regmap_cfg = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = sizeof(u32),
|
||||
.max_register = STM32_LPTIM_MAX_REGISTER,
|
||||
};
|
||||
|
||||
static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata)
|
||||
{
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Quadrature encoder mode bit can only be written and read back when
|
||||
* Low-Power Timer supports it.
|
||||
*/
|
||||
ret = regmap_update_bits(ddata->regmap, STM32_LPTIM_CFGR,
|
||||
STM32_LPTIM_ENC, STM32_LPTIM_ENC);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(ddata->regmap, STM32_LPTIM_CFGR, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(ddata->regmap, STM32_LPTIM_CFGR,
|
||||
STM32_LPTIM_ENC, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ddata->has_encoder = !!(val & STM32_LPTIM_ENC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_lptimer_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct stm32_lptimer *ddata;
|
||||
struct resource *res;
|
||||
void __iomem *mmio;
|
||||
int ret;
|
||||
|
||||
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
|
||||
if (!ddata)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
mmio = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(mmio))
|
||||
return PTR_ERR(mmio);
|
||||
|
||||
ddata->regmap = devm_regmap_init_mmio_clk(dev, "mux", mmio,
|
||||
&stm32_lptimer_regmap_cfg);
|
||||
if (IS_ERR(ddata->regmap))
|
||||
return PTR_ERR(ddata->regmap);
|
||||
|
||||
ddata->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(ddata->clk))
|
||||
return PTR_ERR(ddata->clk);
|
||||
|
||||
ret = stm32_lptimer_detect_encoder(ddata);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, ddata);
|
||||
|
||||
return devm_of_platform_populate(&pdev->dev);
|
||||
}
|
||||
|
||||
static const struct of_device_id stm32_lptimer_of_match[] = {
|
||||
{ .compatible = "st,stm32-lptimer", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, stm32_lptimer_of_match);
|
||||
|
||||
static struct platform_driver stm32_lptimer_driver = {
|
||||
.probe = stm32_lptimer_probe,
|
||||
.driver = {
|
||||
.name = "stm32-lptimer",
|
||||
.of_match_table = stm32_lptimer_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(stm32_lptimer_driver);
|
||||
|
||||
MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
|
||||
MODULE_DESCRIPTION("STMicroelectronics STM32 Low-Power Timer");
|
||||
MODULE_ALIAS("platform:stm32-lptimer");
|
||||
MODULE_LICENSE("GPL v2");
|
@@ -86,8 +86,11 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc)
|
||||
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
u8 dev_ctl;
|
||||
int ret;
|
||||
|
||||
clk_prepare_enable(t7l66xb->clk32k);
|
||||
ret = clk_prepare_enable(t7l66xb->clk32k);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
raw_spin_lock_irqsave(&t7l66xb->lock, flags);
|
||||
|
||||
@@ -286,8 +289,12 @@ static int t7l66xb_resume(struct platform_device *dev)
|
||||
{
|
||||
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
|
||||
struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(t7l66xb->clk48m);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_prepare_enable(t7l66xb->clk48m);
|
||||
if (pdata && pdata->resume)
|
||||
pdata->resume(dev);
|
||||
|
||||
@@ -361,7 +368,9 @@ static int t7l66xb_probe(struct platform_device *dev)
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
clk_prepare_enable(t7l66xb->clk48m);
|
||||
ret = clk_prepare_enable(t7l66xb->clk48m);
|
||||
if (ret)
|
||||
goto err_clk_enable;
|
||||
|
||||
if (pdata->enable)
|
||||
pdata->enable(dev);
|
||||
@@ -386,6 +395,8 @@ static int t7l66xb_probe(struct platform_device *dev)
|
||||
return 0;
|
||||
|
||||
t7l66xb_detach_irq(dev);
|
||||
clk_disable_unprepare(t7l66xb->clk48m);
|
||||
err_clk_enable:
|
||||
iounmap(t7l66xb->scr);
|
||||
err_ioremap:
|
||||
release_resource(&t7l66xb->rscr);
|
||||
|
@@ -173,9 +173,17 @@ static const struct i2c_device_id tps6105x_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tps6105x_id);
|
||||
|
||||
static const struct of_device_id tps6105x_of_match[] = {
|
||||
{ .compatible = "ti,tps61050" },
|
||||
{ .compatible = "ti,tps61052" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tps6105x_of_match);
|
||||
|
||||
static struct i2c_driver tps6105x_driver = {
|
||||
.driver = {
|
||||
.name = "tps6105x",
|
||||
.of_match_table = tps6105x_of_match,
|
||||
},
|
||||
.probe = tps6105x_probe,
|
||||
.remove = tps6105x_remove,
|
||||
|
@@ -32,7 +32,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/i2c/tps65010.h>
|
||||
#include <linux/mfd/tps65010.h>
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
|
106
drivers/mfd/tps68470.c
Normal file
106
drivers/mfd/tps68470.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* TPS68470 chip Parent driver
|
||||
*
|
||||
* Copyright (C) 2017 Intel Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Rajmohan Mani <rajmohan.mani@intel.com>
|
||||
* Tianshu Qiu <tian.shu.qiu@intel.com>
|
||||
* Jian Xu Zheng <jian.xu.zheng@intel.com>
|
||||
* Yuning Pu <yuning.pu@intel.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.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/tps68470.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
static const struct mfd_cell tps68470s[] = {
|
||||
{ .name = "tps68470-gpio" },
|
||||
{ .name = "tps68470_pmic_opregion" },
|
||||
};
|
||||
|
||||
static const struct regmap_config tps68470_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = TPS68470_REG_MAX,
|
||||
};
|
||||
|
||||
static int tps68470_chip_init(struct device *dev, struct regmap *regmap)
|
||||
{
|
||||
unsigned int version;
|
||||
int ret;
|
||||
|
||||
/* Force software reset */
|
||||
ret = regmap_write(regmap, TPS68470_REG_RESET, TPS68470_REG_RESET_MASK);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(regmap, TPS68470_REG_REVID, &version);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read revision register: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(dev, "TPS68470 REVID: 0x%x\n", version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps68470_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(dev, "devm_regmap_init_i2c Error %ld\n",
|
||||
PTR_ERR(regmap));
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, regmap);
|
||||
|
||||
ret = tps68470_chip_init(dev, regmap);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "TPS68470 Init Error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, tps68470s,
|
||||
ARRAY_SIZE(tps68470s), NULL, 0, NULL);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "devm_mfd_add_devices failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct acpi_device_id tps68470_acpi_ids[] = {
|
||||
{"INT3472"},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, tps68470_acpi_ids);
|
||||
|
||||
static struct i2c_driver tps68470_driver = {
|
||||
.driver = {
|
||||
.name = "tps68470",
|
||||
.acpi_match_table = tps68470_acpi_ids,
|
||||
},
|
||||
.probe_new = tps68470_probe,
|
||||
};
|
||||
builtin_i2c_driver(tps68470_driver);
|
@@ -44,7 +44,7 @@
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
#include <linux/mfd/twl.h>
|
||||
|
||||
/* Register descriptions for audio */
|
||||
#include <linux/mfd/twl4030-audio.h>
|
||||
@@ -173,7 +173,7 @@ static struct twl_private *twl_priv;
|
||||
static struct twl_mapping twl4030_map[] = {
|
||||
/*
|
||||
* NOTE: don't change this table without updating the
|
||||
* <linux/i2c/twl.h> defines for TWL4030_MODULE_*
|
||||
* <linux/mfd/twl.h> defines for TWL4030_MODULE_*
|
||||
* so they continue to match the order in this table.
|
||||
*/
|
||||
|
||||
@@ -344,7 +344,7 @@ static const struct regmap_config twl4030_regmap_config[4] = {
|
||||
static struct twl_mapping twl6030_map[] = {
|
||||
/*
|
||||
* NOTE: don't change this table without updating the
|
||||
* <linux/i2c/twl.h> defines for TWL4030_MODULE_*
|
||||
* <linux/mfd/twl.h> defines for TWL4030_MODULE_*
|
||||
* so they continue to match the order in this table.
|
||||
*/
|
||||
|
||||
@@ -448,7 +448,7 @@ static struct regmap *twl_get_regmap(u8 mod_no)
|
||||
* @reg: register address (just offset will do)
|
||||
* @num_bytes: number of bytes to transfer
|
||||
*
|
||||
* Returns the result of operation - 0 is success
|
||||
* Returns 0 on success or else a negative error code.
|
||||
*/
|
||||
int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
|
||||
{
|
||||
@@ -476,7 +476,7 @@ EXPORT_SYMBOL(twl_i2c_write);
|
||||
* @reg: register address (just offset will do)
|
||||
* @num_bytes: number of bytes to transfer
|
||||
*
|
||||
* Returns result of operation - num_bytes is success else failure.
|
||||
* Returns 0 on success or else a negative error code.
|
||||
*/
|
||||
int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
|
||||
{
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
#include <linux/mfd/twl.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/twl4030-audio.h>
|
||||
|
||||
|
@@ -33,7 +33,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
#include <linux/mfd/twl.h>
|
||||
|
||||
#include "twl-core.h"
|
||||
|
||||
|
@@ -25,7 +25,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
#include <linux/mfd/twl.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
@@ -35,7 +35,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
#include <linux/mfd/twl.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/of.h>
|
||||
|
Reference in New Issue
Block a user