- New Drivers

- Add new driver for MAXIM MAX77620/MAX20024 PMIC
    - Add new driver for Hisilicon HI665X PMIC
  - New Device Support
    - Add support for AXP809 in axp20x-rsb
    - Add support for Power Supply in axp20x
  - New core features
    - devm_mfd_* managed resources
  - Fix-ups
    - Remove unused code; da9063-irq, wm8400-core, tps6105x, smsc-ece1099,
 			 twl4030-power
    - Improve clean-up in error path; intel_quark_i2c_gpio
    - Explicitly include headers; syscon.h
    - Allow building as modules; max77693
    - Use IS_ENABLED() instead of rolling your own; dm355evm_msp, wm8400-core
    - DT adaptions; axp20x, hi655x, arizona, max77620
    - Remove CLK_IS_ROOT flag; intel-lpss, intel_quark
    - Move to gpiochip API; asic3, dm355evm_msp, htc-egpio, htc-i2cpld, sm501,
 				  tc6393xb, tps65010, ucb1x00, vexpress
    - Make use of devm_mfd_* calls; act8945a, as3711, atmel-hlcdc, bcm590xx,
 				   hi6421-pmic-core, lp3943, menf21bmc, mt6397,
 				   rdc321x, rk808, rn5t618, rt5033, sky81452,
 				   stw481x, tps6507x, tps65217, wm8400,
  - Bug Fixes
    - Fix ACPI child matching; mfd-core
    - Fix start-up ordering issues; mt6397-core, arizona-core
    - Fix forgotten register state on resume; intel-lpss
    - Fix Clock related issues; twl6040
    - Fix scheduling whilst atomic; omap-usb-tll
    - Kconfig changes; vexpress
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJXPzwAAAoJEFGvii+H/HdhkPEP/iTvgiL+CpAk7UwAhCNolR5j
 l3vb49lOlmqx87zELdToJmySAd/byiZN0YQEmcn+t4BCs/8CeaWeNkb8vltJvuac
 Fmz88bhXfgFYk87nx/6tRMvuM3fKXlk/YYRZkklV7mkBjcPLiqBZSi/MG/SV53a9
 A+vGW56B2/vHiUgTBkYs9UZNqkFCkmhuVYbHjtFwTfL84lwy9u4tNRrktss6g1lx
 Ak9uiDhaUP/vxKe/7/qCTZXgV/IYb2+tcNjMJ+Cztmyht8VTrhGSXbDPH7MyRYUI
 EBBWRXAQelR5qHxOYDSBNIemZe3AniCBp7tjqcwlN9cdE8q9pJxOk+0XStjC+XeW
 Qt1aIwQisk8jfII8BIGr2pAzc8Jh9/TtcK+wKMRQ2o5g2tvcG90hHIJWQlbdy4ST
 SX799w0KvTItdaMhTHThTOfJRj777v/H2cj8DBCCEeoBHOCHnzbJSIuKahPa9PM3
 W0dyZOpsDXoegyksjBUYjdhGoggjEdirt+oXJe4rY7UxeEml+YZS54fseVzgNzNq
 //Nxk1GMNOVXgo3NrlO8JTs2G5gFPc8VOuPW60G1fm8DyNW13RbUG74QPpSd4U7S
 zZM/OZ3D0E4nrPjXf/GCS3QRwM7p1ubiOgSTTZkaLJYGBcHSezGXK8XpFSNReRop
 Un13GPM09Sl9VN9a2Ybi
 =FSmn
 -----END PGP SIGNATURE-----

Merge tag 'mfd-for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd

Pull MFD updates from Lee Jones:
 "New Drivers:
   - Add new driver for MAXIM MAX77620/MAX20024 PMIC
   - Add new driver for Hisilicon HI665X PMIC

  New Device Support:
   - Add support for AXP809 in axp20x-rsb
   - Add support for Power Supply in axp20x

  New core features:
   - devm_mfd_* managed resources

  Fix-ups:
   - Remove unused code (da9063-irq, wm8400-core, tps6105x,
     smsc-ece1099, twl4030-power)
   - Improve clean-up in error path (intel_quark_i2c_gpio)
   - Explicitly include headers (syscon.h)
   - Allow building as modules (max77693)
   - Use IS_ENABLED() instead of rolling your own (dm355evm_msp,
     wm8400-core)
   - DT adaptions (axp20x, hi655x, arizona, max77620)
   - Remove CLK_IS_ROOT flag (intel-lpss, intel_quark)
   - Move to gpiochip API (asic3, dm355evm_msp, htc-egpio, htc-i2cpld,
     sm501, tc6393xb, tps65010, ucb1x00, vexpress)
   - Make use of devm_mfd_* calls (act8945a, as3711, atmel-hlcdc,
     bcm590xx, hi6421-pmic-core, lp3943, menf21bmc, mt6397, rdc321x,
     rk808, rn5t618, rt5033, sky81452, stw481x, tps6507x, tps65217,
     wm8400)

  Bug Fixes"
   - Fix ACPI child matching (mfd-core)
   - Fix start-up ordering issues (mt6397-core, arizona-core)
   - Fix forgotten register state on resume (intel-lpss)
   - Fix Clock related issues (twl6040)
   - Fix scheduling whilst atomic (omap-usb-tll)
   - Kconfig changes (vexpress)"

* tag 'mfd-for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (73 commits)
  mfd: hi655x: Add MFD driver for hi655x
  mfd: ab8500-debugfs: Trivial fix of spelling mistake on "between"
  mfd: vexpress: Add !ARCH_USES_GETTIMEOFFSET dependency
  mfd: Add device-tree binding doc for PMIC MAX77620/MAX20024
  mfd: max77620: Add core driver for MAX77620/MAX20024
  mfd: arizona: Add defines for GPSW values that can be used from DT
  mfd: omap-usb-tll: Fix scheduling while atomic BUG
  mfd: wm5110: ARIZONA_CLOCK_CONTROL should be volatile
  mfd: axp20x: Add a cell for the ac power_supply part of the axp20x PMICs
  mfd: intel_soc_pmic_core: Terminate panel control GPIO lookup table correctly
  mfd: wl1273-core: Use devm_mfd_add_devices() for mfd_device registration
  mfd: tps65910: Use devm_mfd_add_devices and devm_regmap_add_irq_chip
  mfd: sec: Use devm_mfd_add_devices and devm_regmap_add_irq_chip
  mfd: rc5t583: Use devm_mfd_add_devices and devm_request_threaded_irq
  mfd: max77686: Use devm_mfd_add_devices and devm_regmap_add_irq_chip
  mfd: as3722: Use devm_mfd_add_devices and devm_regmap_add_irq_chip
  mfd: twl4030-power: Remove driver path in file comment
  MAINTAINERS: Add entry for X-Powers AXP family PMIC drivers
  mfd: smsc-ece1099: Remove unnecessarily remove callback
  mfd: Use IS_ENABLED(CONFIG_FOO) instead of checking FOO || FOO_MODULE
  ...
This commit is contained in:
Linus Torvalds 2016-05-20 11:10:24 -07:00
commit 6eb59af580
68 changed files with 1856 additions and 485 deletions

View file

@ -134,7 +134,7 @@ config MFD_CROS_EC
select MFD_CORE
select CHROME_PLATFORMS
select CROS_EC_PROTO
depends on X86 || ARM || COMPILE_TEST
depends on X86 || ARM || ARM64 || COMPILE_TEST
help
If you say Y here you get support for the ChromeOS Embedded
Controller (EC) providing keyboard, battery and power services.
@ -319,6 +319,16 @@ config MFD_HI6421_PMIC
menus in order to enable them.
We communicate with the Hi6421 via memory-mapped I/O.
config MFD_HI655X_PMIC
tristate "HiSilicon Hi655X series PMU/Codec IC"
depends on ARCH_HISI || COMPILE_TEST
depends on OF
select MFD_CORE
select REGMAP_MMIO
select REGMAP_IRQ
help
Select this option to enable Hisilicon hi655x series pmic driver.
config HTC_EGPIO
bool "HTC EGPIO support"
depends on GPIOLIB && ARM
@ -527,6 +537,21 @@ config MFD_MAX14577
additional drivers must be enabled in order to use the functionality
of the device.
config MFD_MAX77620
bool "Maxim Semiconductor MAX77620 and MAX20024 PMIC Support"
depends on I2C=y
depends on OF
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
select IRQ_DOMAIN
help
Say yes here to add support for Maxim Semiconductor MAX77620 and
MAX20024 which are Power Management IC with General purpose pins,
RTC, regulators, clock generator, watchdog etc. 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_MAX77686
tristate "Maxim Semiconductor MAX77686/802 PMIC Support"
depends on I2C
@ -543,8 +568,8 @@ config MFD_MAX77686
of the device.
config MFD_MAX77693
bool "Maxim Semiconductor MAX77693 PMIC Support"
depends on I2C=y
tristate "Maxim Semiconductor MAX77693 PMIC Support"
depends on I2C
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
@ -1568,7 +1593,7 @@ endmenu
config MFD_VEXPRESS_SYSREG
bool "Versatile Express System Registers"
depends on VEXPRESS_CONFIG && GPIOLIB
depends on VEXPRESS_CONFIG && GPIOLIB && !ARCH_USES_GETTIMEOFFSET
default y
select CLKSRC_MMIO
select GPIO_GENERIC_PLATFORM

View file

@ -128,6 +128,7 @@ obj-$(CONFIG_MFD_DA9063) += da9063.o
obj-$(CONFIG_MFD_DA9150) += da9150-core.o
obj-$(CONFIG_MFD_MAX14577) += max14577.o
obj-$(CONFIG_MFD_MAX77620) += max77620.o
obj-$(CONFIG_MFD_MAX77686) += max77686.o
obj-$(CONFIG_MFD_MAX77693) += max77693.o
obj-$(CONFIG_MFD_MAX77843) += max77843.o
@ -195,6 +196,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_HI655X_PMIC) += hi655x-pmic.o
obj-$(CONFIG_MFD_DLN2) += dln2.o
obj-$(CONFIG_MFD_RT5033) += rt5033.o
obj-$(CONFIG_MFD_SKY81452) += sky81452.o

View file

@ -46,8 +46,9 @@ static int act8945a_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, regmap);
ret = mfd_add_devices(&i2c->dev, PLATFORM_DEVID_NONE, act8945a_devs,
ARRAY_SIZE(act8945a_devs), NULL, 0, NULL);
ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_NONE,
act8945a_devs, ARRAY_SIZE(act8945a_devs),
NULL, 0, NULL);
if (ret) {
dev_err(&i2c->dev, "Failed to add sub devices\n");
return ret;
@ -56,13 +57,6 @@ static int act8945a_i2c_probe(struct i2c_client *i2c,
return 0;
}
static int act8945a_i2c_remove(struct i2c_client *i2c)
{
mfd_remove_devices(&i2c->dev);
return 0;
}
static const struct i2c_device_id act8945a_i2c_id[] = {
{ "act8945a", 0 },
{}
@ -81,7 +75,6 @@ static struct i2c_driver act8945a_i2c_driver = {
.of_match_table = of_match_ptr(act8945a_of_match),
},
.probe = act8945a_i2c_probe,
.remove = act8945a_i2c_remove,
.id_table = act8945a_i2c_id,
};

View file

@ -908,12 +908,12 @@ static const char * const wm5102_supplies[] = {
static const struct mfd_cell wm5102_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-gpio" },
{
.name = "arizona-extcon",
.parent_supplies = wm5102_supplies,
.num_parent_supplies = 1, /* We only need MICVDD */
},
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{
@ -925,12 +925,12 @@ static const struct mfd_cell wm5102_devs[] = {
static const struct mfd_cell wm5110_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-gpio" },
{
.name = "arizona-extcon",
.parent_supplies = wm5102_supplies,
.num_parent_supplies = 1, /* We only need MICVDD */
},
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{
@ -966,12 +966,12 @@ static const char * const wm8997_supplies[] = {
static const struct mfd_cell wm8997_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-gpio" },
{
.name = "arizona-extcon",
.parent_supplies = wm8997_supplies,
.num_parent_supplies = 1, /* We only need MICVDD */
},
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{
@ -982,12 +982,13 @@ static const struct mfd_cell wm8997_devs[] = {
};
static const struct mfd_cell wm8998_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-gpio" },
{
.name = "arizona-extcon",
.parent_supplies = wm5102_supplies,
.num_parent_supplies = 1, /* We only need MICVDD */
},
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{
@ -995,7 +996,6 @@ static const struct mfd_cell wm8998_devs[] = {
.parent_supplies = wm5102_supplies,
.num_parent_supplies = ARRAY_SIZE(wm5102_supplies),
},
{ .name = "arizona-micsupp" },
};
int arizona_dev_init(struct arizona *arizona)

View file

@ -168,12 +168,15 @@ static struct irq_chip arizona_irq_chip = {
.irq_set_wake = arizona_irq_set_wake,
};
static struct lock_class_key arizona_irq_lock_class;
static int arizona_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
struct arizona *data = h->host_data;
irq_set_chip_data(virq, data);
irq_set_lockdep_class(virq, &arizona_irq_lock_class);
irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_simple_irq);
irq_set_nested_thread(virq, 1);
irq_set_noprobe(virq);

View file

@ -189,22 +189,14 @@ static int as3711_i2c_probe(struct i2c_client *client,
as3711_subdevs[AS3711_BACKLIGHT].pdata_size = 0;
}
ret = mfd_add_devices(as3711->dev, -1, as3711_subdevs,
ARRAY_SIZE(as3711_subdevs), NULL, 0, NULL);
ret = devm_mfd_add_devices(as3711->dev, -1, as3711_subdevs,
ARRAY_SIZE(as3711_subdevs), NULL, 0, NULL);
if (ret < 0)
dev_err(&client->dev, "add mfd devices failed: %d\n", ret);
return ret;
}
static int as3711_i2c_remove(struct i2c_client *client)
{
struct as3711 *as3711 = i2c_get_clientdata(client);
mfd_remove_devices(as3711->dev);
return 0;
}
static const struct i2c_device_id as3711_i2c_id[] = {
{.name = "as3711", .driver_data = 0},
{}
@ -218,7 +210,6 @@ static struct i2c_driver as3711_i2c_driver = {
.of_match_table = of_match_ptr(as3711_of_match),
},
.probe = as3711_i2c_probe,
.remove = as3711_i2c_remove,
.id_table = as3711_i2c_id,
};

View file

@ -385,9 +385,10 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
return ret;
irq_flags = as3722->irq_flags | IRQF_ONESHOT;
ret = regmap_add_irq_chip(as3722->regmap, as3722->chip_irq,
irq_flags, -1, &as3722_irq_chip,
&as3722->irq_data);
ret = devm_regmap_add_irq_chip(as3722->dev, as3722->regmap,
as3722->chip_irq,
irq_flags, -1, &as3722_irq_chip,
&as3722->irq_data);
if (ret < 0) {
dev_err(as3722->dev, "Failed to add regmap irq: %d\n", ret);
return ret;
@ -395,33 +396,20 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
ret = as3722_configure_pullups(as3722);
if (ret < 0)
goto scrub;
return ret;
ret = mfd_add_devices(&i2c->dev, -1, as3722_devs,
ARRAY_SIZE(as3722_devs), NULL, 0,
regmap_irq_get_domain(as3722->irq_data));
ret = devm_mfd_add_devices(&i2c->dev, -1, as3722_devs,
ARRAY_SIZE(as3722_devs), NULL, 0,
regmap_irq_get_domain(as3722->irq_data));
if (ret) {
dev_err(as3722->dev, "Failed to add MFD devices: %d\n", ret);
goto scrub;
return ret;
}
device_init_wakeup(as3722->dev, true);
dev_dbg(as3722->dev, "AS3722 core driver initialized successfully\n");
return 0;
scrub:
regmap_del_irq_chip(as3722->chip_irq, as3722->irq_data);
return ret;
}
static int as3722_i2c_remove(struct i2c_client *i2c)
{
struct as3722 *as3722 = i2c_get_clientdata(i2c);
mfd_remove_devices(as3722->dev);
regmap_del_irq_chip(as3722->chip_irq, as3722->irq_data);
return 0;
}
static int __maybe_unused as3722_i2c_suspend(struct device *dev)
@ -470,7 +458,6 @@ static struct i2c_driver as3722_i2c_driver = {
.pm = &as3722_pm_ops,
},
.probe = as3722_i2c_probe,
.remove = as3722_i2c_remove,
.id_table = as3722_i2c_id,
};

View file

@ -446,7 +446,7 @@ static int asic3_gpio_direction(struct gpio_chip *chip,
unsigned long flags;
struct asic3 *asic;
asic = container_of(chip, struct asic3, gpio);
asic = gpiochip_get_data(chip);
gpio_base = ASIC3_GPIO_TO_BASE(offset);
if (gpio_base > ASIC3_GPIO_D_BASE) {
@ -492,7 +492,7 @@ static int asic3_gpio_get(struct gpio_chip *chip,
u32 mask = ASIC3_GPIO_TO_MASK(offset);
struct asic3 *asic;
asic = container_of(chip, struct asic3, gpio);
asic = gpiochip_get_data(chip);
gpio_base = ASIC3_GPIO_TO_BASE(offset);
if (gpio_base > ASIC3_GPIO_D_BASE) {
@ -513,7 +513,7 @@ static void asic3_gpio_set(struct gpio_chip *chip,
unsigned long flags;
struct asic3 *asic;
asic = container_of(chip, struct asic3, gpio);
asic = gpiochip_get_data(chip);
gpio_base = ASIC3_GPIO_TO_BASE(offset);
if (gpio_base > ASIC3_GPIO_D_BASE) {
@ -540,7 +540,7 @@ static void asic3_gpio_set(struct gpio_chip *chip,
static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct asic3 *asic = container_of(chip, struct asic3, gpio);
struct asic3 *asic = gpiochip_get_data(chip);
return asic->irq_base + offset;
}
@ -595,7 +595,7 @@ static __init int asic3_gpio_probe(struct platform_device *pdev,
alt_reg[i]);
}
return gpiochip_add(&asic->gpio);
return gpiochip_add_data(&asic->gpio, asic);
}
static int asic3_gpio_remove(struct platform_device *pdev)

View file

@ -128,16 +128,9 @@ static int atmel_hlcdc_probe(struct platform_device *pdev)
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;
return devm_mfd_add_devices(dev, -1, atmel_hlcdc_cells,
ARRAY_SIZE(atmel_hlcdc_cells),
NULL, 0, NULL);
}
static const struct of_device_id atmel_hlcdc_match[] = {
@ -152,7 +145,6 @@ MODULE_DEVICE_TABLE(of, atmel_hlcdc_match);
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,

View file

@ -61,6 +61,7 @@ static int axp20x_rsb_remove(struct sunxi_rsb_device *rdev)
static const struct of_device_id axp20x_rsb_of_match[] = {
{ .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
{ .compatible = "x-powers,axp809", .data = (void *)AXP809_ID },
{ },
};
MODULE_DEVICE_TABLE(of, axp20x_rsb_of_match);

View file

@ -37,6 +37,7 @@ static const char * const axp20x_model_names[] = {
"AXP221",
"AXP223",
"AXP288",
"AXP809",
};
static const struct regmap_range axp152_writeable_ranges[] = {
@ -85,6 +86,7 @@ static const struct regmap_access_table axp20x_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges),
};
/* AXP22x ranges are shared with the AXP809, as they cover the same range */
static const struct regmap_range axp22x_writeable_ranges[] = {
regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
@ -128,6 +130,12 @@ static struct resource axp152_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
static struct resource axp20x_ac_power_supply_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_OVER_V, "ACIN_OVER_V"),
};
static struct resource axp20x_pek_resources[] = {
{
.name = "PEK_DBR",
@ -211,6 +219,20 @@ static struct resource axp288_fuel_gauge_resources[] = {
},
};
static struct resource axp809_pek_resources[] = {
{
.name = "PEK_DBR",
.start = AXP809_IRQ_PEK_RIS_EDGE,
.end = AXP809_IRQ_PEK_RIS_EDGE,
.flags = IORESOURCE_IRQ,
}, {
.name = "PEK_DBF",
.start = AXP809_IRQ_PEK_FAL_EDGE,
.end = AXP809_IRQ_PEK_FAL_EDGE,
.flags = IORESOURCE_IRQ,
},
};
static const struct regmap_config axp152_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@ -378,6 +400,41 @@ static const struct regmap_irq axp288_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1),
};
static const struct regmap_irq axp809_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP809, ACIN_OVER_V, 0, 7),
INIT_REGMAP_IRQ(AXP809, ACIN_PLUGIN, 0, 6),
INIT_REGMAP_IRQ(AXP809, ACIN_REMOVAL, 0, 5),
INIT_REGMAP_IRQ(AXP809, VBUS_OVER_V, 0, 4),
INIT_REGMAP_IRQ(AXP809, VBUS_PLUGIN, 0, 3),
INIT_REGMAP_IRQ(AXP809, VBUS_REMOVAL, 0, 2),
INIT_REGMAP_IRQ(AXP809, VBUS_V_LOW, 0, 1),
INIT_REGMAP_IRQ(AXP809, BATT_PLUGIN, 1, 7),
INIT_REGMAP_IRQ(AXP809, BATT_REMOVAL, 1, 6),
INIT_REGMAP_IRQ(AXP809, BATT_ENT_ACT_MODE, 1, 5),
INIT_REGMAP_IRQ(AXP809, BATT_EXIT_ACT_MODE, 1, 4),
INIT_REGMAP_IRQ(AXP809, CHARG, 1, 3),
INIT_REGMAP_IRQ(AXP809, CHARG_DONE, 1, 2),
INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH, 2, 7),
INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH_END, 2, 6),
INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW, 2, 5),
INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW_END, 2, 4),
INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH, 2, 3),
INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH_END, 2, 2),
INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW, 2, 1),
INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW_END, 2, 0),
INIT_REGMAP_IRQ(AXP809, DIE_TEMP_HIGH, 3, 7),
INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL1, 3, 1),
INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL2, 3, 0),
INIT_REGMAP_IRQ(AXP809, TIMER, 4, 7),
INIT_REGMAP_IRQ(AXP809, PEK_RIS_EDGE, 4, 6),
INIT_REGMAP_IRQ(AXP809, PEK_FAL_EDGE, 4, 5),
INIT_REGMAP_IRQ(AXP809, PEK_SHORT, 4, 4),
INIT_REGMAP_IRQ(AXP809, PEK_LONG, 4, 3),
INIT_REGMAP_IRQ(AXP809, PEK_OVER_OFF, 4, 2),
INIT_REGMAP_IRQ(AXP809, GPIO1_INPUT, 4, 1),
INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0),
};
static const struct regmap_irq_chip axp152_regmap_irq_chip = {
.name = "axp152_irq_chip",
.status_base = AXP152_IRQ1_STATE,
@ -428,6 +485,18 @@ static const struct regmap_irq_chip axp288_regmap_irq_chip = {
};
static const struct regmap_irq_chip axp809_regmap_irq_chip = {
.name = "axp809",
.status_base = AXP20X_IRQ1_STATE,
.ack_base = AXP20X_IRQ1_STATE,
.mask_base = AXP20X_IRQ1_EN,
.mask_invert = true,
.init_ack_masked = true,
.irqs = axp809_regmap_irqs,
.num_irqs = ARRAY_SIZE(axp809_regmap_irqs),
.num_regs = 5,
};
static struct mfd_cell axp20x_cells[] = {
{
.name = "axp20x-pek",
@ -435,6 +504,11 @@ static struct mfd_cell axp20x_cells[] = {
.resources = axp20x_pek_resources,
}, {
.name = "axp20x-regulator",
}, {
.name = "axp20x-ac-power-supply",
.of_compatible = "x-powers,axp202-ac-power-supply",
.num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources),
.resources = axp20x_ac_power_supply_resources,
}, {
.name = "axp20x-usb-power-supply",
.of_compatible = "x-powers,axp202-usb-power-supply",
@ -572,6 +646,16 @@ static struct mfd_cell axp288_cells[] = {
},
};
static struct mfd_cell axp809_cells[] = {
{
.name = "axp20x-pek",
.num_resources = ARRAY_SIZE(axp809_pek_resources),
.resources = axp809_pek_resources,
}, {
.name = "axp20x-regulator",
},
};
static struct axp20x_dev *axp20x_pm_power_off;
static void axp20x_power_off(void)
{
@ -631,6 +715,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_cfg = &axp288_regmap_config;
axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
break;
case AXP809_ID:
axp20x->nr_cells = ARRAY_SIZE(axp809_cells);
axp20x->cells = axp809_cells;
axp20x->regmap_cfg = &axp22x_regmap_config;
axp20x->regmap_irq_chip = &axp809_regmap_irq_chip;
break;
default:
dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
return -EINVAL;

View file

@ -82,8 +82,8 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri,
goto err;
}
ret = mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs,
ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
ret = devm_mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs,
ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
if (ret < 0) {
dev_err(&i2c_pri->dev, "failed to add sub-devices: %d\n", ret);
goto err;
@ -96,12 +96,6 @@ err:
return ret;
}
static int bcm590xx_i2c_remove(struct i2c_client *i2c)
{
mfd_remove_devices(&i2c->dev);
return 0;
}
static const struct of_device_id bcm590xx_of_match[] = {
{ .compatible = "brcm,bcm59056" },
{ }
@ -120,7 +114,6 @@ static struct i2c_driver bcm590xx_i2c_driver = {
.of_match_table = of_match_ptr(bcm590xx_of_match),
},
.probe = bcm590xx_i2c_probe,
.remove = bcm590xx_i2c_remove,
.id_table = bcm590xx_i2c_id,
};
module_i2c_driver(bcm590xx_i2c_driver);

View file

@ -25,14 +25,6 @@
#define DA9063_REG_EVENT_B_OFFSET 1
#define DA9063_REG_EVENT_C_OFFSET 2
#define DA9063_REG_EVENT_D_OFFSET 3
#define EVENTS_BUF_LEN 4
static const u8 mask_events_buf[] = { [0 ... (EVENTS_BUF_LEN - 1)] = ~0 };
struct da9063_irq_data {
u16 reg;
u8 mask;
};
static const struct regmap_irq da9063_irqs[] = {
/* DA9063 event A register */

View file

@ -33,25 +33,25 @@
* This driver was tested with firmware revision A4.
*/
#if defined(CONFIG_INPUT_DM355EVM) || defined(CONFIG_INPUT_DM355EVM_MODULE)
#if IS_ENABLED(CONFIG_INPUT_DM355EVM)
#define msp_has_keyboard() true
#else
#define msp_has_keyboard() false
#endif
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
#if IS_ENABLED(CONFIG_LEDS_GPIO)
#define msp_has_leds() true
#else
#define msp_has_leds() false
#endif
#if defined(CONFIG_RTC_DRV_DM355EVM) || defined(CONFIG_RTC_DRV_DM355EVM_MODULE)
#if IS_ENABLED(CONFIG_RTC_DRV_DM355EVM)
#define msp_has_rtc() true
#else
#define msp_has_rtc() false
#endif
#if defined(CONFIG_VIDEO_TVP514X) || defined(CONFIG_VIDEO_TVP514X_MODULE)
#if IS_ENABLED(CONFIG_VIDEO_TVP514X)
#define msp_has_tvp() true
#else
#define msp_has_tvp() false
@ -260,7 +260,7 @@ static int add_children(struct i2c_client *client)
/* GPIO-ish stuff */
dm355evm_msp_gpio.parent = &client->dev;
status = gpiochip_add(&dm355evm_msp_gpio);
status = gpiochip_add_data(&dm355evm_msp_gpio, NULL);
if (status < 0)
return status;

View file

@ -76,8 +76,8 @@ static int hi6421_pmic_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pmic);
ret = mfd_add_devices(&pdev->dev, 0, hi6421_devs,
ARRAY_SIZE(hi6421_devs), NULL, 0, NULL);
ret = devm_mfd_add_devices(&pdev->dev, 0, hi6421_devs,
ARRAY_SIZE(hi6421_devs), NULL, 0, NULL);
if (ret) {
dev_err(&pdev->dev, "add mfd devices failed: %d\n", ret);
return ret;
@ -86,13 +86,6 @@ static int hi6421_pmic_probe(struct platform_device *pdev)
return 0;
}
static int hi6421_pmic_remove(struct platform_device *pdev)
{
mfd_remove_devices(&pdev->dev);
return 0;
}
static const struct of_device_id of_hi6421_pmic_match_tbl[] = {
{ .compatible = "hisilicon,hi6421-pmic", },
{ },
@ -105,7 +98,6 @@ static struct platform_driver hi6421_pmic_driver = {
.of_match_table = of_hi6421_pmic_match_tbl,
},
.probe = hi6421_pmic_probe,
.remove = hi6421_pmic_remove,
};
module_platform_driver(hi6421_pmic_driver);

162
drivers/mfd/hi655x-pmic.c Normal file
View file

@ -0,0 +1,162 @@
/*
* Device driver for MFD hi655x PMIC
*
* Copyright (c) 2016 Hisilicon.
*
* Authors:
* Chen Feng <puck.chen@hisilicon.com>
* Fei Wang <w.f@huawei.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.
*/
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/mfd/core.h>
#include <linux/mfd/hi655x-pmic.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
static const struct mfd_cell hi655x_pmic_devs[] = {
{ .name = "hi655x-regulator", },
};
static const struct regmap_irq hi655x_irqs[] = {
{ .reg_offset = 0, .mask = OTMP_D1R_INT },
{ .reg_offset = 0, .mask = VSYS_2P5_R_INT },
{ .reg_offset = 0, .mask = VSYS_UV_D3R_INT },
{ .reg_offset = 0, .mask = VSYS_6P0_D200UR_INT },
{ .reg_offset = 0, .mask = PWRON_D4SR_INT },
{ .reg_offset = 0, .mask = PWRON_D20F_INT },
{ .reg_offset = 0, .mask = PWRON_D20R_INT },
{ .reg_offset = 0, .mask = RESERVE_INT },
};
static const struct regmap_irq_chip hi655x_irq_chip = {
.name = "hi655x-pmic",
.irqs = hi655x_irqs,
.num_regs = 1,
.num_irqs = ARRAY_SIZE(hi655x_irqs),
.status_base = HI655X_IRQ_STAT_BASE,
.mask_base = HI655X_IRQ_MASK_BASE,
};
static struct regmap_config hi655x_regmap_config = {
.reg_bits = 32,
.reg_stride = HI655X_STRIDE,
.val_bits = 8,
.max_register = HI655X_BUS_ADDR(0xFFF),
};
static void hi655x_local_irq_clear(struct regmap *map)
{
int i;
regmap_write(map, HI655X_ANA_IRQM_BASE, HI655X_IRQ_CLR);
for (i = 0; i < HI655X_IRQ_ARRAY; i++) {
regmap_write(map, HI655X_IRQ_STAT_BASE + i * HI655X_STRIDE,
HI655X_IRQ_CLR);
}
}
static int hi655x_pmic_probe(struct platform_device *pdev)
{
int ret;
struct hi655x_pmic *pmic;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
void __iomem *base;
pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic)
return -ENOMEM;
pmic->dev = dev;
pmic->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!pmic->res)
return -ENOENT;
base = devm_ioremap_resource(dev, pmic->res);
if (!base)
return -ENOMEM;
pmic->regmap = devm_regmap_init_mmio_clk(dev, NULL, base,
&hi655x_regmap_config);
regmap_read(pmic->regmap, HI655X_BUS_ADDR(HI655X_VER_REG), &pmic->ver);
if ((pmic->ver < PMU_VER_START) || (pmic->ver > PMU_VER_END)) {
dev_warn(dev, "PMU version %d unsupported\n", pmic->ver);
return -EINVAL;
}
hi655x_local_irq_clear(pmic->regmap);
pmic->gpio = of_get_named_gpio(np, "pmic-gpios", 0);
if (!gpio_is_valid(pmic->gpio)) {
dev_err(dev, "Failed to get the pmic-gpios\n");
return -ENODEV;
}
ret = devm_gpio_request_one(dev, pmic->gpio, GPIOF_IN,
"hi655x_pmic_irq");
if (ret < 0) {
dev_err(dev, "Failed to request gpio %d ret = %d\n",
pmic->gpio, ret);
return ret;
}
ret = regmap_add_irq_chip(pmic->regmap, gpio_to_irq(pmic->gpio),
IRQF_TRIGGER_LOW | IRQF_NO_SUSPEND, 0,
&hi655x_irq_chip, &pmic->irq_data);
if (ret) {
dev_err(dev, "Failed to obtain 'hi655x_pmic_irq' %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, pmic);
ret = mfd_add_devices(dev, PLATFORM_DEVID_AUTO, hi655x_pmic_devs,
ARRAY_SIZE(hi655x_pmic_devs), NULL, 0, NULL);
if (ret) {
dev_err(dev, "Failed to register device %d\n", ret);
regmap_del_irq_chip(gpio_to_irq(pmic->gpio), pmic->irq_data);
return ret;
}
return 0;
}
static int hi655x_pmic_remove(struct platform_device *pdev)
{
struct hi655x_pmic *pmic = platform_get_drvdata(pdev);
regmap_del_irq_chip(gpio_to_irq(pmic->gpio), pmic->irq_data);
mfd_remove_devices(&pdev->dev);
return 0;
}
static const struct of_device_id hi655x_pmic_match[] = {
{ .compatible = "hisilicon,hi655x-pmic", },
{},
};
static struct platform_driver hi655x_pmic_driver = {
.driver = {
.name = "hi655x-pmic",
.of_match_table = of_match_ptr(hi655x_pmic_match),
},
.probe = hi655x_pmic_probe,
.remove = hi655x_pmic_remove,
};
module_platform_driver(hi655x_pmic_driver);
MODULE_AUTHOR("Chen Feng <[email protected]>");
MODULE_DESCRIPTION("Hisilicon hi655x PMIC driver");
MODULE_LICENSE("GPL v2");

View file

@ -155,7 +155,7 @@ static int egpio_get(struct gpio_chip *chip, unsigned offset)
pr_debug("egpio_get_value(%d)\n", chip->base + offset);
egpio = container_of(chip, struct egpio_chip, chip);
egpio = gpiochip_get_data(chip);
ei = dev_get_drvdata(egpio->dev);
bit = egpio_bit(ei, offset);
reg = egpio->reg_start + egpio_pos(ei, offset);
@ -170,7 +170,7 @@ static int egpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct egpio_chip *egpio;
egpio = container_of(chip, struct egpio_chip, chip);
egpio = gpiochip_get_data(chip);
return test_bit(offset, &egpio->is_out) ? -EINVAL : 0;
}
@ -192,7 +192,7 @@ static void egpio_set(struct gpio_chip *chip, unsigned offset, int value)
pr_debug("egpio_set(%s, %d(%d), %d)\n",
chip->label, offset, offset+chip->base, value);
egpio = container_of(chip, struct egpio_chip, chip);
egpio = gpiochip_get_data(chip);
ei = dev_get_drvdata(egpio->dev);
bit = egpio_bit(ei, offset);
pos = egpio_pos(ei, offset);
@ -216,7 +216,7 @@ static int egpio_direction_output(struct gpio_chip *chip,
{
struct egpio_chip *egpio;
egpio = container_of(chip, struct egpio_chip, chip);
egpio = gpiochip_get_data(chip);
if (test_bit(offset, &egpio->is_out)) {
egpio_set(chip, offset, value);
return 0;
@ -330,7 +330,7 @@ static int __init egpio_probe(struct platform_device *pdev)
chip->base = pdata->chip[i].gpio_base;
chip->ngpio = pdata->chip[i].num_gpios;
gpiochip_add(chip);
gpiochip_add_data(chip, &ei->chip[i]);
}
/* Set initial pin values */

View file

@ -227,8 +227,7 @@ static irqreturn_t htcpld_handler(int irq, void *dev)
static void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val)
{
struct i2c_client *client;
struct htcpld_chip *chip_data =
container_of(chip, struct htcpld_chip, chip_out);
struct htcpld_chip *chip_data = gpiochip_get_data(chip);
unsigned long flags;
client = chip_data->client;
@ -257,14 +256,12 @@ static void htcpld_chip_set_ni(struct work_struct *work)
static int htcpld_chip_get(struct gpio_chip *chip, unsigned offset)
{
struct htcpld_chip *chip_data;
struct htcpld_chip *chip_data = gpiochip_get_data(chip);
u8 cache;
if (!strncmp(chip->label, "htcpld-out", 10)) {
chip_data = container_of(chip, struct htcpld_chip, chip_out);
cache = chip_data->cache_out;
} else if (!strncmp(chip->label, "htcpld-in", 9)) {
chip_data = container_of(chip, struct htcpld_chip, chip_in);
cache = chip_data->cache_in;
} else
return -EINVAL;
@ -291,9 +288,7 @@ static int htcpld_direction_input(struct gpio_chip *chip,
static int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct htcpld_chip *chip_data;
chip_data = container_of(chip, struct htcpld_chip, chip_in);
struct htcpld_chip *chip_data = gpiochip_get_data(chip);
if (offset < chip_data->nirqs)
return chip_data->irq_start + offset;
@ -451,14 +446,14 @@ static int htcpld_register_chip_gpio(
gpio_chip->ngpio = plat_chip_data->num_gpios;
/* Add the GPIO chips */
ret = gpiochip_add(&(chip->chip_out));
ret = gpiochip_add_data(&(chip->chip_out), chip);
if (ret) {
dev_warn(dev, "Unable to register output GPIOs for 0x%x: %d\n",
plat_chip_data->addr, ret);
return ret;
}
ret = gpiochip_add(&(chip->chip_in));
ret = gpiochip_add_data(&(chip->chip_in), chip);
if (ret) {
dev_warn(dev, "Unable to register input GPIOs for 0x%x: %d\n",
plat_chip_data->addr, ret);

View file

@ -34,6 +34,7 @@
#define LPSS_DEV_SIZE 0x200
#define LPSS_PRIV_OFFSET 0x200
#define LPSS_PRIV_SIZE 0x100
#define LPSS_PRIV_REG_COUNT (LPSS_PRIV_SIZE / 4)
#define LPSS_IDMA64_OFFSET 0x800
#define LPSS_IDMA64_SIZE 0x800
@ -76,6 +77,7 @@ struct intel_lpss {
struct mfd_cell *cell;
struct device *dev;
void __iomem *priv;
u32 priv_ctx[LPSS_PRIV_REG_COUNT];
int devid;
u32 caps;
u32 active_ltr;
@ -336,8 +338,8 @@ static int intel_lpss_register_clock(struct intel_lpss *lpss)
return 0;
/* Root clock */
clk = clk_register_fixed_rate(NULL, dev_name(lpss->dev), NULL,
CLK_IS_ROOT, lpss->info->clk_rate);
clk = clk_register_fixed_rate(NULL, dev_name(lpss->dev), NULL, 0,
lpss->info->clk_rate);
if (IS_ERR(clk))
return PTR_ERR(clk);
@ -493,6 +495,16 @@ EXPORT_SYMBOL_GPL(intel_lpss_prepare);
int intel_lpss_suspend(struct device *dev)
{
struct intel_lpss *lpss = dev_get_drvdata(dev);
unsigned int i;
/* Save device context */
for (i = 0; i < LPSS_PRIV_REG_COUNT; i++)
lpss->priv_ctx[i] = readl(lpss->priv + i * 4);
/* Put the device into reset state */
writel(0, lpss->priv + LPSS_PRIV_RESETS);
return 0;
}
EXPORT_SYMBOL_GPL(intel_lpss_suspend);
@ -500,8 +512,13 @@ EXPORT_SYMBOL_GPL(intel_lpss_suspend);
int intel_lpss_resume(struct device *dev)
{
struct intel_lpss *lpss = dev_get_drvdata(dev);
unsigned int i;
intel_lpss_init_dev(lpss);
intel_lpss_deassert_reset(lpss);
/* Restore device context */
for (i = 0; i < LPSS_PRIV_REG_COUNT; i++)
writel(lpss->priv_ctx[i], lpss->priv + i * 4);
return 0;
}

View file

@ -53,7 +53,7 @@
#define INTEL_QUARK_I2C_CLK_HZ 33000000
struct intel_quark_mfd {
struct pci_dev *pdev;
struct device *dev;
struct clk *i2c_clk;
struct clk_lookup *i2c_clk_lookup;
};
@ -123,14 +123,14 @@ static const struct pci_device_id intel_quark_mfd_ids[] = {
};
MODULE_DEVICE_TABLE(pci, intel_quark_mfd_ids);
static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd)
static int intel_quark_register_i2c_clk(struct device *dev)
{
struct pci_dev *pdev = quark_mfd->pdev;
struct intel_quark_mfd *quark_mfd = dev_get_drvdata(dev);
struct clk *i2c_clk;
i2c_clk = clk_register_fixed_rate(&pdev->dev,
i2c_clk = clk_register_fixed_rate(dev,
INTEL_QUARK_I2C_CONTROLLER_CLK, NULL,
CLK_IS_ROOT, INTEL_QUARK_I2C_CLK_HZ);
0, INTEL_QUARK_I2C_CLK_HZ);
if (IS_ERR(i2c_clk))
return PTR_ERR(i2c_clk);
@ -139,18 +139,19 @@ static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd)
INTEL_QUARK_I2C_CONTROLLER_CLK);
if (!quark_mfd->i2c_clk_lookup) {
dev_err(&pdev->dev, "Fixed clk register failed\n");
clk_unregister(quark_mfd->i2c_clk);
dev_err(dev, "Fixed clk register failed\n");
return -ENOMEM;
}
return 0;
}
static void intel_quark_unregister_i2c_clk(struct pci_dev *pdev)
static void intel_quark_unregister_i2c_clk(struct device *dev)
{
struct intel_quark_mfd *quark_mfd = dev_get_drvdata(&pdev->dev);
struct intel_quark_mfd *quark_mfd = dev_get_drvdata(dev);
if (!quark_mfd->i2c_clk || !quark_mfd->i2c_clk_lookup)
if (!quark_mfd->i2c_clk_lookup)
return;
clkdev_drop(quark_mfd->i2c_clk_lookup);
@ -245,30 +246,38 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,
quark_mfd = devm_kzalloc(&pdev->dev, sizeof(*quark_mfd), GFP_KERNEL);
if (!quark_mfd)
return -ENOMEM;
quark_mfd->pdev = pdev;
ret = intel_quark_register_i2c_clk(quark_mfd);
quark_mfd->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, quark_mfd);
ret = intel_quark_register_i2c_clk(&pdev->dev);
if (ret)
return ret;
dev_set_drvdata(&pdev->dev, quark_mfd);
ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]);
if (ret)
return ret;
goto err_unregister_i2c_clk;
ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]);
if (ret)
return ret;
goto err_unregister_i2c_clk;
return mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells,
ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0,
NULL);
ret = mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells,
ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0,
NULL);
if (ret)
goto err_unregister_i2c_clk;
return 0;
err_unregister_i2c_clk:
intel_quark_unregister_i2c_clk(&pdev->dev);
return ret;
}
static void intel_quark_mfd_remove(struct pci_dev *pdev)
{
intel_quark_unregister_i2c_clk(pdev);
intel_quark_unregister_i2c_clk(&pdev->dev);
mfd_remove_devices(&pdev->dev);
}

View file

@ -35,6 +35,7 @@ static struct gpiod_lookup_table panel_gpio_table = {
.table = {
/* Panel EN/DISABLE */
GPIO_LOOKUP("gpio_crystalcove", 94, "panel", GPIO_ACTIVE_HIGH),
{ },
},
};

View file

@ -123,16 +123,9 @@ static int lp3943_probe(struct i2c_client *cl, const struct i2c_device_id *id)
lp3943->mux_cfg = lp3943_mux_cfg;
i2c_set_clientdata(cl, lp3943);
return mfd_add_devices(dev, -1, lp3943_devs, ARRAY_SIZE(lp3943_devs),
NULL, 0, NULL);
}
static int lp3943_remove(struct i2c_client *cl)
{
struct lp3943 *lp3943 = i2c_get_clientdata(cl);
mfd_remove_devices(lp3943->dev);
return 0;
return devm_mfd_add_devices(dev, -1, lp3943_devs,
ARRAY_SIZE(lp3943_devs),
NULL, 0, NULL);
}
static const struct i2c_device_id lp3943_ids[] = {
@ -151,7 +144,6 @@ MODULE_DEVICE_TABLE(of, lp3943_of_match);
static struct i2c_driver lp3943_driver = {
.probe = lp3943_probe,
.remove = lp3943_remove,
.driver = {
.name = "lp3943",
.of_match_table = of_match_ptr(lp3943_of_match),

View file

@ -112,7 +112,7 @@ static irqreturn_t lp8788_irq_handler(int irq, void *ptr)
struct lp8788_irq_data *irqd = ptr;
struct lp8788 *lp = irqd->lp;
u8 status[NUM_REGS], addr, mask;
bool handled;
bool handled = false;
int i;
if (lp8788_read_multi_bytes(lp, LP8788_INT_1, status, NUM_REGS))

590
drivers/mfd/max77620.c Normal file
View file

@ -0,0 +1,590 @@
/*
* Maxim MAX77620 MFD Driver
*
* Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
*
* Author:
* Laxman Dewangan <ldewangan@nvidia.com>
* Chaitanya Bandi <bandik@nvidia.com>
* Mallikarjun Kasoju <mkasoju@nvidia.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.
*/
/****************** Teminology used in driver ********************
* Here are some terminology used from datasheet for quick reference:
* Flexible Power Sequence (FPS):
* The Flexible Power Sequencer (FPS) allows each regulator to power up under
* hardware or software control. Additionally, each regulator can power on
* independently or among a group of other regulators with an adjustable
* power-up and power-down delays (sequencing). GPIO1, GPIO2, and GPIO3 can
* be programmed to be part of a sequence allowing external regulators to be
* sequenced along with internal regulators. 32KHz clock can be programmed to
* be part of a sequence.
* There is 3 FPS confguration registers and all resources are configured to
* any of these FPS or no FPS.
*/
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/mfd/max77620.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
static struct resource gpio_resources[] = {
DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO),
};
static struct resource power_resources[] = {
DEFINE_RES_IRQ(MAX77620_IRQ_LBT_MBATLOW),
};
static struct resource rtc_resources[] = {
DEFINE_RES_IRQ(MAX77620_IRQ_TOP_RTC),
};
static struct resource thermal_resources[] = {
DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM1),
DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM2),
};
static const struct regmap_irq max77620_top_irqs[] = {
REGMAP_IRQ_REG(MAX77620_IRQ_TOP_GLBL, 0, MAX77620_IRQ_TOP_GLBL_MASK),
REGMAP_IRQ_REG(MAX77620_IRQ_TOP_SD, 0, MAX77620_IRQ_TOP_SD_MASK),
REGMAP_IRQ_REG(MAX77620_IRQ_TOP_LDO, 0, MAX77620_IRQ_TOP_LDO_MASK),
REGMAP_IRQ_REG(MAX77620_IRQ_TOP_GPIO, 0, MAX77620_IRQ_TOP_GPIO_MASK),
REGMAP_IRQ_REG(MAX77620_IRQ_TOP_RTC, 0, MAX77620_IRQ_TOP_RTC_MASK),
REGMAP_IRQ_REG(MAX77620_IRQ_TOP_32K, 0, MAX77620_IRQ_TOP_32K_MASK),
REGMAP_IRQ_REG(MAX77620_IRQ_TOP_ONOFF, 0, MAX77620_IRQ_TOP_ONOFF_MASK),
REGMAP_IRQ_REG(MAX77620_IRQ_LBT_MBATLOW, 1, MAX77620_IRQ_LBM_MASK),
REGMAP_IRQ_REG(MAX77620_IRQ_LBT_TJALRM1, 1, MAX77620_IRQ_TJALRM1_MASK),
REGMAP_IRQ_REG(MAX77620_IRQ_LBT_TJALRM2, 1, MAX77620_IRQ_TJALRM2_MASK),
};
static const struct mfd_cell max77620_children[] = {
{ .name = "max77620-pinctrl", },
{ .name = "max77620-clock", },
{ .name = "max77620-pmic", },
{ .name = "max77620-watchdog", },
{
.name = "max77620-gpio",
.resources = gpio_resources,
.num_resources = ARRAY_SIZE(gpio_resources),
}, {
.name = "max77620-rtc",
.resources = rtc_resources,
.num_resources = ARRAY_SIZE(rtc_resources),
}, {
.name = "max77620-power",
.resources = power_resources,
.num_resources = ARRAY_SIZE(power_resources),
}, {
.name = "max77620-thermal",
.resources = thermal_resources,
.num_resources = ARRAY_SIZE(thermal_resources),
},
};
static const struct mfd_cell max20024_children[] = {
{ .name = "max20024-pinctrl", },
{ .name = "max77620-clock", },
{ .name = "max20024-pmic", },
{ .name = "max77620-watchdog", },
{
.name = "max77620-gpio",
.resources = gpio_resources,
.num_resources = ARRAY_SIZE(gpio_resources),
}, {
.name = "max77620-rtc",
.resources = rtc_resources,
.num_resources = ARRAY_SIZE(rtc_resources),
}, {
.name = "max20024-power",
.resources = power_resources,
.num_resources = ARRAY_SIZE(power_resources),
},
};
static struct regmap_irq_chip max77620_top_irq_chip = {
.name = "max77620-top",
.irqs = max77620_top_irqs,
.num_irqs = ARRAY_SIZE(max77620_top_irqs),
.num_regs = 2,
.status_base = MAX77620_REG_IRQTOP,
.mask_base = MAX77620_REG_IRQTOPM,
};
static const struct regmap_range max77620_readable_ranges[] = {
regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4),
};
static const struct regmap_access_table max77620_readable_table = {
.yes_ranges = max77620_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(max77620_readable_ranges),
};
static const struct regmap_range max20024_readable_ranges[] = {
regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4),
regmap_reg_range(MAX20024_REG_MAX_ADD, MAX20024_REG_MAX_ADD),
};
static const struct regmap_access_table max20024_readable_table = {
.yes_ranges = max20024_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(max20024_readable_ranges),
};
static const struct regmap_range max77620_writable_ranges[] = {
regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4),
};
static const struct regmap_access_table max77620_writable_table = {
.yes_ranges = max77620_writable_ranges,
.n_yes_ranges = ARRAY_SIZE(max77620_writable_ranges),
};
static const struct regmap_range max77620_cacheable_ranges[] = {
regmap_reg_range(MAX77620_REG_SD0_CFG, MAX77620_REG_LDO_CFG3),
regmap_reg_range(MAX77620_REG_FPS_CFG0, MAX77620_REG_FPS_SD3),
};
static const struct regmap_access_table max77620_volatile_table = {
.no_ranges = max77620_cacheable_ranges,
.n_no_ranges = ARRAY_SIZE(max77620_cacheable_ranges),
};
static const struct regmap_config max77620_regmap_config = {
.name = "power-slave",
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX77620_REG_DVSSD4 + 1,
.cache_type = REGCACHE_RBTREE,
.rd_table = &max77620_readable_table,
.wr_table = &max77620_writable_table,
.volatile_table = &max77620_volatile_table,
};
static const struct regmap_config max20024_regmap_config = {
.name = "power-slave",
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX20024_REG_MAX_ADD + 1,
.cache_type = REGCACHE_RBTREE,
.rd_table = &max20024_readable_table,
.wr_table = &max77620_writable_table,
.volatile_table = &max77620_volatile_table,
};
/* max77620_get_fps_period_reg_value: Get FPS bit field value from
* requested periods.
* MAX77620 supports the FPS period of 40, 80, 160, 320, 540, 1280, 2560
* and 5120 microseconds. MAX20024 supports the FPS period of 20, 40, 80,
* 160, 320, 540, 1280 and 2560 microseconds.
* The FPS register has 3 bits field to set the FPS period as
* bits max77620 max20024
* 000 40 20
* 001 80 40
* :::
*/
static int max77620_get_fps_period_reg_value(struct max77620_chip *chip,
int tperiod)
{
int fps_min_period;
int i;
switch (chip->chip_id) {
case MAX20024:
fps_min_period = MAX20024_FPS_PERIOD_MIN_US;
break;
case MAX77620:
fps_min_period = MAX77620_FPS_PERIOD_MIN_US;
default:
return -EINVAL;
}
for (i = 0; i < 7; i++) {
if (fps_min_period >= tperiod)
return i;
fps_min_period *= 2;
}
return i;
}
/* max77620_config_fps: Configure FPS configuration registers
* based on platform specific information.
*/
static int max77620_config_fps(struct max77620_chip *chip,
struct device_node *fps_np)
{
struct device *dev = chip->dev;
unsigned int mask = 0, config = 0;
u32 fps_max_period;
u32 param_val;
int tperiod, fps_id;
int ret;
char fps_name[10];
switch (chip->chip_id) {
case MAX20024:
fps_max_period = MAX20024_FPS_PERIOD_MAX_US;
break;
case MAX77620:
fps_max_period = MAX77620_FPS_PERIOD_MAX_US;
default:
return -EINVAL;
}
for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) {
sprintf(fps_name, "fps%d", fps_id);
if (!strcmp(fps_np->name, fps_name))
break;
}
if (fps_id == MAX77620_FPS_COUNT) {
dev_err(dev, "FPS node name %s is not valid\n", fps_np->name);
return -EINVAL;
}
ret = of_property_read_u32(fps_np, "maxim,shutdown-fps-time-period-us",
&param_val);
if (!ret) {
mask |= MAX77620_FPS_TIME_PERIOD_MASK;
chip->shutdown_fps_period[fps_id] = min(param_val,
fps_max_period);
tperiod = max77620_get_fps_period_reg_value(chip,
chip->shutdown_fps_period[fps_id]);
config |= tperiod << MAX77620_FPS_TIME_PERIOD_SHIFT;
}
ret = of_property_read_u32(fps_np, "maxim,suspend-fps-time-period-us",
&param_val);
if (!ret)
chip->suspend_fps_period[fps_id] = min(param_val,
fps_max_period);
ret = of_property_read_u32(fps_np, "maxim,fps-event-source",
&param_val);
if (!ret) {
if (param_val > 2) {
dev_err(dev, "FPS%d event-source invalid\n", fps_id);
return -EINVAL;
}
mask |= MAX77620_FPS_EN_SRC_MASK;
config |= param_val << MAX77620_FPS_EN_SRC_SHIFT;
if (param_val == 2) {
mask |= MAX77620_FPS_ENFPS_SW_MASK;
config |= MAX77620_FPS_ENFPS_SW;
}
}
if (!chip->sleep_enable && !chip->enable_global_lpm) {
ret = of_property_read_u32(fps_np,
"maxim,device-state-on-disabled-event",
&param_val);
if (!ret) {
if (param_val == 0)
chip->sleep_enable = true;
else if (param_val == 1)
chip->enable_global_lpm = true;
}
}
ret = regmap_update_bits(chip->rmap, MAX77620_REG_FPS_CFG0 + fps_id,
mask, config);
if (ret < 0) {
dev_err(dev, "Failed to update FPS CFG: %d\n", ret);
return ret;
}
return 0;
}
static int max77620_initialise_fps(struct max77620_chip *chip)
{
struct device *dev = chip->dev;
struct device_node *fps_np, *fps_child;
u8 config;
int fps_id;
int ret;
for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) {
chip->shutdown_fps_period[fps_id] = -1;
chip->suspend_fps_period[fps_id] = -1;
}
fps_np = of_get_child_by_name(dev->of_node, "fps");
if (!fps_np)
goto skip_fps;
for_each_child_of_node(fps_np, fps_child) {
ret = max77620_config_fps(chip, fps_child);
if (ret < 0)
return ret;
}
config = chip->enable_global_lpm ? MAX77620_ONOFFCNFG2_SLP_LPM_MSK : 0;
ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
MAX77620_ONOFFCNFG2_SLP_LPM_MSK, config);
if (ret < 0) {
dev_err(dev, "Failed to update SLP_LPM: %d\n", ret);
return ret;
}
skip_fps:
/* Enable wake on EN0 pin */
ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
MAX77620_ONOFFCNFG2_WK_EN0,
MAX77620_ONOFFCNFG2_WK_EN0);
if (ret < 0) {
dev_err(dev, "Failed to update WK_EN0: %d\n", ret);
return ret;
}
/* For MAX20024, SLPEN will be POR reset if CLRSE is b11 */
if ((chip->chip_id == MAX20024) && chip->sleep_enable) {
config = MAX77620_ONOFFCNFG1_SLPEN | MAX20024_ONOFFCNFG1_CLRSE;
ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1,
config, config);
if (ret < 0) {
dev_err(dev, "Failed to update SLPEN: %d\n", ret);
return ret;
}
}
return 0;
}
static int max77620_read_es_version(struct max77620_chip *chip)
{
unsigned int val;
u8 cid_val[6];
int i;
int ret;
for (i = MAX77620_REG_CID0; i <= MAX77620_REG_CID5; i++) {
ret = regmap_read(chip->rmap, i, &val);
if (ret < 0) {
dev_err(chip->dev, "Failed to read CID: %d\n", ret);
return ret;
}
dev_dbg(chip->dev, "CID%d: 0x%02x\n",
i - MAX77620_REG_CID0, val);
cid_val[i - MAX77620_REG_CID0] = val;
}
/* CID4 is OTP Version and CID5 is ES version */
dev_info(chip->dev, "PMIC Version OTP:0x%02X and ES:0x%X\n",
cid_val[4], MAX77620_CID5_DIDM(cid_val[5]));
return ret;
}
static int max77620_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct regmap_config *rmap_config;
struct max77620_chip *chip;
const struct mfd_cell *mfd_cells;
int n_mfd_cells;
int ret;
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
i2c_set_clientdata(client, chip);
chip->dev = &client->dev;
chip->irq_base = -1;
chip->chip_irq = client->irq;
chip->chip_id = (enum max77620_chip_id)id->driver_data;
switch (chip->chip_id) {
case MAX77620:
mfd_cells = max77620_children;
n_mfd_cells = ARRAY_SIZE(max77620_children);
rmap_config = &max77620_regmap_config;
break;
case MAX20024:
mfd_cells = max20024_children;
n_mfd_cells = ARRAY_SIZE(max20024_children);
rmap_config = &max20024_regmap_config;
break;
default:
dev_err(chip->dev, "ChipID is invalid %d\n", chip->chip_id);
return -EINVAL;
}
chip->rmap = devm_regmap_init_i2c(client, rmap_config);
if (IS_ERR(chip->rmap)) {
ret = PTR_ERR(chip->rmap);
dev_err(chip->dev, "Failed to intialise regmap: %d\n", ret);
return ret;
}
ret = max77620_read_es_version(chip);
if (ret < 0)
return ret;
ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq,
IRQF_ONESHOT | IRQF_SHARED,
chip->irq_base, &max77620_top_irq_chip,
&chip->top_irq_data);
if (ret < 0) {
dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret);
return ret;
}
ret = max77620_initialise_fps(chip);
if (ret < 0)
return ret;
ret = devm_mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE,
mfd_cells, n_mfd_cells, NULL, 0,
regmap_irq_get_domain(chip->top_irq_data));
if (ret < 0) {
dev_err(chip->dev, "Failed to add MFD children: %d\n", ret);
return ret;
}
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int max77620_set_fps_period(struct max77620_chip *chip,
int fps_id, int time_period)
{
int period = max77620_get_fps_period_reg_value(chip, time_period);
int ret;
ret = regmap_update_bits(chip->rmap, MAX77620_REG_FPS_CFG0 + fps_id,
MAX77620_FPS_TIME_PERIOD_MASK,
period << MAX77620_FPS_TIME_PERIOD_SHIFT);
if (ret < 0) {
dev_err(chip->dev, "Failed to update FPS period: %d\n", ret);
return ret;
}
return 0;
}
static int max77620_i2c_suspend(struct device *dev)
{
struct max77620_chip *chip = dev_get_drvdata(dev);
struct i2c_client *client = to_i2c_client(dev);
unsigned int config;
int fps;
int ret;
for (fps = 0; fps < MAX77620_FPS_COUNT; fps++) {
if (chip->suspend_fps_period[fps] < 0)
continue;
ret = max77620_set_fps_period(chip, fps,
chip->suspend_fps_period[fps]);
if (ret < 0)
return ret;
}
/*
* For MAX20024: No need to configure SLPEN on suspend as
* it will be configured on Init.
*/
if (chip->chip_id == MAX20024)
goto out;
config = (chip->sleep_enable) ? MAX77620_ONOFFCNFG1_SLPEN : 0;
ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1,
MAX77620_ONOFFCNFG1_SLPEN,
config);
if (ret < 0) {
dev_err(dev, "Failed to configure sleep in suspend: %d\n", ret);
return ret;
}
/* Disable WK_EN0 */
ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
MAX77620_ONOFFCNFG2_WK_EN0, 0);
if (ret < 0) {
dev_err(dev, "Failed to configure WK_EN in suspend: %d\n", ret);
return ret;
}
out:
disable_irq(client->irq);
return 0;
}
static int max77620_i2c_resume(struct device *dev)
{
struct max77620_chip *chip = dev_get_drvdata(dev);
struct i2c_client *client = to_i2c_client(dev);
int ret;
int fps;
for (fps = 0; fps < MAX77620_FPS_COUNT; fps++) {
if (chip->shutdown_fps_period[fps] < 0)
continue;
ret = max77620_set_fps_period(chip, fps,
chip->shutdown_fps_period[fps]);
if (ret < 0)
return ret;
}
/*
* For MAX20024: No need to configure WKEN0 on resume as
* it is configured on Init.
*/
if (chip->chip_id == MAX20024)
goto out;
/* Enable WK_EN0 */
ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
MAX77620_ONOFFCNFG2_WK_EN0,
MAX77620_ONOFFCNFG2_WK_EN0);
if (ret < 0) {
dev_err(dev, "Failed to configure WK_EN0 n resume: %d\n", ret);
return ret;
}
out:
enable_irq(client->irq);
return 0;
}
#endif
static const struct i2c_device_id max77620_id[] = {
{"max77620", MAX77620},
{"max20024", MAX20024},
{},
};
MODULE_DEVICE_TABLE(i2c, max77620_id);
static const struct dev_pm_ops max77620_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(max77620_i2c_suspend, max77620_i2c_resume)
};
static struct i2c_driver max77620_driver = {
.driver = {
.name = "max77620",
.pm = &max77620_pm_ops,
},
.probe = max77620_probe,
.id_table = max77620_id,
};
module_i2c_driver(max77620_driver);
MODULE_DESCRIPTION("MAX77620/MAX20024 Multi Function Device Core Driver");
MODULE_AUTHOR("Laxman Dewangan <[email protected]>");
MODULE_AUTHOR("Chaitanya Bandi <[email protected]>");
MODULE_AUTHOR("Mallikarjun Kasoju <[email protected]>");
MODULE_LICENSE("GPL v2");

View file

@ -2,7 +2,7 @@
* max77686.c - mfd core driver for the Maxim 77686/802
*
* Copyright (C) 2012 Samsung Electronics
* Chiwoong Byun <woong.byun@smasung.com>
* Chiwoong Byun <woong.byun@samsung.com>
* Jonghwa Lee <jonghwa3.lee@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
@ -230,37 +230,23 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
return -ENODEV;
}
ret = regmap_add_irq_chip(max77686->regmap, max77686->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
IRQF_SHARED, 0, irq_chip,
&max77686->irq_data);
ret = devm_regmap_add_irq_chip(&i2c->dev, max77686->regmap,
max77686->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
IRQF_SHARED, 0, irq_chip,
&max77686->irq_data);
if (ret < 0) {
dev_err(&i2c->dev, "failed to add PMIC irq chip: %d\n", ret);
return ret;
}
ret = mfd_add_devices(max77686->dev, -1, cells, n_devs, NULL, 0, NULL);
ret = devm_mfd_add_devices(max77686->dev, -1, cells, n_devs, NULL,
0, NULL);
if (ret < 0) {
dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
goto err_del_irqc;
return ret;
}
return 0;
err_del_irqc:
regmap_del_irq_chip(max77686->irq, max77686->irq_data);
return ret;
}
static int max77686_i2c_remove(struct i2c_client *i2c)
{
struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
mfd_remove_devices(max77686->dev);
regmap_del_irq_chip(max77686->irq, max77686->irq_data);
return 0;
}
@ -317,22 +303,10 @@ static struct i2c_driver max77686_i2c_driver = {
.of_match_table = of_match_ptr(max77686_pmic_dt_match),
},
.probe = max77686_i2c_probe,
.remove = max77686_i2c_remove,
.id_table = max77686_i2c_id,
};
static int __init max77686_i2c_init(void)
{
return i2c_add_driver(&max77686_i2c_driver);
}
/* init early so consumer devices can complete system boot */
subsys_initcall(max77686_i2c_init);
static void __exit max77686_i2c_exit(void)
{
i2c_del_driver(&max77686_i2c_driver);
}
module_exit(max77686_i2c_exit);
module_i2c_driver(max77686_i2c_driver);
MODULE_DESCRIPTION("MAXIM 77686/802 multi-function core driver");
MODULE_AUTHOR("Chiwoong Byun <[email protected]>");

View file

@ -2,7 +2,7 @@
* max77693.c - mfd core driver for the MAX 77693
*
* Copyright (C) 2012 Samsung Electronics
* SangYoung Son <hello.son@smasung.com>
* SangYoung Son <hello.son@samsung.com>
*
* This program is not provided / owned by Maxim Integrated Products.
*
@ -368,6 +368,7 @@ static const struct of_device_id max77693_dt_match[] = {
{ .compatible = "maxim,max77693" },
{},
};
MODULE_DEVICE_TABLE(of, max77693_dt_match);
#endif
static struct i2c_driver max77693_i2c_driver = {
@ -381,18 +382,7 @@ static struct i2c_driver max77693_i2c_driver = {
.id_table = max77693_i2c_id,
};
static int __init max77693_i2c_init(void)
{
return i2c_add_driver(&max77693_i2c_driver);
}
/* init early so consumer devices can complete system boot */
subsys_initcall(max77693_i2c_init);
static void __exit max77693_i2c_exit(void)
{
i2c_del_driver(&max77693_i2c_driver);
}
module_exit(max77693_i2c_exit);
module_i2c_driver(max77693_i2c_driver);
MODULE_DESCRIPTION("MAXIM 77693 multi-function core driver");
MODULE_AUTHOR("SangYoung, Son <[email protected]>");

View file

@ -96,8 +96,8 @@ menf21bmc_probe(struct i2c_client *client, const struct i2c_device_id *ids)
return ret;
}
ret = mfd_add_devices(&client->dev, 0, menf21bmc_cell,
ARRAY_SIZE(menf21bmc_cell), NULL, 0, NULL);
ret = devm_mfd_add_devices(&client->dev, 0, menf21bmc_cell,
ARRAY_SIZE(menf21bmc_cell), NULL, 0, NULL);
if (ret < 0) {
dev_err(&client->dev, "failed to add BMC sub-devices\n");
return ret;
@ -106,12 +106,6 @@ menf21bmc_probe(struct i2c_client *client, const struct i2c_device_id *ids)
return 0;
}
static int menf21bmc_remove(struct i2c_client *client)
{
mfd_remove_devices(&client->dev);
return 0;
}
static const struct i2c_device_id menf21bmc_id_table[] = {
{ "menf21bmc" },
{ }
@ -122,7 +116,6 @@ static struct i2c_driver menf21bmc_driver = {
.driver.name = "menf21bmc",
.id_table = menf21bmc_id_table,
.probe = menf21bmc_probe,
.remove = menf21bmc_remove,
};
module_i2c_driver(menf21bmc_driver);

View file

@ -107,7 +107,7 @@ static void mfd_acpi_add_device(const struct mfd_cell *cell,
strlcpy(ids[0].id, match->pnpid, sizeof(ids[0].id));
list_for_each_entry(child, &parent->children, node) {
if (acpi_match_device_ids(child, ids)) {
if (!acpi_match_device_ids(child, ids)) {
adev = child;
break;
}
@ -334,6 +334,44 @@ void mfd_remove_devices(struct device *parent)
}
EXPORT_SYMBOL(mfd_remove_devices);
static void devm_mfd_dev_release(struct device *dev, void *res)
{
mfd_remove_devices(dev);
}
/**
* devm_mfd_add_devices - Resource managed version of mfd_add_devices()
*
* Returns 0 on success or an appropriate negative error number on failure.
* All child-devices of the MFD will automatically be removed when it gets
* unbinded.
*/
int devm_mfd_add_devices(struct device *dev, int id,
const struct mfd_cell *cells, int n_devs,
struct resource *mem_base,
int irq_base, struct irq_domain *domain)
{
struct device **ptr;
int ret;
ptr = devres_alloc(devm_mfd_dev_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return -ENOMEM;
ret = mfd_add_devices(dev, id, cells, n_devs, mem_base,
irq_base, domain);
if (ret < 0) {
devres_free(ptr);
return ret;
}
*ptr = dev;
devres_add(dev, ptr);
return ret;
}
EXPORT_SYMBOL(devm_mfd_add_devices);
int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
{
struct mfd_cell cell_entry;

View file

@ -267,17 +267,26 @@ static int mt6397_probe(struct platform_device *pdev)
ret = regmap_read(pmic->regmap, MT6397_CID, &id);
if (ret) {
dev_err(pmic->dev, "Failed to read chip id: %d\n", ret);
goto fail_irq;
return ret;
}
pmic->irq = platform_get_irq(pdev, 0);
if (pmic->irq <= 0)
return pmic->irq;
switch (id & 0xff) {
case MT6323_CID_CODE:
pmic->int_con[0] = MT6323_INT_CON0;
pmic->int_con[1] = MT6323_INT_CON1;
pmic->int_status[0] = MT6323_INT_STATUS0;
pmic->int_status[1] = MT6323_INT_STATUS1;
ret = mfd_add_devices(&pdev->dev, -1, mt6323_devs,
ARRAY_SIZE(mt6323_devs), NULL, 0, NULL);
ret = mt6397_irq_init(pmic);
if (ret)
return ret;
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs,
ARRAY_SIZE(mt6323_devs), NULL,
0, NULL);
break;
case MT6397_CID_CODE:
@ -286,8 +295,13 @@ static int mt6397_probe(struct platform_device *pdev)
pmic->int_con[1] = MT6397_INT_CON1;
pmic->int_status[0] = MT6397_INT_STATUS0;
pmic->int_status[1] = MT6397_INT_STATUS1;
ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs,
ARRAY_SIZE(mt6397_devs), NULL, 0, NULL);
ret = mt6397_irq_init(pmic);
if (ret)
return ret;
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs,
ARRAY_SIZE(mt6397_devs), NULL,
0, NULL);
break;
default:
@ -296,14 +310,6 @@ static int mt6397_probe(struct platform_device *pdev)
break;
}
pmic->irq = platform_get_irq(pdev, 0);
if (pmic->irq > 0) {
ret = mt6397_irq_init(pmic);
if (ret)
return ret;
}
fail_irq:
if (ret) {
irq_domain_remove(pmic->irq_domain);
dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
@ -312,13 +318,6 @@ fail_irq:
return ret;
}
static int mt6397_remove(struct platform_device *pdev)
{
mfd_remove_devices(&pdev->dev);
return 0;
}
static const struct of_device_id mt6397_of_match[] = {
{ .compatible = "mediatek,mt6397" },
{ .compatible = "mediatek,mt6323" },
@ -334,7 +333,6 @@ MODULE_DEVICE_TABLE(platform, mt6397_id);
static struct platform_driver mt6397_driver = {
.probe = mt6397_probe,
.remove = mt6397_remove,
.driver = {
.name = "mt6397",
.of_match_table = of_match_ptr(mt6397_of_match),

View file

@ -269,6 +269,8 @@ static int usbtll_omap_probe(struct platform_device *pdev)
if (IS_ERR(tll->ch_clk[i]))
dev_dbg(dev, "can't get clock : %s\n", clkname);
else
clk_prepare(tll->ch_clk[i]);
}
pm_runtime_put_sync(dev);
@ -301,9 +303,12 @@ static int usbtll_omap_remove(struct platform_device *pdev)
tll_dev = NULL;
spin_unlock(&tll_lock);
for (i = 0; i < tll->nch; i++)
if (!IS_ERR(tll->ch_clk[i]))
for (i = 0; i < tll->nch; i++) {
if (!IS_ERR(tll->ch_clk[i])) {
clk_unprepare(tll->ch_clk[i]);
clk_put(tll->ch_clk[i]);
}
}
pm_runtime_disable(&pdev->dev);
return 0;
@ -420,7 +425,7 @@ int omap_tll_enable(struct usbhs_omap_platform_data *pdata)
if (IS_ERR(tll->ch_clk[i]))
continue;
r = clk_prepare_enable(tll->ch_clk[i]);
r = clk_enable(tll->ch_clk[i]);
if (r) {
dev_err(tll_dev,
"Error enabling ch %d clock: %d\n", i, r);
@ -448,7 +453,7 @@ int omap_tll_disable(struct usbhs_omap_platform_data *pdata)
for (i = 0; i < tll->nch; i++) {
if (omap_usb_mode_needs_tll(pdata->port_mode[i])) {
if (!IS_ERR(tll->ch_clk[i]))
clk_disable_unprepare(tll->ch_clk[i]);
clk_disable(tll->ch_clk[i]);
}
}

View file

@ -389,17 +389,10 @@ int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base)
irq_clear_status_flags(__irq, IRQ_NOREQUEST);
}
ret = request_threaded_irq(irq, NULL, rc5t583_irq, IRQF_ONESHOT,
"rc5t583", rc5t583);
ret = devm_request_threaded_irq(rc5t583->dev, irq, NULL, rc5t583_irq,
IRQF_ONESHOT, "rc5t583", rc5t583);
if (ret < 0)
dev_err(rc5t583->dev,
"Error in registering interrupt error: %d\n", ret);
return ret;
}
int rc5t583_irq_exit(struct rc5t583 *rc5t583)
{
if (rc5t583->chip_irq)
free_irq(rc5t583->chip_irq, rc5t583);
return 0;
}

View file

@ -252,7 +252,6 @@ static int rc5t583_i2c_probe(struct i2c_client *i2c,
struct rc5t583 *rc5t583;
struct rc5t583_platform_data *pdata = dev_get_platdata(&i2c->dev);
int ret;
bool irq_init_success = false;
if (!pdata) {
dev_err(&i2c->dev, "Err: Platform data not found\n");
@ -284,32 +283,16 @@ static int rc5t583_i2c_probe(struct i2c_client *i2c,
/* Still continue with warning, if irq init fails */
if (ret)
dev_warn(&i2c->dev, "IRQ init failed: %d\n", ret);
else
irq_init_success = true;
}
ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs,
ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL);
ret = devm_mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs,
ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL);
if (ret) {
dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret);
goto err_add_devs;
return ret;
}
return 0;
err_add_devs:
if (irq_init_success)
rc5t583_irq_exit(rc5t583);
return ret;
}
static int rc5t583_i2c_remove(struct i2c_client *i2c)
{
struct rc5t583 *rc5t583 = i2c_get_clientdata(i2c);
mfd_remove_devices(rc5t583->dev);
rc5t583_irq_exit(rc5t583);
return 0;
}
static const struct i2c_device_id rc5t583_i2c_id[] = {
@ -324,7 +307,6 @@ static struct i2c_driver rc5t583_i2c_driver = {
.name = "rc5t583",
},
.probe = rc5t583_i2c_probe,
.remove = rc5t583_i2c_remove,
.id_table = rc5t583_i2c_id,
};

View file

@ -85,14 +85,10 @@ static int rdc321x_sb_probe(struct pci_dev *pdev,
rdc321x_gpio_pdata.sb_pdev = pdev;
rdc321x_wdt_pdata.sb_pdev = pdev;
return mfd_add_devices(&pdev->dev, -1,
rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells),
NULL, 0, NULL);
}
static void rdc321x_sb_remove(struct pci_dev *pdev)
{
mfd_remove_devices(&pdev->dev);
return devm_mfd_add_devices(&pdev->dev, -1,
rdc321x_sb_cells,
ARRAY_SIZE(rdc321x_sb_cells),
NULL, 0, NULL);
}
static const struct pci_device_id rdc321x_sb_table[] = {
@ -105,7 +101,6 @@ static struct pci_driver rdc321x_sb_driver = {
.name = "RDC321x Southbridge",
.id_table = rdc321x_sb_table,
.probe = rdc321x_sb_probe,
.remove = rdc321x_sb_remove,
};
module_pci_driver(rdc321x_sb_driver);

View file

@ -213,9 +213,9 @@ static int rk808_probe(struct i2c_client *client,
rk808->i2c = client;
i2c_set_clientdata(client, rk808);
ret = mfd_add_devices(&client->dev, -1,
rk808s, ARRAY_SIZE(rk808s),
NULL, 0, regmap_irq_get_domain(rk808->irq_data));
ret = devm_mfd_add_devices(&client->dev, -1,
rk808s, ARRAY_SIZE(rk808s), NULL, 0,
regmap_irq_get_domain(rk808->irq_data));
if (ret) {
dev_err(&client->dev, "failed to add MFD devices %d\n", ret);
goto err_irq;
@ -240,7 +240,6 @@ static int rk808_remove(struct i2c_client *client)
struct rk808 *rk808 = i2c_get_clientdata(client);
regmap_del_irq_chip(client->irq, rk808->irq_data);
mfd_remove_devices(&client->dev);
pm_power_off = NULL;
return 0;

View file

@ -78,8 +78,8 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c,
return ret;
}
ret = mfd_add_devices(&i2c->dev, -1, rn5t618_cells,
ARRAY_SIZE(rn5t618_cells), NULL, 0, NULL);
ret = devm_mfd_add_devices(&i2c->dev, -1, rn5t618_cells,
ARRAY_SIZE(rn5t618_cells), NULL, 0, NULL);
if (ret) {
dev_err(&i2c->dev, "failed to add sub-devices: %d\n", ret);
return ret;
@ -102,7 +102,6 @@ static int rn5t618_i2c_remove(struct i2c_client *i2c)
pm_power_off = NULL;
}
mfd_remove_devices(&i2c->dev);
return 0;
}

View file

@ -97,9 +97,9 @@ static int rt5033_i2c_probe(struct i2c_client *i2c,
return ret;
}
ret = mfd_add_devices(rt5033->dev, -1, rt5033_devs,
ARRAY_SIZE(rt5033_devs), NULL, 0,
regmap_irq_get_domain(rt5033->irq_data));
ret = devm_mfd_add_devices(rt5033->dev, -1, rt5033_devs,
ARRAY_SIZE(rt5033_devs), NULL, 0,
regmap_irq_get_domain(rt5033->irq_data));
if (ret < 0) {
dev_err(&i2c->dev, "Failed to add RT5033 child devices.\n");
return ret;
@ -110,13 +110,6 @@ static int rt5033_i2c_probe(struct i2c_client *i2c,
return 0;
}
static int rt5033_i2c_remove(struct i2c_client *i2c)
{
mfd_remove_devices(&i2c->dev);
return 0;
}
static const struct i2c_device_id rt5033_i2c_id[] = {
{ "rt5033", },
{ }
@ -135,7 +128,6 @@ static struct i2c_driver rt5033_driver = {
.of_match_table = of_match_ptr(rt5033_dt_match),
},
.probe = rt5033_i2c_probe,
.remove = rt5033_i2c_remove,
.id_table = rt5033_i2c_id,
};
module_i2c_driver(rt5033_driver);

View file

@ -481,29 +481,16 @@ static int sec_pmic_probe(struct i2c_client *i2c,
/* If this happens the probe function is problem */
BUG();
}
ret = mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs, NULL,
0, NULL);
ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs,
NULL, 0, NULL);
if (ret)
goto err_mfd;
return ret;
device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup);
sec_pmic_configure(sec_pmic);
sec_pmic_dump_rev(sec_pmic);
return ret;
err_mfd:
sec_irq_exit(sec_pmic);
return ret;
}
static int sec_pmic_remove(struct i2c_client *i2c)
{
struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
mfd_remove_devices(sec_pmic->dev);
sec_irq_exit(sec_pmic);
return 0;
}
static void sec_pmic_shutdown(struct i2c_client *i2c)
@ -583,7 +570,6 @@ static struct i2c_driver sec_pmic_driver = {
.of_match_table = of_match_ptr(sec_dt_match),
},
.probe = sec_pmic_probe,
.remove = sec_pmic_remove,
.shutdown = sec_pmic_shutdown,
.id_table = sec_pmic_id,
};

View file

@ -483,10 +483,11 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
return -EINVAL;
}
ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
sec_pmic->irq_base, sec_irq_chip,
&sec_pmic->irq_data);
ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic,
sec_pmic->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
sec_pmic->irq_base, sec_irq_chip,
&sec_pmic->irq_data);
if (ret != 0) {
dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
return ret;
@ -500,8 +501,3 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
return 0;
}
void sec_irq_exit(struct sec_pmic_dev *sec_pmic)
{
regmap_del_irq_chip(sec_pmic->irq, sec_pmic->irq_data);
}

View file

@ -64,19 +64,14 @@ static int sky81452_probe(struct i2c_client *client,
cells[1].platform_data = pdata->regulator_init_data;
cells[1].pdata_size = sizeof(*pdata->regulator_init_data);
ret = mfd_add_devices(dev, -1, cells, ARRAY_SIZE(cells), NULL, 0, NULL);
ret = devm_mfd_add_devices(dev, -1, cells, ARRAY_SIZE(cells),
NULL, 0, NULL);
if (ret)
dev_err(dev, "failed to add child devices. err=%d\n", ret);
return ret;
}
static int sky81452_remove(struct i2c_client *client)
{
mfd_remove_devices(&client->dev);
return 0;
}
static const struct i2c_device_id sky81452_ids[] = {
{ "sky81452" },
{ }
@ -97,7 +92,6 @@ static struct i2c_driver sky81452_driver = {
.of_match_table = of_match_ptr(sky81452_of_match),
},
.probe = sky81452_probe,
.remove = sky81452_remove,
.id_table = sky81452_ids,
};

View file

@ -879,11 +879,6 @@ static int sm501_register_display(struct sm501_devdata *sm,
#ifdef CONFIG_MFD_SM501_GPIO
static inline struct sm501_gpio_chip *to_sm501_gpio(struct gpio_chip *gc)
{
return container_of(gc, struct sm501_gpio_chip, gpio);
}
static inline struct sm501_devdata *sm501_gpio_to_dev(struct sm501_gpio *gpio)
{
return container_of(gpio, struct sm501_devdata, gpio);
@ -892,7 +887,7 @@ static inline struct sm501_devdata *sm501_gpio_to_dev(struct sm501_gpio *gpio)
static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct sm501_gpio_chip *smgpio = to_sm501_gpio(chip);
struct sm501_gpio_chip *smgpio = gpiochip_get_data(chip);
unsigned long result;
result = smc501_readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
@ -923,7 +918,7 @@ static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip,
static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct sm501_gpio_chip *smchip = to_sm501_gpio(chip);
struct sm501_gpio_chip *smchip = gpiochip_get_data(chip);
struct sm501_gpio *smgpio = smchip->ourgpio;
unsigned long bit = 1 << offset;
void __iomem *regs = smchip->regbase;
@ -948,7 +943,7 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
{
struct sm501_gpio_chip *smchip = to_sm501_gpio(chip);
struct sm501_gpio_chip *smchip = gpiochip_get_data(chip);
struct sm501_gpio *smgpio = smchip->ourgpio;
void __iomem *regs = smchip->regbase;
unsigned long bit = 1 << offset;
@ -974,7 +969,7 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
static int sm501_gpio_output(struct gpio_chip *chip,
unsigned offset, int value)
{
struct sm501_gpio_chip *smchip = to_sm501_gpio(chip);
struct sm501_gpio_chip *smchip = gpiochip_get_data(chip);
struct sm501_gpio *smgpio = smchip->ourgpio;
unsigned long bit = 1 << offset;
void __iomem *regs = smchip->regbase;
@ -1039,7 +1034,7 @@ static int sm501_gpio_register_chip(struct sm501_devdata *sm,
gchip->base = base;
chip->ourgpio = gpio;
return gpiochip_add(gchip);
return gpiochip_add_data(gchip, chip);
}
static int sm501_register_gpio(struct sm501_devdata *sm)

View file

@ -80,15 +80,6 @@ err:
return ret;
}
static int smsc_i2c_remove(struct i2c_client *i2c)
{
struct smsc *smsc = i2c_get_clientdata(i2c);
mfd_remove_devices(smsc->dev);
return 0;
}
static const struct i2c_device_id smsc_i2c_id[] = {
{ "smscece1099", 0},
{},
@ -100,7 +91,6 @@ static struct i2c_driver smsc_i2c_driver = {
.name = "smsc",
},
.probe = smsc_i2c_probe,
.remove = smsc_i2c_remove,
.id_table = smsc_i2c_id,
};

View file

@ -206,8 +206,8 @@ static int stw481x_probe(struct i2c_client *client,
stw481x_cells[i].pdata_size = sizeof(*stw481x);
}
ret = mfd_add_devices(&client->dev, 0, stw481x_cells,
ARRAY_SIZE(stw481x_cells), NULL, 0, NULL);
ret = devm_mfd_add_devices(&client->dev, 0, stw481x_cells,
ARRAY_SIZE(stw481x_cells), NULL, 0, NULL);
if (ret)
return ret;
@ -216,12 +216,6 @@ static int stw481x_probe(struct i2c_client *client,
return ret;
}
static int stw481x_remove(struct i2c_client *client)
{
mfd_remove_devices(&client->dev);
return 0;
}
/*
* This ID table is completely unused, as this is a pure
* device-tree probed driver, but it has to be here due to
@ -246,7 +240,6 @@ static struct i2c_driver stw481x_driver = {
.of_match_table = stw481x_match,
},
.probe = stw481x_probe,
.remove = stw481x_remove,
.id_table = stw481x_id,
};

View file

@ -24,7 +24,7 @@
#include <linux/mfd/core.h>
#include <linux/mfd/tmio.h>
#include <linux/mfd/tc6393xb.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include <linux/slab.h>
#define SCR_REVID 0x08 /* b Revision ID */
@ -434,7 +434,7 @@ static struct mfd_cell tc6393xb_cells[] = {
static int tc6393xb_gpio_get(struct gpio_chip *chip,
unsigned offset)
{
struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
struct tc6393xb *tc6393xb = gpiochip_get_data(chip);
/* XXX: does dsr also represent inputs? */
return !!(tmio_ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8))
@ -444,7 +444,7 @@ static int tc6393xb_gpio_get(struct gpio_chip *chip,
static void __tc6393xb_gpio_set(struct gpio_chip *chip,
unsigned offset, int value)
{
struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
struct tc6393xb *tc6393xb = gpiochip_get_data(chip);
u8 dsr;
dsr = tmio_ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8));
@ -459,7 +459,7 @@ static void __tc6393xb_gpio_set(struct gpio_chip *chip,
static void tc6393xb_gpio_set(struct gpio_chip *chip,
unsigned offset, int value)
{
struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
struct tc6393xb *tc6393xb = gpiochip_get_data(chip);
unsigned long flags;
spin_lock_irqsave(&tc6393xb->lock, flags);
@ -472,7 +472,7 @@ static void tc6393xb_gpio_set(struct gpio_chip *chip,
static int tc6393xb_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
{
struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
struct tc6393xb *tc6393xb = gpiochip_get_data(chip);
unsigned long flags;
u8 doecr;
@ -490,7 +490,7 @@ static int tc6393xb_gpio_direction_input(struct gpio_chip *chip,
static int tc6393xb_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
struct tc6393xb *tc6393xb = gpiochip_get_data(chip);
unsigned long flags;
u8 doecr;
@ -517,7 +517,7 @@ static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb, int gpio_base)
tc6393xb->gpio.direction_input = tc6393xb_gpio_direction_input;
tc6393xb->gpio.direction_output = tc6393xb_gpio_direction_output;
return gpiochip_add(&tc6393xb->gpio);
return gpiochip_add_data(&tc6393xb->gpio, tc6393xb);
}
/*--------------------------------------------------------------------------*/

View file

@ -21,7 +21,6 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/regulator/driver.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps6105x.h>

View file

@ -34,7 +34,7 @@
#include <linux/i2c/tps65010.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
/*-------------------------------------------------------------------------*/
@ -477,7 +477,7 @@ tps65010_output(struct gpio_chip *chip, unsigned offset, int value)
if (offset < 4) {
struct tps65010 *tps;
tps = container_of(chip, struct tps65010, chip);
tps = gpiochip_get_data(chip);
if (!(tps->outmask & (1 << offset)))
return -EINVAL;
tps65010_set_gpio_out_value(offset + 1, value);
@ -494,7 +494,7 @@ static int tps65010_gpio_get(struct gpio_chip *chip, unsigned offset)
int value;
struct tps65010 *tps;
tps = container_of(chip, struct tps65010, chip);
tps = gpiochip_get_data(chip);
if (offset < 4) {
value = i2c_smbus_read_byte_data(tps->client, TPS_DEFGPIO);
@ -651,7 +651,7 @@ static int tps65010_probe(struct i2c_client *client,
tps->chip.ngpio = 7;
tps->chip.can_sleep = 1;
status = gpiochip_add(&tps->chip);
status = gpiochip_add_data(&tps->chip, tps);
if (status < 0)
dev_err(&client->dev, "can't add gpiochip, err %d\n",
status);

View file

@ -100,16 +100,8 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c,
tps6507x->read_dev = tps6507x_i2c_read_device;
tps6507x->write_dev = tps6507x_i2c_write_device;
return mfd_add_devices(tps6507x->dev, -1, tps6507x_devs,
ARRAY_SIZE(tps6507x_devs), NULL, 0, NULL);
}
static int tps6507x_i2c_remove(struct i2c_client *i2c)
{
struct tps6507x_dev *tps6507x = i2c_get_clientdata(i2c);
mfd_remove_devices(tps6507x->dev);
return 0;
return devm_mfd_add_devices(tps6507x->dev, -1, tps6507x_devs,
ARRAY_SIZE(tps6507x_devs), NULL, 0, NULL);
}
static const struct i2c_device_id tps6507x_i2c_id[] = {
@ -132,7 +124,6 @@ static struct i2c_driver tps6507x_i2c_driver = {
.of_match_table = of_match_ptr(tps6507x_of_match),
},
.probe = tps6507x_i2c_probe,
.remove = tps6507x_i2c_remove,
.id_table = tps6507x_i2c_id,
};

View file

@ -205,8 +205,8 @@ static int tps65217_probe(struct i2c_client *client,
return ret;
}
ret = mfd_add_devices(tps->dev, -1, tps65217s,
ARRAY_SIZE(tps65217s), NULL, 0, NULL);
ret = devm_mfd_add_devices(tps->dev, -1, tps65217s,
ARRAY_SIZE(tps65217s), NULL, 0, NULL);
if (ret < 0) {
dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret);
return ret;
@ -235,15 +235,6 @@ static int tps65217_probe(struct i2c_client *client,
return 0;
}
static int tps65217_remove(struct i2c_client *client)
{
struct tps65217 *tps = i2c_get_clientdata(client);
mfd_remove_devices(tps->dev);
return 0;
}
static const struct i2c_device_id tps65217_id_table[] = {
{"tps65217", TPS65217},
{ /* sentinel */ }
@ -257,7 +248,6 @@ static struct i2c_driver tps65217_driver = {
},
.id_table = tps65217_id_table,
.probe = tps65217_probe,
.remove = tps65217_remove,
};
static int __init tps65217_init(void)

View file

@ -252,9 +252,10 @@ static int tps65910_irq_init(struct tps65910 *tps65910, int irq,
}
tps65910->chip_irq = irq;
ret = regmap_add_irq_chip(tps65910->regmap, tps65910->chip_irq,
IRQF_ONESHOT, pdata->irq_base,
tps6591x_irqs_chip, &tps65910->irq_data);
ret = devm_regmap_add_irq_chip(tps65910->dev, tps65910->regmap,
tps65910->chip_irq,
IRQF_ONESHOT, pdata->irq_base,
tps6591x_irqs_chip, &tps65910->irq_data);
if (ret < 0) {
dev_warn(tps65910->dev, "Failed to add irq_chip %d\n", ret);
tps65910->chip_irq = 0;
@ -262,13 +263,6 @@ static int tps65910_irq_init(struct tps65910 *tps65910, int irq,
return ret;
}
static int tps65910_irq_exit(struct tps65910 *tps65910)
{
if (tps65910->chip_irq > 0)
regmap_del_irq_chip(tps65910->chip_irq, tps65910->irq_data);
return 0;
}
static bool is_volatile_reg(struct device *dev, unsigned int reg)
{
struct tps65910 *tps65910 = dev_get_drvdata(dev);
@ -510,29 +504,18 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
pm_power_off = tps65910_power_off;
}
ret = mfd_add_devices(tps65910->dev, -1,
tps65910s, ARRAY_SIZE(tps65910s),
NULL, 0,
regmap_irq_get_domain(tps65910->irq_data));
ret = devm_mfd_add_devices(tps65910->dev, -1,
tps65910s, ARRAY_SIZE(tps65910s),
NULL, 0,
regmap_irq_get_domain(tps65910->irq_data));
if (ret < 0) {
dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret);
tps65910_irq_exit(tps65910);
return ret;
}
return ret;
}
static int tps65910_i2c_remove(struct i2c_client *i2c)
{
struct tps65910 *tps65910 = i2c_get_clientdata(i2c);
tps65910_irq_exit(tps65910);
mfd_remove_devices(tps65910->dev);
return 0;
}
static const struct i2c_device_id tps65910_i2c_id[] = {
{ "tps65910", TPS65910 },
{ "tps65911", TPS65911 },
@ -547,7 +530,6 @@ static struct i2c_driver tps65910_i2c_driver = {
.of_match_table = of_match_ptr(tps65910_of_match),
},
.probe = tps65910_i2c_probe,
.remove = tps65910_i2c_remove,
.id_table = tps65910_i2c_id,
};

View file

@ -1,5 +1,4 @@
/*
* linux/drivers/i2c/chips/twl4030-power.c
*
* Handle TWL4030 Power initialization
*

View file

@ -291,7 +291,11 @@ int twl6040_power(struct twl6040 *twl6040, int on)
if (twl6040->power_count++)
goto out;
clk_prepare_enable(twl6040->clk32k);
ret = clk_prepare_enable(twl6040->clk32k);
if (ret) {
twl6040->power_count = 0;
goto out;
}
/* Allow writes to the chip */
regcache_cache_only(twl6040->regmap, false);
@ -300,6 +304,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
/* use automatic power-up sequence */
ret = twl6040_power_up_automatic(twl6040);
if (ret) {
clk_disable_unprepare(twl6040->clk32k);
twl6040->power_count = 0;
goto out;
}
@ -307,6 +312,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
/* use manual power-up sequence */
ret = twl6040_power_up_manual(twl6040);
if (ret) {
clk_disable_unprepare(twl6040->clk32k);
twl6040->power_count = 0;
goto out;
}

View file

@ -28,7 +28,7 @@
#include <linux/mutex.h>
#include <linux/mfd/ucb1x00.h>
#include <linux/pm.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
static DEFINE_MUTEX(ucb1x00_mutex);
static LIST_HEAD(ucb1x00_drivers);
@ -109,7 +109,7 @@ unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
struct ucb1x00 *ucb = gpiochip_get_data(chip);
unsigned long flags;
spin_lock_irqsave(&ucb->io_lock, flags);
@ -126,7 +126,7 @@ static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
struct ucb1x00 *ucb = gpiochip_get_data(chip);
unsigned val;
ucb1x00_enable(ucb);
@ -138,7 +138,7 @@ static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset)
static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
struct ucb1x00 *ucb = gpiochip_get_data(chip);
unsigned long flags;
spin_lock_irqsave(&ucb->io_lock, flags);
@ -154,7 +154,7 @@ static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
, int value)
{
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
struct ucb1x00 *ucb = gpiochip_get_data(chip);
unsigned long flags;
unsigned old, mask = 1 << offset;
@ -181,7 +181,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
static int ucb1x00_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
struct ucb1x00 *ucb = gpiochip_get_data(chip);
return ucb->irq_base > 0 ? ucb->irq_base + offset : -ENXIO;
}
@ -579,7 +579,7 @@ static int ucb1x00_probe(struct mcp *mcp)
ucb->gpio.direction_input = ucb1x00_gpio_direction_input;
ucb->gpio.direction_output = ucb1x00_gpio_direction_output;
ucb->gpio.to_irq = ucb1x00_to_irq;
ret = gpiochip_add(&ucb->gpio);
ret = gpiochip_add_data(&ucb->gpio, ucb);
if (ret)
goto err_gpio_add;
} else

View file

@ -202,7 +202,7 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
bgpio_init(mmc_gpio_chip, &pdev->dev, 0x4, base + SYS_MCI,
NULL, NULL, NULL, NULL, 0);
mmc_gpio_chip->ngpio = 2;
gpiochip_add(mmc_gpio_chip);
gpiochip_add_data(mmc_gpio_chip, NULL);
return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
vexpress_sysreg_cells,

View file

@ -170,15 +170,6 @@ static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume)
return 0;
}
static int wl1273_core_remove(struct i2c_client *client)
{
dev_dbg(&client->dev, "%s\n", __func__);
mfd_remove_devices(&client->dev);
return 0;
}
static int wl1273_core_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@ -237,8 +228,8 @@ static int wl1273_core_probe(struct i2c_client *client,
dev_dbg(&client->dev, "%s: number of children: %d.\n",
__func__, children);
r = mfd_add_devices(&client->dev, -1, core->cells,
children, NULL, 0, NULL);
r = devm_mfd_add_devices(&client->dev, -1, core->cells,
children, NULL, 0, NULL);
if (r)
goto err;
@ -258,7 +249,6 @@ static struct i2c_driver wl1273_core_driver = {
},
.probe = wl1273_core_probe,
.id_table = wl1273_driver_id_table,
.remove = wl1273_core_remove,
};
static int __init wl1273_core_init(void)

View file

@ -3066,6 +3066,7 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_AOD_IRQ_RAW_STATUS:
case ARIZONA_FX_CTRL2:
case ARIZONA_ASRC_STATUS:
case ARIZONA_CLOCK_CONTROL:
case ARIZONA_DSP_STATUS:
case ARIZONA_DSP1_STATUS_1:
case ARIZONA_DSP1_STATUS_2:

View file

@ -35,27 +35,6 @@ static bool wm8400_volatile(struct device *dev, unsigned int reg)
}
}
/**
* wm8400_reg_read - Single register read
*
* @wm8400: Pointer to wm8400 control structure
* @reg: Register to read
*
* @return Read value
*/
u16 wm8400_reg_read(struct wm8400 *wm8400, u8 reg)
{
unsigned int val;
int ret;
ret = regmap_read(wm8400->regmap, reg, &val);
if (ret < 0)
return ret;
return val;
}
EXPORT_SYMBOL_GPL(wm8400_reg_read);
int wm8400_block_read(struct wm8400 *wm8400, u8 reg, int count, u16 *data)
{
return regmap_bulk_read(wm8400->regmap, reg, data, count);
@ -70,7 +49,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400)
.pdata_size = sizeof(*wm8400),
};
return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL);
return devm_mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL);
}
/*
@ -111,7 +90,7 @@ static int wm8400_init(struct wm8400 *wm8400,
ret = wm8400_register_codec(wm8400);
if (ret != 0) {
dev_err(wm8400->dev, "Failed to register codec\n");
goto err_children;
return ret;
}
if (pdata && pdata->platform_init) {
@ -119,21 +98,12 @@ static int wm8400_init(struct wm8400 *wm8400,
if (ret != 0) {
dev_err(wm8400->dev, "Platform init failed: %d\n",
ret);
goto err_children;
return ret;
}
} else
dev_warn(wm8400->dev, "No platform initialisation supplied\n");
return 0;
err_children:
mfd_remove_devices(wm8400->dev);
return ret;
}
static void wm8400_release(struct wm8400 *wm8400)
{
mfd_remove_devices(wm8400->dev);
}
static const struct regmap_config wm8400_regmap_config = {
@ -156,7 +126,7 @@ void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400)
}
EXPORT_SYMBOL_GPL(wm8400_reset_codec_reg_cache);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
#if IS_ENABLED(CONFIG_I2C)
static int wm8400_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@ -176,15 +146,6 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
return wm8400_init(wm8400, dev_get_platdata(&i2c->dev));
}
static int wm8400_i2c_remove(struct i2c_client *i2c)
{
struct wm8400 *wm8400 = i2c_get_clientdata(i2c);
wm8400_release(wm8400);
return 0;
}
static const struct i2c_device_id wm8400_i2c_id[] = {
{ "wm8400", 0 },
{ }
@ -196,7 +157,6 @@ static struct i2c_driver wm8400_i2c_driver = {
.name = "WM8400",
},
.probe = wm8400_i2c_probe,
.remove = wm8400_i2c_remove,
.id_table = wm8400_i2c_id,
};
#endif
@ -205,7 +165,7 @@ static int __init wm8400_module_init(void)
{
int ret = -ENODEV;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
#if IS_ENABLED(CONFIG_I2C)
ret = i2c_add_driver(&wm8400_i2c_driver);
if (ret != 0)
pr_err("Failed to register I2C driver: %d\n", ret);
@ -217,7 +177,7 @@ subsys_initcall(wm8400_module_init);
static void __exit wm8400_module_exit(void)
{
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
#if IS_ENABLED(CONFIG_I2C)
i2c_del_driver(&wm8400_i2c_driver);
#endif
}