mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
Hi Linus,
Changes to the core:
- Honour PLATFORM_DEVID_NONE and PLATFORM_DEVID_AUTO dev IDs
Changes to existing drivers:
- IRQ additions/fixes; axp20x, da9063-core
- Code simplification; i2c-dln2
- Regmap additions/fixes; max77693
- Error checking/handling improvements; dln2, db8500-prcmu
- Bug fixes; dln2, wm8350-core
- DT support/documentation; max77693, max77686, tps65217, twl4030-power,
gpio-tc3589x
- Decouple syscon interface from platform devices
- Use MFD hotplug registration; rtsx_usb, viperboard, hid-sensor-hub
- Regulator fixups; sec-core
- Power Management additions/fixes; rts5227, tc6393xb
- Remove relic/redundant code; ab8500-sysctrl, lpc_sch, max77693-private
- Clean-up/coding style changes; tps65090
- Clk additions/fixes; tc6393xb, tc6387xb, t7l66xb
- Add USB-SPI support; dln2
- Trivial changes; max14577, arizona-spi, lpc_sch, wm8997-tables, wm5102-tables
wm5110-tables, axp20x, atmel-hlcdc, rtsx_pci
New drivers/supported devices:
- axp288 PMIC support added to axp20x
- s2mps13 support added to sec-core
- New support for Diolan DLN-2
- New support for atmel-hlcdc
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQIcBAABAgAGBQJUhZDaAAoJEFGvii+H/HdhEY4P+gOlEIU+LYDdKmRjXLp85+ZS
zrkLQdxvRp61LzzcIMGnduPFAOk8ixb3nRqSJv7P5WQG26I6qoI44zeTF2iSmLTp
iVLtXRFSlo/lRyWT+2jXwL5iC47PCoJuJajNeM/YEbMERR3sWWAPrATZrQSPoKcZ
D3qtXge3d+zq2rqpSvNAFNPEC4i9xawwa9GHMte9T/XhaoyVhaK6ITMsh0RK4B0p
RRc2zy9BGEkuZMu3aC7P/qhfu3uSrxzI6FCHNSbZt/p5aq8klMBGqpK9Tgg4UHUG
jqAd2lCXHVSVI07CO0YvVUDWV+5NlB1kAeRddohJujV9o5ciaqKCGPKK1Fz0PMxf
u30t0X4Fb4QCAZVeo1hX9KWKQaQinUzPhANT4Sz0DY1S7arZ6PlJO/obGIys5JCf
ElJuYNSRqRp6DcaoTHf19DUcxJXnqk73PU3hmsdS4UkweBWDYeagK2gqDwjIhAY6
DJZ5uqaa829fx/Jj8sUo0EgWZs/Cahf/td7y35fM4bMgU+vHd1xeBvMeltiJ2kuC
OoZwtyHbV29sMCL2i5VQMkTkLJz49hPOEZolDKUxsV1QEPhi62DRmiHZlKABh3+D
wzTkTRLfDhlrNedY529/1i3IxIlnzWXfInohe+WadapTFXuISIv6dyAyh9eNKnfd
ZVf+1NwaCGbZbbPkSBqK
=dJJd
-----END PGP SIGNATURE-----
Merge tag 'mfd-for-linus-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones:
"Changes to the core:
- Honour PLATFORM_DEVID_NONE and PLATFORM_DEVID_AUTO dev IDs
Changes to existing drivers:
- IRQ additions/fixes; axp20x, da9063-core
- Code simplification; i2c-dln2
- Regmap additions/fixes; max77693
- Error checking/handling improvements; dln2, db8500-prcmu
- Bug fixes; dln2, wm8350-core
- DT support/documentation; max77693, max77686, tps65217, twl4030-power,
gpio-tc3589x
- Decouple syscon interface from platform devices
- Use MFD hotplug registration; rtsx_usb, viperboard, hid-sensor-hub
- Regulator fixups; sec-core
- Power Management additions/fixes; rts5227, tc6393xb
- Remove relic/redundant code; ab8500-sysctrl, lpc_sch, max77693-private
- Clean-up/coding style changes; tps65090
- Clk additions/fixes; tc6393xb, tc6387xb, t7l66xb
- Add USB-SPI support; dln2
- Trivial changes; max14577, arizona-spi, lpc_sch, wm8997-tables, wm5102-tables
wm5110-tables, axp20x, atmel-hlcdc, rtsx_pci
New drivers/supported devices:
- axp288 PMIC support added to axp20x
- s2mps13 support added to sec-core
- New support for Diolan DLN-2
- New support for atmel-hlcdc"
* tag 'mfd-for-linus-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (55 commits)
mfd: rtsx: Add func to split u32 into register
mfd: atmel-hlcdc: Add Kconfig option description and name
mfd: da9063: Get irq base dynamically before registering device
mfd: max14577: Fix obvious typo in company name in copyright
mfd: axp20x: Constify axp20x_acpi_match and rid unused warning
mfd: t7l66xb: prepare/unprepare clocks
mfd: tc6387xb: prepare/unprepare clocks
mfd: dln2: add support for USB-SPI module
mfd: wm5110: Add missing registers for AIF2 channels 3-6
mfd: tc3589x: get rid of static base
mfd: arizona: Document HP_CTRL_1L and HP_CTRL_1R registers
mfd: wm8997: Mark INTERRUPT_STATUS_2_MASK as readable
mfd: tc6393xb: Prepare/unprepare clocks
mfd: tps65090: Fix bonkers indenting strategy
mfd: tc6393xb: Fail ohci suspend if full state restore is required
mfd: lpc_sch: Don't call mfd_remove_devices()
mfd: wm8350-core: Fix probable mask then right shift defect
mfd: ab8500-sysctrl: Drop ab8500_restart
mfd: db8500-prcmu: Provide sane error path values
mfd: db8500-prcmu: Check return of devm_ioremap for error
...
This commit is contained in:
commit
3a7dbed7f2
63 changed files with 3431 additions and 273 deletions
|
|
@ -59,6 +59,17 @@ config MFD_AAT2870_CORE
|
|||
additional drivers must be enabled in order to use the
|
||||
functionality of the device.
|
||||
|
||||
config MFD_ATMEL_HLCDC
|
||||
tristate "Atmel HLCDC (High-end LCD Controller)"
|
||||
select MFD_CORE
|
||||
select REGMAP_MMIO
|
||||
depends on OF
|
||||
help
|
||||
If you say yes here you get support for the HLCDC block.
|
||||
This driver provides common support for accessing the device,
|
||||
additional drivers must be enabled in order to use the
|
||||
functionality of the device.
|
||||
|
||||
config MFD_BCM590XX
|
||||
tristate "Broadcom BCM590xx PMUs"
|
||||
select MFD_CORE
|
||||
|
|
@ -74,7 +85,8 @@ config MFD_AXP20X
|
|||
select REGMAP_IRQ
|
||||
depends on I2C=y
|
||||
help
|
||||
If you say Y here you get support for the X-Powers AXP202 and AXP209.
|
||||
If you say Y here you get support for the X-Powers AXP202, AXP209 and
|
||||
AXP288 power management IC (PMIC).
|
||||
This driver include only the core APIs. You have to select individual
|
||||
components like regulators or the PEK (Power Enable Key) under the
|
||||
corresponding menus.
|
||||
|
|
@ -183,6 +195,16 @@ config MFD_DA9063
|
|||
Additional drivers must be enabled in order to use the functionality
|
||||
of the device.
|
||||
|
||||
config MFD_DLN2
|
||||
tristate "Diolan DLN2 support"
|
||||
select MFD_CORE
|
||||
depends on USB
|
||||
help
|
||||
This adds support for Diolan USB-I2C/SPI/GPIO Master Adapter
|
||||
DLN-2. Additional drivers such as I2C_DLN2, GPIO_DLN2,
|
||||
etc. must be enabled in order to use the functionality of
|
||||
the device.
|
||||
|
||||
config MFD_MC13XXX
|
||||
tristate
|
||||
depends on (SPI_MASTER || I2C)
|
||||
|
|
@ -655,7 +677,6 @@ config MFD_SEC_CORE
|
|||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
select REGULATOR
|
||||
help
|
||||
Support for the Samsung Electronics MFD series.
|
||||
This driver provides common support for accessing the device,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ obj-$(CONFIG_MFD_CROS_EC) += cros_ec.o
|
|||
obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
|
||||
obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
|
||||
|
||||
rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
|
||||
rtsx_pci-objs := rtsx_pcr.o rtsx_gops.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
|
||||
obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o
|
||||
obj-$(CONFIG_MFD_RTSX_USB) += rtsx_usb.o
|
||||
|
||||
|
|
@ -157,6 +157,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
|
|||
obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
|
||||
obj-$(CONFIG_MFD_TPS65090) += tps65090.o
|
||||
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
|
||||
obj-$(CONFIG_MFD_ATMEL_HLCDC) += atmel-hlcdc.o
|
||||
obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
|
||||
obj-$(CONFIG_MFD_PALMAS) += palmas.o
|
||||
obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o
|
||||
|
|
@ -174,6 +175,7 @@ obj-$(CONFIG_MFD_STW481X) += stw481x.o
|
|||
obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o
|
||||
obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o
|
||||
obj-$(CONFIG_MFD_HI6421_PMIC) += hi6421-pmic-core.o
|
||||
obj-$(CONFIG_MFD_DLN2) += dln2.o
|
||||
|
||||
intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
|
||||
obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
|
||||
|
|
|
|||
|
|
@ -85,63 +85,6 @@ shutdown:
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the AB WD to reset the platform. It will perform a hard
|
||||
* reset instead of a soft reset. Write the reset reason to
|
||||
* the AB before reset, which can be read upon restart.
|
||||
*/
|
||||
void ab8500_restart(char mode, const char *cmd)
|
||||
{
|
||||
struct ab8500_platform_data *plat;
|
||||
struct ab8500_sysctrl_platform_data *pdata;
|
||||
u16 reason = 0;
|
||||
u8 val;
|
||||
|
||||
if (sysctrl_dev == NULL) {
|
||||
pr_err("%s: sysctrl not initialized\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
plat = dev_get_platdata(sysctrl_dev->parent);
|
||||
pdata = plat->sysctrl;
|
||||
if (pdata && pdata->reboot_reason_code)
|
||||
reason = pdata->reboot_reason_code(cmd);
|
||||
else
|
||||
pr_warn("[%s] No reboot reason set. Default reason %d\n",
|
||||
__func__, reason);
|
||||
|
||||
/*
|
||||
* Disable RTC alarm, just a precaution so that no alarm
|
||||
* is running when WD reset is executed.
|
||||
*/
|
||||
abx500_get_register_interruptible(sysctrl_dev, AB8500_RTC,
|
||||
RTC_CTRL , &val);
|
||||
abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
|
||||
RTC_CTRL , (val & ~RTC_ALARM_ENABLE));
|
||||
|
||||
/*
|
||||
* Android is not using the RTC alarm registers during reboot
|
||||
* so we borrow them for writing the reason of reset
|
||||
*/
|
||||
|
||||
/* reason[8 LSB] */
|
||||
val = reason & 0xFF;
|
||||
abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
|
||||
AB8500_ALARM_MIN_LOW , val);
|
||||
|
||||
/* reason[8 MSB] */
|
||||
val = (reason>>8) & 0xFF;
|
||||
abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
|
||||
AB8500_ALARM_MIN_MID , val);
|
||||
|
||||
/* Setting WD timeout to 0 */
|
||||
ab8500_sysctrl_write(AB8500_MAINWDOGTIMER, 0xFF, 0x0);
|
||||
|
||||
/* Setting the parameters to AB8500 WD*/
|
||||
ab8500_sysctrl_write(AB8500_MAINWDOGCTRL, 0xFF, (AB8500_ENABLE_WD |
|
||||
AB8500_WD_RESTART_ON_EXPIRE | AB8500_KICK_WD));
|
||||
}
|
||||
|
||||
static inline bool valid_bank(u8 bank)
|
||||
{
|
||||
return ((bank == AB8500_SYS_CTRL1_BLOCK) ||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,9 @@ static int arizona_spi_probe(struct spi_device *spi)
|
|||
static int arizona_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
struct arizona *arizona = spi_get_drvdata(spi);
|
||||
|
||||
arizona_dev_exit(arizona);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
122
drivers/mfd/atmel-hlcdc.c
Normal file
122
drivers/mfd/atmel-hlcdc.c
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Free Electrons
|
||||
* Copyright (C) 2014 Atmel
|
||||
*
|
||||
* Author: Boris BREZILLON <boris.brezillon@free-electrons.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 in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mfd/atmel-hlcdc.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define ATMEL_HLCDC_REG_MAX (0x4000 - 0x4)
|
||||
|
||||
static const struct mfd_cell atmel_hlcdc_cells[] = {
|
||||
{
|
||||
.name = "atmel-hlcdc-pwm",
|
||||
.of_compatible = "atmel,hlcdc-pwm",
|
||||
},
|
||||
{
|
||||
.name = "atmel-hlcdc-dc",
|
||||
.of_compatible = "atmel,hlcdc-display-controller",
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_config atmel_hlcdc_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.max_register = ATMEL_HLCDC_REG_MAX,
|
||||
};
|
||||
|
||||
static int atmel_hlcdc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct atmel_hlcdc *hlcdc;
|
||||
struct resource *res;
|
||||
void __iomem *regs;
|
||||
|
||||
hlcdc = devm_kzalloc(dev, sizeof(*hlcdc), GFP_KERNEL);
|
||||
if (!hlcdc)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
hlcdc->irq = platform_get_irq(pdev, 0);
|
||||
if (hlcdc->irq < 0)
|
||||
return hlcdc->irq;
|
||||
|
||||
hlcdc->periph_clk = devm_clk_get(dev, "periph_clk");
|
||||
if (IS_ERR(hlcdc->periph_clk)) {
|
||||
dev_err(dev, "failed to get peripheral clock\n");
|
||||
return PTR_ERR(hlcdc->periph_clk);
|
||||
}
|
||||
|
||||
hlcdc->sys_clk = devm_clk_get(dev, "sys_clk");
|
||||
if (IS_ERR(hlcdc->sys_clk)) {
|
||||
dev_err(dev, "failed to get system clock\n");
|
||||
return PTR_ERR(hlcdc->sys_clk);
|
||||
}
|
||||
|
||||
hlcdc->slow_clk = devm_clk_get(dev, "slow_clk");
|
||||
if (IS_ERR(hlcdc->slow_clk)) {
|
||||
dev_err(dev, "failed to get slow clock\n");
|
||||
return PTR_ERR(hlcdc->slow_clk);
|
||||
}
|
||||
|
||||
hlcdc->regmap = devm_regmap_init_mmio(dev, regs,
|
||||
&atmel_hlcdc_regmap_config);
|
||||
if (IS_ERR(hlcdc->regmap))
|
||||
return PTR_ERR(hlcdc->regmap);
|
||||
|
||||
dev_set_drvdata(dev, hlcdc);
|
||||
|
||||
return mfd_add_devices(dev, -1, atmel_hlcdc_cells,
|
||||
ARRAY_SIZE(atmel_hlcdc_cells),
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
|
||||
static int atmel_hlcdc_remove(struct platform_device *pdev)
|
||||
{
|
||||
mfd_remove_devices(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id atmel_hlcdc_match[] = {
|
||||
{ .compatible = "atmel,sama5d3-hlcdc" },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static struct platform_driver atmel_hlcdc_driver = {
|
||||
.probe = atmel_hlcdc_probe,
|
||||
.remove = atmel_hlcdc_remove,
|
||||
.driver = {
|
||||
.name = "atmel-hlcdc",
|
||||
.of_match_table = atmel_hlcdc_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(atmel_hlcdc_driver);
|
||||
|
||||
MODULE_ALIAS("platform:atmel-hlcdc");
|
||||
MODULE_AUTHOR("Boris Brezillon <[email protected]>");
|
||||
MODULE_DESCRIPTION("Atmel HLCDC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* axp20x.c - MFD core driver for the X-Powers AXP202 and AXP209
|
||||
* axp20x.c - MFD core driver for the X-Powers' Power Management ICs
|
||||
*
|
||||
* AXP20x comprises an adaptive USB-Compatible PWM charger, 2 BUCK DC-DC
|
||||
* converters, 5 LDOs, multiple 12-bit ADCs of voltage, current and temperature
|
||||
* as well as 4 configurable GPIOs.
|
||||
* AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC
|
||||
* converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
|
||||
* as well as configurable GPIOs.
|
||||
*
|
||||
* Author: Carlo Caione <carlo@caione.org>
|
||||
*
|
||||
|
|
@ -25,9 +25,16 @@
|
|||
#include <linux/mfd/core.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#define AXP20X_OFF 0x80
|
||||
|
||||
static const char const *axp20x_model_names[] = {
|
||||
"AXP202",
|
||||
"AXP209",
|
||||
"AXP288",
|
||||
};
|
||||
|
||||
static const struct regmap_range axp20x_writeable_ranges[] = {
|
||||
regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
|
||||
regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
|
||||
|
|
@ -47,6 +54,25 @@ static const struct regmap_access_table axp20x_volatile_table = {
|
|||
.n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range axp288_writeable_ranges[] = {
|
||||
regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
|
||||
regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
|
||||
};
|
||||
|
||||
static const struct regmap_range axp288_volatile_ranges[] = {
|
||||
regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table axp288_writeable_table = {
|
||||
.yes_ranges = axp288_writeable_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(axp288_writeable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table axp288_volatile_table = {
|
||||
.yes_ranges = axp288_volatile_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(axp288_volatile_ranges),
|
||||
};
|
||||
|
||||
static struct resource axp20x_pek_resources[] = {
|
||||
{
|
||||
.name = "PEK_DBR",
|
||||
|
|
@ -61,6 +87,39 @@ static struct resource axp20x_pek_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct resource axp288_battery_resources[] = {
|
||||
{
|
||||
.start = AXP288_IRQ_QWBTU,
|
||||
.end = AXP288_IRQ_QWBTU,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_WBTU,
|
||||
.end = AXP288_IRQ_WBTU,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_QWBTO,
|
||||
.end = AXP288_IRQ_QWBTO,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_WBTO,
|
||||
.end = AXP288_IRQ_WBTO,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_WL2,
|
||||
.end = AXP288_IRQ_WL2,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_WL1,
|
||||
.end = AXP288_IRQ_WL1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_config axp20x_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
|
@ -70,47 +129,96 @@ static const struct regmap_config axp20x_regmap_config = {
|
|||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
#define AXP20X_IRQ(_irq, _off, _mask) \
|
||||
[AXP20X_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
|
||||
static const struct regmap_config axp288_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.wr_table = &axp288_writeable_table,
|
||||
.volatile_table = &axp288_volatile_table,
|
||||
.max_register = AXP288_FG_TUNE5,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
#define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \
|
||||
[_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
|
||||
|
||||
static const struct regmap_irq axp20x_regmap_irqs[] = {
|
||||
AXP20X_IRQ(ACIN_OVER_V, 0, 7),
|
||||
AXP20X_IRQ(ACIN_PLUGIN, 0, 6),
|
||||
AXP20X_IRQ(ACIN_REMOVAL, 0, 5),
|
||||
AXP20X_IRQ(VBUS_OVER_V, 0, 4),
|
||||
AXP20X_IRQ(VBUS_PLUGIN, 0, 3),
|
||||
AXP20X_IRQ(VBUS_REMOVAL, 0, 2),
|
||||
AXP20X_IRQ(VBUS_V_LOW, 0, 1),
|
||||
AXP20X_IRQ(BATT_PLUGIN, 1, 7),
|
||||
AXP20X_IRQ(BATT_REMOVAL, 1, 6),
|
||||
AXP20X_IRQ(BATT_ENT_ACT_MODE, 1, 5),
|
||||
AXP20X_IRQ(BATT_EXIT_ACT_MODE, 1, 4),
|
||||
AXP20X_IRQ(CHARG, 1, 3),
|
||||
AXP20X_IRQ(CHARG_DONE, 1, 2),
|
||||
AXP20X_IRQ(BATT_TEMP_HIGH, 1, 1),
|
||||
AXP20X_IRQ(BATT_TEMP_LOW, 1, 0),
|
||||
AXP20X_IRQ(DIE_TEMP_HIGH, 2, 7),
|
||||
AXP20X_IRQ(CHARG_I_LOW, 2, 6),
|
||||
AXP20X_IRQ(DCDC1_V_LONG, 2, 5),
|
||||
AXP20X_IRQ(DCDC2_V_LONG, 2, 4),
|
||||
AXP20X_IRQ(DCDC3_V_LONG, 2, 3),
|
||||
AXP20X_IRQ(PEK_SHORT, 2, 1),
|
||||
AXP20X_IRQ(PEK_LONG, 2, 0),
|
||||
AXP20X_IRQ(N_OE_PWR_ON, 3, 7),
|
||||
AXP20X_IRQ(N_OE_PWR_OFF, 3, 6),
|
||||
AXP20X_IRQ(VBUS_VALID, 3, 5),
|
||||
AXP20X_IRQ(VBUS_NOT_VALID, 3, 4),
|
||||
AXP20X_IRQ(VBUS_SESS_VALID, 3, 3),
|
||||
AXP20X_IRQ(VBUS_SESS_END, 3, 2),
|
||||
AXP20X_IRQ(LOW_PWR_LVL1, 3, 1),
|
||||
AXP20X_IRQ(LOW_PWR_LVL2, 3, 0),
|
||||
AXP20X_IRQ(TIMER, 4, 7),
|
||||
AXP20X_IRQ(PEK_RIS_EDGE, 4, 6),
|
||||
AXP20X_IRQ(PEK_FAL_EDGE, 4, 5),
|
||||
AXP20X_IRQ(GPIO3_INPUT, 4, 3),
|
||||
AXP20X_IRQ(GPIO2_INPUT, 4, 2),
|
||||
AXP20X_IRQ(GPIO1_INPUT, 4, 1),
|
||||
AXP20X_IRQ(GPIO0_INPUT, 4, 0),
|
||||
INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V, 0, 7),
|
||||
INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN, 0, 6),
|
||||
INIT_REGMAP_IRQ(AXP20X, ACIN_REMOVAL, 0, 5),
|
||||
INIT_REGMAP_IRQ(AXP20X, VBUS_OVER_V, 0, 4),
|
||||
INIT_REGMAP_IRQ(AXP20X, VBUS_PLUGIN, 0, 3),
|
||||
INIT_REGMAP_IRQ(AXP20X, VBUS_REMOVAL, 0, 2),
|
||||
INIT_REGMAP_IRQ(AXP20X, VBUS_V_LOW, 0, 1),
|
||||
INIT_REGMAP_IRQ(AXP20X, BATT_PLUGIN, 1, 7),
|
||||
INIT_REGMAP_IRQ(AXP20X, BATT_REMOVAL, 1, 6),
|
||||
INIT_REGMAP_IRQ(AXP20X, BATT_ENT_ACT_MODE, 1, 5),
|
||||
INIT_REGMAP_IRQ(AXP20X, BATT_EXIT_ACT_MODE, 1, 4),
|
||||
INIT_REGMAP_IRQ(AXP20X, CHARG, 1, 3),
|
||||
INIT_REGMAP_IRQ(AXP20X, CHARG_DONE, 1, 2),
|
||||
INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_HIGH, 1, 1),
|
||||
INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_LOW, 1, 0),
|
||||
INIT_REGMAP_IRQ(AXP20X, DIE_TEMP_HIGH, 2, 7),
|
||||
INIT_REGMAP_IRQ(AXP20X, CHARG_I_LOW, 2, 6),
|
||||
INIT_REGMAP_IRQ(AXP20X, DCDC1_V_LONG, 2, 5),
|
||||
INIT_REGMAP_IRQ(AXP20X, DCDC2_V_LONG, 2, 4),
|
||||
INIT_REGMAP_IRQ(AXP20X, DCDC3_V_LONG, 2, 3),
|
||||
INIT_REGMAP_IRQ(AXP20X, PEK_SHORT, 2, 1),
|
||||
INIT_REGMAP_IRQ(AXP20X, PEK_LONG, 2, 0),
|
||||
INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_ON, 3, 7),
|
||||
INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_OFF, 3, 6),
|
||||
INIT_REGMAP_IRQ(AXP20X, VBUS_VALID, 3, 5),
|
||||
INIT_REGMAP_IRQ(AXP20X, VBUS_NOT_VALID, 3, 4),
|
||||
INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_VALID, 3, 3),
|
||||
INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_END, 3, 2),
|
||||
INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL1, 3, 1),
|
||||
INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL2, 3, 0),
|
||||
INIT_REGMAP_IRQ(AXP20X, TIMER, 4, 7),
|
||||
INIT_REGMAP_IRQ(AXP20X, PEK_RIS_EDGE, 4, 6),
|
||||
INIT_REGMAP_IRQ(AXP20X, PEK_FAL_EDGE, 4, 5),
|
||||
INIT_REGMAP_IRQ(AXP20X, GPIO3_INPUT, 4, 3),
|
||||
INIT_REGMAP_IRQ(AXP20X, GPIO2_INPUT, 4, 2),
|
||||
INIT_REGMAP_IRQ(AXP20X, GPIO1_INPUT, 4, 1),
|
||||
INIT_REGMAP_IRQ(AXP20X, GPIO0_INPUT, 4, 0),
|
||||
};
|
||||
|
||||
/* some IRQs are compatible with axp20x models */
|
||||
static const struct regmap_irq axp288_regmap_irqs[] = {
|
||||
INIT_REGMAP_IRQ(AXP288, VBUS_FALL, 0, 2),
|
||||
INIT_REGMAP_IRQ(AXP288, VBUS_RISE, 0, 3),
|
||||
INIT_REGMAP_IRQ(AXP288, OV, 0, 4),
|
||||
|
||||
INIT_REGMAP_IRQ(AXP288, DONE, 1, 2),
|
||||
INIT_REGMAP_IRQ(AXP288, CHARGING, 1, 3),
|
||||
INIT_REGMAP_IRQ(AXP288, SAFE_QUIT, 1, 4),
|
||||
INIT_REGMAP_IRQ(AXP288, SAFE_ENTER, 1, 5),
|
||||
INIT_REGMAP_IRQ(AXP288, ABSENT, 1, 6),
|
||||
INIT_REGMAP_IRQ(AXP288, APPEND, 1, 7),
|
||||
|
||||
INIT_REGMAP_IRQ(AXP288, QWBTU, 2, 0),
|
||||
INIT_REGMAP_IRQ(AXP288, WBTU, 2, 1),
|
||||
INIT_REGMAP_IRQ(AXP288, QWBTO, 2, 2),
|
||||
INIT_REGMAP_IRQ(AXP288, WBTO, 2, 3),
|
||||
INIT_REGMAP_IRQ(AXP288, QCBTU, 2, 4),
|
||||
INIT_REGMAP_IRQ(AXP288, CBTU, 2, 5),
|
||||
INIT_REGMAP_IRQ(AXP288, QCBTO, 2, 6),
|
||||
INIT_REGMAP_IRQ(AXP288, CBTO, 2, 7),
|
||||
|
||||
INIT_REGMAP_IRQ(AXP288, WL2, 3, 0),
|
||||
INIT_REGMAP_IRQ(AXP288, WL1, 3, 1),
|
||||
INIT_REGMAP_IRQ(AXP288, GPADC, 3, 2),
|
||||
INIT_REGMAP_IRQ(AXP288, OT, 3, 7),
|
||||
|
||||
INIT_REGMAP_IRQ(AXP288, GPIO0, 4, 0),
|
||||
INIT_REGMAP_IRQ(AXP288, GPIO1, 4, 1),
|
||||
INIT_REGMAP_IRQ(AXP288, POKO, 4, 2),
|
||||
INIT_REGMAP_IRQ(AXP288, POKL, 4, 3),
|
||||
INIT_REGMAP_IRQ(AXP288, POKS, 4, 4),
|
||||
INIT_REGMAP_IRQ(AXP288, POKN, 4, 5),
|
||||
INIT_REGMAP_IRQ(AXP288, POKP, 4, 6),
|
||||
INIT_REGMAP_IRQ(AXP288, TIMER, 4, 7),
|
||||
|
||||
INIT_REGMAP_IRQ(AXP288, MV_CHNG, 5, 0),
|
||||
INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1),
|
||||
};
|
||||
|
||||
static const struct of_device_id axp20x_of_match[] = {
|
||||
|
|
@ -128,16 +236,39 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
|
||||
|
||||
static const struct acpi_device_id axp20x_acpi_match[] = {
|
||||
{
|
||||
.id = "INT33F4",
|
||||
.driver_data = AXP288_ID,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, axp20x_acpi_match);
|
||||
|
||||
static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
|
||||
.name = "axp20x_irq_chip",
|
||||
.status_base = AXP20X_IRQ1_STATE,
|
||||
.ack_base = AXP20X_IRQ1_STATE,
|
||||
.mask_base = AXP20X_IRQ1_EN,
|
||||
.num_regs = 5,
|
||||
.irqs = axp20x_regmap_irqs,
|
||||
.num_irqs = ARRAY_SIZE(axp20x_regmap_irqs),
|
||||
.mask_invert = true,
|
||||
.init_ack_masked = true,
|
||||
.irqs = axp20x_regmap_irqs,
|
||||
.num_irqs = ARRAY_SIZE(axp20x_regmap_irqs),
|
||||
.num_regs = 5,
|
||||
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip axp288_regmap_irq_chip = {
|
||||
.name = "axp288_irq_chip",
|
||||
.status_base = AXP20X_IRQ1_STATE,
|
||||
.ack_base = AXP20X_IRQ1_STATE,
|
||||
.mask_base = AXP20X_IRQ1_EN,
|
||||
.mask_invert = true,
|
||||
.init_ack_masked = true,
|
||||
.irqs = axp288_regmap_irqs,
|
||||
.num_irqs = ARRAY_SIZE(axp288_regmap_irqs),
|
||||
.num_regs = 6,
|
||||
|
||||
};
|
||||
|
||||
static struct mfd_cell axp20x_cells[] = {
|
||||
|
|
@ -150,36 +281,155 @@ static struct mfd_cell axp20x_cells[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct resource axp288_adc_resources[] = {
|
||||
{
|
||||
.name = "GPADC",
|
||||
.start = AXP288_IRQ_GPADC,
|
||||
.end = AXP288_IRQ_GPADC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource axp288_charger_resources[] = {
|
||||
{
|
||||
.start = AXP288_IRQ_OV,
|
||||
.end = AXP288_IRQ_OV,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_DONE,
|
||||
.end = AXP288_IRQ_DONE,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_CHARGING,
|
||||
.end = AXP288_IRQ_CHARGING,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_SAFE_QUIT,
|
||||
.end = AXP288_IRQ_SAFE_QUIT,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_SAFE_ENTER,
|
||||
.end = AXP288_IRQ_SAFE_ENTER,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_QCBTU,
|
||||
.end = AXP288_IRQ_QCBTU,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_CBTU,
|
||||
.end = AXP288_IRQ_CBTU,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_QCBTO,
|
||||
.end = AXP288_IRQ_QCBTO,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_CBTO,
|
||||
.end = AXP288_IRQ_CBTO,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell axp288_cells[] = {
|
||||
{
|
||||
.name = "axp288_adc",
|
||||
.num_resources = ARRAY_SIZE(axp288_adc_resources),
|
||||
.resources = axp288_adc_resources,
|
||||
},
|
||||
{
|
||||
.name = "axp288_charger",
|
||||
.num_resources = ARRAY_SIZE(axp288_charger_resources),
|
||||
.resources = axp288_charger_resources,
|
||||
},
|
||||
{
|
||||
.name = "axp288_battery",
|
||||
.num_resources = ARRAY_SIZE(axp288_battery_resources),
|
||||
.resources = axp288_battery_resources,
|
||||
},
|
||||
};
|
||||
|
||||
static struct axp20x_dev *axp20x_pm_power_off;
|
||||
static void axp20x_power_off(void)
|
||||
{
|
||||
if (axp20x_pm_power_off->variant == AXP288_ID)
|
||||
return;
|
||||
|
||||
regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
|
||||
AXP20X_OFF);
|
||||
}
|
||||
|
||||
static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev)
|
||||
{
|
||||
const struct acpi_device_id *acpi_id;
|
||||
const struct of_device_id *of_id;
|
||||
|
||||
if (dev->of_node) {
|
||||
of_id = of_match_device(axp20x_of_match, dev);
|
||||
if (!of_id) {
|
||||
dev_err(dev, "Unable to match OF ID\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
axp20x->variant = (long) of_id->data;
|
||||
} else {
|
||||
acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
|
||||
if (!acpi_id || !acpi_id->driver_data) {
|
||||
dev_err(dev, "Unable to match ACPI ID and data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
axp20x->variant = (long) acpi_id->driver_data;
|
||||
}
|
||||
|
||||
switch (axp20x->variant) {
|
||||
case AXP202_ID:
|
||||
case AXP209_ID:
|
||||
axp20x->nr_cells = ARRAY_SIZE(axp20x_cells);
|
||||
axp20x->cells = axp20x_cells;
|
||||
axp20x->regmap_cfg = &axp20x_regmap_config;
|
||||
axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip;
|
||||
break;
|
||||
case AXP288_ID:
|
||||
axp20x->cells = axp288_cells;
|
||||
axp20x->nr_cells = ARRAY_SIZE(axp288_cells);
|
||||
axp20x->regmap_cfg = &axp288_regmap_config;
|
||||
axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
|
||||
return -EINVAL;
|
||||
}
|
||||
dev_info(dev, "AXP20x variant %s found\n",
|
||||
axp20x_model_names[axp20x->variant]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int axp20x_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct axp20x_dev *axp20x;
|
||||
const struct of_device_id *of_id;
|
||||
int ret;
|
||||
|
||||
axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL);
|
||||
if (!axp20x)
|
||||
return -ENOMEM;
|
||||
|
||||
of_id = of_match_device(axp20x_of_match, &i2c->dev);
|
||||
if (!of_id) {
|
||||
dev_err(&i2c->dev, "Unable to setup AXP20X data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
axp20x->variant = (long) of_id->data;
|
||||
ret = axp20x_match_device(axp20x, &i2c->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
axp20x->i2c_client = i2c;
|
||||
axp20x->dev = &i2c->dev;
|
||||
dev_set_drvdata(axp20x->dev, axp20x);
|
||||
|
||||
axp20x->regmap = devm_regmap_init_i2c(i2c, &axp20x_regmap_config);
|
||||
axp20x->regmap = devm_regmap_init_i2c(i2c, axp20x->regmap_cfg);
|
||||
if (IS_ERR(axp20x->regmap)) {
|
||||
ret = PTR_ERR(axp20x->regmap);
|
||||
dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
|
||||
|
|
@ -188,15 +438,15 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
|
|||
|
||||
ret = regmap_add_irq_chip(axp20x->regmap, i2c->irq,
|
||||
IRQF_ONESHOT | IRQF_SHARED, -1,
|
||||
&axp20x_regmap_irq_chip,
|
||||
axp20x->regmap_irq_chip,
|
||||
&axp20x->regmap_irqc);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells,
|
||||
ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
|
||||
ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells,
|
||||
axp20x->nr_cells, NULL, 0, NULL);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
|
||||
|
|
@ -234,6 +484,7 @@ static struct i2c_driver axp20x_i2c_driver = {
|
|||
.name = "axp20x",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(axp20x_of_match),
|
||||
.acpi_match_table = ACPI_PTR(axp20x_acpi_match),
|
||||
},
|
||||
.probe = axp20x_i2c_probe,
|
||||
.remove = axp20x_i2c_remove,
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
|
|||
da9063->irq_base = pdata->irq_base;
|
||||
} else {
|
||||
da9063->flags = 0;
|
||||
da9063->irq_base = 0;
|
||||
da9063->irq_base = -1;
|
||||
}
|
||||
da9063->chip_irq = irq;
|
||||
|
||||
|
|
@ -168,6 +168,8 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
|
|||
return ret;
|
||||
}
|
||||
|
||||
da9063->irq_base = regmap_irq_chip_get_base(da9063->regmap_irq);
|
||||
|
||||
ret = mfd_add_devices(da9063->dev, -1, da9063_devs,
|
||||
ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base,
|
||||
NULL);
|
||||
|
|
|
|||
|
|
@ -3150,23 +3150,28 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
|
|||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu");
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "no prcmu memory region provided\n");
|
||||
return -ENOENT;
|
||||
return -EINVAL;
|
||||
}
|
||||
prcmu_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
|
||||
if (!prcmu_base) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to ioremap prcmu register memory\n");
|
||||
return -ENOENT;
|
||||
return -ENOMEM;
|
||||
}
|
||||
init_prcm_registers();
|
||||
dbx500_fw_version_init(pdev, pdata->version_offset);
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "no prcmu tcdm region provided\n");
|
||||
return -ENOENT;
|
||||
return -EINVAL;
|
||||
}
|
||||
tcdm_base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!tcdm_base) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to ioremap prcmu-tcdm register memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Clean up the mailbox interrupts after pre-kernel code. */
|
||||
writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
|
||||
|
|
@ -3174,15 +3179,14 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
|
|||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq <= 0) {
|
||||
dev_err(&pdev->dev, "no prcmu irq provided\n");
|
||||
return -ENOENT;
|
||||
return irq;
|
||||
}
|
||||
|
||||
err = request_threaded_irq(irq, prcmu_irq_handler,
|
||||
prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
|
||||
if (err < 0) {
|
||||
pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n");
|
||||
err = -EBUSY;
|
||||
goto no_irq_return;
|
||||
return err;
|
||||
}
|
||||
|
||||
db8500_irq_init(np);
|
||||
|
|
@ -3206,7 +3210,7 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
|
|||
if (err) {
|
||||
mfd_remove_devices(&pdev->dev);
|
||||
pr_err("prcmu: Failed to add subdevices\n");
|
||||
goto no_irq_return;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3214,12 +3218,10 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
|
|||
if (err) {
|
||||
mfd_remove_devices(&pdev->dev);
|
||||
pr_err("prcmu: Failed to add ab8500 subdevice\n");
|
||||
goto no_irq_return;
|
||||
return err;
|
||||
}
|
||||
|
||||
pr_info("DB8500 PRCMU initialized\n");
|
||||
|
||||
no_irq_return:
|
||||
return err;
|
||||
}
|
||||
static const struct of_device_id db8500_prcmu_match[] = {
|
||||
|
|
|
|||
781
drivers/mfd/dln2.c
Normal file
781
drivers/mfd/dln2.c
Normal file
|
|
@ -0,0 +1,781 @@
|
|||
/*
|
||||
* Driver for the Diolan DLN-2 USB adapter
|
||||
*
|
||||
* Copyright (c) 2014 Intel Corporation
|
||||
*
|
||||
* Derived from:
|
||||
* i2c-diolan-u2c.c
|
||||
* Copyright (c) 2010-2011 Ericsson AB
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/dln2.h>
|
||||
#include <linux/rculist.h>
|
||||
|
||||
struct dln2_header {
|
||||
__le16 size;
|
||||
__le16 id;
|
||||
__le16 echo;
|
||||
__le16 handle;
|
||||
};
|
||||
|
||||
struct dln2_response {
|
||||
struct dln2_header hdr;
|
||||
__le16 result;
|
||||
};
|
||||
|
||||
#define DLN2_GENERIC_MODULE_ID 0x00
|
||||
#define DLN2_GENERIC_CMD(cmd) DLN2_CMD(cmd, DLN2_GENERIC_MODULE_ID)
|
||||
#define CMD_GET_DEVICE_VER DLN2_GENERIC_CMD(0x30)
|
||||
#define CMD_GET_DEVICE_SN DLN2_GENERIC_CMD(0x31)
|
||||
|
||||
#define DLN2_HW_ID 0x200
|
||||
#define DLN2_USB_TIMEOUT 200 /* in ms */
|
||||
#define DLN2_MAX_RX_SLOTS 16
|
||||
#define DLN2_MAX_URBS 16
|
||||
#define DLN2_RX_BUF_SIZE 512
|
||||
|
||||
enum dln2_handle {
|
||||
DLN2_HANDLE_EVENT = 0, /* don't change, hardware defined */
|
||||
DLN2_HANDLE_CTRL,
|
||||
DLN2_HANDLE_GPIO,
|
||||
DLN2_HANDLE_I2C,
|
||||
DLN2_HANDLE_SPI,
|
||||
DLN2_HANDLES
|
||||
};
|
||||
|
||||
/*
|
||||
* Receive context used between the receive demultiplexer and the transfer
|
||||
* routine. While sending a request the transfer routine will look for a free
|
||||
* receive context and use it to wait for a response and to receive the URB and
|
||||
* thus the response data.
|
||||
*/
|
||||
struct dln2_rx_context {
|
||||
/* completion used to wait for a response */
|
||||
struct completion done;
|
||||
|
||||
/* if non-NULL the URB contains the response */
|
||||
struct urb *urb;
|
||||
|
||||
/* if true then this context is used to wait for a response */
|
||||
bool in_use;
|
||||
};
|
||||
|
||||
/*
|
||||
* Receive contexts for a particular DLN2 module (i2c, gpio, etc.). We use the
|
||||
* handle header field to identify the module in dln2_dev.mod_rx_slots and then
|
||||
* the echo header field to index the slots field and find the receive context
|
||||
* for a particular request.
|
||||
*/
|
||||
struct dln2_mod_rx_slots {
|
||||
/* RX slots bitmap */
|
||||
DECLARE_BITMAP(bmap, DLN2_MAX_RX_SLOTS);
|
||||
|
||||
/* used to wait for a free RX slot */
|
||||
wait_queue_head_t wq;
|
||||
|
||||
/* used to wait for an RX operation to complete */
|
||||
struct dln2_rx_context slots[DLN2_MAX_RX_SLOTS];
|
||||
|
||||
/* avoid races between alloc/free_rx_slot and dln2_rx_transfer */
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
struct dln2_dev {
|
||||
struct usb_device *usb_dev;
|
||||
struct usb_interface *interface;
|
||||
u8 ep_in;
|
||||
u8 ep_out;
|
||||
|
||||
struct urb *rx_urb[DLN2_MAX_URBS];
|
||||
void *rx_buf[DLN2_MAX_URBS];
|
||||
|
||||
struct dln2_mod_rx_slots mod_rx_slots[DLN2_HANDLES];
|
||||
|
||||
struct list_head event_cb_list;
|
||||
spinlock_t event_cb_lock;
|
||||
|
||||
bool disconnect;
|
||||
int active_transfers;
|
||||
wait_queue_head_t disconnect_wq;
|
||||
spinlock_t disconnect_lock;
|
||||
};
|
||||
|
||||
struct dln2_event_cb_entry {
|
||||
struct list_head list;
|
||||
u16 id;
|
||||
struct platform_device *pdev;
|
||||
dln2_event_cb_t callback;
|
||||
};
|
||||
|
||||
int dln2_register_event_cb(struct platform_device *pdev, u16 id,
|
||||
dln2_event_cb_t event_cb)
|
||||
{
|
||||
struct dln2_dev *dln2 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct dln2_event_cb_entry *i, *entry;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
entry->id = id;
|
||||
entry->callback = event_cb;
|
||||
entry->pdev = pdev;
|
||||
|
||||
spin_lock_irqsave(&dln2->event_cb_lock, flags);
|
||||
|
||||
list_for_each_entry(i, &dln2->event_cb_list, list) {
|
||||
if (i->id == id) {
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
list_add_rcu(&entry->list, &dln2->event_cb_list);
|
||||
|
||||
spin_unlock_irqrestore(&dln2->event_cb_lock, flags);
|
||||
|
||||
if (ret)
|
||||
kfree(entry);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dln2_register_event_cb);
|
||||
|
||||
void dln2_unregister_event_cb(struct platform_device *pdev, u16 id)
|
||||
{
|
||||
struct dln2_dev *dln2 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct dln2_event_cb_entry *i;
|
||||
unsigned long flags;
|
||||
bool found = false;
|
||||
|
||||
spin_lock_irqsave(&dln2->event_cb_lock, flags);
|
||||
|
||||
list_for_each_entry(i, &dln2->event_cb_list, list) {
|
||||
if (i->id == id) {
|
||||
list_del_rcu(&i->list);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dln2->event_cb_lock, flags);
|
||||
|
||||
if (found) {
|
||||
synchronize_rcu();
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(dln2_unregister_event_cb);
|
||||
|
||||
/*
|
||||
* Returns true if a valid transfer slot is found. In this case the URB must not
|
||||
* be resubmitted immediately in dln2_rx as we need the data when dln2_transfer
|
||||
* is woke up. It will be resubmitted there.
|
||||
*/
|
||||
static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb,
|
||||
u16 handle, u16 rx_slot)
|
||||
{
|
||||
struct device *dev = &dln2->interface->dev;
|
||||
struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle];
|
||||
struct dln2_rx_context *rxc;
|
||||
bool valid_slot = false;
|
||||
|
||||
if (rx_slot >= DLN2_MAX_RX_SLOTS)
|
||||
goto out;
|
||||
|
||||
rxc = &rxs->slots[rx_slot];
|
||||
|
||||
/*
|
||||
* No need to disable interrupts as this lock is not taken in interrupt
|
||||
* context elsewhere in this driver. This function (or its callers) are
|
||||
* also not exported to other modules.
|
||||
*/
|
||||
spin_lock(&rxs->lock);
|
||||
if (rxc->in_use && !rxc->urb) {
|
||||
rxc->urb = urb;
|
||||
complete(&rxc->done);
|
||||
valid_slot = true;
|
||||
}
|
||||
spin_unlock(&rxs->lock);
|
||||
|
||||
out:
|
||||
if (!valid_slot)
|
||||
dev_warn(dev, "bad/late response %d/%d\n", handle, rx_slot);
|
||||
|
||||
return valid_slot;
|
||||
}
|
||||
|
||||
static void dln2_run_event_callbacks(struct dln2_dev *dln2, u16 id, u16 echo,
|
||||
void *data, int len)
|
||||
{
|
||||
struct dln2_event_cb_entry *i;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
list_for_each_entry_rcu(i, &dln2->event_cb_list, list) {
|
||||
if (i->id == id) {
|
||||
i->callback(i->pdev, echo, data, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void dln2_rx(struct urb *urb)
|
||||
{
|
||||
struct dln2_dev *dln2 = urb->context;
|
||||
struct dln2_header *hdr = urb->transfer_buffer;
|
||||
struct device *dev = &dln2->interface->dev;
|
||||
u16 id, echo, handle, size;
|
||||
u8 *data;
|
||||
int len;
|
||||
int err;
|
||||
|
||||
switch (urb->status) {
|
||||
case 0:
|
||||
/* success */
|
||||
break;
|
||||
case -ECONNRESET:
|
||||
case -ENOENT:
|
||||
case -ESHUTDOWN:
|
||||
case -EPIPE:
|
||||
/* this urb is terminated, clean up */
|
||||
dev_dbg(dev, "urb shutting down with status %d\n", urb->status);
|
||||
return;
|
||||
default:
|
||||
dev_dbg(dev, "nonzero urb status received %d\n", urb->status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (urb->actual_length < sizeof(struct dln2_header)) {
|
||||
dev_err(dev, "short response: %d\n", urb->actual_length);
|
||||
goto out;
|
||||
}
|
||||
|
||||
handle = le16_to_cpu(hdr->handle);
|
||||
id = le16_to_cpu(hdr->id);
|
||||
echo = le16_to_cpu(hdr->echo);
|
||||
size = le16_to_cpu(hdr->size);
|
||||
|
||||
if (size != urb->actual_length) {
|
||||
dev_err(dev, "size mismatch: handle %x cmd %x echo %x size %d actual %d\n",
|
||||
handle, id, echo, size, urb->actual_length);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (handle >= DLN2_HANDLES) {
|
||||
dev_warn(dev, "invalid handle %d\n", handle);
|
||||
goto out;
|
||||
}
|
||||
|
||||
data = urb->transfer_buffer + sizeof(struct dln2_header);
|
||||
len = urb->actual_length - sizeof(struct dln2_header);
|
||||
|
||||
if (handle == DLN2_HANDLE_EVENT) {
|
||||
dln2_run_event_callbacks(dln2, id, echo, data, len);
|
||||
} else {
|
||||
/* URB will be re-submitted in _dln2_transfer (free_rx_slot) */
|
||||
if (dln2_transfer_complete(dln2, urb, handle, echo))
|
||||
return;
|
||||
}
|
||||
|
||||
out:
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (err < 0)
|
||||
dev_err(dev, "failed to resubmit RX URB: %d\n", err);
|
||||
}
|
||||
|
||||
static void *dln2_prep_buf(u16 handle, u16 cmd, u16 echo, const void *obuf,
|
||||
int *obuf_len, gfp_t gfp)
|
||||
{
|
||||
int len;
|
||||
void *buf;
|
||||
struct dln2_header *hdr;
|
||||
|
||||
len = *obuf_len + sizeof(*hdr);
|
||||
buf = kmalloc(len, gfp);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
hdr = (struct dln2_header *)buf;
|
||||
hdr->id = cpu_to_le16(cmd);
|
||||
hdr->size = cpu_to_le16(len);
|
||||
hdr->echo = cpu_to_le16(echo);
|
||||
hdr->handle = cpu_to_le16(handle);
|
||||
|
||||
memcpy(buf + sizeof(*hdr), obuf, *obuf_len);
|
||||
|
||||
*obuf_len = len;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int dln2_send_wait(struct dln2_dev *dln2, u16 handle, u16 cmd, u16 echo,
|
||||
const void *obuf, int obuf_len)
|
||||
{
|
||||
int ret = 0;
|
||||
int len = obuf_len;
|
||||
void *buf;
|
||||
int actual;
|
||||
|
||||
buf = dln2_prep_buf(handle, cmd, echo, obuf, &len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = usb_bulk_msg(dln2->usb_dev,
|
||||
usb_sndbulkpipe(dln2->usb_dev, dln2->ep_out),
|
||||
buf, len, &actual, DLN2_USB_TIMEOUT);
|
||||
|
||||
kfree(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool find_free_slot(struct dln2_dev *dln2, u16 handle, int *slot)
|
||||
{
|
||||
struct dln2_mod_rx_slots *rxs;
|
||||
unsigned long flags;
|
||||
|
||||
if (dln2->disconnect) {
|
||||
*slot = -ENODEV;
|
||||
return true;
|
||||
}
|
||||
|
||||
rxs = &dln2->mod_rx_slots[handle];
|
||||
|
||||
spin_lock_irqsave(&rxs->lock, flags);
|
||||
|
||||
*slot = find_first_zero_bit(rxs->bmap, DLN2_MAX_RX_SLOTS);
|
||||
|
||||
if (*slot < DLN2_MAX_RX_SLOTS) {
|
||||
struct dln2_rx_context *rxc = &rxs->slots[*slot];
|
||||
|
||||
set_bit(*slot, rxs->bmap);
|
||||
rxc->in_use = true;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&rxs->lock, flags);
|
||||
|
||||
return *slot < DLN2_MAX_RX_SLOTS;
|
||||
}
|
||||
|
||||
static int alloc_rx_slot(struct dln2_dev *dln2, u16 handle)
|
||||
{
|
||||
int ret;
|
||||
int slot;
|
||||
|
||||
/*
|
||||
* No need to timeout here, the wait is bounded by the timeout in
|
||||
* _dln2_transfer.
|
||||
*/
|
||||
ret = wait_event_interruptible(dln2->mod_rx_slots[handle].wq,
|
||||
find_free_slot(dln2, handle, &slot));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
static void free_rx_slot(struct dln2_dev *dln2, u16 handle, int slot)
|
||||
{
|
||||
struct dln2_mod_rx_slots *rxs;
|
||||
struct urb *urb = NULL;
|
||||
unsigned long flags;
|
||||
struct dln2_rx_context *rxc;
|
||||
|
||||
rxs = &dln2->mod_rx_slots[handle];
|
||||
|
||||
spin_lock_irqsave(&rxs->lock, flags);
|
||||
|
||||
clear_bit(slot, rxs->bmap);
|
||||
|
||||
rxc = &rxs->slots[slot];
|
||||
rxc->in_use = false;
|
||||
urb = rxc->urb;
|
||||
rxc->urb = NULL;
|
||||
reinit_completion(&rxc->done);
|
||||
|
||||
spin_unlock_irqrestore(&rxs->lock, flags);
|
||||
|
||||
if (urb) {
|
||||
int err;
|
||||
struct device *dev = &dln2->interface->dev;
|
||||
|
||||
err = usb_submit_urb(urb, GFP_KERNEL);
|
||||
if (err < 0)
|
||||
dev_err(dev, "failed to resubmit RX URB: %d\n", err);
|
||||
}
|
||||
|
||||
wake_up_interruptible(&rxs->wq);
|
||||
}
|
||||
|
||||
static int _dln2_transfer(struct dln2_dev *dln2, u16 handle, u16 cmd,
|
||||
const void *obuf, unsigned obuf_len,
|
||||
void *ibuf, unsigned *ibuf_len)
|
||||
{
|
||||
int ret = 0;
|
||||
int rx_slot;
|
||||
struct dln2_response *rsp;
|
||||
struct dln2_rx_context *rxc;
|
||||
struct device *dev = &dln2->interface->dev;
|
||||
const unsigned long timeout = DLN2_USB_TIMEOUT * HZ / 1000;
|
||||
struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle];
|
||||
int size;
|
||||
|
||||
spin_lock(&dln2->disconnect_lock);
|
||||
if (!dln2->disconnect)
|
||||
dln2->active_transfers++;
|
||||
else
|
||||
ret = -ENODEV;
|
||||
spin_unlock(&dln2->disconnect_lock);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rx_slot = alloc_rx_slot(dln2, handle);
|
||||
if (rx_slot < 0) {
|
||||
ret = rx_slot;
|
||||
goto out_decr;
|
||||
}
|
||||
|
||||
ret = dln2_send_wait(dln2, handle, cmd, rx_slot, obuf, obuf_len);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "USB write failed: %d\n", ret);
|
||||
goto out_free_rx_slot;
|
||||
}
|
||||
|
||||
rxc = &rxs->slots[rx_slot];
|
||||
|
||||
ret = wait_for_completion_interruptible_timeout(&rxc->done, timeout);
|
||||
if (ret <= 0) {
|
||||
if (!ret)
|
||||
ret = -ETIMEDOUT;
|
||||
goto out_free_rx_slot;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (dln2->disconnect) {
|
||||
ret = -ENODEV;
|
||||
goto out_free_rx_slot;
|
||||
}
|
||||
|
||||
/* if we got here we know that the response header has been checked */
|
||||
rsp = rxc->urb->transfer_buffer;
|
||||
size = le16_to_cpu(rsp->hdr.size);
|
||||
|
||||
if (size < sizeof(*rsp)) {
|
||||
ret = -EPROTO;
|
||||
goto out_free_rx_slot;
|
||||
}
|
||||
|
||||
if (le16_to_cpu(rsp->result) > 0x80) {
|
||||
dev_dbg(dev, "%d received response with error %d\n",
|
||||
handle, le16_to_cpu(rsp->result));
|
||||
ret = -EREMOTEIO;
|
||||
goto out_free_rx_slot;
|
||||
}
|
||||
|
||||
if (!ibuf)
|
||||
goto out_free_rx_slot;
|
||||
|
||||
if (*ibuf_len > size - sizeof(*rsp))
|
||||
*ibuf_len = size - sizeof(*rsp);
|
||||
|
||||
memcpy(ibuf, rsp + 1, *ibuf_len);
|
||||
|
||||
out_free_rx_slot:
|
||||
free_rx_slot(dln2, handle, rx_slot);
|
||||
out_decr:
|
||||
spin_lock(&dln2->disconnect_lock);
|
||||
dln2->active_transfers--;
|
||||
spin_unlock(&dln2->disconnect_lock);
|
||||
if (dln2->disconnect)
|
||||
wake_up(&dln2->disconnect_wq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dln2_transfer(struct platform_device *pdev, u16 cmd,
|
||||
const void *obuf, unsigned obuf_len,
|
||||
void *ibuf, unsigned *ibuf_len)
|
||||
{
|
||||
struct dln2_platform_data *dln2_pdata;
|
||||
struct dln2_dev *dln2;
|
||||
u16 handle;
|
||||
|
||||
dln2 = dev_get_drvdata(pdev->dev.parent);
|
||||
dln2_pdata = dev_get_platdata(&pdev->dev);
|
||||
handle = dln2_pdata->handle;
|
||||
|
||||
return _dln2_transfer(dln2, handle, cmd, obuf, obuf_len, ibuf,
|
||||
ibuf_len);
|
||||
}
|
||||
EXPORT_SYMBOL(dln2_transfer);
|
||||
|
||||
static int dln2_check_hw(struct dln2_dev *dln2)
|
||||
{
|
||||
int ret;
|
||||
__le32 hw_type;
|
||||
int len = sizeof(hw_type);
|
||||
|
||||
ret = _dln2_transfer(dln2, DLN2_HANDLE_CTRL, CMD_GET_DEVICE_VER,
|
||||
NULL, 0, &hw_type, &len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (len < sizeof(hw_type))
|
||||
return -EREMOTEIO;
|
||||
|
||||
if (le32_to_cpu(hw_type) != DLN2_HW_ID) {
|
||||
dev_err(&dln2->interface->dev, "Device ID 0x%x not supported\n",
|
||||
le32_to_cpu(hw_type));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dln2_print_serialno(struct dln2_dev *dln2)
|
||||
{
|
||||
int ret;
|
||||
__le32 serial_no;
|
||||
int len = sizeof(serial_no);
|
||||
struct device *dev = &dln2->interface->dev;
|
||||
|
||||
ret = _dln2_transfer(dln2, DLN2_HANDLE_CTRL, CMD_GET_DEVICE_SN, NULL, 0,
|
||||
&serial_no, &len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (len < sizeof(serial_no))
|
||||
return -EREMOTEIO;
|
||||
|
||||
dev_info(dev, "Diolan DLN2 serial %u\n", le32_to_cpu(serial_no));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dln2_hw_init(struct dln2_dev *dln2)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dln2_check_hw(dln2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return dln2_print_serialno(dln2);
|
||||
}
|
||||
|
||||
static void dln2_free_rx_urbs(struct dln2_dev *dln2)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DLN2_MAX_URBS; i++) {
|
||||
usb_kill_urb(dln2->rx_urb[i]);
|
||||
usb_free_urb(dln2->rx_urb[i]);
|
||||
kfree(dln2->rx_buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void dln2_free(struct dln2_dev *dln2)
|
||||
{
|
||||
dln2_free_rx_urbs(dln2);
|
||||
usb_put_dev(dln2->usb_dev);
|
||||
kfree(dln2);
|
||||
}
|
||||
|
||||
static int dln2_setup_rx_urbs(struct dln2_dev *dln2,
|
||||
struct usb_host_interface *hostif)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
const int rx_max_size = DLN2_RX_BUF_SIZE;
|
||||
struct device *dev = &dln2->interface->dev;
|
||||
|
||||
for (i = 0; i < DLN2_MAX_URBS; i++) {
|
||||
dln2->rx_buf[i] = kmalloc(rx_max_size, GFP_KERNEL);
|
||||
if (!dln2->rx_buf[i])
|
||||
return -ENOMEM;
|
||||
|
||||
dln2->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!dln2->rx_urb[i])
|
||||
return -ENOMEM;
|
||||
|
||||
usb_fill_bulk_urb(dln2->rx_urb[i], dln2->usb_dev,
|
||||
usb_rcvbulkpipe(dln2->usb_dev, dln2->ep_in),
|
||||
dln2->rx_buf[i], rx_max_size, dln2_rx, dln2);
|
||||
|
||||
ret = usb_submit_urb(dln2->rx_urb[i], GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to submit RX URB: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dln2_platform_data dln2_pdata_gpio = {
|
||||
.handle = DLN2_HANDLE_GPIO,
|
||||
};
|
||||
|
||||
/* Only one I2C port seems to be supported on current hardware */
|
||||
static struct dln2_platform_data dln2_pdata_i2c = {
|
||||
.handle = DLN2_HANDLE_I2C,
|
||||
.port = 0,
|
||||
};
|
||||
|
||||
/* Only one SPI port supported */
|
||||
static struct dln2_platform_data dln2_pdata_spi = {
|
||||
.handle = DLN2_HANDLE_SPI,
|
||||
.port = 0,
|
||||
};
|
||||
|
||||
static const struct mfd_cell dln2_devs[] = {
|
||||
{
|
||||
.name = "dln2-gpio",
|
||||
.platform_data = &dln2_pdata_gpio,
|
||||
.pdata_size = sizeof(struct dln2_platform_data),
|
||||
},
|
||||
{
|
||||
.name = "dln2-i2c",
|
||||
.platform_data = &dln2_pdata_i2c,
|
||||
.pdata_size = sizeof(struct dln2_platform_data),
|
||||
},
|
||||
{
|
||||
.name = "dln2-spi",
|
||||
.platform_data = &dln2_pdata_spi,
|
||||
.pdata_size = sizeof(struct dln2_platform_data),
|
||||
},
|
||||
};
|
||||
|
||||
static void dln2_disconnect(struct usb_interface *interface)
|
||||
{
|
||||
struct dln2_dev *dln2 = usb_get_intfdata(interface);
|
||||
int i, j;
|
||||
|
||||
/* don't allow starting new transfers */
|
||||
spin_lock(&dln2->disconnect_lock);
|
||||
dln2->disconnect = true;
|
||||
spin_unlock(&dln2->disconnect_lock);
|
||||
|
||||
/* cancel in progress transfers */
|
||||
for (i = 0; i < DLN2_HANDLES; i++) {
|
||||
struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[i];
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rxs->lock, flags);
|
||||
|
||||
/* cancel all response waiters */
|
||||
for (j = 0; j < DLN2_MAX_RX_SLOTS; j++) {
|
||||
struct dln2_rx_context *rxc = &rxs->slots[j];
|
||||
|
||||
if (rxc->in_use)
|
||||
complete(&rxc->done);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&rxs->lock, flags);
|
||||
}
|
||||
|
||||
/* wait for transfers to end */
|
||||
wait_event(dln2->disconnect_wq, !dln2->active_transfers);
|
||||
|
||||
mfd_remove_devices(&interface->dev);
|
||||
|
||||
dln2_free(dln2);
|
||||
}
|
||||
|
||||
static int dln2_probe(struct usb_interface *interface,
|
||||
const struct usb_device_id *usb_id)
|
||||
{
|
||||
struct usb_host_interface *hostif = interface->cur_altsetting;
|
||||
struct device *dev = &interface->dev;
|
||||
struct dln2_dev *dln2;
|
||||
int ret;
|
||||
int i, j;
|
||||
|
||||
if (hostif->desc.bInterfaceNumber != 0 ||
|
||||
hostif->desc.bNumEndpoints < 2)
|
||||
return -ENODEV;
|
||||
|
||||
dln2 = kzalloc(sizeof(*dln2), GFP_KERNEL);
|
||||
if (!dln2)
|
||||
return -ENOMEM;
|
||||
|
||||
dln2->ep_out = hostif->endpoint[0].desc.bEndpointAddress;
|
||||
dln2->ep_in = hostif->endpoint[1].desc.bEndpointAddress;
|
||||
dln2->usb_dev = usb_get_dev(interface_to_usbdev(interface));
|
||||
dln2->interface = interface;
|
||||
usb_set_intfdata(interface, dln2);
|
||||
init_waitqueue_head(&dln2->disconnect_wq);
|
||||
|
||||
for (i = 0; i < DLN2_HANDLES; i++) {
|
||||
init_waitqueue_head(&dln2->mod_rx_slots[i].wq);
|
||||
spin_lock_init(&dln2->mod_rx_slots[i].lock);
|
||||
for (j = 0; j < DLN2_MAX_RX_SLOTS; j++)
|
||||
init_completion(&dln2->mod_rx_slots[i].slots[j].done);
|
||||
}
|
||||
|
||||
spin_lock_init(&dln2->event_cb_lock);
|
||||
spin_lock_init(&dln2->disconnect_lock);
|
||||
INIT_LIST_HEAD(&dln2->event_cb_list);
|
||||
|
||||
ret = dln2_setup_rx_urbs(dln2, hostif);
|
||||
if (ret)
|
||||
goto out_cleanup;
|
||||
|
||||
ret = dln2_hw_init(dln2);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to initialize hardware\n");
|
||||
goto out_cleanup;
|
||||
}
|
||||
|
||||
ret = mfd_add_hotplug_devices(dev, dln2_devs, ARRAY_SIZE(dln2_devs));
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "failed to add mfd devices to core\n");
|
||||
goto out_cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_cleanup:
|
||||
dln2_free(dln2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct usb_device_id dln2_table[] = {
|
||||
{ USB_DEVICE(0xa257, 0x2013) },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, dln2_table);
|
||||
|
||||
static struct usb_driver dln2_driver = {
|
||||
.name = "dln2",
|
||||
.probe = dln2_probe,
|
||||
.disconnect = dln2_disconnect,
|
||||
.id_table = dln2_table,
|
||||
};
|
||||
|
||||
module_usb_driver(dln2_driver);
|
||||
|
||||
MODULE_AUTHOR("Octavian Purdila <[email protected]>");
|
||||
MODULE_DESCRIPTION("Core driver for the Diolan DLN2 interface adapter");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -193,11 +193,7 @@ static int lpc_sch_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0, NULL);
|
||||
if (ret)
|
||||
mfd_remove_devices(&dev->dev);
|
||||
|
||||
return ret;
|
||||
return mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
static void lpc_sch_remove(struct pci_dev *dev)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* max14577.c - mfd core driver for the Maxim 14577/77836
|
||||
*
|
||||
* Copyright (C) 2014 Samsung Electrnoics
|
||||
* Copyright (C) 2014 Samsung Electronics
|
||||
* Chanwoo Choi <cw00.choi@samsung.com>
|
||||
* Krzysztof Kozlowski <k.kozlowski@samsung.com>
|
||||
*
|
||||
|
|
|
|||
|
|
@ -43,9 +43,15 @@
|
|||
|
||||
static const struct mfd_cell max77693_devs[] = {
|
||||
{ .name = "max77693-pmic", },
|
||||
{ .name = "max77693-charger", },
|
||||
{
|
||||
.name = "max77693-charger",
|
||||
.of_compatible = "maxim,max77693-charger",
|
||||
},
|
||||
{ .name = "max77693-muic", },
|
||||
{ .name = "max77693-haptic", },
|
||||
{
|
||||
.name = "max77693-haptic",
|
||||
.of_compatible = "maxim,max77693-haptic",
|
||||
},
|
||||
{
|
||||
.name = "max77693-flash",
|
||||
.of_compatible = "maxim,max77693-flash",
|
||||
|
|
@ -147,6 +153,12 @@ static const struct regmap_irq_chip max77693_muic_irq_chip = {
|
|||
.num_irqs = ARRAY_SIZE(max77693_muic_irqs),
|
||||
};
|
||||
|
||||
static const struct regmap_config max77693_regmap_haptic_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = MAX77693_HAPTIC_REG_END,
|
||||
};
|
||||
|
||||
static int max77693_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
|
@ -196,6 +208,15 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
|
|||
}
|
||||
i2c_set_clientdata(max77693->haptic, max77693);
|
||||
|
||||
max77693->regmap_haptic = devm_regmap_init_i2c(max77693->haptic,
|
||||
&max77693_regmap_haptic_config);
|
||||
if (IS_ERR(max77693->regmap_haptic)) {
|
||||
ret = PTR_ERR(max77693->regmap_haptic);
|
||||
dev_err(max77693->dev,
|
||||
"failed to initialize haptic register map: %d\n", ret);
|
||||
goto err_regmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize register map for MUIC device because use regmap-muic
|
||||
* instance of MUIC device when irq of max77693 is initialized
|
||||
|
|
@ -207,7 +228,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
|
|||
ret = PTR_ERR(max77693->regmap_muic);
|
||||
dev_err(max77693->dev,
|
||||
"failed to allocate register map: %d\n", ret);
|
||||
goto err_regmap_muic;
|
||||
goto err_regmap;
|
||||
}
|
||||
|
||||
ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
|
||||
|
|
@ -217,7 +238,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
|
|||
&max77693->irq_data_led);
|
||||
if (ret) {
|
||||
dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
|
||||
goto err_regmap_muic;
|
||||
goto err_regmap;
|
||||
}
|
||||
|
||||
ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
|
||||
|
|
@ -280,7 +301,7 @@ err_irq_charger:
|
|||
regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
|
||||
err_irq_topsys:
|
||||
regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
|
||||
err_regmap_muic:
|
||||
err_regmap:
|
||||
i2c_unregister_device(max77693->haptic);
|
||||
err_i2c_haptic:
|
||||
i2c_unregister_device(max77693->muic);
|
||||
|
|
|
|||
|
|
@ -125,9 +125,15 @@ static int mfd_add_device(struct device *parent, int id,
|
|||
struct platform_device *pdev;
|
||||
struct device_node *np = NULL;
|
||||
int ret = -ENOMEM;
|
||||
int platform_id;
|
||||
int r;
|
||||
|
||||
pdev = platform_device_alloc(cell->name, id + cell->id);
|
||||
if (id < 0)
|
||||
platform_id = id;
|
||||
else
|
||||
platform_id = id + cell->id;
|
||||
|
||||
pdev = platform_device_alloc(cell->name, platform_id);
|
||||
if (!pdev)
|
||||
goto fail_alloc;
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,12 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
|
|||
|
||||
static int rts5227_optimize_phy(struct rtsx_pcr *pcr)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = rtsx_gops_pm_reset(pcr);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* Optimize RX sensitivity */
|
||||
return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,6 +130,10 @@ static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
|
|||
{
|
||||
int err;
|
||||
|
||||
err = rtsx_gops_pm_reset(pcr);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV,
|
||||
PHY_REG_REV_RESV | PHY_REG_REV_RXIDLE_LATCHED |
|
||||
PHY_REG_REV_P1_EN | PHY_REG_REV_RXIDLE_EN |
|
||||
|
|
|
|||
37
drivers/mfd/rtsx_gops.c
Normal file
37
drivers/mfd/rtsx_gops.c
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* Driver for Realtek PCI-Express card reader
|
||||
*
|
||||
* Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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 as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Micky Ching <micky_ching@realsil.com.cn>
|
||||
*/
|
||||
|
||||
#include <linux/mfd/rtsx_pci.h>
|
||||
#include "rtsx_pcr.h"
|
||||
|
||||
int rtsx_gops_pm_reset(struct rtsx_pcr *pcr)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* init aspm */
|
||||
rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0xFF, 0x00);
|
||||
err = rtsx_pci_update_cfg_byte(pcr, LCTLR, ~LCTLR_ASPM_CTL_MASK, 0x00);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* reset PM_CTRL3 before send buffer cmd */
|
||||
return rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
|
||||
}
|
||||
|
|
@ -72,4 +72,7 @@ do { \
|
|||
pcr->ms_pull_ctl_disable_tbl = __device##_ms_pull_ctl_disable_tbl; \
|
||||
} while (0)
|
||||
|
||||
/* generic operations */
|
||||
int rtsx_gops_pm_reset(struct rtsx_pcr *pcr);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -647,8 +647,8 @@ static int rtsx_usb_probe(struct usb_interface *intf,
|
|||
/* initialize USB SG transfer timer */
|
||||
setup_timer(&ucr->sg_timer, rtsx_usb_sg_timed_out, (unsigned long) ucr);
|
||||
|
||||
ret = mfd_add_devices(&intf->dev, usb_dev->devnum, rtsx_usb_cells,
|
||||
ARRAY_SIZE(rtsx_usb_cells), NULL, 0, NULL);
|
||||
ret = mfd_add_hotplug_devices(&intf->dev, rtsx_usb_cells,
|
||||
ARRAY_SIZE(rtsx_usb_cells));
|
||||
if (ret)
|
||||
goto out_init_fail;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@
|
|||
#include <linux/mfd/samsung/irq.h>
|
||||
#include <linux/mfd/samsung/s2mpa01.h>
|
||||
#include <linux/mfd/samsung/s2mps11.h>
|
||||
#include <linux/mfd/samsung/s2mps13.h>
|
||||
#include <linux/mfd/samsung/s2mps14.h>
|
||||
#include <linux/mfd/samsung/s2mpu02.h>
|
||||
#include <linux/mfd/samsung/s5m8763.h>
|
||||
#include <linux/mfd/samsung/s5m8767.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
static const struct mfd_cell s5m8751_devs[] = {
|
||||
|
|
@ -74,6 +74,15 @@ static const struct mfd_cell s2mps11_devs[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static const struct mfd_cell s2mps13_devs[] = {
|
||||
{ .name = "s2mps13-pmic", },
|
||||
{ .name = "s2mps13-rtc", },
|
||||
{
|
||||
.name = "s2mps13-clk",
|
||||
.of_compatible = "samsung,s2mps13-clk",
|
||||
},
|
||||
};
|
||||
|
||||
static const struct mfd_cell s2mps14_devs[] = {
|
||||
{
|
||||
.name = "s2mps14-pmic",
|
||||
|
|
@ -107,6 +116,9 @@ static const struct of_device_id sec_dt_match[] = {
|
|||
}, {
|
||||
.compatible = "samsung,s2mps11-pmic",
|
||||
.data = (void *)S2MPS11X,
|
||||
}, {
|
||||
.compatible = "samsung,s2mps13-pmic",
|
||||
.data = (void *)S2MPS13X,
|
||||
}, {
|
||||
.compatible = "samsung,s2mps14-pmic",
|
||||
.data = (void *)S2MPS14X,
|
||||
|
|
@ -194,6 +206,15 @@ static const struct regmap_config s2mps11_regmap_config = {
|
|||
.cache_type = REGCACHE_FLAT,
|
||||
};
|
||||
|
||||
static const struct regmap_config s2mps13_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = S2MPS13_REG_LDODSCH5,
|
||||
.volatile_reg = s2mps11_volatile,
|
||||
.cache_type = REGCACHE_FLAT,
|
||||
};
|
||||
|
||||
static const struct regmap_config s2mps14_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
|
@ -325,6 +346,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
|
|||
case S2MPS11X:
|
||||
regmap = &s2mps11_regmap_config;
|
||||
break;
|
||||
case S2MPS13X:
|
||||
regmap = &s2mps13_regmap_config;
|
||||
break;
|
||||
case S2MPS14X:
|
||||
regmap = &s2mps14_regmap_config;
|
||||
break;
|
||||
|
|
@ -378,6 +402,10 @@ static int sec_pmic_probe(struct i2c_client *i2c,
|
|||
sec_devs = s2mps11_devs;
|
||||
num_sec_devs = ARRAY_SIZE(s2mps11_devs);
|
||||
break;
|
||||
case S2MPS13X:
|
||||
sec_devs = s2mps13_devs;
|
||||
num_sec_devs = ARRAY_SIZE(s2mps13_devs);
|
||||
break;
|
||||
case S2MPS14X:
|
||||
sec_devs = s2mps14_devs;
|
||||
num_sec_devs = ARRAY_SIZE(s2mps14_devs);
|
||||
|
|
@ -432,15 +460,6 @@ static int sec_pmic_suspend(struct device *dev)
|
|||
*/
|
||||
disable_irq(sec_pmic->irq);
|
||||
|
||||
switch (sec_pmic->device_type) {
|
||||
case S2MPS14X:
|
||||
case S2MPU02:
|
||||
regulator_suspend_prepare(PM_SUSPEND_MEM);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -389,14 +389,22 @@ static const struct regmap_irq_chip s2mps11_irq_chip = {
|
|||
.ack_base = S2MPS11_REG_INT1,
|
||||
};
|
||||
|
||||
#define S2MPS1X_IRQ_CHIP_COMMON_DATA \
|
||||
.irqs = s2mps14_irqs, \
|
||||
.num_irqs = ARRAY_SIZE(s2mps14_irqs), \
|
||||
.num_regs = 3, \
|
||||
.status_base = S2MPS14_REG_INT1, \
|
||||
.mask_base = S2MPS14_REG_INT1M, \
|
||||
.ack_base = S2MPS14_REG_INT1 \
|
||||
|
||||
static const struct regmap_irq_chip s2mps13_irq_chip = {
|
||||
.name = "s2mps13",
|
||||
S2MPS1X_IRQ_CHIP_COMMON_DATA,
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip s2mps14_irq_chip = {
|
||||
.name = "s2mps14",
|
||||
.irqs = s2mps14_irqs,
|
||||
.num_irqs = ARRAY_SIZE(s2mps14_irqs),
|
||||
.num_regs = 3,
|
||||
.status_base = S2MPS14_REG_INT1,
|
||||
.mask_base = S2MPS14_REG_INT1M,
|
||||
.ack_base = S2MPS14_REG_INT1,
|
||||
S2MPS1X_IRQ_CHIP_COMMON_DATA,
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip s2mpu02_irq_chip = {
|
||||
|
|
@ -452,6 +460,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
|
|||
case S2MPS11X:
|
||||
sec_irq_chip = &s2mps11_irq_chip;
|
||||
break;
|
||||
case S2MPS13X:
|
||||
sec_irq_chip = &s2mps13_irq_chip;
|
||||
break;
|
||||
case S2MPS14X:
|
||||
sec_irq_chip = &s2mps14_irq_chip;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
|
@ -22,31 +23,94 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static struct platform_driver syscon_driver;
|
||||
|
||||
static DEFINE_SPINLOCK(syscon_list_slock);
|
||||
static LIST_HEAD(syscon_list);
|
||||
|
||||
struct syscon {
|
||||
struct device_node *np;
|
||||
struct regmap *regmap;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static int syscon_match_node(struct device *dev, void *data)
|
||||
{
|
||||
struct device_node *dn = data;
|
||||
static struct regmap_config syscon_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
};
|
||||
|
||||
return (dev->of_node == dn) ? 1 : 0;
|
||||
static struct syscon *of_syscon_register(struct device_node *np)
|
||||
{
|
||||
struct syscon *syscon;
|
||||
struct regmap *regmap;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
struct regmap_config syscon_config = syscon_regmap_config;
|
||||
|
||||
if (!of_device_is_compatible(np, "syscon"))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
syscon = kzalloc(sizeof(*syscon), GFP_KERNEL);
|
||||
if (!syscon)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
base = of_iomap(np, 0);
|
||||
if (!base) {
|
||||
ret = -ENOMEM;
|
||||
goto err_map;
|
||||
}
|
||||
|
||||
/* Parse the device's DT node for an endianness specification */
|
||||
if (of_property_read_bool(np, "big-endian"))
|
||||
syscon_config.val_format_endian = REGMAP_ENDIAN_BIG;
|
||||
else if (of_property_read_bool(np, "little-endian"))
|
||||
syscon_config.val_format_endian = REGMAP_ENDIAN_LITTLE;
|
||||
|
||||
regmap = regmap_init_mmio(NULL, base, &syscon_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
pr_err("regmap init failed\n");
|
||||
ret = PTR_ERR(regmap);
|
||||
goto err_regmap;
|
||||
}
|
||||
|
||||
syscon->regmap = regmap;
|
||||
syscon->np = np;
|
||||
|
||||
spin_lock(&syscon_list_slock);
|
||||
list_add_tail(&syscon->list, &syscon_list);
|
||||
spin_unlock(&syscon_list_slock);
|
||||
|
||||
return syscon;
|
||||
|
||||
err_regmap:
|
||||
iounmap(base);
|
||||
err_map:
|
||||
kfree(syscon);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
struct regmap *syscon_node_to_regmap(struct device_node *np)
|
||||
{
|
||||
struct syscon *syscon;
|
||||
struct device *dev;
|
||||
struct syscon *entry, *syscon = NULL;
|
||||
|
||||
dev = driver_find_device(&syscon_driver.driver, NULL, np,
|
||||
syscon_match_node);
|
||||
if (!dev)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
spin_lock(&syscon_list_slock);
|
||||
|
||||
syscon = dev_get_drvdata(dev);
|
||||
list_for_each_entry(entry, &syscon_list, list)
|
||||
if (entry->np == np) {
|
||||
syscon = entry;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock(&syscon_list_slock);
|
||||
|
||||
if (!syscon)
|
||||
syscon = of_syscon_register(np);
|
||||
|
||||
if (IS_ERR(syscon))
|
||||
return ERR_CAST(syscon);
|
||||
|
||||
return syscon->regmap;
|
||||
}
|
||||
|
|
@ -110,17 +174,6 @@ struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle);
|
||||
|
||||
static const struct of_device_id of_syscon_match[] = {
|
||||
{ .compatible = "syscon", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct regmap_config syscon_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
};
|
||||
|
||||
static int syscon_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
|
@ -167,7 +220,6 @@ static struct platform_driver syscon_driver = {
|
|||
.driver = {
|
||||
.name = "syscon",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_syscon_match,
|
||||
},
|
||||
.probe = syscon_probe,
|
||||
.id_table = syscon_ids,
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc)
|
|||
unsigned long flags;
|
||||
u8 dev_ctl;
|
||||
|
||||
clk_enable(t7l66xb->clk32k);
|
||||
clk_prepare_enable(t7l66xb->clk32k);
|
||||
|
||||
spin_lock_irqsave(&t7l66xb->lock, flags);
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc)
|
|||
|
||||
spin_unlock_irqrestore(&t7l66xb->lock, flags);
|
||||
|
||||
clk_disable(t7l66xb->clk32k);
|
||||
clk_disable_unprepare(t7l66xb->clk32k);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -285,7 +285,7 @@ static int t7l66xb_suspend(struct platform_device *dev, pm_message_t state)
|
|||
|
||||
if (pdata && pdata->suspend)
|
||||
pdata->suspend(dev);
|
||||
clk_disable(t7l66xb->clk48m);
|
||||
clk_disable_unprepare(t7l66xb->clk48m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -295,7 +295,7 @@ 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);
|
||||
|
||||
clk_enable(t7l66xb->clk48m);
|
||||
clk_prepare_enable(t7l66xb->clk48m);
|
||||
if (pdata && pdata->resume)
|
||||
pdata->resume(dev);
|
||||
|
||||
|
|
@ -369,7 +369,7 @@ static int t7l66xb_probe(struct platform_device *dev)
|
|||
goto err_ioremap;
|
||||
}
|
||||
|
||||
clk_enable(t7l66xb->clk48m);
|
||||
clk_prepare_enable(t7l66xb->clk48m);
|
||||
|
||||
if (pdata && pdata->enable)
|
||||
pdata->enable(dev);
|
||||
|
|
@ -414,9 +414,9 @@ static int t7l66xb_remove(struct platform_device *dev)
|
|||
int ret;
|
||||
|
||||
ret = pdata->disable(dev);
|
||||
clk_disable(t7l66xb->clk48m);
|
||||
clk_disable_unprepare(t7l66xb->clk48m);
|
||||
clk_put(t7l66xb->clk48m);
|
||||
clk_disable(t7l66xb->clk32k);
|
||||
clk_disable_unprepare(t7l66xb->clk32k);
|
||||
clk_put(t7l66xb->clk32k);
|
||||
t7l66xb_detach_irq(dev);
|
||||
iounmap(t7l66xb->scr);
|
||||
|
|
|
|||
|
|
@ -241,10 +241,8 @@ static struct irq_domain_ops tc3589x_irq_ops = {
|
|||
|
||||
static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
|
||||
{
|
||||
int base = tc3589x->irq_base;
|
||||
|
||||
tc3589x->domain = irq_domain_add_simple(
|
||||
np, TC3589x_NR_INTERNAL_IRQS, base,
|
||||
np, TC3589x_NR_INTERNAL_IRQS, 0,
|
||||
&tc3589x_irq_ops, tc3589x);
|
||||
|
||||
if (!tc3589x->domain) {
|
||||
|
|
@ -298,7 +296,7 @@ static int tc3589x_device_init(struct tc3589x *tc3589x)
|
|||
if (blocks & TC3589x_BLOCK_GPIO) {
|
||||
ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
|
||||
ARRAY_SIZE(tc3589x_dev_gpio), NULL,
|
||||
tc3589x->irq_base, tc3589x->domain);
|
||||
0, tc3589x->domain);
|
||||
if (ret) {
|
||||
dev_err(tc3589x->dev, "failed to add gpio child\n");
|
||||
return ret;
|
||||
|
|
@ -309,7 +307,7 @@ static int tc3589x_device_init(struct tc3589x *tc3589x)
|
|||
if (blocks & TC3589x_BLOCK_KEYPAD) {
|
||||
ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
|
||||
ARRAY_SIZE(tc3589x_dev_keypad), NULL,
|
||||
tc3589x->irq_base, tc3589x->domain);
|
||||
0, tc3589x->domain);
|
||||
if (ret) {
|
||||
dev_err(tc3589x->dev, "failed to keypad child\n");
|
||||
return ret;
|
||||
|
|
@ -404,7 +402,6 @@ static int tc3589x_probe(struct i2c_client *i2c,
|
|||
tc3589x->dev = &i2c->dev;
|
||||
tc3589x->i2c = i2c;
|
||||
tc3589x->pdata = pdata;
|
||||
tc3589x->irq_base = pdata->irq_base;
|
||||
|
||||
switch (version) {
|
||||
case TC3589X_TC35893:
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
|
|||
|
||||
if (pdata && pdata->suspend)
|
||||
pdata->suspend(dev);
|
||||
clk_disable(tc6387xb->clk32k);
|
||||
clk_disable_unprepare(tc6387xb->clk32k);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ static int tc6387xb_resume(struct platform_device *dev)
|
|||
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
|
||||
struct tc6387xb_platform_data *pdata = dev_get_platdata(&dev->dev);
|
||||
|
||||
clk_enable(tc6387xb->clk32k);
|
||||
clk_prepare_enable(tc6387xb->clk32k);
|
||||
if (pdata && pdata->resume)
|
||||
pdata->resume(dev);
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc)
|
|||
struct platform_device *dev = to_platform_device(mmc->dev.parent);
|
||||
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
|
||||
|
||||
clk_enable(tc6387xb->clk32k);
|
||||
clk_prepare_enable(tc6387xb->clk32k);
|
||||
|
||||
tmio_core_mmc_enable(tc6387xb->scr + 0x200, 0,
|
||||
tc6387xb_mmc_resources[0].start & 0xfffe);
|
||||
|
|
@ -113,7 +113,7 @@ static int tc6387xb_mmc_disable(struct platform_device *mmc)
|
|||
struct platform_device *dev = to_platform_device(mmc->dev.parent);
|
||||
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
|
||||
|
||||
clk_disable(tc6387xb->clk32k);
|
||||
clk_disable_unprepare(tc6387xb->clk32k);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -214,7 +214,7 @@ static int tc6387xb_remove(struct platform_device *dev)
|
|||
mfd_remove_devices(&dev->dev);
|
||||
iounmap(tc6387xb->scr);
|
||||
release_resource(&tc6387xb->rscr);
|
||||
clk_disable(tc6387xb->clk32k);
|
||||
clk_disable_unprepare(tc6387xb->clk32k);
|
||||
clk_put(tc6387xb->clk32k);
|
||||
kfree(tc6387xb);
|
||||
|
||||
|
|
|
|||
|
|
@ -263,6 +263,17 @@ static int tc6393xb_ohci_disable(struct platform_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tc6393xb_ohci_suspend(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb_platform_data *tcpd = dev_get_platdata(dev->dev.parent);
|
||||
|
||||
/* We can't properly store/restore OHCI state, so fail here */
|
||||
if (tcpd->resume_restore)
|
||||
return -EBUSY;
|
||||
|
||||
return tc6393xb_ohci_disable(dev);
|
||||
}
|
||||
|
||||
static int tc6393xb_fb_enable(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
|
||||
|
|
@ -403,7 +414,7 @@ static struct mfd_cell tc6393xb_cells[] = {
|
|||
.num_resources = ARRAY_SIZE(tc6393xb_ohci_resources),
|
||||
.resources = tc6393xb_ohci_resources,
|
||||
.enable = tc6393xb_ohci_enable,
|
||||
.suspend = tc6393xb_ohci_disable,
|
||||
.suspend = tc6393xb_ohci_suspend,
|
||||
.resume = tc6393xb_ohci_enable,
|
||||
.disable = tc6393xb_ohci_disable,
|
||||
},
|
||||
|
|
@ -654,7 +665,7 @@ static int tc6393xb_probe(struct platform_device *dev)
|
|||
goto err_ioremap;
|
||||
}
|
||||
|
||||
ret = clk_enable(tc6393xb->clk);
|
||||
ret = clk_prepare_enable(tc6393xb->clk);
|
||||
if (ret)
|
||||
goto err_clk_enable;
|
||||
|
||||
|
|
@ -717,7 +728,7 @@ err_gpio_add:
|
|||
gpiochip_remove(&tc6393xb->gpio);
|
||||
tcpd->disable(dev);
|
||||
err_enable:
|
||||
clk_disable(tc6393xb->clk);
|
||||
clk_disable_unprepare(tc6393xb->clk);
|
||||
err_clk_enable:
|
||||
iounmap(tc6393xb->scr);
|
||||
err_ioremap:
|
||||
|
|
@ -748,7 +759,7 @@ static int tc6393xb_remove(struct platform_device *dev)
|
|||
gpiochip_remove(&tc6393xb->gpio);
|
||||
|
||||
ret = tcpd->disable(dev);
|
||||
clk_disable(tc6393xb->clk);
|
||||
clk_disable_unprepare(tc6393xb->clk);
|
||||
iounmap(tc6393xb->scr);
|
||||
release_resource(&tc6393xb->rscr);
|
||||
clk_put(tc6393xb->clk);
|
||||
|
|
@ -776,7 +787,7 @@ static int tc6393xb_suspend(struct platform_device *dev, pm_message_t state)
|
|||
ioread8(tc6393xb->scr + SCR_GPI_BCR(i));
|
||||
}
|
||||
ret = tcpd->suspend(dev);
|
||||
clk_disable(tc6393xb->clk);
|
||||
clk_disable_unprepare(tc6393xb->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -788,7 +799,7 @@ static int tc6393xb_resume(struct platform_device *dev)
|
|||
int ret;
|
||||
int i;
|
||||
|
||||
clk_enable(tc6393xb->clk);
|
||||
clk_prepare_enable(tc6393xb->clk);
|
||||
|
||||
ret = tcpd->resume(dev);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -76,58 +76,58 @@ static struct mfd_cell tps65090s[] = {
|
|||
static const struct regmap_irq tps65090_irqs[] = {
|
||||
/* INT1 IRQs*/
|
||||
[TPS65090_IRQ_VAC_STATUS_CHANGE] = {
|
||||
.mask = TPS65090_INT1_MASK_VAC_STATUS_CHANGE,
|
||||
.mask = TPS65090_INT1_MASK_VAC_STATUS_CHANGE,
|
||||
},
|
||||
[TPS65090_IRQ_VSYS_STATUS_CHANGE] = {
|
||||
.mask = TPS65090_INT1_MASK_VSYS_STATUS_CHANGE,
|
||||
.mask = TPS65090_INT1_MASK_VSYS_STATUS_CHANGE,
|
||||
},
|
||||
[TPS65090_IRQ_BAT_STATUS_CHANGE] = {
|
||||
.mask = TPS65090_INT1_MASK_BAT_STATUS_CHANGE,
|
||||
.mask = TPS65090_INT1_MASK_BAT_STATUS_CHANGE,
|
||||
},
|
||||
[TPS65090_IRQ_CHARGING_STATUS_CHANGE] = {
|
||||
.mask = TPS65090_INT1_MASK_CHARGING_STATUS_CHANGE,
|
||||
.mask = TPS65090_INT1_MASK_CHARGING_STATUS_CHANGE,
|
||||
},
|
||||
[TPS65090_IRQ_CHARGING_COMPLETE] = {
|
||||
.mask = TPS65090_INT1_MASK_CHARGING_COMPLETE,
|
||||
.mask = TPS65090_INT1_MASK_CHARGING_COMPLETE,
|
||||
},
|
||||
[TPS65090_IRQ_OVERLOAD_DCDC1] = {
|
||||
.mask = TPS65090_INT1_MASK_OVERLOAD_DCDC1,
|
||||
.mask = TPS65090_INT1_MASK_OVERLOAD_DCDC1,
|
||||
},
|
||||
[TPS65090_IRQ_OVERLOAD_DCDC2] = {
|
||||
.mask = TPS65090_INT1_MASK_OVERLOAD_DCDC2,
|
||||
.mask = TPS65090_INT1_MASK_OVERLOAD_DCDC2,
|
||||
},
|
||||
/* INT2 IRQs*/
|
||||
[TPS65090_IRQ_OVERLOAD_DCDC3] = {
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_DCDC3,
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_DCDC3,
|
||||
},
|
||||
[TPS65090_IRQ_OVERLOAD_FET1] = {
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET1,
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET1,
|
||||
},
|
||||
[TPS65090_IRQ_OVERLOAD_FET2] = {
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET2,
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET2,
|
||||
},
|
||||
[TPS65090_IRQ_OVERLOAD_FET3] = {
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET3,
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET3,
|
||||
},
|
||||
[TPS65090_IRQ_OVERLOAD_FET4] = {
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET4,
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET4,
|
||||
},
|
||||
[TPS65090_IRQ_OVERLOAD_FET5] = {
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET5,
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET5,
|
||||
},
|
||||
[TPS65090_IRQ_OVERLOAD_FET6] = {
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET6,
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET6,
|
||||
},
|
||||
[TPS65090_IRQ_OVERLOAD_FET7] = {
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET7,
|
||||
.reg_offset = 1,
|
||||
.mask = TPS65090_INT2_MASK_OVERLOAD_FET7,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ MODULE_DEVICE_TABLE(of, tps65090_of_match);
|
|||
#endif
|
||||
|
||||
static int tps65090_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tps65090_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
int irq_base = 0;
|
||||
|
|
@ -210,11 +210,11 @@ static int tps65090_i2c_probe(struct i2c_client *client,
|
|||
|
||||
if (client->irq) {
|
||||
ret = regmap_add_irq_chip(tps65090->rmap, client->irq,
|
||||
IRQF_ONESHOT | IRQF_TRIGGER_LOW, irq_base,
|
||||
&tps65090_irq_chip, &tps65090->irq_data);
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"IRQ init failed with err: %d\n", ret);
|
||||
IRQF_ONESHOT | IRQF_TRIGGER_LOW, irq_base,
|
||||
&tps65090_irq_chip, &tps65090->irq_data);
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"IRQ init failed with err: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -223,8 +223,8 @@ static int tps65090_i2c_probe(struct i2c_client *client,
|
|||
}
|
||||
|
||||
ret = mfd_add_devices(tps65090->dev, -1, tps65090s,
|
||||
ARRAY_SIZE(tps65090s), NULL,
|
||||
0, regmap_irq_get_domain(tps65090->irq_data));
|
||||
ARRAY_SIZE(tps65090s), NULL,
|
||||
0, regmap_irq_get_domain(tps65090->irq_data));
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "add mfd devices failed with err: %d\n",
|
||||
ret);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,11 @@
|
|||
static const struct mfd_cell tps65217s[] = {
|
||||
{
|
||||
.name = "tps65217-pmic",
|
||||
.of_compatible = "ti,tps65217-pmic",
|
||||
},
|
||||
{
|
||||
.name = "tps65217-bl",
|
||||
.of_compatible = "ti,tps65217-bl",
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -830,6 +830,9 @@ static struct twl4030_power_data osc_off_idle = {
|
|||
};
|
||||
|
||||
static struct of_device_id twl4030_power_of_match[] = {
|
||||
{
|
||||
.compatible = "ti,twl4030-power",
|
||||
},
|
||||
{
|
||||
.compatible = "ti,twl4030-power-reset",
|
||||
.data = &omap3_reset,
|
||||
|
|
|
|||
|
|
@ -93,9 +93,8 @@ static int vprbrd_probe(struct usb_interface *interface,
|
|||
version >> 8, version & 0xff,
|
||||
vb->usb_dev->bus->busnum, vb->usb_dev->devnum);
|
||||
|
||||
ret = mfd_add_devices(&interface->dev, PLATFORM_DEVID_AUTO,
|
||||
vprbrd_devs, ARRAY_SIZE(vprbrd_devs), NULL, 0,
|
||||
NULL);
|
||||
ret = mfd_add_hotplug_devices(&interface->dev, vprbrd_devs,
|
||||
ARRAY_SIZE(vprbrd_devs));
|
||||
if (ret != 0) {
|
||||
dev_err(&interface->dev, "Failed to add mfd devices to core.");
|
||||
goto error;
|
||||
|
|
|
|||
|
|
@ -336,8 +336,6 @@ static const struct reg_default wm5102_reg_default[] = {
|
|||
{ 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */
|
||||
{ 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */
|
||||
{ 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */
|
||||
{ 0x00000225, 0x0400 }, /* R549 - HP Ctrl 1L */
|
||||
{ 0x00000226, 0x0400 }, /* R550 - HP Ctrl 1R */
|
||||
{ 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */
|
||||
{ 0x0000029B, 0x0020 }, /* R667 - Headphone Detect 1 */
|
||||
{ 0x0000029C, 0x0000 }, /* R668 - Headphone Detect 2 */
|
||||
|
|
@ -1112,6 +1110,8 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
|
|||
case ARIZONA_MIC_BIAS_CTRL_1:
|
||||
case ARIZONA_MIC_BIAS_CTRL_2:
|
||||
case ARIZONA_MIC_BIAS_CTRL_3:
|
||||
case ARIZONA_HP_CTRL_1L:
|
||||
case ARIZONA_HP_CTRL_1R:
|
||||
case ARIZONA_ACCESSORY_DETECT_MODE_1:
|
||||
case ARIZONA_HEADPHONE_DETECT_1:
|
||||
case ARIZONA_HEADPHONE_DETECT_2:
|
||||
|
|
@ -1949,6 +1949,8 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg)
|
|||
case ARIZONA_DSP1_SCRATCH_1:
|
||||
case ARIZONA_DSP1_SCRATCH_2:
|
||||
case ARIZONA_DSP1_SCRATCH_3:
|
||||
case ARIZONA_HP_CTRL_1L:
|
||||
case ARIZONA_HP_CTRL_1R:
|
||||
case ARIZONA_HEADPHONE_DETECT_2:
|
||||
case ARIZONA_HP_DACVAL:
|
||||
case ARIZONA_MIC_DETECT_3:
|
||||
|
|
|
|||
|
|
@ -895,8 +895,16 @@ static const struct reg_default wm5110_reg_default[] = {
|
|||
{ 0x00000548, 0x1818 }, /* R1352 - AIF2 Frame Ctrl 2 */
|
||||
{ 0x00000549, 0x0000 }, /* R1353 - AIF2 Frame Ctrl 3 */
|
||||
{ 0x0000054A, 0x0001 }, /* R1354 - AIF2 Frame Ctrl 4 */
|
||||
{ 0x0000054B, 0x0002 }, /* R1355 - AIF2 Frame Ctrl 5 */
|
||||
{ 0x0000054C, 0x0003 }, /* R1356 - AIF2 Frame Ctrl 6 */
|
||||
{ 0x0000054D, 0x0004 }, /* R1357 - AIF2 Frame Ctrl 7 */
|
||||
{ 0x0000054E, 0x0005 }, /* R1358 - AIF2 Frame Ctrl 8 */
|
||||
{ 0x00000551, 0x0000 }, /* R1361 - AIF2 Frame Ctrl 11 */
|
||||
{ 0x00000552, 0x0001 }, /* R1362 - AIF2 Frame Ctrl 12 */
|
||||
{ 0x00000553, 0x0002 }, /* R1363 - AIF2 Frame Ctrl 13 */
|
||||
{ 0x00000554, 0x0003 }, /* R1364 - AIF2 Frame Ctrl 14 */
|
||||
{ 0x00000555, 0x0004 }, /* R1365 - AIF2 Frame Ctrl 15 */
|
||||
{ 0x00000556, 0x0005 }, /* R1366 - AIF2 Frame Ctrl 16 */
|
||||
{ 0x00000559, 0x0000 }, /* R1369 - AIF2 Tx Enables */
|
||||
{ 0x0000055A, 0x0000 }, /* R1370 - AIF2 Rx Enables */
|
||||
{ 0x00000580, 0x000C }, /* R1408 - AIF3 BCLK Ctrl */
|
||||
|
|
@ -1790,6 +1798,8 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
|
|||
case ARIZONA_MIC_BIAS_CTRL_1:
|
||||
case ARIZONA_MIC_BIAS_CTRL_2:
|
||||
case ARIZONA_MIC_BIAS_CTRL_3:
|
||||
case ARIZONA_HP_CTRL_1L:
|
||||
case ARIZONA_HP_CTRL_1R:
|
||||
case ARIZONA_ACCESSORY_DETECT_MODE_1:
|
||||
case ARIZONA_HEADPHONE_DETECT_1:
|
||||
case ARIZONA_HEADPHONE_DETECT_2:
|
||||
|
|
@ -1934,8 +1944,16 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
|
|||
case ARIZONA_AIF2_FRAME_CTRL_2:
|
||||
case ARIZONA_AIF2_FRAME_CTRL_3:
|
||||
case ARIZONA_AIF2_FRAME_CTRL_4:
|
||||
case ARIZONA_AIF2_FRAME_CTRL_5:
|
||||
case ARIZONA_AIF2_FRAME_CTRL_6:
|
||||
case ARIZONA_AIF2_FRAME_CTRL_7:
|
||||
case ARIZONA_AIF2_FRAME_CTRL_8:
|
||||
case ARIZONA_AIF2_FRAME_CTRL_11:
|
||||
case ARIZONA_AIF2_FRAME_CTRL_12:
|
||||
case ARIZONA_AIF2_FRAME_CTRL_13:
|
||||
case ARIZONA_AIF2_FRAME_CTRL_14:
|
||||
case ARIZONA_AIF2_FRAME_CTRL_15:
|
||||
case ARIZONA_AIF2_FRAME_CTRL_16:
|
||||
case ARIZONA_AIF2_TX_ENABLES:
|
||||
case ARIZONA_AIF2_RX_ENABLES:
|
||||
case ARIZONA_AIF3_BCLK_CTRL:
|
||||
|
|
@ -2825,6 +2843,8 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
|
|||
case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
|
||||
case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS:
|
||||
case ARIZONA_MIC_DETECT_3:
|
||||
case ARIZONA_HP_CTRL_1L:
|
||||
case ARIZONA_HP_CTRL_1R:
|
||||
case ARIZONA_HEADPHONE_DETECT_2:
|
||||
case ARIZONA_INPUT_ENABLES_STATUS:
|
||||
case ARIZONA_OUTPUT_STATUS_1:
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
|
|||
goto err;
|
||||
}
|
||||
|
||||
mode = id2 & WM8350_CONF_STS_MASK >> 10;
|
||||
mode = (id2 & WM8350_CONF_STS_MASK) >> 10;
|
||||
cust_id = id2 & WM8350_CUST_ID_MASK;
|
||||
chip_rev = (id2 & WM8350_CHIP_REV_MASK) >> 12;
|
||||
dev_info(wm8350->dev,
|
||||
|
|
|
|||
|
|
@ -670,6 +670,7 @@ static const struct reg_default wm8997_reg_default[] = {
|
|||
{ 0x00000C23, 0x0000 }, /* R3107 - Misc Pad Ctrl 4 */
|
||||
{ 0x00000C24, 0x0000 }, /* R3108 - Misc Pad Ctrl 5 */
|
||||
{ 0x00000D08, 0xFFFF }, /* R3336 - Interrupt Status 1 Mask */
|
||||
{ 0x00000D09, 0xFFFF }, /* R3337 - Interrupt Status 2 Mask */
|
||||
{ 0x00000D0A, 0xFFFF }, /* R3338 - Interrupt Status 3 Mask */
|
||||
{ 0x00000D0B, 0xFFFF }, /* R3339 - Interrupt Status 4 Mask */
|
||||
{ 0x00000D0C, 0xFEFF }, /* R3340 - Interrupt Status 5 Mask */
|
||||
|
|
@ -886,6 +887,8 @@ static bool wm8997_readable_register(struct device *dev, unsigned int reg)
|
|||
case ARIZONA_MIC_BIAS_CTRL_1:
|
||||
case ARIZONA_MIC_BIAS_CTRL_2:
|
||||
case ARIZONA_MIC_BIAS_CTRL_3:
|
||||
case ARIZONA_HP_CTRL_1L:
|
||||
case ARIZONA_HP_CTRL_1R:
|
||||
case ARIZONA_ACCESSORY_DETECT_MODE_1:
|
||||
case ARIZONA_HEADPHONE_DETECT_1:
|
||||
case ARIZONA_HEADPHONE_DETECT_2:
|
||||
|
|
@ -1328,6 +1331,7 @@ static bool wm8997_readable_register(struct device *dev, unsigned int reg)
|
|||
case ARIZONA_INTERRUPT_STATUS_4:
|
||||
case ARIZONA_INTERRUPT_STATUS_5:
|
||||
case ARIZONA_INTERRUPT_STATUS_1_MASK:
|
||||
case ARIZONA_INTERRUPT_STATUS_2_MASK:
|
||||
case ARIZONA_INTERRUPT_STATUS_3_MASK:
|
||||
case ARIZONA_INTERRUPT_STATUS_4_MASK:
|
||||
case ARIZONA_INTERRUPT_STATUS_5_MASK:
|
||||
|
|
@ -1477,6 +1481,8 @@ static bool wm8997_volatile_register(struct device *dev, unsigned int reg)
|
|||
case ARIZONA_SAMPLE_RATE_3_STATUS:
|
||||
case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
|
||||
case ARIZONA_MIC_DETECT_3:
|
||||
case ARIZONA_HP_CTRL_1L:
|
||||
case ARIZONA_HP_CTRL_1R:
|
||||
case ARIZONA_HEADPHONE_DETECT_2:
|
||||
case ARIZONA_INPUT_ENABLES_STATUS:
|
||||
case ARIZONA_OUTPUT_STATUS_1:
|
||||
|
|
|
|||
Loading…
Reference in a new issue