diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-10 11:10:27 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-10 11:10:27 -0700 |
commit | 3aa78e0cb5c9b8b4ed2a617bb1e1542bfb508379 (patch) | |
tree | a446e1f8a81f63933423ef11ea7d31cc918b30f6 /drivers/mfd | |
parent | dc5ef1f56968c67e81ad1c81ab7dce678f480285 (diff) | |
parent | 25f311fa58c18c19ae1348336265ccb8368638f0 (diff) | |
download | kernel_goldelico_gta04-3aa78e0cb5c9b8b4ed2a617bb1e1542bfb508379.zip kernel_goldelico_gta04-3aa78e0cb5c9b8b4ed2a617bb1e1542bfb508379.tar.gz kernel_goldelico_gta04-3aa78e0cb5c9b8b4ed2a617bb1e1542bfb508379.tar.bz2 |
Merge tag 'mfd-3.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next
Pull MFD update from Samuel Ortiz:
"For the 3.11 merge we only have one new MFD driver for the Kontron
PLD.
But we also have:
- Support for the TPS659038 PMIC from the palmas driver.
- Intel's Coleto Creek and Avoton SoCs support from the lpc_ich
driver.
- RTL8411B support from the rtsx driver.
- More DT support for the Arizona, max8998, twl4030-power and the
ti_am335x_tsadc drivers.
- The SSBI driver move under MFD.
- A conversion to the devm_* API for most of the MFD drivers.
- The twl4030-power got split from twl-core into its own module.
- A major ti_am335x_adc cleanup, leading to a proper DT support.
- Our regular arizona and wm* updates and cleanups from the Wolfson
folks.
- A better error handling and initialization, and a regulator
subdevice addition for the 88pm80x driver.
- A bulk platform_set_drvdata() call removal that's no longer need
since commit 0998d0631001 ("device-core: Ensure drvdata = NULL when
no driver is bound")
* tag 'mfd-3.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next: (102 commits)
mfd: sec: Provide max_register to regmap
mfd: wm8994: Remove duplicate check for active JACKDET
MAINTAINERS: Add include directory to MFD file patterns
mfd: sec: Remove fields not used since regmap conversion
watchdog: Kontron PLD watchdog timer driver
mfd: max8998: Add support for Device Tree
regulator: max8998: Use arrays for specifying voltages in platform data
mfd: max8998: Add irq domain support
regulator: palmas: Add TPS659038 support
mfd: Kontron PLD mfd driver
mfd: palmas: Add TPS659038 PMIC support
mfd: palmas: Add SMPS10_BOOST feature
mfd: palmas: Check if irq is valid
mfd: lpc_ich: iTCO_wdt patch for Intel Coleto Creek DeviceIDs
mfd: twl-core: Change TWL6025 references to TWL6032
mfd: davinci_voicecodec: Fix build breakage
mfd: vexpress: Make the driver optional for arm and arm64
mfd: htc-egpio: Use devm_ioremap_nocache() instead of ioremap_nocache()
mfd: davinci_voicecodec: Convert to use devm_* APIs
mfd: twl4030-power: Fix relocking on error
...
Diffstat (limited to 'drivers/mfd')
57 files changed, 3609 insertions, 643 deletions
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index 582bda5..6c95483 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -22,13 +22,12 @@ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/err.h> #include <linux/i2c.h> #include <linux/mfd/core.h> #include <linux/mfd/88pm80x.h> #include <linux/slab.h> -#define PM800_CHIP_ID (0x00) - /* Interrupt Registers */ #define PM800_INT_STATUS1 (0x05) #define PM800_ONKEY_INT_STS1 (1 << 0) @@ -113,20 +112,11 @@ enum { PM800_MAX_IRQ, }; -enum { - /* Procida */ - PM800_CHIP_A0 = 0x60, - PM800_CHIP_A1 = 0x61, - PM800_CHIP_B0 = 0x62, - PM800_CHIP_C0 = 0x63, - PM800_CHIP_END = PM800_CHIP_C0, - - /* Make sure to update this to the last stepping */ - PM8XXX_CHIP_END = PM800_CHIP_END -}; +/* PM800: generation identification number */ +#define PM800_CHIP_GEN_ID_NUM 0x3 static const struct i2c_device_id pm80x_id_table[] = { - {"88PM800", CHIP_PM800}, + {"88PM800", 0}, {} /* NULL terminated */ }; MODULE_DEVICE_TABLE(i2c, pm80x_id_table); @@ -167,6 +157,13 @@ static struct mfd_cell onkey_devs[] = { }, }; +static struct mfd_cell regulator_devs[] = { + { + .name = "88pm80x-regulator", + .id = -1, + }, +}; + static const struct regmap_irq pm800_irqs[] = { /* INT0 */ [PM800_IRQ_ONKEY] = { @@ -315,10 +312,59 @@ out: return ret; } +static int device_onkey_init(struct pm80x_chip *chip, + struct pm80x_platform_data *pdata) +{ + int ret; + + ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], + ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0, + NULL); + if (ret) { + dev_err(chip->dev, "Failed to add onkey subdev\n"); + return ret; + } + + return 0; +} + +static int device_rtc_init(struct pm80x_chip *chip, + struct pm80x_platform_data *pdata) +{ + int ret; + + rtc_devs[0].platform_data = pdata->rtc; + rtc_devs[0].pdata_size = + pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0; + ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], + ARRAY_SIZE(rtc_devs), NULL, 0, NULL); + if (ret) { + dev_err(chip->dev, "Failed to add rtc subdev\n"); + return ret; + } + + return 0; +} + +static int device_regulator_init(struct pm80x_chip *chip, + struct pm80x_platform_data *pdata) +{ + int ret; + + ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], + ARRAY_SIZE(regulator_devs), NULL, 0, NULL); + if (ret) { + dev_err(chip->dev, "Failed to add regulator subdev\n"); + return ret; + } + + return 0; +} + static int device_irq_init_800(struct pm80x_chip *chip) { struct regmap *map = chip->regmap; - unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + unsigned long flags = IRQF_ONESHOT; int data, mask, ret = -EINVAL; if (!map || !chip->irq) { @@ -362,6 +408,7 @@ static struct regmap_irq_chip pm800_irq_chip = { .status_base = PM800_INT_STATUS1, .mask_base = PM800_INT_ENA_1, .ack_base = PM800_INT_STATUS1, + .mask_invert = 1, }; static int pm800_pages_init(struct pm80x_chip *chip) @@ -369,77 +416,72 @@ static int pm800_pages_init(struct pm80x_chip *chip) struct pm80x_subchip *subchip; struct i2c_client *client = chip->client; + int ret = 0; + subchip = chip->subchip; - /* PM800 block power: i2c addr 0x31 */ - if (subchip->power_page_addr) { - subchip->power_page = - i2c_new_dummy(client->adapter, subchip->power_page_addr); - subchip->regmap_power = - devm_regmap_init_i2c(subchip->power_page, - &pm80x_regmap_config); - i2c_set_clientdata(subchip->power_page, chip); - } else - dev_info(chip->dev, - "PM800 block power 0x31: No power_page_addr\n"); - - /* PM800 block GPADC: i2c addr 0x32 */ - if (subchip->gpadc_page_addr) { - subchip->gpadc_page = i2c_new_dummy(client->adapter, - subchip->gpadc_page_addr); - subchip->regmap_gpadc = - devm_regmap_init_i2c(subchip->gpadc_page, - &pm80x_regmap_config); - i2c_set_clientdata(subchip->gpadc_page, chip); - } else - dev_info(chip->dev, - "PM800 block GPADC 0x32: No gpadc_page_addr\n"); + if (!subchip || !subchip->power_page_addr || !subchip->gpadc_page_addr) + return -ENODEV; + + /* PM800 block power page */ + subchip->power_page = i2c_new_dummy(client->adapter, + subchip->power_page_addr); + if (subchip->power_page == NULL) { + ret = -ENODEV; + goto out; + } - return 0; + subchip->regmap_power = devm_regmap_init_i2c(subchip->power_page, + &pm80x_regmap_config); + if (IS_ERR(subchip->regmap_power)) { + ret = PTR_ERR(subchip->regmap_power); + dev_err(chip->dev, + "Failed to allocate regmap_power: %d\n", ret); + goto out; + } + + i2c_set_clientdata(subchip->power_page, chip); + + /* PM800 block GPADC */ + subchip->gpadc_page = i2c_new_dummy(client->adapter, + subchip->gpadc_page_addr); + if (subchip->gpadc_page == NULL) { + ret = -ENODEV; + goto out; + } + + subchip->regmap_gpadc = devm_regmap_init_i2c(subchip->gpadc_page, + &pm80x_regmap_config); + if (IS_ERR(subchip->regmap_gpadc)) { + ret = PTR_ERR(subchip->regmap_gpadc); + dev_err(chip->dev, + "Failed to allocate regmap_gpadc: %d\n", ret); + goto out; + } + i2c_set_clientdata(subchip->gpadc_page, chip); + +out: + return ret; } static void pm800_pages_exit(struct pm80x_chip *chip) { struct pm80x_subchip *subchip; - regmap_exit(chip->regmap); - i2c_unregister_device(chip->client); - subchip = chip->subchip; - if (subchip->power_page) { - regmap_exit(subchip->regmap_power); + + if (subchip && subchip->power_page) i2c_unregister_device(subchip->power_page); - } - if (subchip->gpadc_page) { - regmap_exit(subchip->regmap_gpadc); + + if (subchip && subchip->gpadc_page) i2c_unregister_device(subchip->gpadc_page); - } } static int device_800_init(struct pm80x_chip *chip, struct pm80x_platform_data *pdata) { - int ret, pmic_id; + int ret; unsigned int val; - ret = regmap_read(chip->regmap, PM800_CHIP_ID, &val); - if (ret < 0) { - dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); - goto out; - } - - pmic_id = val & PM80X_VERSION_MASK; - - if ((pmic_id >= PM800_CHIP_A0) && (pmic_id <= PM800_CHIP_END)) { - chip->version = val; - dev_info(chip->dev, - "88PM80x:Marvell 88PM800 (ID:0x%x) detected\n", val); - } else { - dev_err(chip->dev, - "Failed to detect Marvell 88PM800:ChipID[0x%x]\n", val); - ret = -EINVAL; - goto out; - } - /* * alarm wake up bit will be clear in device_irq_init(), * read before that @@ -468,27 +510,22 @@ static int device_800_init(struct pm80x_chip *chip, goto out; } - ret = - mfd_add_devices(chip->dev, 0, &onkey_devs[0], - ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0, - NULL); - if (ret < 0) { + ret = device_onkey_init(chip, pdata); + if (ret) { dev_err(chip->dev, "Failed to add onkey subdev\n"); goto out_dev; - } else - dev_info(chip->dev, "[%s]:Added mfd onkey_devs\n", __func__); - - if (pdata && pdata->rtc) { - rtc_devs[0].platform_data = pdata->rtc; - rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata); - ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], - ARRAY_SIZE(rtc_devs), NULL, 0, NULL); - if (ret < 0) { - dev_err(chip->dev, "Failed to add rtc subdev\n"); - goto out_dev; - } else - dev_info(chip->dev, - "[%s]:Added mfd rtc_devs\n", __func__); + } + + ret = device_rtc_init(chip, pdata); + if (ret) { + dev_err(chip->dev, "Failed to add rtc subdev\n"); + goto out; + } + + ret = device_regulator_init(chip, pdata); + if (ret) { + dev_err(chip->dev, "Failed to add regulators subdev\n"); + goto out; } return 0; @@ -507,7 +544,7 @@ static int pm800_probe(struct i2c_client *client, struct pm80x_platform_data *pdata = client->dev.platform_data; struct pm80x_subchip *subchip; - ret = pm80x_init(client, id); + ret = pm80x_init(client); if (ret) { dev_err(&client->dev, "pm800_init fail\n"); goto out_init; @@ -524,28 +561,31 @@ static int pm800_probe(struct i2c_client *client, goto err_subchip_alloc; } - subchip->power_page_addr = pdata->power_page_addr; - subchip->gpadc_page_addr = pdata->gpadc_page_addr; + /* pm800 has 2 addtional pages to support power and gpadc. */ + subchip->power_page_addr = client->addr + 1; + subchip->gpadc_page_addr = client->addr + 2; chip->subchip = subchip; - ret = device_800_init(chip, pdata); - if (ret) { - dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); - goto err_subchip_alloc; - } - ret = pm800_pages_init(chip); if (ret) { dev_err(&client->dev, "pm800_pages_init failed!\n"); goto err_page_init; } + ret = device_800_init(chip, pdata); + if (ret) { + dev_err(chip->dev, "Failed to initialize 88pm800 devices\n"); + goto err_device_init; + } + if (pdata->plat_config) pdata->plat_config(chip, pdata); + return 0; + +err_device_init: + pm800_pages_exit(chip); err_page_init: - mfd_remove_devices(chip->dev); - device_irq_exit_800(chip); err_subchip_alloc: pm80x_deinit(); out_init: @@ -567,7 +607,7 @@ static int pm800_remove(struct i2c_client *client) static struct i2c_driver pm800_driver = { .driver = { - .name = "88PM80X", + .name = "88PM800", .owner = THIS_MODULE, .pm = &pm80x_pm_ops, }, diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index 65d7ac09..5216022 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -29,10 +29,8 @@ #include <linux/slab.h> #include <linux/delay.h> -#define PM805_CHIP_ID (0x00) - static const struct i2c_device_id pm80x_id_table[] = { - {"88PM805", CHIP_PM805}, + {"88PM805", 0}, {} /* NULL terminated */ }; MODULE_DEVICE_TABLE(i2c, pm80x_id_table); @@ -138,7 +136,7 @@ static struct regmap_irq pm805_irqs[] = { static int device_irq_init_805(struct pm80x_chip *chip) { struct regmap *map = chip->regmap; - unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + unsigned long flags = IRQF_ONESHOT; int data, mask, ret = -EINVAL; if (!map || !chip->irq) { @@ -192,7 +190,6 @@ static struct regmap_irq_chip pm805_irq_chip = { static int device_805_init(struct pm80x_chip *chip) { int ret = 0; - unsigned int val; struct regmap *map = chip->regmap; if (!map) { @@ -200,13 +197,6 @@ static int device_805_init(struct pm80x_chip *chip) return -EINVAL; } - ret = regmap_read(map, PM805_CHIP_ID, &val); - if (ret < 0) { - dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); - goto out_irq_init; - } - chip->version = val; - chip->regmap_irq_chip = &pm805_irq_chip; ret = device_irq_init_805(chip); @@ -239,7 +229,7 @@ static int pm805_probe(struct i2c_client *client, struct pm80x_chip *chip; struct pm80x_platform_data *pdata = client->dev.platform_data; - ret = pm80x_init(client, id); + ret = pm80x_init(client); if (ret) { dev_err(&client->dev, "pm805_init fail!\n"); goto out_init; @@ -249,7 +239,7 @@ static int pm805_probe(struct i2c_client *client, ret = device_805_init(chip); if (ret) { - dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); + dev_err(chip->dev, "Failed to initialize 88pm805 devices\n"); goto err_805_init; } @@ -276,7 +266,7 @@ static int pm805_remove(struct i2c_client *client) static struct i2c_driver pm805_driver = { .driver = { - .name = "88PM80X", + .name = "88PM805", .owner = THIS_MODULE, .pm = &pm80x_pm_ops, }, diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c index f736a46..5e72f65 100644 --- a/drivers/mfd/88pm80x.c +++ b/drivers/mfd/88pm80x.c @@ -18,6 +18,23 @@ #include <linux/uaccess.h> #include <linux/err.h> +/* 88pm80x chips have same definition for chip id register. */ +#define PM80X_CHIP_ID (0x00) +#define PM80X_CHIP_ID_NUM(x) (((x) >> 5) & 0x7) +#define PM80X_CHIP_ID_REVISION(x) ((x) & 0x1F) + +struct pm80x_chip_mapping { + unsigned int id; + int type; +}; + +static struct pm80x_chip_mapping chip_mapping[] = { + /* 88PM800 chip id number */ + {0x3, CHIP_PM800}, + /* 88PM805 chip id number */ + {0x0, CHIP_PM805}, +}; + /* * workaround: some registers needed by pm805 are defined in pm800, so * need to use this global variable to maintain the relation between @@ -31,12 +48,13 @@ const struct regmap_config pm80x_regmap_config = { }; EXPORT_SYMBOL_GPL(pm80x_regmap_config); -int pm80x_init(struct i2c_client *client, - const struct i2c_device_id *id) + +int pm80x_init(struct i2c_client *client) { struct pm80x_chip *chip; struct regmap *map; - int ret = 0; + unsigned int val; + int i, ret = 0; chip = devm_kzalloc(&client->dev, sizeof(struct pm80x_chip), GFP_KERNEL); @@ -51,10 +69,6 @@ int pm80x_init(struct i2c_client *client, return ret; } - chip->id = id->driver_data; - if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805) - return -EINVAL; - chip->client = client; chip->regmap = map; @@ -64,6 +78,25 @@ int pm80x_init(struct i2c_client *client, dev_set_drvdata(chip->dev, chip); i2c_set_clientdata(chip->client, chip); + ret = regmap_read(chip->regmap, PM80X_CHIP_ID, &val); + if (ret < 0) { + dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(chip_mapping); i++) { + if (chip_mapping[i].id == PM80X_CHIP_ID_NUM(val)) { + chip->type = chip_mapping[i].type; + break; + } + } + + if (i == ARRAY_SIZE(chip_mapping)) { + dev_err(chip->dev, + "Failed to detect Marvell 88PM800:ChipID[0x%x]\n", val); + return -EINVAL; + } + device_init_wakeup(&client->dev, 1); /* diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 31ca555..eeb481d 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -1150,17 +1150,17 @@ static int pm860x_probe(struct i2c_client *client, return -EINVAL; } - chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL); + chip = devm_kzalloc(&client->dev, + sizeof(struct pm860x_chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; chip->id = verify_addr(client); - chip->regmap = regmap_init_i2c(client, &pm860x_regmap_config); + chip->regmap = devm_regmap_init_i2c(client, &pm860x_regmap_config); if (IS_ERR(chip->regmap)) { ret = PTR_ERR(chip->regmap); dev_err(&client->dev, "Failed to allocate register map: %d\n", ret); - kfree(chip); return ret; } chip->client = client; @@ -1203,8 +1203,6 @@ static int pm860x_remove(struct i2c_client *client) regmap_exit(chip->regmap_companion); i2c_unregister_device(chip->companion); } - regmap_exit(chip->regmap); - kfree(chip); return 0; } diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d54e985..aecd6dd 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -53,7 +53,7 @@ config MFD_CROS_EC help If you say Y here you get support for the ChromeOS Embedded Controller (EC) providing keyboard, battery and power services. - You also ned to enable the driver for the bus you are using. The + You also need to enable the driver for the bus you are using. The protocol for talking to the EC is defined by the bus driver. config MFD_CROS_EC_I2C @@ -242,6 +242,27 @@ config MFD_JZ4740_ADC Say yes here if you want support for the ADC unit in the JZ4740 SoC. This driver is necessary for jz4740-battery and jz4740-hwmon driver. +config MFD_KEMPLD + tristate "Kontron module PLD device" + select MFD_CORE + help + This is the core driver for the PLD (Programmable Logic Device) found + on some Kontron ETX and COMexpress (ETXexpress) modules. The PLD + device may provide functions like watchdog, GPIO, UART and I2C bus. + + The following modules are supported: + * COMe-bIP# + * COMe-bPC2 (ETXexpress-PC) + * COMe-bSC# (ETXexpress-SC T#) + * COMe-cCT6 + * COMe-cDC2 (microETXexpress-DC) + * COMe-cPC2 (microETXexpress-PC) + * COMe-mCT10 + * ETX-OH + + This driver can also be built as a module. If so, the module + will be called kempld-core. + config MFD_88PM800 tristate "Marvell 88PM800" depends on I2C=y && GENERIC_HARDIRQS @@ -342,6 +363,7 @@ config MFD_MAX8998 bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support" depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE + select IRQ_DOMAIN help Say yes here to support for Maxim Semiconductor MAX8998 and National Semiconductor LP3974. This is a Power Management IC. @@ -419,7 +441,8 @@ config MFD_PM8XXX config MFD_PM8921_CORE tristate "Qualcomm PM8921 PMIC chip" - depends on SSBI && BROKEN + depends on (ARCH_MSM || HEXAGON) + depends on BROKEN select MFD_CORE select MFD_PM8XXX help @@ -1046,6 +1069,12 @@ config MFD_WM5110 help Support for Wolfson Microelectronics WM5110 low power audio SoC +config MFD_WM8997 + bool "Support Wolfson Microelectronics WM8997" + depends on MFD_ARIZONA + help + Support for Wolfson Microelectronics WM8997 low power audio SoC + config MFD_WM8400 bool "Wolfson Microelectronics WM8400" select MFD_CORE @@ -1144,7 +1173,8 @@ config MCP_UCB1200_TS endmenu config VEXPRESS_CONFIG - bool + bool "ARM Versatile Express platform infrastructure" + depends on ARM || ARM64 help Platform configuration infrastructure for the ARM Ltd. Versatile Express. diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 718e94a..3c90051 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -43,6 +43,9 @@ endif ifneq ($(CONFIG_MFD_WM5110),n) obj-$(CONFIG_MFD_ARIZONA) += wm5110-tables.o endif +ifneq ($(CONFIG_MFD_WM8997),n) +obj-$(CONFIG_MFD_ARIZONA) += wm8997-tables.o +endif obj-$(CONFIG_MFD_WM8400) += wm8400-core.o wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o wm831x-objs += wm831x-auxadc.o @@ -126,6 +129,7 @@ obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o obj-$(CONFIG_PMIC_ADP5520) += adp5520.o +obj-$(CONFIG_MFD_KEMPLD) += kempld-core.o obj-$(CONFIG_LPC_SCH) += lpc_sch.o obj-$(CONFIG_LPC_ICH) += lpc_ich.o obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o @@ -140,7 +144,7 @@ obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o -obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o +obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o ssbi.o obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o obj-$(CONFIG_MFD_TPS65090) += tps65090.o diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c index dfdb0a2..d4f5945 100644 --- a/drivers/mfd/aat2870-core.c +++ b/drivers/mfd/aat2870-core.c @@ -312,8 +312,9 @@ static ssize_t aat2870_reg_write_file(struct file *file, while (*start == ' ') start++; - if (strict_strtoul(start, 16, &val)) - return -EINVAL; + ret = kstrtoul(start, 16, &val); + if (ret) + return ret; ret = aat2870->write(aat2870, (u8)addr, (u8)val); if (ret) diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index a9bb140..ddc669d 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -491,7 +491,7 @@ static ssize_t ab3100_get_set_reg(struct file *file, char buf[32]; ssize_t buf_size; int regp; - unsigned long user_reg; + u8 user_reg; int err; int i = 0; @@ -514,34 +514,29 @@ static ssize_t ab3100_get_set_reg(struct file *file, /* * Advance pointer to end of string then terminate * the register string. This is needed to satisfy - * the strict_strtoul() function. + * the kstrtou8() function. */ while ((i < buf_size) && (buf[i] != ' ')) i++; buf[i] = '\0'; - err = strict_strtoul(&buf[regp], 16, &user_reg); + err = kstrtou8(&buf[regp], 16, &user_reg); if (err) return err; - if (user_reg > 0xff) - return -EINVAL; /* Either we read or we write a register here */ if (!priv->mode) { /* Reading */ - u8 reg = (u8) user_reg; u8 regvalue; - ab3100_get_register_interruptible(ab3100, reg, ®value); + ab3100_get_register_interruptible(ab3100, user_reg, ®value); dev_info(ab3100->dev, "debug read AB3100 reg[0x%02x]: 0x%02x\n", - reg, regvalue); + user_reg, regvalue); } else { int valp; - unsigned long user_value; - u8 reg = (u8) user_reg; - u8 value; + u8 user_value; u8 regvalue; /* @@ -557,20 +552,17 @@ static ssize_t ab3100_get_set_reg(struct file *file, i++; buf[i] = '\0'; - err = strict_strtoul(&buf[valp], 16, &user_value); + err = kstrtou8(&buf[valp], 16, &user_value); if (err) return err; - if (user_reg > 0xff) - return -EINVAL; - value = (u8) user_value; - ab3100_set_register_interruptible(ab3100, reg, value); - ab3100_get_register_interruptible(ab3100, reg, ®value); + ab3100_set_register_interruptible(ab3100, user_reg, user_value); + ab3100_get_register_interruptible(ab3100, user_reg, ®value); dev_info(ab3100->dev, "debug write reg[0x%02x] with 0x%02x, " "after readback: 0x%02x\n", - reg, value, regvalue); + user_reg, user_value, regvalue); } return buf_size; } diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c index d7ce016..c9af16c 100644 --- a/drivers/mfd/ab3100-otp.c +++ b/drivers/mfd/ab3100-otp.c @@ -187,7 +187,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) int err = 0; int i; - otp = kzalloc(sizeof(struct ab3100_otp), GFP_KERNEL); + otp = devm_kzalloc(&pdev->dev, sizeof(struct ab3100_otp), GFP_KERNEL); if (!otp) { dev_err(&pdev->dev, "could not allocate AB3100 OTP device\n"); return -ENOMEM; @@ -199,7 +199,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) err = ab3100_otp_read(otp); if (err) - goto err_otp_read; + return err; dev_info(&pdev->dev, "AB3100 OTP readout registered\n"); @@ -208,22 +208,19 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) err = device_create_file(&pdev->dev, &ab3100_otp_attrs[i]); if (err) - goto err_create_file; + goto err; } /* debugfs entries */ err = ab3100_otp_init_debugfs(&pdev->dev, otp); if (err) - goto err_init_debugfs; + goto err; return 0; -err_init_debugfs: -err_create_file: +err: while (--i >= 0) device_remove_file(&pdev->dev, &ab3100_otp_attrs[i]); -err_otp_read: - kfree(otp); return err; } @@ -236,7 +233,6 @@ static int __exit ab3100_otp_remove(struct platform_device *pdev) device_remove_file(&pdev->dev, &ab3100_otp_attrs[i]); ab3100_otp_exit_debugfs(otp); - kfree(otp); return 0; } diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 258b367..b6c2cdc 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -650,6 +650,21 @@ static struct resource ab8500_rtc_resources[] = { }, }; +static struct resource ab8540_rtc_resources[] = { + { + .name = "1S", + .start = AB8540_INT_RTC_1S, + .end = AB8540_INT_RTC_1S, + .flags = IORESOURCE_IRQ, + }, + { + .name = "ALARM", + .start = AB8500_INT_RTC_ALARM, + .end = AB8500_INT_RTC_ALARM, + .flags = IORESOURCE_IRQ, + }, +}; + static struct resource ab8500_poweronkey_db_resources[] = { { .name = "ONKEY_DBF", @@ -1051,6 +1066,10 @@ static struct mfd_cell ab8500_devs[] = { .of_compatible = "stericsson,ab8500-sysctrl", }, { + .name = "ab8500-ext-regulator", + .of_compatible = "stericsson,ab8500-ext-regulator", + }, + { .name = "ab8500-regulator", .of_compatible = "stericsson,ab8500-regulator", }, @@ -1099,10 +1118,6 @@ static struct mfd_cell ab8500_devs[] = { .id = 3, }, { - .name = "ab8500-leds", - .of_compatible = "stericsson,ab8500-leds", - }, - { .name = "ab8500-denc", .of_compatible = "stericsson,ab8500-denc", }, @@ -1124,6 +1139,7 @@ static struct mfd_cell ab8500_devs[] = { }, { .name = "ab8500-codec", + .of_compatible = "stericsson,ab8500-codec", }, }; @@ -1139,6 +1155,9 @@ static struct mfd_cell ab9540_devs[] = { .name = "ab8500-sysctrl", }, { + .name = "ab8500-ext-regulator", + }, + { .name = "ab8500-regulator", }, { @@ -1171,9 +1190,6 @@ static struct mfd_cell ab9540_devs[] = { .id = 1, }, { - .name = "ab8500-leds", - }, - { .name = "abx500-temp", .num_resources = ARRAY_SIZE(ab8500_temp_resources), .resources = ab8500_temp_resources, @@ -1242,9 +1258,6 @@ static struct mfd_cell ab8505_devs[] = { .id = 1, }, { - .name = "ab8500-leds", - }, - { .name = "pinctrl-ab8505", }, { @@ -1274,6 +1287,9 @@ static struct mfd_cell ab8540_devs[] = { .name = "ab8500-sysctrl", }, { + .name = "ab8500-ext-regulator", + }, + { .name = "ab8500-regulator", }, { @@ -1287,11 +1303,6 @@ static struct mfd_cell ab8540_devs[] = { .resources = ab8505_gpadc_resources, }, { - .name = "ab8500-rtc", - .num_resources = ARRAY_SIZE(ab8500_rtc_resources), - .resources = ab8500_rtc_resources, - }, - { .name = "ab8500-acc-det", .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), .resources = ab8500_av_acc_detect_resources, @@ -1306,9 +1317,6 @@ static struct mfd_cell ab8540_devs[] = { .id = 1, }, { - .name = "ab8500-leds", - }, - { .name = "abx500-temp", .num_resources = ARRAY_SIZE(ab8500_temp_resources), .resources = ab8500_temp_resources, @@ -1331,6 +1339,24 @@ static struct mfd_cell ab8540_devs[] = { }, }; +static struct mfd_cell ab8540_cut1_devs[] = { + { + .name = "ab8500-rtc", + .of_compatible = "stericsson,ab8500-rtc", + .num_resources = ARRAY_SIZE(ab8500_rtc_resources), + .resources = ab8500_rtc_resources, + }, +}; + +static struct mfd_cell ab8540_cut2_devs[] = { + { + .name = "ab8540-rtc", + .of_compatible = "stericsson,ab8540-rtc", + .num_resources = ARRAY_SIZE(ab8540_rtc_resources), + .resources = ab8540_rtc_resources, + }, +}; + static ssize_t show_chip_id(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1734,11 +1760,22 @@ static int ab8500_probe(struct platform_device *pdev) ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, ARRAY_SIZE(ab9540_devs), NULL, ab8500->irq_base, ab8500->domain); - else if (is_ab8540(ab8500)) + else if (is_ab8540(ab8500)) { ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs, ARRAY_SIZE(ab8540_devs), NULL, - ab8500->irq_base, ab8500->domain); - else if (is_ab8505(ab8500)) + ab8500->irq_base, NULL); + if (ret) + return ret; + + if (is_ab8540_1p2_or_earlier(ab8500)) + ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut1_devs, + ARRAY_SIZE(ab8540_cut1_devs), NULL, + ab8500->irq_base, NULL); + else /* ab8540 >= cut2 */ + ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut2_devs, + ARRAY_SIZE(ab8540_cut2_devs), NULL, + ab8500->irq_base, NULL); + } else if (is_ab8505(ab8500)) ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs, ARRAY_SIZE(ab8505_devs), NULL, ab8500->irq_base, ab8500->domain); diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 37b7ce4..7d1f1b0 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -2757,7 +2757,7 @@ static ssize_t show_irq(struct device *dev, unsigned int irq_index; int err; - err = strict_strtoul(attr->attr.name, 0, &name); + err = kstrtoul(attr->attr.name, 0, &name); if (err) return err; @@ -2937,7 +2937,6 @@ static struct dentry *ab8500_gpadc_dir; static int ab8500_debug_probe(struct platform_device *plf) { struct dentry *file; - int ret = -ENOMEM; struct ab8500 *ab8500; struct resource *res; debug_bank = AB8500_MISC; @@ -2946,24 +2945,26 @@ static int ab8500_debug_probe(struct platform_device *plf) ab8500 = dev_get_drvdata(plf->dev.parent); num_irqs = ab8500->mask_size; - irq_count = kzalloc(sizeof(*irq_count)*num_irqs, GFP_KERNEL); + irq_count = devm_kzalloc(&plf->dev, + sizeof(*irq_count)*num_irqs, GFP_KERNEL); if (!irq_count) return -ENOMEM; - dev_attr = kzalloc(sizeof(*dev_attr)*num_irqs,GFP_KERNEL); + dev_attr = devm_kzalloc(&plf->dev, + sizeof(*dev_attr)*num_irqs,GFP_KERNEL); if (!dev_attr) - goto out_freeirq_count; + return -ENOMEM; - event_name = kzalloc(sizeof(*event_name)*num_irqs, GFP_KERNEL); + event_name = devm_kzalloc(&plf->dev, + sizeof(*event_name)*num_irqs, GFP_KERNEL); if (!event_name) - goto out_freedev_attr; + return -ENOMEM; res = platform_get_resource_byname(plf, 0, "IRQ_AB8500"); if (!res) { dev_err(&plf->dev, "AB8500 irq not found, err %d\n", irq_first); - ret = -ENXIO; - goto out_freeevent_name; + return ENXIO; } irq_ab8500 = res->start; @@ -2971,16 +2972,14 @@ static int ab8500_debug_probe(struct platform_device *plf) if (irq_first < 0) { dev_err(&plf->dev, "First irq not found, err %d\n", irq_first); - ret = irq_first; - goto out_freeevent_name; + return irq_first; } irq_last = platform_get_irq_byname(plf, "IRQ_LAST"); if (irq_last < 0) { dev_err(&plf->dev, "Last irq not found, err %d\n", irq_last); - ret = irq_last; - goto out_freeevent_name; + return irq_last; } ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); @@ -3189,22 +3188,13 @@ err: if (ab8500_dir) debugfs_remove_recursive(ab8500_dir); dev_err(&plf->dev, "failed to create debugfs entries.\n"); -out_freeevent_name: - kfree(event_name); -out_freedev_attr: - kfree(dev_attr); -out_freeirq_count: - kfree(irq_count); - return ret; + return -ENOMEM; } static int ab8500_debug_remove(struct platform_device *plf) { debugfs_remove_recursive(ab8500_dir); - kfree(event_name); - kfree(dev_attr); - kfree(irq_count); return 0; } diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 3598b0e..7623e91 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -919,7 +919,7 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) int ret = 0; struct ab8500_gpadc *gpadc; - gpadc = kzalloc(sizeof(struct ab8500_gpadc), GFP_KERNEL); + gpadc = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_gpadc), GFP_KERNEL); if (!gpadc) { dev_err(&pdev->dev, "Error: No memory\n"); return -ENOMEM; @@ -999,8 +999,6 @@ fail_irq: free_irq(gpadc->irq_sw, gpadc); free_irq(gpadc->irq_hw, gpadc); fail: - kfree(gpadc); - gpadc = NULL; return ret; } @@ -1025,8 +1023,6 @@ static int ab8500_gpadc_remove(struct platform_device *pdev) pm_runtime_put_noidle(gpadc->dev); - kfree(gpadc); - gpadc = NULL; return 0; } diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c index 3714acb..f3a15aa 100644 --- a/drivers/mfd/abx500-core.c +++ b/drivers/mfd/abx500-core.c @@ -36,7 +36,9 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops) { struct abx500_device_entry *dev_entry; - dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL); + dev_entry = devm_kzalloc(dev, + sizeof(struct abx500_device_entry), + GFP_KERNEL); if (!dev_entry) { dev_err(dev, "register_ops kzalloc failed"); return -ENOMEM; @@ -54,12 +56,8 @@ void abx500_remove_ops(struct device *dev) struct abx500_device_entry *dev_entry, *tmp; list_for_each_entry_safe(dev_entry, tmp, &abx500_list, list) - { - if (dev_entry->dev == dev) { + if (dev_entry->dev == dev) list_del(&dev_entry->list); - kfree(dev_entry); - } - } } EXPORT_SYMBOL(abx500_remove_ops); diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c index 0d2eba0..28346ad 100644 --- a/drivers/mfd/adp5520.c +++ b/drivers/mfd/adp5520.c @@ -223,7 +223,7 @@ static int adp5520_probe(struct i2c_client *client, return -ENODEV; } - chip = kzalloc(sizeof(*chip), GFP_KERNEL); + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; @@ -244,7 +244,7 @@ static int adp5520_probe(struct i2c_client *client, if (ret) { dev_err(&client->dev, "failed to request irq %d\n", chip->irq); - goto out_free_chip; + return ret; } } @@ -302,9 +302,6 @@ out_free_irq: if (chip->irq) free_irq(chip->irq, chip); -out_free_chip: - kfree(chip); - return ret; } @@ -317,7 +314,6 @@ static int adp5520_remove(struct i2c_client *client) adp5520_remove_subdevs(chip); adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0); - kfree(chip); return 0; } diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 74b4481..89a1153 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -554,6 +554,7 @@ static int arizona_of_get_core_pdata(struct arizona *arizona) const struct of_device_id arizona_of_match[] = { { .compatible = "wlf,wm5102", .data = (void *)WM5102 }, { .compatible = "wlf,wm5110", .data = (void *)WM5110 }, + { .compatible = "wlf,wm8997", .data = (void *)WM8997 }, {}, }; EXPORT_SYMBOL_GPL(arizona_of_match); @@ -586,6 +587,15 @@ static struct mfd_cell wm5110_devs[] = { { .name = "wm5110-codec" }, }; +static struct mfd_cell wm8997_devs[] = { + { .name = "arizona-micsupp" }, + { .name = "arizona-extcon" }, + { .name = "arizona-gpio" }, + { .name = "arizona-haptics" }, + { .name = "arizona-pwm" }, + { .name = "wm8997-codec" }, +}; + int arizona_dev_init(struct arizona *arizona) { struct device *dev = arizona->dev; @@ -608,6 +618,7 @@ int arizona_dev_init(struct arizona *arizona) switch (arizona->type) { case WM5102: case WM5110: + case WM8997: for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++) arizona->core_supplies[i].supply = wm5102_core_supplies[i]; @@ -683,6 +694,7 @@ int arizona_dev_init(struct arizona *arizona) switch (reg) { case 0x5102: case 0x5110: + case 0x8997: break; default: dev_err(arizona->dev, "Unknown device ID: %x\n", reg); @@ -768,6 +780,17 @@ int arizona_dev_init(struct arizona *arizona) apply_patch = wm5110_patch; break; #endif +#ifdef CONFIG_MFD_WM8997 + case 0x8997: + type_name = "WM8997"; + if (arizona->type != WM8997) { + dev_err(arizona->dev, "WM8997 registered as %d\n", + arizona->type); + arizona->type = WM8997; + } + apply_patch = wm8997_patch; + break; +#endif default: dev_err(arizona->dev, "Unknown device ID %x\n", reg); goto err_reset; @@ -934,6 +957,10 @@ int arizona_dev_init(struct arizona *arizona) ret = mfd_add_devices(arizona->dev, -1, wm5110_devs, ARRAY_SIZE(wm5110_devs), NULL, 0, NULL); break; + case WM8997: + ret = mfd_add_devices(arizona->dev, -1, wm8997_devs, + ARRAY_SIZE(wm8997_devs), NULL, 0, NULL); + break; } if (ret != 0) { diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c index deb267e..51dbabf 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c @@ -45,6 +45,11 @@ static int arizona_i2c_probe(struct i2c_client *i2c, regmap_config = &wm5110_i2c_regmap; break; #endif +#ifdef CONFIG_MFD_WM8997 + case WM8997: + regmap_config = &wm8997_i2c_regmap; + break; +#endif default: dev_err(&i2c->dev, "Unknown device type %ld\n", id->driver_data); @@ -80,6 +85,7 @@ static int arizona_i2c_remove(struct i2c_client *i2c) static const struct i2c_device_id arizona_i2c_id[] = { { "wm5102", WM5102 }, { "wm5110", WM5110 }, + { "wm8997", WM8997 }, { } }; MODULE_DEVICE_TABLE(i2c, arizona_i2c_id); diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index 64cd9b6..88758ab 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -208,6 +208,14 @@ int arizona_irq_init(struct arizona *arizona) ctrlif_error = false; break; #endif +#ifdef CONFIG_MFD_WM8997 + case WM8997: + aod = &wm8997_aod; + irq = &wm8997_irq; + + ctrlif_error = false; + break; +#endif default: BUG_ON("Unknown Arizona class device" == NULL); return -EINVAL; diff --git a/drivers/mfd/arizona.h b/drivers/mfd/arizona.h index db55d98..b4cef77 100644 --- a/drivers/mfd/arizona.h +++ b/drivers/mfd/arizona.h @@ -25,6 +25,8 @@ extern const struct regmap_config wm5102_spi_regmap; extern const struct regmap_config wm5110_i2c_regmap; extern const struct regmap_config wm5110_spi_regmap; +extern const struct regmap_config wm8997_i2c_regmap; + extern const struct dev_pm_ops arizona_pm_ops; extern const struct of_device_id arizona_of_match[]; @@ -35,6 +37,9 @@ extern const struct regmap_irq_chip wm5102_irq; extern const struct regmap_irq_chip wm5110_aod; extern const struct regmap_irq_chip wm5110_irq; +extern const struct regmap_irq_chip wm8997_aod; +extern const struct regmap_irq_chip wm8997_irq; + int arizona_dev_init(struct arizona *arizona); int arizona_dev_exit(struct arizona *arizona); int arizona_irq_init(struct arizona *arizona); diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 1b15986..9532f74 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -958,7 +958,8 @@ static int __init asic3_probe(struct platform_device *pdev) unsigned long clksel; int ret = 0; - asic = kzalloc(sizeof(struct asic3), GFP_KERNEL); + asic = devm_kzalloc(&pdev->dev, + sizeof(struct asic3), GFP_KERNEL); if (asic == NULL) { printk(KERN_ERR "kzalloc failed\n"); return -ENOMEM; @@ -970,16 +971,14 @@ static int __init asic3_probe(struct platform_device *pdev) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { - ret = -ENOMEM; dev_err(asic->dev, "no MEM resource\n"); - goto out_free; + return -ENOMEM; } asic->mapping = ioremap(mem->start, resource_size(mem)); if (!asic->mapping) { - ret = -ENOMEM; dev_err(asic->dev, "Couldn't ioremap\n"); - goto out_free; + return -ENOMEM; } asic->irq_base = pdata->irq_base; @@ -1033,9 +1032,6 @@ static int __init asic3_probe(struct platform_device *pdev) out_unmap: iounmap(asic->mapping); - out_free: - kfree(asic); - return ret; } @@ -1058,8 +1054,6 @@ static int asic3_remove(struct platform_device *pdev) iounmap(asic->mapping); - kfree(asic); - return 0; } diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c index 10cd14e..1f36885 100644 --- a/drivers/mfd/cros_ec.c +++ b/drivers/mfd/cros_ec.c @@ -104,23 +104,19 @@ int cros_ec_register(struct cros_ec_device *ec_dev) ec_dev->command_sendrecv = cros_ec_command_sendrecv; if (ec_dev->din_size) { - ec_dev->din = kmalloc(ec_dev->din_size, GFP_KERNEL); - if (!ec_dev->din) { - err = -ENOMEM; - goto fail_din; - } + ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL); + if (!ec_dev->din) + return -ENOMEM; } if (ec_dev->dout_size) { - ec_dev->dout = kmalloc(ec_dev->dout_size, GFP_KERNEL); - if (!ec_dev->dout) { - err = -ENOMEM; - goto fail_dout; - } + ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL); + if (!ec_dev->dout) + return -ENOMEM; } if (!ec_dev->irq) { dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq); - goto fail_irq; + return err; } err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread, @@ -128,7 +124,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev) "chromeos-ec", ec_dev); if (err) { dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err); - goto fail_irq; + return err; } err = mfd_add_devices(dev, 0, cros_devs, @@ -145,11 +141,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev) fail_mfd: free_irq(ec_dev->irq, ec_dev); -fail_irq: - kfree(ec_dev->dout); -fail_dout: - kfree(ec_dev->din); -fail_din: + return err; } EXPORT_SYMBOL(cros_ec_register); @@ -158,8 +150,6 @@ int cros_ec_remove(struct cros_ec_device *ec_dev) { mfd_remove_devices(ec_dev->dev); free_irq(ec_dev->irq, ec_dev); - kfree(ec_dev->dout); - kfree(ec_dev->din); return 0; } diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index c60ab0c..fb643985 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c @@ -46,56 +46,39 @@ void davinci_vc_write(struct davinci_vc *davinci_vc, static int __init davinci_vc_probe(struct platform_device *pdev) { struct davinci_vc *davinci_vc; - struct resource *res, *mem; + struct resource *res; struct mfd_cell *cell = NULL; int ret; - davinci_vc = kzalloc(sizeof(struct davinci_vc), GFP_KERNEL); + davinci_vc = devm_kzalloc(&pdev->dev, + sizeof(struct davinci_vc), GFP_KERNEL); if (!davinci_vc) { dev_dbg(&pdev->dev, "could not allocate memory for private data\n"); return -ENOMEM; } - davinci_vc->clk = clk_get(&pdev->dev, NULL); + davinci_vc->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(davinci_vc->clk)) { dev_dbg(&pdev->dev, "could not get the clock for voice codec\n"); - ret = -ENODEV; - goto fail1; + return -ENODEV; } clk_enable(davinci_vc->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no mem resource\n"); - ret = -ENODEV; - goto fail2; - } - davinci_vc->pbase = res->start; - davinci_vc->base_size = resource_size(res); - - mem = request_mem_region(davinci_vc->pbase, davinci_vc->base_size, - pdev->name); - if (!mem) { - dev_err(&pdev->dev, "VCIF region already claimed\n"); - ret = -EBUSY; - goto fail2; - } - - davinci_vc->base = ioremap(davinci_vc->pbase, davinci_vc->base_size); - if (!davinci_vc->base) { - dev_err(&pdev->dev, "can't ioremap mem resource.\n"); - ret = -ENOMEM; - goto fail3; + davinci_vc->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(davinci_vc->base)) { + ret = PTR_ERR(davinci_vc->base); + goto fail; } res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (!res) { dev_err(&pdev->dev, "no DMA resource\n"); ret = -ENXIO; - goto fail4; + goto fail; } davinci_vc->davinci_vcif.dma_tx_channel = res->start; @@ -106,7 +89,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev) if (!res) { dev_err(&pdev->dev, "no DMA resource\n"); ret = -ENXIO; - goto fail4; + goto fail; } davinci_vc->davinci_vcif.dma_rx_channel = res->start; @@ -132,21 +115,13 @@ static int __init davinci_vc_probe(struct platform_device *pdev) DAVINCI_VC_CELLS, NULL, 0, NULL); if (ret != 0) { dev_err(&pdev->dev, "fail to register client devices\n"); - goto fail4; + goto fail; } return 0; -fail4: - iounmap(davinci_vc->base); -fail3: - release_mem_region(davinci_vc->pbase, davinci_vc->base_size); -fail2: +fail: clk_disable(davinci_vc->clk); - clk_put(davinci_vc->clk); - davinci_vc->clk = NULL; -fail1: - kfree(davinci_vc); return ret; } @@ -157,14 +132,7 @@ static int davinci_vc_remove(struct platform_device *pdev) mfd_remove_devices(&pdev->dev); - iounmap(davinci_vc->base); - release_mem_region(davinci_vc->pbase, davinci_vc->base_size); - clk_disable(davinci_vc->clk); - clk_put(davinci_vc->clk); - davinci_vc->clk = NULL; - - kfree(davinci_vc); return 0; } diff --git a/drivers/mfd/dbx500-prcmu-regs.h b/drivers/mfd/dbx500-prcmu-regs.h index ca355dd..4f6f0fa 100644 --- a/drivers/mfd/dbx500-prcmu-regs.h +++ b/drivers/mfd/dbx500-prcmu-regs.h @@ -16,8 +16,8 @@ #define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end)) #define PRCM_ACLK_MGT (0x004) -#define PRCM_SVACLK_MGT (0x008) -#define PRCM_SIACLK_MGT (0x00C) +#define PRCM_SVAMMCSPCLK_MGT (0x008) +#define PRCM_SIAMMDSPCLK_MGT (0x00C) #define PRCM_SGACLK_MGT (0x014) #define PRCM_UARTCLK_MGT (0x018) #define PRCM_MSP02CLK_MGT (0x01C) diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c index bbaec0c..26aca54 100644 --- a/drivers/mfd/htc-egpio.c +++ b/drivers/mfd/htc-egpio.c @@ -270,7 +270,7 @@ static int __init egpio_probe(struct platform_device *pdev) int ret; /* Initialize ei data structure. */ - ei = kzalloc(sizeof(*ei), GFP_KERNEL); + ei = devm_kzalloc(&pdev->dev, sizeof(*ei), GFP_KERNEL); if (!ei) return -ENOMEM; @@ -286,7 +286,8 @@ static int __init egpio_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) goto fail; - ei->base_addr = ioremap_nocache(res->start, resource_size(res)); + ei->base_addr = devm_ioremap_nocache(&pdev->dev, res->start, + resource_size(res)); if (!ei->base_addr) goto fail; pr_debug("EGPIO phys=%08x virt=%p\n", (u32)res->start, ei->base_addr); @@ -306,7 +307,9 @@ static int __init egpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ei); ei->nchips = pdata->num_chips; - ei->chip = kzalloc(sizeof(struct egpio_chip) * ei->nchips, GFP_KERNEL); + ei->chip = devm_kzalloc(&pdev->dev, + sizeof(struct egpio_chip) * ei->nchips, + GFP_KERNEL); if (!ei->chip) { ret = -ENOMEM; goto fail; @@ -361,7 +364,6 @@ static int __init egpio_probe(struct platform_device *pdev) fail: printk(KERN_ERR "EGPIO failed to setup\n"); - kfree(ei); return ret; } @@ -379,9 +381,6 @@ static int __exit egpio_remove(struct platform_device *pdev) irq_set_chained_handler(ei->chained_irq, NULL); device_init_wakeup(&pdev->dev, 0); } - iounmap(ei->base_addr); - kfree(ei->chip); - kfree(ei); return 0; } diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c index 324187c..c9dfce6 100644 --- a/drivers/mfd/htc-i2cpld.c +++ b/drivers/mfd/htc-i2cpld.c @@ -514,8 +514,8 @@ static int htcpld_setup_chips(struct platform_device *pdev) /* Setup each chip's output GPIOs */ htcpld->nchips = pdata->num_chip; - htcpld->chip = kzalloc(sizeof(struct htcpld_chip) * htcpld->nchips, - GFP_KERNEL); + htcpld->chip = devm_kzalloc(dev, sizeof(struct htcpld_chip) * htcpld->nchips, + GFP_KERNEL); if (!htcpld->chip) { dev_warn(dev, "Unable to allocate memory for chips\n"); return -ENOMEM; @@ -580,12 +580,11 @@ static int htcpld_core_probe(struct platform_device *pdev) return -ENXIO; } - htcpld = kzalloc(sizeof(struct htcpld_data), GFP_KERNEL); + htcpld = devm_kzalloc(dev, sizeof(struct htcpld_data), GFP_KERNEL); if (!htcpld) return -ENOMEM; /* Find chained irq */ - ret = -EINVAL; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res) { int flags; @@ -598,7 +597,7 @@ static int htcpld_core_probe(struct platform_device *pdev) flags, pdev->name, htcpld); if (ret) { dev_warn(dev, "Unable to setup chained irq handler: %d\n", ret); - goto fail; + return ret; } else device_init_wakeup(dev, 0); } @@ -609,7 +608,7 @@ static int htcpld_core_probe(struct platform_device *pdev) /* Setup the htcpld chips */ ret = htcpld_setup_chips(pdev); if (ret) - goto fail; + return ret; /* Request the GPIO(s) for the int reset and set them up */ if (pdata->int_reset_gpio_hi) { @@ -644,10 +643,6 @@ static int htcpld_core_probe(struct platform_device *pdev) dev_info(dev, "Initialized successfully\n"); return 0; - -fail: - kfree(htcpld); - return ret; } /* The I2C Driver -- used internally */ diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index 0285fce..0a5e85f 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c @@ -147,7 +147,7 @@ static int __init pasic3_probe(struct platform_device *pdev) if (!request_mem_region(r->start, resource_size(r), "pasic3")) return -EBUSY; - asic = kzalloc(sizeof(struct pasic3_data), GFP_KERNEL); + asic = devm_kzalloc(dev, sizeof(struct pasic3_data), GFP_KERNEL); if (!asic) return -ENOMEM; @@ -156,7 +156,6 @@ static int __init pasic3_probe(struct platform_device *pdev) asic->mapping = ioremap(r->start, resource_size(r)); if (!asic->mapping) { dev_err(dev, "couldn't ioremap PASIC3\n"); - kfree(asic); return -ENOMEM; } @@ -195,7 +194,6 @@ static int pasic3_remove(struct platform_device *pdev) iounmap(asic->mapping); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(r->start, resource_size(r)); - kfree(asic); return 0; } diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c index d8d5137..4f2462f 100644 --- a/drivers/mfd/intel_msic.c +++ b/drivers/mfd/intel_msic.c @@ -438,7 +438,6 @@ static int intel_msic_remove(struct platform_device *pdev) struct intel_msic *msic = platform_get_drvdata(pdev); intel_msic_remove_devices(msic); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 45ece11..fcbb2e9 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c @@ -183,11 +183,10 @@ static int cmodio_pci_probe(struct pci_dev *dev, struct cmodio_device *priv; int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(&dev->dev, "unable to allocate private data\n"); - ret = -ENOMEM; - goto out_return; + return -ENOMEM; } pci_set_drvdata(dev, priv); @@ -197,7 +196,7 @@ static int cmodio_pci_probe(struct pci_dev *dev, ret = pci_enable_device(dev); if (ret) { dev_err(&dev->dev, "unable to enable device\n"); - goto out_free_priv; + return ret; } pci_set_master(dev); @@ -248,9 +247,7 @@ out_pci_release_regions: pci_release_regions(dev); out_pci_disable_device: pci_disable_device(dev); -out_free_priv: - kfree(priv); -out_return: + return ret; } @@ -263,7 +260,6 @@ static void cmodio_pci_remove(struct pci_dev *dev) iounmap(priv->ctrl); pci_release_regions(dev); pci_disable_device(dev); - kfree(priv); } #define PCI_VENDOR_ID_JANZ 0x13c3 diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index e80587f..3c0e8cf 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c @@ -86,13 +86,13 @@ static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc) static inline void jz4740_adc_clk_enable(struct jz4740_adc *adc) { if (atomic_inc_return(&adc->clk_ref) == 1) - clk_enable(adc->clk); + clk_prepare_enable(adc->clk); } static inline void jz4740_adc_clk_disable(struct jz4740_adc *adc) { if (atomic_dec_return(&adc->clk_ref) == 0) - clk_disable(adc->clk); + clk_disable_unprepare(adc->clk); } static inline void jz4740_adc_set_enabled(struct jz4740_adc *adc, int engine, @@ -294,7 +294,6 @@ static int jz4740_adc_probe(struct platform_device *pdev) err_clk_put: clk_put(adc->clk); err_iounmap: - platform_set_drvdata(pdev, NULL); iounmap(adc->base); err_release_mem_region: release_mem_region(adc->mem->start, resource_size(adc->mem)); @@ -317,8 +316,6 @@ static int jz4740_adc_remove(struct platform_device *pdev) clk_put(adc->clk); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c new file mode 100644 index 0000000..686a456 --- /dev/null +++ b/drivers/mfd/kempld-core.c @@ -0,0 +1,641 @@ +/* + * Kontron PLD MFD core driver + * + * Copyright (c) 2010-2013 Kontron Europe GmbH + * Author: Michael Brunner <michael.brunner@kontron.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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. + */ + +#include <linux/platform_device.h> +#include <linux/mfd/core.h> +#include <linux/mfd/kempld.h> +#include <linux/module.h> +#include <linux/dmi.h> +#include <linux/io.h> +#include <linux/delay.h> + +#define MAX_ID_LEN 4 +static char force_device_id[MAX_ID_LEN + 1] = ""; +module_param_string(force_device_id, force_device_id, sizeof(force_device_id), 0); +MODULE_PARM_DESC(force_device_id, "Override detected product"); + +/* + * Get hardware mutex to block firmware from accessing the pld. + * It is possible for the firmware may hold the mutex for an extended length of + * time. This function will block until access has been granted. + */ +static void kempld_get_hardware_mutex(struct kempld_device_data *pld) +{ + /* The mutex bit will read 1 until access has been granted */ + while (ioread8(pld->io_index) & KEMPLD_MUTEX_KEY) + msleep(1); +} + +static void kempld_release_hardware_mutex(struct kempld_device_data *pld) +{ + /* The harware mutex is released when 1 is written to the mutex bit. */ + iowrite8(KEMPLD_MUTEX_KEY, pld->io_index); +} + +static int kempld_get_info_generic(struct kempld_device_data *pld) +{ + u16 version; + u8 spec; + + kempld_get_mutex(pld); + + version = kempld_read16(pld, KEMPLD_VERSION); + spec = kempld_read8(pld, KEMPLD_SPEC); + pld->info.buildnr = kempld_read16(pld, KEMPLD_BUILDNR); + + pld->info.minor = KEMPLD_VERSION_GET_MINOR(version); + pld->info.major = KEMPLD_VERSION_GET_MAJOR(version); + pld->info.number = KEMPLD_VERSION_GET_NUMBER(version); + pld->info.type = KEMPLD_VERSION_GET_TYPE(version); + + if (spec == 0xff) { + pld->info.spec_minor = 0; + pld->info.spec_major = 1; + } else { + pld->info.spec_minor = KEMPLD_SPEC_GET_MINOR(spec); + pld->info.spec_major = KEMPLD_SPEC_GET_MAJOR(spec); + } + + if (pld->info.spec_major > 0) + pld->feature_mask = kempld_read16(pld, KEMPLD_FEATURE); + else + pld->feature_mask = 0; + + kempld_release_mutex(pld); + + return 0; +} + +enum kempld_cells { + KEMPLD_I2C = 0, + KEMPLD_WDT, + KEMPLD_GPIO, + KEMPLD_UART, +}; + +static struct mfd_cell kempld_devs[] = { + [KEMPLD_I2C] = { + .name = "kempld-i2c", + }, + [KEMPLD_WDT] = { + .name = "kempld-wdt", + }, + [KEMPLD_GPIO] = { + .name = "kempld-gpio", + }, + [KEMPLD_UART] = { + .name = "kempld-uart", + }, +}; + +#define KEMPLD_MAX_DEVS ARRAY_SIZE(kempld_devs) + +static int kempld_register_cells_generic(struct kempld_device_data *pld) +{ + struct mfd_cell devs[KEMPLD_MAX_DEVS]; + int i = 0; + + if (pld->feature_mask & KEMPLD_FEATURE_BIT_I2C) + devs[i++] = kempld_devs[KEMPLD_I2C]; + + if (pld->feature_mask & KEMPLD_FEATURE_BIT_WATCHDOG) + devs[i++] = kempld_devs[KEMPLD_WDT]; + + if (pld->feature_mask & KEMPLD_FEATURE_BIT_GPIO) + devs[i++] = kempld_devs[KEMPLD_GPIO]; + + if (pld->feature_mask & KEMPLD_FEATURE_MASK_UART) + devs[i++] = kempld_devs[KEMPLD_UART]; + + return mfd_add_devices(pld->dev, -1, devs, i, NULL, 0, NULL); +} + +static struct resource kempld_ioresource = { + .start = KEMPLD_IOINDEX, + .end = KEMPLD_IODATA, + .flags = IORESOURCE_IO, +}; + +static const struct kempld_platform_data kempld_platform_data_generic = { + .pld_clock = KEMPLD_CLK, + .ioresource = &kempld_ioresource, + .get_hardware_mutex = kempld_get_hardware_mutex, + .release_hardware_mutex = kempld_release_hardware_mutex, + .get_info = kempld_get_info_generic, + .register_cells = kempld_register_cells_generic, +}; + +static struct platform_device *kempld_pdev; + +static int kempld_create_platform_device(const struct dmi_system_id *id) +{ + struct kempld_platform_data *pdata = id->driver_data; + int ret; + + kempld_pdev = platform_device_alloc("kempld", -1); + if (!kempld_pdev) + return -ENOMEM; + + ret = platform_device_add_data(kempld_pdev, pdata, sizeof(*pdata)); + if (ret) + goto err; + + ret = platform_device_add_resources(kempld_pdev, pdata->ioresource, 1); + if (ret) + goto err; + + ret = platform_device_add(kempld_pdev); + if (ret) + goto err; + + return 0; +err: + platform_device_put(kempld_pdev); + return ret; +} + +/** + * kempld_read8 - read 8 bit register + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * + * kempld_get_mutex must be called prior to calling this function. + */ +u8 kempld_read8(struct kempld_device_data *pld, u8 index) +{ + iowrite8(index, pld->io_index); + return ioread8(pld->io_data); +} +EXPORT_SYMBOL_GPL(kempld_read8); + +/** + * kempld_write8 - write 8 bit register + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * @data: new register value + * + * kempld_get_mutex must be called prior to calling this function. + */ +void kempld_write8(struct kempld_device_data *pld, u8 index, u8 data) +{ + iowrite8(index, pld->io_index); + iowrite8(data, pld->io_data); +} +EXPORT_SYMBOL_GPL(kempld_write8); + +/** + * kempld_read16 - read 16 bit register + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * + * kempld_get_mutex must be called prior to calling this function. + */ +u16 kempld_read16(struct kempld_device_data *pld, u8 index) +{ + return kempld_read8(pld, index) | kempld_read8(pld, index + 1) << 8; +} +EXPORT_SYMBOL_GPL(kempld_read16); + +/** + * kempld_write16 - write 16 bit register + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * @data: new register value + * + * kempld_get_mutex must be called prior to calling this function. + */ +void kempld_write16(struct kempld_device_data *pld, u8 index, u16 data) +{ + kempld_write8(pld, index, (u8)data); + kempld_write8(pld, index + 1, (u8)(data >> 8)); +} +EXPORT_SYMBOL_GPL(kempld_write16); + +/** + * kempld_read32 - read 32 bit register + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * + * kempld_get_mutex must be called prior to calling this function. + */ +u32 kempld_read32(struct kempld_device_data *pld, u8 index) +{ + return kempld_read16(pld, index) | kempld_read16(pld, index + 2) << 16; +} +EXPORT_SYMBOL_GPL(kempld_read32); + +/** + * kempld_write32 - write 32 bit register + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * @data: new register value + * + * kempld_get_mutex must be called prior to calling this function. + */ +void kempld_write32(struct kempld_device_data *pld, u8 index, u32 data) +{ + kempld_write16(pld, index, (u16)data); + kempld_write16(pld, index + 2, (u16)(data >> 16)); +} +EXPORT_SYMBOL_GPL(kempld_write32); + +/** + * kempld_get_mutex - acquire PLD mutex + * @pld: kempld_device_data structure describing the PLD + */ +void kempld_get_mutex(struct kempld_device_data *pld) +{ + struct kempld_platform_data *pdata = pld->dev->platform_data; + + mutex_lock(&pld->lock); + pdata->get_hardware_mutex(pld); +} +EXPORT_SYMBOL_GPL(kempld_get_mutex); + +/** + * kempld_release_mutex - release PLD mutex + * @pld: kempld_device_data structure describing the PLD + */ +void kempld_release_mutex(struct kempld_device_data *pld) +{ + struct kempld_platform_data *pdata = pld->dev->platform_data; + + pdata->release_hardware_mutex(pld); + mutex_unlock(&pld->lock); +} +EXPORT_SYMBOL_GPL(kempld_release_mutex); + +/** + * kempld_get_info - update device specific information + * @pld: kempld_device_data structure describing the PLD + * + * This function calls the configured board specific kempld_get_info_XXXX + * function which is responsible for gathering information about the specific + * hardware. The information is then stored within the pld structure. + */ +static int kempld_get_info(struct kempld_device_data *pld) +{ + struct kempld_platform_data *pdata = pld->dev->platform_data; + + return pdata->get_info(pld); +} + +/* + * kempld_register_cells - register cell drivers + * + * This function registers cell drivers for the detected hardware by calling + * the configured kempld_register_cells_XXXX function which is responsible + * to detect and register the needed cell drivers. + */ +static int kempld_register_cells(struct kempld_device_data *pld) +{ + struct kempld_platform_data *pdata = pld->dev->platform_data; + + return pdata->register_cells(pld); +} + +static int kempld_detect_device(struct kempld_device_data *pld) +{ + char *version_type; + u8 index_reg; + int ret; + + mutex_lock(&pld->lock); + + /* Check for empty IO space */ + index_reg = ioread8(pld->io_index); + if (index_reg == 0xff && ioread8(pld->io_data) == 0xff) { + mutex_unlock(&pld->lock); + return -ENODEV; + } + + /* Release hardware mutex if aquired */ + if (!(index_reg & KEMPLD_MUTEX_KEY)) + iowrite8(KEMPLD_MUTEX_KEY, pld->io_index); + + mutex_unlock(&pld->lock); + + ret = kempld_get_info(pld); + if (ret) + return ret; + + switch (pld->info.type) { + case 0: + version_type = "release"; + break; + case 1: + version_type = "debug"; + break; + case 2: + version_type = "custom"; + break; + default: + version_type = "unspecified"; + } + + dev_info(pld->dev, "Found Kontron PLD %d\n", pld->info.number); + dev_info(pld->dev, "%s version %d.%d build %d, specification %d.%d\n", + version_type, pld->info.major, pld->info.minor, + pld->info.buildnr, pld->info.spec_major, + pld->info.spec_minor); + + return kempld_register_cells(pld); +} + +static int kempld_probe(struct platform_device *pdev) +{ + struct kempld_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct kempld_device_data *pld; + struct resource *ioport; + int ret; + + pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL); + if (!pld) + return -ENOMEM; + + ioport = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!ioport) + return -EINVAL; + + pld->io_base = devm_ioport_map(dev, ioport->start, + ioport->end - ioport->start); + if (!pld->io_base) + return -ENOMEM; + + pld->io_index = pld->io_base; + pld->io_data = pld->io_base + 1; + pld->pld_clock = pdata->pld_clock; + pld->dev = dev; + + mutex_init(&pld->lock); + platform_set_drvdata(pdev, pld); + + ret = kempld_detect_device(pld); + if (ret) + return ret; + + return 0; +} + +static int kempld_remove(struct platform_device *pdev) +{ + struct kempld_device_data *pld = platform_get_drvdata(pdev); + struct kempld_platform_data *pdata = pld->dev->platform_data; + + mfd_remove_devices(&pdev->dev); + pdata->release_hardware_mutex(pld); + + return 0; +} + +static struct platform_driver kempld_driver = { + .driver = { + .name = "kempld", + .owner = THIS_MODULE, + }, + .probe = kempld_probe, + .remove = kempld_remove, +}; + +static struct dmi_system_id __initdata kempld_dmi_table[] = { + { + .ident = "CCR2", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CCR6", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP6"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CHR2", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CHR2", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CHR2", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CHR6", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T6"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CHR6", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T6"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CHR6", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC6"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CNTG", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-PC"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CNTG", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-bPC2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CNTX", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "PXT"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "FRI2", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BIOS_VERSION, "FRI2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "FRI2", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Fish River Island II"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "MBR1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "ETX-OH"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "NTC1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "nanoETXexpress-TT"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "NTC1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "nETXe-TT"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "NTC1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-mTT"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "NUP1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-mCT"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "UNP1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-DC"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "UNP1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-cDC2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "UNTG", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-PC"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "UNTG", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-cPC2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "UUP6", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-cCT6"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, + {} +}; +MODULE_DEVICE_TABLE(dmi, kempld_dmi_table); + +static int __init kempld_init(void) +{ + const struct dmi_system_id *id; + int ret; + + if (force_device_id[0]) { + for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++) + if (strstr(id->ident, force_device_id)) + if (id->callback && id->callback(id)) + break; + if (id->matches[0].slot == DMI_NONE) + return -ENODEV; + } else { + if (!dmi_check_system(kempld_dmi_table)) + return -ENODEV; + } + + ret = platform_driver_register(&kempld_driver); + if (ret) + return ret; + + return 0; +} + +static void __exit kempld_exit(void) +{ + if (kempld_pdev) + platform_device_unregister(kempld_pdev); + + platform_driver_unregister(&kempld_driver); +} + +module_init(kempld_init); +module_exit(kempld_exit); + +MODULE_DESCRIPTION("KEM PLD Core Driver"); +MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:kempld-core"); diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 9f12f91..2403332 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -51,6 +51,8 @@ * document number TBD : Lynx Point * document number TBD : Lynx Point-LP * document number TBD : Wellsburg + * document number TBD : Avoton SoC + * document number TBD : Coleto Creek */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -207,6 +209,8 @@ enum lpc_chipsets { LPC_LPT, /* Lynx Point */ LPC_LPT_LP, /* Lynx Point-LP */ LPC_WBG, /* Wellsburg */ + LPC_AVN, /* Avoton SoC */ + LPC_COLETO, /* Coleto Creek */ }; struct lpc_ich_info lpc_chipset_info[] = { @@ -491,6 +495,14 @@ struct lpc_ich_info lpc_chipset_info[] = { .name = "Wellsburg", .iTCO_version = 2, }, + [LPC_AVN] = { + .name = "Avoton SoC", + .iTCO_version = 1, + }, + [LPC_COLETO] = { + .name = "Coleto Creek", + .iTCO_version = 2, + }, }; /* @@ -704,6 +716,11 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = { { PCI_VDEVICE(INTEL, 0x8d5d), LPC_WBG}, { PCI_VDEVICE(INTEL, 0x8d5e), LPC_WBG}, { PCI_VDEVICE(INTEL, 0x8d5f), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x1f38), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, lpc_ich_ids); @@ -973,18 +990,7 @@ static struct pci_driver lpc_ich_driver = { .remove = lpc_ich_remove, }; -static int __init lpc_ich_init(void) -{ - return pci_register_driver(&lpc_ich_driver); -} - -static void __exit lpc_ich_exit(void) -{ - pci_unregister_driver(&lpc_ich_driver); -} - -module_init(lpc_ich_init); -module_exit(lpc_ich_exit); +module_pci_driver(lpc_ich_driver); MODULE_AUTHOR("Aaron Sierra <asierra@xes-inc.com>"); MODULE_DESCRIPTION("LPC interface for Intel ICH"); diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 1cbb176..f27a218 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -37,6 +37,7 @@ static struct mfd_cell max77686_devs[] = { { .name = "max77686-pmic", }, { .name = "max77686-rtc", }, + { .name = "max77686-clk", }, }; static struct regmap_config max77686_regmap_config = { @@ -84,12 +85,12 @@ static int max77686_i2c_probe(struct i2c_client *i2c, pdata = max77686_i2c_parse_dt_pdata(&i2c->dev); if (!pdata) { - ret = -EIO; dev_err(&i2c->dev, "No platform data found.\n"); - goto err; + return -EIO; } - max77686 = kzalloc(sizeof(struct max77686_dev), GFP_KERNEL); + max77686 = devm_kzalloc(&i2c->dev, + sizeof(struct max77686_dev), GFP_KERNEL); if (max77686 == NULL) return -ENOMEM; @@ -107,7 +108,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c, ret = PTR_ERR(max77686->regmap); dev_err(max77686->dev, "Failed to allocate register map: %d\n", ret); - kfree(max77686); return ret; } @@ -115,8 +115,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c, MAX77686_REG_DEVICE_ID, &data) < 0) { dev_err(max77686->dev, "device not found on this channel (this is not an error)\n"); - ret = -ENODEV; - goto err; + return -ENODEV; } else dev_info(max77686->dev, "device found\n"); @@ -127,17 +126,11 @@ static int max77686_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(max77686->dev, -1, max77686_devs, ARRAY_SIZE(max77686_devs), NULL, 0, NULL); + if (ret < 0) { + mfd_remove_devices(max77686->dev); + i2c_unregister_device(max77686->rtc); + } - if (ret < 0) - goto err_mfd; - - return ret; - -err_mfd: - mfd_remove_devices(max77686->dev); - i2c_unregister_device(max77686->rtc); -err: - kfree(max77686); return ret; } @@ -147,7 +140,6 @@ static int max77686_i2c_remove(struct i2c_client *i2c) mfd_remove_devices(max77686->dev); i2c_unregister_device(max77686->rtc); - kfree(max77686); return 0; } diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c index 92bbebd..8042b32 100644 --- a/drivers/mfd/max8925-i2c.c +++ b/drivers/mfd/max8925-i2c.c @@ -170,7 +170,8 @@ static int max8925_probe(struct i2c_client *client, return -EINVAL; } - chip = kzalloc(sizeof(struct max8925_chip), GFP_KERNEL); + chip = devm_kzalloc(&client->dev, + sizeof(struct max8925_chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; chip->i2c = client; @@ -199,7 +200,6 @@ static int max8925_remove(struct i2c_client *client) max8925_device_exit(chip); i2c_unregister_device(chip->adc); i2c_unregister_device(chip->rtc); - kfree(chip); return 0; } diff --git a/drivers/mfd/max8998-irq.c b/drivers/mfd/max8998-irq.c index 5919710..c469477 100644 --- a/drivers/mfd/max8998-irq.c +++ b/drivers/mfd/max8998-irq.c @@ -14,6 +14,7 @@ #include <linux/device.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/irqdomain.h> #include <linux/mfd/max8998-private.h> struct max8998_irq_data { @@ -99,7 +100,8 @@ static struct max8998_irq_data max8998_irqs[] = { static inline struct max8998_irq_data * irq_to_max8998_irq(struct max8998_dev *max8998, int irq) { - return &max8998_irqs[irq - max8998->irq_base]; + struct irq_data *data = irq_get_irq_data(irq); + return &max8998_irqs[data->hwirq]; } static void max8998_irq_lock(struct irq_data *data) @@ -176,8 +178,14 @@ static irqreturn_t max8998_irq_thread(int irq, void *data) /* Report */ for (i = 0; i < MAX8998_IRQ_NR; i++) { - if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask) - handle_nested_irq(max8998->irq_base + i); + if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask) { + irq = irq_find_mapping(max8998->irq_domain, i); + if (WARN_ON(!irq)) { + disable_irq_nosync(max8998->irq); + return IRQ_NONE; + } + handle_nested_irq(irq); + } } return IRQ_HANDLED; @@ -185,27 +193,40 @@ static irqreturn_t max8998_irq_thread(int irq, void *data) int max8998_irq_resume(struct max8998_dev *max8998) { - if (max8998->irq && max8998->irq_base) - max8998_irq_thread(max8998->irq_base, max8998); + if (max8998->irq && max8998->irq_domain) + max8998_irq_thread(max8998->irq, max8998); + return 0; +} + +static int max8998_irq_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + struct max8997_dev *max8998 = d->host_data; + + irq_set_chip_data(irq, max8998); + irq_set_chip_and_handler(irq, &max8998_irq_chip, handle_edge_irq); + irq_set_nested_thread(irq, 1); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + irq_set_noprobe(irq); +#endif return 0; } +static struct irq_domain_ops max8998_irq_domain_ops = { + .map = max8998_irq_domain_map, +}; + int max8998_irq_init(struct max8998_dev *max8998) { int i; - int cur_irq; int ret; + struct irq_domain *domain; if (!max8998->irq) { dev_warn(max8998->dev, "No interrupt specified, no interrupts\n"); - max8998->irq_base = 0; - return 0; - } - - if (!max8998->irq_base) { - dev_err(max8998->dev, - "No interrupt base specified, no interrupts\n"); return 0; } @@ -221,19 +242,13 @@ int max8998_irq_init(struct max8998_dev *max8998) max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM1, 0xff); max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM2, 0xff); - /* register with genirq */ - for (i = 0; i < MAX8998_IRQ_NR; i++) { - cur_irq = i + max8998->irq_base; - irq_set_chip_data(cur_irq, max8998); - irq_set_chip_and_handler(cur_irq, &max8998_irq_chip, - handle_edge_irq); - irq_set_nested_thread(cur_irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(cur_irq, IRQF_VALID); -#else - irq_set_noprobe(cur_irq); -#endif + domain = irq_domain_add_simple(NULL, MAX8998_IRQ_NR, + max8998->irq_base, &max8998_irq_domain_ops, max8998); + if (!domain) { + dev_err(max8998->dev, "could not create irq domain\n"); + return -ENODEV; } + max8998->irq_domain = domain; ret = request_threaded_irq(max8998->irq, NULL, max8998_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index d7218cc..21af51a 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -20,12 +20,15 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/err.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/i2c.h> #include <linux/interrupt.h> +#include <linux/of.h> +#include <linux/of_irq.h> #include <linux/pm_runtime.h> #include <linux/mutex.h> #include <linux/mfd/core.h> @@ -128,6 +131,56 @@ int max8998_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask) } EXPORT_SYMBOL(max8998_update_reg); +#ifdef CONFIG_OF +static struct of_device_id max8998_dt_match[] = { + { .compatible = "maxim,max8998", .data = (void *)TYPE_MAX8998 }, + { .compatible = "national,lp3974", .data = (void *)TYPE_LP3974 }, + { .compatible = "ti,lp3974", .data = (void *)TYPE_LP3974 }, + {}, +}; +MODULE_DEVICE_TABLE(of, max8998_dt_match); +#endif + +/* + * Only the common platform data elements for max8998 are parsed here from the + * device tree. Other sub-modules of max8998 such as pmic, rtc and others have + * to parse their own platform data elements from device tree. + * + * The max8998 platform data structure is instantiated here and the drivers for + * the sub-modules need not instantiate another instance while parsing their + * platform data. + */ +static struct max8998_platform_data *max8998_i2c_parse_dt_pdata( + struct device *dev) +{ + struct max8998_platform_data *pd; + + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + if (!pd) + return ERR_PTR(-ENOMEM); + + pd->ono = irq_of_parse_and_map(dev->of_node, 1); + + /* + * ToDo: the 'wakeup' member in the platform data is more of a linux + * specfic information. Hence, there is no binding for that yet and + * not parsed here. + */ + return pd; +} + +static inline int max8998_i2c_get_driver_data(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(max8998_dt_match, i2c->dev.of_node); + return (int)match->data; + } + + return (int)id->driver_data; +} + static int max8998_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -139,11 +192,20 @@ static int max8998_i2c_probe(struct i2c_client *i2c, if (max8998 == NULL) return -ENOMEM; + if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { + pdata = max8998_i2c_parse_dt_pdata(&i2c->dev); + if (IS_ERR(pdata)) { + ret = PTR_ERR(pdata); + goto err; + } + } + i2c_set_clientdata(i2c, max8998); max8998->dev = &i2c->dev; max8998->i2c = i2c; max8998->irq = i2c->irq; - max8998->type = id->driver_data; + max8998->type = max8998_i2c_get_driver_data(i2c, id); + max8998->pdata = pdata; if (pdata) { max8998->ono = pdata->ono; max8998->irq_base = pdata->irq_base; @@ -158,7 +220,7 @@ static int max8998_i2c_probe(struct i2c_client *i2c, pm_runtime_set_active(max8998->dev); - switch (id->driver_data) { + switch (max8998->type) { case TYPE_LP3974: ret = mfd_add_devices(max8998->dev, -1, lp3974_devs, ARRAY_SIZE(lp3974_devs), @@ -314,6 +376,7 @@ static struct i2c_driver max8998_i2c_driver = { .name = "max8998", .owner = THIS_MODULE, .pm = &max8998_pm, + .of_match_table = of_match_ptr(max8998_dt_match), }, .probe = max8998_i2c_probe, .remove = max8998_i2c_remove, diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c index f99d629..13198d9 100644 --- a/drivers/mfd/mcp-sa11x0.c +++ b/drivers/mfd/mcp-sa11x0.c @@ -225,8 +225,6 @@ static int mcp_sa11x0_probe(struct platform_device *dev) if (ret == 0) return 0; - platform_set_drvdata(dev, NULL); - err_ioremap: iounmap(m->base1); iounmap(m->base0); @@ -252,7 +250,6 @@ static int mcp_sa11x0_remove(struct platform_device *dev) mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0); mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1); - platform_set_drvdata(dev, NULL); mcp_host_del(mcp); iounmap(m->base1); iounmap(m->base0); diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index 53e9fe6..e4d1c70 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -23,78 +23,7 @@ #include <linux/err.h> #include <linux/mfd/core.h> #include <linux/mfd/palmas.h> -#include <linux/of_platform.h> - -enum palmas_ids { - PALMAS_PMIC_ID, - PALMAS_GPIO_ID, - PALMAS_LEDS_ID, - PALMAS_WDT_ID, - PALMAS_RTC_ID, - PALMAS_PWRBUTTON_ID, - PALMAS_GPADC_ID, - PALMAS_RESOURCE_ID, - PALMAS_CLK_ID, - PALMAS_PWM_ID, - PALMAS_USB_ID, -}; - -static struct resource palmas_rtc_resources[] = { - { - .start = PALMAS_RTC_ALARM_IRQ, - .end = PALMAS_RTC_ALARM_IRQ, - .flags = IORESOURCE_IRQ, - }, -}; - -static const struct mfd_cell palmas_children[] = { - { - .name = "palmas-pmic", - .id = PALMAS_PMIC_ID, - }, - { - .name = "palmas-gpio", - .id = PALMAS_GPIO_ID, - }, - { - .name = "palmas-leds", - .id = PALMAS_LEDS_ID, - }, - { - .name = "palmas-wdt", - .id = PALMAS_WDT_ID, - }, - { - .name = "palmas-rtc", - .id = PALMAS_RTC_ID, - .resources = &palmas_rtc_resources[0], - .num_resources = ARRAY_SIZE(palmas_rtc_resources), - }, - { - .name = "palmas-pwrbutton", - .id = PALMAS_PWRBUTTON_ID, - }, - { - .name = "palmas-gpadc", - .id = PALMAS_GPADC_ID, - }, - { - .name = "palmas-resource", - .id = PALMAS_RESOURCE_ID, - }, - { - .name = "palmas-clk", - .id = PALMAS_CLK_ID, - }, - { - .name = "palmas-pwm", - .id = PALMAS_PWM_ID, - }, - { - .name = "palmas-usb", - .id = PALMAS_USB_ID, - } -}; +#include <linux/of_device.h> static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = { { @@ -302,6 +231,21 @@ static void palmas_dt_to_pdata(struct i2c_client *i2c, palmas_set_pdata_irq_flag(i2c, pdata); } +static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST; +static unsigned int tps659038_features; + +static const struct of_device_id of_palmas_match_tbl[] = { + { + .compatible = "ti,palmas", + .data = &palmas_features, + }, + { + .compatible = "ti,tps659038", + .data = &tps659038_features, + }, + { }, +}; + static int palmas_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -309,9 +253,9 @@ static int palmas_i2c_probe(struct i2c_client *i2c, struct palmas_platform_data *pdata; struct device_node *node = i2c->dev.of_node; int ret = 0, i; - unsigned int reg, addr; + unsigned int reg, addr, *features; int slave; - struct mfd_cell *children; + const struct of_device_id *match; pdata = dev_get_platdata(&i2c->dev); @@ -333,9 +277,16 @@ static int palmas_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, palmas); palmas->dev = &i2c->dev; - palmas->id = id->driver_data; palmas->irq = i2c->irq; + match = of_match_device(of_match_ptr(of_palmas_match_tbl), &i2c->dev); + + if (!match) + return -ENODATA; + + features = (unsigned int *)match->data; + palmas->features = *features; + for (i = 0; i < PALMAS_NUM_CLIENTS; i++) { if (i == 0) palmas->i2c_clients[i] = i2c; @@ -362,6 +313,11 @@ static int palmas_i2c_probe(struct i2c_client *i2c, } } + if (!palmas->irq) { + dev_warn(palmas->dev, "IRQ missing: skipping irq request\n"); + goto no_irq; + } + /* Change interrupt line output polarity */ if (pdata->irq_flags & IRQ_TYPE_LEVEL_HIGH) reg = PALMAS_POLARITY_CTRL_INT_POLARITY; @@ -388,6 +344,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c, if (ret < 0) goto err; +no_irq: slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE); addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE, PALMAS_PRIMARY_SECONDARY_PAD1); @@ -472,42 +429,8 @@ static int palmas_i2c_probe(struct i2c_client *i2c, return ret; } - children = kmemdup(palmas_children, sizeof(palmas_children), - GFP_KERNEL); - if (!children) { - ret = -ENOMEM; - goto err_irq; - } - - children[PALMAS_PMIC_ID].platform_data = pdata->pmic_pdata; - children[PALMAS_PMIC_ID].pdata_size = sizeof(*pdata->pmic_pdata); - - children[PALMAS_GPADC_ID].platform_data = pdata->gpadc_pdata; - children[PALMAS_GPADC_ID].pdata_size = sizeof(*pdata->gpadc_pdata); - - children[PALMAS_RESOURCE_ID].platform_data = pdata->resource_pdata; - children[PALMAS_RESOURCE_ID].pdata_size = - sizeof(*pdata->resource_pdata); - - children[PALMAS_USB_ID].platform_data = pdata->usb_pdata; - children[PALMAS_USB_ID].pdata_size = sizeof(*pdata->usb_pdata); - - children[PALMAS_CLK_ID].platform_data = pdata->clk_pdata; - children[PALMAS_CLK_ID].pdata_size = sizeof(*pdata->clk_pdata); - - ret = mfd_add_devices(palmas->dev, -1, - children, ARRAY_SIZE(palmas_children), - NULL, 0, - regmap_irq_get_domain(palmas->irq_data)); - kfree(children); - - if (ret < 0) - goto err_devices; - return ret; -err_devices: - mfd_remove_devices(palmas->dev); err_irq: regmap_del_irq_chip(palmas->irq, palmas->irq_data); err: @@ -533,11 +456,6 @@ static const struct i2c_device_id palmas_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, palmas_i2c_id); -static struct of_device_id of_palmas_match_tbl[] = { - { .compatible = "ti,palmas", }, - { /* end */ } -}; - static struct i2c_driver palmas_i2c_driver = { .driver = { .name = "palmas", diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index 2a2d316..c436bf2 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c @@ -35,12 +35,33 @@ static u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr) return val & 0x0F; } +static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr) +{ + u8 val = 0; + + rtsx_pci_read_register(pcr, RTL8411B_PACKAGE_MODE, &val); + + if (val & 0x2) + return 1; + else + return 0; +} + static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr) { return rtsx_pci_write_register(pcr, CD_PAD_CTL, CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); } +static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr) +{ + if (rtl8411b_is_qfn48(pcr)) + rtsx_pci_write_register(pcr, CARD_PULL_CTL3, 0xFF, 0xF5); + + return rtsx_pci_write_register(pcr, CD_PAD_CTL, + CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); +} + static int rtl8411_turn_on_led(struct rtsx_pcr *pcr) { return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00); @@ -214,6 +235,20 @@ static const struct pcr_ops rtl8411_pcr_ops = { .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, }; +static const struct pcr_ops rtl8411b_pcr_ops = { + .extra_init_hw = rtl8411b_extra_init_hw, + .optimize_phy = NULL, + .turn_on_led = rtl8411_turn_on_led, + .turn_off_led = rtl8411_turn_off_led, + .enable_auto_blink = rtl8411_enable_auto_blink, + .disable_auto_blink = rtl8411_disable_auto_blink, + .card_power_on = rtl8411_card_power_on, + .card_power_off = rtl8411_card_power_off, + .switch_output_voltage = rtl8411_switch_output_voltage, + .cd_deglitch = rtl8411_cd_deglitch, + .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, +}; + /* SD Pull Control Enable: * SD_DAT[3:0] ==> pull up * SD_CD ==> pull up @@ -276,6 +311,74 @@ static const u32 rtl8411_ms_pull_ctl_disable_tbl[] = { 0, }; +static const u32 rtl8411b_qfn64_sd_pull_ctl_enable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA), + RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x09 | 0xD0), + RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn48_sd_pull_ctl_enable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x69 | 0x90), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x08 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn64_sd_pull_ctl_disable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0), + RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn48_sd_pull_ctl_disable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn64_ms_pull_ctl_enable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0), + RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn48_ms_pull_ctl_enable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn64_ms_pull_ctl_disable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0), + RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn48_ms_pull_ctl_disable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + void rtl8411_init_params(struct rtsx_pcr *pcr) { pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; @@ -288,3 +391,32 @@ void rtl8411_init_params(struct rtsx_pcr *pcr) pcr->ms_pull_ctl_enable_tbl = rtl8411_ms_pull_ctl_enable_tbl; pcr->ms_pull_ctl_disable_tbl = rtl8411_ms_pull_ctl_disable_tbl; } + +void rtl8411b_init_params(struct rtsx_pcr *pcr) +{ + pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; + pcr->num_slots = 2; + pcr->ops = &rtl8411b_pcr_ops; + + pcr->ic_version = rtl8411_get_ic_version(pcr); + + if (rtl8411b_is_qfn48(pcr)) { + pcr->sd_pull_ctl_enable_tbl = + rtl8411b_qfn48_sd_pull_ctl_enable_tbl; + pcr->sd_pull_ctl_disable_tbl = + rtl8411b_qfn48_sd_pull_ctl_disable_tbl; + pcr->ms_pull_ctl_enable_tbl = + rtl8411b_qfn48_ms_pull_ctl_enable_tbl; + pcr->ms_pull_ctl_disable_tbl = + rtl8411b_qfn48_ms_pull_ctl_disable_tbl; + } else { + pcr->sd_pull_ctl_enable_tbl = + rtl8411b_qfn64_sd_pull_ctl_enable_tbl; + pcr->sd_pull_ctl_disable_tbl = + rtl8411b_qfn64_sd_pull_ctl_disable_tbl; + pcr->ms_pull_ctl_enable_tbl = + rtl8411b_qfn64_ms_pull_ctl_enable_tbl; + pcr->ms_pull_ctl_disable_tbl = + rtl8411b_qfn64_ms_pull_ctl_disable_tbl; + } +} diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index e968c01..dd186c4 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -57,6 +57,7 @@ static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = { { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { 0, } }; @@ -1038,6 +1039,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr) case 0x5249: rts5249_init_params(pcr); break; + + case 0x5287: + rtl8411b_init_params(pcr); + break; } dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n", diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h index 55fcfc2..c0cac7e 100644 --- a/drivers/mfd/rtsx_pcr.h +++ b/drivers/mfd/rtsx_pcr.h @@ -33,5 +33,6 @@ void rts5229_init_params(struct rtsx_pcr *pcr); void rtl8411_init_params(struct rtsx_pcr *pcr); void rts5227_init_params(struct rtsx_pcr *pcr); void rts5249_init_params(struct rtsx_pcr *pcr); +void rtl8411b_init_params(struct rtsx_pcr *pcr); #endif diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 77ee26ef..7976768 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -25,6 +25,9 @@ #include <linux/mfd/samsung/core.h> #include <linux/mfd/samsung/irq.h> #include <linux/mfd/samsung/rtc.h> +#include <linux/mfd/samsung/s2mps11.h> +#include <linux/mfd/samsung/s5m8763.h> +#include <linux/mfd/samsung/s5m8767.h> #include <linux/regmap.h> static struct mfd_cell s5m8751_devs[] = { @@ -105,6 +108,26 @@ static struct regmap_config sec_regmap_config = { .val_bits = 8, }; +static struct regmap_config s2mps11_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPS11_REG_L38CTRL, +}; + +static struct regmap_config s5m8763_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S5M8763_REG_LBCNFG2, +}; + +static struct regmap_config s5m8767_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S5M8767_REG_LDO28CTRL, +}; #ifdef CONFIG_OF /* @@ -160,6 +183,7 @@ static int sec_pmic_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct sec_platform_data *pdata = i2c->dev.platform_data; + const struct regmap_config *regmap; struct sec_pmic_dev *sec_pmic; int ret; @@ -190,7 +214,22 @@ static int sec_pmic_probe(struct i2c_client *i2c, sec_pmic->pdata = pdata; } - sec_pmic->regmap = devm_regmap_init_i2c(i2c, &sec_regmap_config); + switch (sec_pmic->device_type) { + case S2MPS11X: + regmap = &s2mps11_regmap_config; + break; + case S5M8763X: + regmap = &s5m8763_regmap_config; + break; + case S5M8767X: + regmap = &s5m8767_regmap_config; + break; + default: + regmap = &sec_regmap_config; + break; + } + + sec_pmic->regmap = devm_regmap_init_i2c(i2c, regmap); if (IS_ERR(sec_pmic->regmap)) { ret = PTR_ERR(sec_pmic->regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", @@ -230,13 +269,12 @@ static int sec_pmic_probe(struct i2c_client *i2c, BUG(); } - if (ret < 0) + if (ret) goto err; return ret; err: - mfd_remove_devices(sec_pmic->dev); sec_irq_exit(sec_pmic); i2c_unregister_device(sec_pmic->rtc); return ret; diff --git a/drivers/mfd/ssbi.c b/drivers/mfd/ssbi.c new file mode 100644 index 0000000..102a228 --- /dev/null +++ b/drivers/mfd/ssbi.c @@ -0,0 +1,333 @@ +/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2010, Google Inc. + * + * Original authors: Code Aurora Forum + * + * Author: Dima Zavin <dima@android.com> + * - Largely rewritten from original to not be an i2c driver. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only 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. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/ssbi.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> + +/* SSBI 2.0 controller registers */ +#define SSBI2_CMD 0x0008 +#define SSBI2_RD 0x0010 +#define SSBI2_STATUS 0x0014 +#define SSBI2_MODE2 0x001C + +/* SSBI_CMD fields */ +#define SSBI_CMD_RDWRN (1 << 24) + +/* SSBI_STATUS fields */ +#define SSBI_STATUS_RD_READY (1 << 2) +#define SSBI_STATUS_READY (1 << 1) +#define SSBI_STATUS_MCHN_BUSY (1 << 0) + +/* SSBI_MODE2 fields */ +#define SSBI_MODE2_REG_ADDR_15_8_SHFT 0x04 +#define SSBI_MODE2_REG_ADDR_15_8_MASK (0x7f << SSBI_MODE2_REG_ADDR_15_8_SHFT) + +#define SET_SSBI_MODE2_REG_ADDR_15_8(MD, AD) \ + (((MD) & 0x0F) | ((((AD) >> 8) << SSBI_MODE2_REG_ADDR_15_8_SHFT) & \ + SSBI_MODE2_REG_ADDR_15_8_MASK)) + +/* SSBI PMIC Arbiter command registers */ +#define SSBI_PA_CMD 0x0000 +#define SSBI_PA_RD_STATUS 0x0004 + +/* SSBI_PA_CMD fields */ +#define SSBI_PA_CMD_RDWRN (1 << 24) +#define SSBI_PA_CMD_ADDR_MASK 0x7fff /* REG_ADDR_7_0, REG_ADDR_8_14*/ + +/* SSBI_PA_RD_STATUS fields */ +#define SSBI_PA_RD_STATUS_TRANS_DONE (1 << 27) +#define SSBI_PA_RD_STATUS_TRANS_DENIED (1 << 26) + +#define SSBI_TIMEOUT_US 100 + +struct ssbi { + struct device *slave; + void __iomem *base; + spinlock_t lock; + enum ssbi_controller_type controller_type; + int (*read)(struct ssbi *, u16 addr, u8 *buf, int len); + int (*write)(struct ssbi *, u16 addr, u8 *buf, int len); +}; + +#define to_ssbi(dev) platform_get_drvdata(to_platform_device(dev)) + +static inline u32 ssbi_readl(struct ssbi *ssbi, u32 reg) +{ + return readl(ssbi->base + reg); +} + +static inline void ssbi_writel(struct ssbi *ssbi, u32 val, u32 reg) +{ + writel(val, ssbi->base + reg); +} + +/* + * Via private exchange with one of the original authors, the hardware + * should generally finish a transaction in about 5us. The worst + * case, is when using the arbiter and both other CPUs have just + * started trying to use the SSBI bus will result in a time of about + * 20us. It should never take longer than this. + * + * As such, this wait merely spins, with a udelay. + */ +static int ssbi_wait_mask(struct ssbi *ssbi, u32 set_mask, u32 clr_mask) +{ + u32 timeout = SSBI_TIMEOUT_US; + u32 val; + + while (timeout--) { + val = ssbi_readl(ssbi, SSBI2_STATUS); + if (((val & set_mask) == set_mask) && ((val & clr_mask) == 0)) + return 0; + udelay(1); + } + + return -ETIMEDOUT; +} + +static int +ssbi_read_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len) +{ + u32 cmd = SSBI_CMD_RDWRN | ((addr & 0xff) << 16); + int ret = 0; + + if (ssbi->controller_type == MSM_SBI_CTRL_SSBI2) { + u32 mode2 = ssbi_readl(ssbi, SSBI2_MODE2); + mode2 = SET_SSBI_MODE2_REG_ADDR_15_8(mode2, addr); + ssbi_writel(ssbi, mode2, SSBI2_MODE2); + } + + while (len) { + ret = ssbi_wait_mask(ssbi, SSBI_STATUS_READY, 0); + if (ret) + goto err; + + ssbi_writel(ssbi, cmd, SSBI2_CMD); + ret = ssbi_wait_mask(ssbi, SSBI_STATUS_RD_READY, 0); + if (ret) + goto err; + *buf++ = ssbi_readl(ssbi, SSBI2_RD) & 0xff; + len--; + } + +err: + return ret; +} + +static int +ssbi_write_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len) +{ + int ret = 0; + + if (ssbi->controller_type == MSM_SBI_CTRL_SSBI2) { + u32 mode2 = ssbi_readl(ssbi, SSBI2_MODE2); + mode2 = SET_SSBI_MODE2_REG_ADDR_15_8(mode2, addr); + ssbi_writel(ssbi, mode2, SSBI2_MODE2); + } + + while (len) { + ret = ssbi_wait_mask(ssbi, SSBI_STATUS_READY, 0); + if (ret) + goto err; + + ssbi_writel(ssbi, ((addr & 0xff) << 16) | *buf, SSBI2_CMD); + ret = ssbi_wait_mask(ssbi, 0, SSBI_STATUS_MCHN_BUSY); + if (ret) + goto err; + buf++; + len--; + } + +err: + return ret; +} + +/* + * See ssbi_wait_mask for an explanation of the time and the + * busywait. + */ +static inline int +ssbi_pa_transfer(struct ssbi *ssbi, u32 cmd, u8 *data) +{ + u32 timeout = SSBI_TIMEOUT_US; + u32 rd_status = 0; + + ssbi_writel(ssbi, cmd, SSBI_PA_CMD); + + while (timeout--) { + rd_status = ssbi_readl(ssbi, SSBI_PA_RD_STATUS); + + if (rd_status & SSBI_PA_RD_STATUS_TRANS_DENIED) + return -EPERM; + + if (rd_status & SSBI_PA_RD_STATUS_TRANS_DONE) { + if (data) + *data = rd_status & 0xff; + return 0; + } + udelay(1); + } + + return -ETIMEDOUT; +} + +static int +ssbi_pa_read_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len) +{ + u32 cmd; + int ret = 0; + + cmd = SSBI_PA_CMD_RDWRN | (addr & SSBI_PA_CMD_ADDR_MASK) << 8; + + while (len) { + ret = ssbi_pa_transfer(ssbi, cmd, buf); + if (ret) + goto err; + buf++; + len--; + } + +err: + return ret; +} + +static int +ssbi_pa_write_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len) +{ + u32 cmd; + int ret = 0; + + while (len) { + cmd = (addr & SSBI_PA_CMD_ADDR_MASK) << 8 | *buf; + ret = ssbi_pa_transfer(ssbi, cmd, NULL); + if (ret) + goto err; + buf++; + len--; + } + +err: + return ret; +} + +int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len) +{ + struct ssbi *ssbi = to_ssbi(dev); + unsigned long flags; + int ret; + + spin_lock_irqsave(&ssbi->lock, flags); + ret = ssbi->read(ssbi, addr, buf, len); + spin_unlock_irqrestore(&ssbi->lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(ssbi_read); + +int ssbi_write(struct device *dev, u16 addr, u8 *buf, int len) +{ + struct ssbi *ssbi = to_ssbi(dev); + unsigned long flags; + int ret; + + spin_lock_irqsave(&ssbi->lock, flags); + ret = ssbi->write(ssbi, addr, buf, len); + spin_unlock_irqrestore(&ssbi->lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(ssbi_write); + +static int ssbi_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct resource *mem_res; + struct ssbi *ssbi; + const char *type; + + ssbi = devm_kzalloc(&pdev->dev, sizeof(*ssbi), GFP_KERNEL); + if (!ssbi) + return -ENOMEM; + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + ssbi->base = devm_ioremap_resource(&pdev->dev, mem_res); + if (IS_ERR(ssbi->base)) + return PTR_ERR(ssbi->base); + + platform_set_drvdata(pdev, ssbi); + + type = of_get_property(np, "qcom,controller-type", NULL); + if (type == NULL) { + dev_err(&pdev->dev, "Missing qcom,controller-type property\n"); + return -EINVAL; + } + dev_info(&pdev->dev, "SSBI controller type: '%s'\n", type); + if (strcmp(type, "ssbi") == 0) + ssbi->controller_type = MSM_SBI_CTRL_SSBI; + else if (strcmp(type, "ssbi2") == 0) + ssbi->controller_type = MSM_SBI_CTRL_SSBI2; + else if (strcmp(type, "pmic-arbiter") == 0) + ssbi->controller_type = MSM_SBI_CTRL_PMIC_ARBITER; + else { + dev_err(&pdev->dev, "Unknown qcom,controller-type\n"); + return -EINVAL; + } + + if (ssbi->controller_type == MSM_SBI_CTRL_PMIC_ARBITER) { + ssbi->read = ssbi_pa_read_bytes; + ssbi->write = ssbi_pa_write_bytes; + } else { + ssbi->read = ssbi_read_bytes; + ssbi->write = ssbi_write_bytes; + } + + spin_lock_init(&ssbi->lock); + + return of_platform_populate(np, NULL, NULL, &pdev->dev); +} + +static struct of_device_id ssbi_match_table[] = { + { .compatible = "qcom,ssbi" }, + {} +}; +MODULE_DEVICE_TABLE(of, ssbi_match_table); + +static struct platform_driver ssbi_driver = { + .probe = ssbi_probe, + .driver = { + .name = "ssbi", + .owner = THIS_MODULE, + .of_match_table = ssbi_match_table, + }, +}; +module_platform_driver(ssbi_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_VERSION("1.0"); +MODULE_ALIAS("platform:ssbi"); +MODULE_AUTHOR("Dima Zavin <dima@android.com>"); diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index b32940e..a21bff2 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c @@ -422,7 +422,6 @@ static int t7l66xb_remove(struct platform_device *dev) iounmap(t7l66xb->scr); release_resource(&t7l66xb->rscr); mfd_remove_devices(&dev->dev); - platform_set_drvdata(dev, NULL); kfree(t7l66xb); return ret; diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index 366f7b9..65c425a 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c @@ -217,7 +217,6 @@ static int tc6387xb_remove(struct platform_device *dev) release_resource(&tc6387xb->rscr); clk_disable(tc6387xb->clk32k); clk_put(tc6387xb->clk32k); - platform_set_drvdata(dev, NULL); kfree(tc6387xb); return 0; diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 15e1463..a563dfa 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -756,7 +756,6 @@ static int tc6393xb_remove(struct platform_device *dev) clk_disable(tc6393xb->clk); iounmap(tc6393xb->scr); release_resource(&tc6393xb->rscr); - platform_set_drvdata(dev, NULL); clk_put(tc6393xb->clk); kfree(tc6393xb); diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index e9f3fb5..b003a16 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -22,10 +22,10 @@ #include <linux/regmap.h> #include <linux/mfd/core.h> #include <linux/pm_runtime.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <linux/mfd/ti_am335x_tscadc.h> -#include <linux/input/ti_am335x_tsc.h> -#include <linux/platform_data/ti_am335x_adc.h> static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg) { @@ -48,6 +48,32 @@ static const struct regmap_config tscadc_regmap_config = { .val_bits = 32, }; +void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc) +{ + tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); +} +EXPORT_SYMBOL_GPL(am335x_tsc_se_update); + +void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val) +{ + spin_lock(&tsadc->reg_lock); + tsadc->reg_se_cache |= val; + spin_unlock(&tsadc->reg_lock); + + am335x_tsc_se_update(tsadc); +} +EXPORT_SYMBOL_GPL(am335x_tsc_se_set); + +void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) +{ + spin_lock(&tsadc->reg_lock); + tsadc->reg_se_cache &= ~val; + spin_unlock(&tsadc->reg_lock); + + am335x_tsc_se_update(tsadc); +} +EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); + static void tscadc_idle_config(struct ti_tscadc_dev *config) { unsigned int idleconfig; @@ -63,27 +89,48 @@ static int ti_tscadc_probe(struct platform_device *pdev) struct ti_tscadc_dev *tscadc; struct resource *res; struct clk *clk; - struct mfd_tscadc_board *pdata = pdev->dev.platform_data; + struct device_node *node = pdev->dev.of_node; struct mfd_cell *cell; + struct property *prop; + const __be32 *cur; + u32 val; int err, ctrl; int clk_value, clock_rate; - int tsc_wires, adc_channels = 0, total_channels; + int tsc_wires = 0, adc_channels = 0, total_channels; + int readouts = 0; - if (!pdata) { - dev_err(&pdev->dev, "Could not find platform data\n"); + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "Could not find valid DT data.\n"); return -EINVAL; } - if (pdata->adc_init) - adc_channels = pdata->adc_init->adc_channels; - - tsc_wires = pdata->tsc_init->wires; + node = of_get_child_by_name(pdev->dev.of_node, "tsc"); + of_property_read_u32(node, "ti,wires", &tsc_wires); + of_property_read_u32(node, "ti,coordiante-readouts", &readouts); + + node = of_get_child_by_name(pdev->dev.of_node, "adc"); + of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { + adc_channels++; + if (val > 7) { + dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n", + val); + return -EINVAL; + } + } total_channels = tsc_wires + adc_channels; - if (total_channels > 8) { dev_err(&pdev->dev, "Number of i/p channels more than 8\n"); return -EINVAL; } + if (total_channels == 0) { + dev_err(&pdev->dev, "Need atleast one channel.\n"); + return -EINVAL; + } + + if (readouts * 2 + 2 + adc_channels > 16) { + dev_err(&pdev->dev, "Too many step configurations requested\n"); + return -EINVAL; + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -129,6 +176,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) goto ret; } + spin_lock_init(&tscadc->reg_lock); pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); @@ -173,26 +221,37 @@ static int ti_tscadc_probe(struct platform_device *pdev) ctrl |= CNTRLREG_TSCSSENB; tscadc_writel(tscadc, REG_CTRL, ctrl); + tscadc->used_cells = 0; + tscadc->tsc_cell = -1; + tscadc->adc_cell = -1; + /* TSC Cell */ - cell = &tscadc->cells[TSC_CELL]; - cell->name = "tsc"; - cell->platform_data = tscadc; - cell->pdata_size = sizeof(*tscadc); + if (tsc_wires > 0) { + tscadc->tsc_cell = tscadc->used_cells; + cell = &tscadc->cells[tscadc->used_cells++]; + cell->name = "TI-am335x-tsc"; + cell->of_compatible = "ti,am3359-tsc"; + cell->platform_data = &tscadc; + cell->pdata_size = sizeof(tscadc); + } /* ADC Cell */ - cell = &tscadc->cells[ADC_CELL]; - cell->name = "tiadc"; - cell->platform_data = tscadc; - cell->pdata_size = sizeof(*tscadc); + if (adc_channels > 0) { + tscadc->adc_cell = tscadc->used_cells; + cell = &tscadc->cells[tscadc->used_cells++]; + cell->name = "TI-am335x-adc"; + cell->of_compatible = "ti,am3359-adc"; + cell->platform_data = &tscadc; + cell->pdata_size = sizeof(tscadc); + } err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells, - TSCADC_CELLS, NULL, 0, NULL); + tscadc->used_cells, NULL, 0, NULL); if (err < 0) goto err_disable_clk; device_init_wakeup(&pdev->dev, true); platform_set_drvdata(pdev, tscadc); - return 0; err_disable_clk: @@ -239,7 +298,7 @@ static int tscadc_resume(struct device *dev) CNTRLREG_STEPID | CNTRLREG_4WIRE; tscadc_writel(tscadc_dev, REG_CTRL, ctrl); tscadc_idle_config(tscadc_dev); - tscadc_writel(tscadc_dev, REG_SE, STPENB_STEPENB); + am335x_tsc_se_update(tscadc_dev); restore = tscadc_readl(tscadc_dev, REG_CTRL); tscadc_writel(tscadc_dev, REG_CTRL, (restore | CNTRLREG_TSCSSENB)); @@ -256,11 +315,18 @@ static const struct dev_pm_ops tscadc_pm_ops = { #define TSCADC_PM_OPS NULL #endif +static const struct of_device_id ti_tscadc_dt_ids[] = { + { .compatible = "ti,am3359-tscadc", }, + { } +}; +MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids); + static struct platform_driver ti_tscadc_driver = { .driver = { - .name = "ti_tscadc", + .name = "ti_am3359-tscadc", .owner = THIS_MODULE, .pm = TSCADC_PM_OPS, + .of_match_table = of_match_ptr(ti_tscadc_dt_ids), }, .probe = ti_tscadc_probe, .remove = ti_tscadc_remove, diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c index aeb8e40..479886a 100644 --- a/drivers/mfd/tps65912-core.c +++ b/drivers/mfd/tps65912-core.c @@ -162,7 +162,6 @@ int tps65912_device_init(struct tps65912 *tps65912) err: kfree(init_data); mfd_remove_devices(tps65912->dev); - kfree(tps65912); return ret; } @@ -170,7 +169,6 @@ void tps65912_device_exit(struct tps65912 *tps65912) { mfd_remove_devices(tps65912->dev); tps65912_irq_exit(tps65912); - kfree(tps65912); } MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>"); diff --git a/drivers/mfd/tps65912-i2c.c b/drivers/mfd/tps65912-i2c.c index c041f2c..6a6343e 100644 --- a/drivers/mfd/tps65912-i2c.c +++ b/drivers/mfd/tps65912-i2c.c @@ -77,7 +77,8 @@ static int tps65912_i2c_probe(struct i2c_client *i2c, { struct tps65912 *tps65912; - tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL); + tps65912 = devm_kzalloc(&i2c->dev, + sizeof(struct tps65912), GFP_KERNEL); if (tps65912 == NULL) return -ENOMEM; diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c index b45f460..69a5178 100644 --- a/drivers/mfd/tps65912-spi.c +++ b/drivers/mfd/tps65912-spi.c @@ -85,7 +85,8 @@ static int tps65912_spi_probe(struct spi_device *spi) { struct tps65912 *tps65912; - tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL); + tps65912 = devm_kzalloc(&spi->dev, + sizeof(struct tps65912), GFP_KERNEL); if (tps65912 == NULL) return -ENOMEM; diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 89ab4d9..7f150d9 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -118,7 +118,7 @@ #define TWL6030_BASEADD_GASGAUGE 0x00C0 #define TWL6030_BASEADD_PIH 0x00D0 #define TWL6030_BASEADD_CHARGER 0x00E0 -#define TWL6025_BASEADD_CHARGER 0x00DA +#define TWL6032_BASEADD_CHARGER 0x00DA #define TWL6030_BASEADD_LED 0x00F4 /* subchip/slave 2 0x4A - DFT */ @@ -718,9 +718,9 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, | REGULATOR_CHANGE_STATUS, }; - if (features & TWL6025_SUBCLASS) { + if (features & TWL6032_SUBCLASS) { usb3v3.supply = "ldousb"; - regulator = TWL6025_REG_LDOUSB; + regulator = TWL6032_REG_LDOUSB; } else { usb3v3.supply = "vusb"; regulator = TWL6030_REG_VUSB; @@ -747,8 +747,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, usb3v3.dev_name = dev_name(child); } else if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030()) { - if (features & TWL6025_SUBCLASS) - child = add_regulator(TWL6025_REG_LDOUSB, + if (features & TWL6032_SUBCLASS) + child = add_regulator(TWL6032_REG_LDOUSB, pdata->ldousb, features); else child = add_regulator(TWL6030_REG_VUSB, @@ -872,7 +872,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, /* twl6030 regulators */ if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() && - !(features & TWL6025_SUBCLASS)) { + !(features & TWL6032_SUBCLASS)) { child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1, features); if (IS_ERR(child)) @@ -952,60 +952,60 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, return PTR_ERR(child); } - /* twl6025 regulators */ + /* twl6032 regulators */ if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() && - (features & TWL6025_SUBCLASS)) { - child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5, + (features & TWL6032_SUBCLASS)) { + child = add_regulator(TWL6032_REG_LDO5, pdata->ldo5, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO1, pdata->ldo1, + child = add_regulator(TWL6032_REG_LDO1, pdata->ldo1, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO7, pdata->ldo7, + child = add_regulator(TWL6032_REG_LDO7, pdata->ldo7, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO6, pdata->ldo6, + child = add_regulator(TWL6032_REG_LDO6, pdata->ldo6, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDOLN, pdata->ldoln, + child = add_regulator(TWL6032_REG_LDOLN, pdata->ldoln, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO2, pdata->ldo2, + child = add_regulator(TWL6032_REG_LDO2, pdata->ldo2, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO4, pdata->ldo4, + child = add_regulator(TWL6032_REG_LDO4, pdata->ldo4, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO3, pdata->ldo3, + child = add_regulator(TWL6032_REG_LDO3, pdata->ldo3, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_SMPS3, pdata->smps3, + child = add_regulator(TWL6032_REG_SMPS3, pdata->smps3, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_SMPS4, pdata->smps4, + child = add_regulator(TWL6032_REG_SMPS4, pdata->smps4, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_VIO, pdata->vio6025, + child = add_regulator(TWL6032_REG_VIO, pdata->vio6025, features); if (IS_ERR(child)) return PTR_ERR(child); @@ -1023,6 +1023,14 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, return PTR_ERR(child); } + if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power) { + child = add_child(TWL_MODULE_PM_MASTER, "twl4030_power", + pdata->power, sizeof(*pdata->power), false, + 0, 0); + if (IS_ERR(child)) + return PTR_ERR(child); + } + return 0; } @@ -1176,10 +1184,10 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) if ((id->driver_data) & TWL6030_CLASS) { twl_priv->twl_id = TWL6030_CLASS_ID; twl_priv->twl_map = &twl6030_map[0]; - /* The charger base address is different in twl6025 */ - if ((id->driver_data) & TWL6025_SUBCLASS) + /* The charger base address is different in twl6032 */ + if ((id->driver_data) & TWL6032_SUBCLASS) twl_priv->twl_map[TWL_MODULE_MAIN_CHARGE].base = - TWL6025_BASEADD_CHARGER; + TWL6032_BASEADD_CHARGER; twl_regmap_config = twl6030_regmap_config; } else { twl_priv->twl_id = TWL4030_CLASS_ID; @@ -1234,10 +1242,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) WARN(status < 0, "Error: reading twl_idcode register value\n"); } - /* load power event scripts */ - if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata && pdata->power) - twl4030_power_init(pdata->power); - /* Maybe init the T2 Interrupt subsystem */ if (client->irq) { if (twl_class_is_4030()) { @@ -1292,7 +1296,7 @@ static const struct i2c_device_id twl_ids[] = { { "tps65921", TPS_SUBSET }, /* fewer LDOs; no codec, no LED and vibrator. Charger in USB module*/ { "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */ - { "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */ + { "twl6032", TWL6030_CLASS | TWL6032_SUBCLASS }, /* "Phoenix lite" */ { /* end of list */ }, }; MODULE_DEVICE_TABLE(i2c, twl_ids); @@ -1305,17 +1309,7 @@ static struct i2c_driver twl_driver = { .remove = twl_remove, }; -static int __init twl_init(void) -{ - return i2c_add_driver(&twl_driver); -} -subsys_initcall(twl_init); - -static void __exit twl_exit(void) -{ - i2c_del_driver(&twl_driver); -} -module_exit(twl_exit); +module_i2c_driver(twl_driver); MODULE_AUTHOR("Texas Instruments, Inc."); MODULE_DESCRIPTION("I2C Core interface for TWL"); diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c index d2ab222..a31fba9 100644 --- a/drivers/mfd/twl4030-audio.c +++ b/drivers/mfd/twl4030-audio.c @@ -261,10 +261,8 @@ static int twl4030_audio_probe(struct platform_device *pdev) ret = -ENODEV; } - if (ret) { - platform_set_drvdata(pdev, NULL); + if (ret) twl4030_audio_dev = NULL; - } return ret; } @@ -272,7 +270,6 @@ static int twl4030_audio_probe(struct platform_device *pdev) static int twl4030_audio_remove(struct platform_device *pdev) { mfd_remove_devices(&pdev->dev); - platform_set_drvdata(pdev, NULL); twl4030_audio_dev = NULL; return 0; diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 9d2d1ba..9aa6d1e 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -570,6 +570,7 @@ static struct irq_chip twl4030_sih_irq_chip = { .irq_set_type = twl4030_sih_set_type, .irq_bus_lock = twl4030_sih_bus_lock, .irq_bus_sync_unlock = twl4030_sih_bus_sync_unlock, + .flags = IRQCHIP_SKIP_SET_WAKE, }; /*----------------------------------------------------------------------*/ diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c index 42bd3ea..1ea54d4 100644 --- a/drivers/mfd/twl4030-madc.c +++ b/drivers/mfd/twl4030-madc.c @@ -775,12 +775,10 @@ static int twl4030_madc_probe(struct platform_device *pdev) IRQF_TRIGGER_RISING, "twl4030_madc", madc); if (ret) { dev_dbg(&pdev->dev, "could not request irq\n"); - goto err_irq; + goto err_i2c; } twl4030_madc = madc; return 0; -err_irq: - platform_set_drvdata(pdev, NULL); err_i2c: twl4030_madc_set_current_generator(madc, 0, 0); err_current_generator: @@ -796,7 +794,6 @@ static int twl4030_madc_remove(struct platform_device *pdev) struct twl4030_madc_data *madc = platform_get_drvdata(pdev); free_irq(platform_get_irq(pdev, 0), madc); - platform_set_drvdata(pdev, NULL); twl4030_madc_set_current_generator(madc, 0, 0); twl4030_madc_set_power(madc, 0); kfree(madc); diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index dd362c1..a5fd3c7 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -28,6 +28,7 @@ #include <linux/pm.h> #include <linux/i2c/twl.h> #include <linux/platform_device.h> +#include <linux/of.h> #include <asm/mach-types.h> @@ -492,6 +493,39 @@ int twl4030_remove_script(u8 flags) return err; } +int twl4030_power_configure_scripts(struct twl4030_power_data *pdata) +{ + int err; + int i; + u8 address = twl4030_start_script_address; + + for (i = 0; i < pdata->num; i++) { + err = load_twl4030_script(pdata->scripts[i], address); + if (err) + return err; + address += pdata->scripts[i]->size; + } + + return 0; +} + +int twl4030_power_configure_resources(struct twl4030_power_data *pdata) +{ + struct twl4030_resconfig *resconfig = pdata->resource_config; + int err; + + if (resconfig) { + while (resconfig->resource) { + err = twl4030_configure_resource(resconfig); + if (err) + return err; + resconfig++; + } + } + + return 0; +} + /* * In master mode, start the power off sequence. * After a successful execution, TWL shuts down the power to the SoC @@ -507,43 +541,58 @@ void twl4030_power_off(void) pr_err("TWL4030 Unable to power off\n"); } -void twl4030_power_init(struct twl4030_power_data *twl4030_scripts) +static bool twl4030_power_use_poweroff(struct twl4030_power_data *pdata, + struct device_node *node) { + if (pdata && pdata->use_poweroff) + return true; + + if (of_property_read_bool(node, "ti,use_poweroff")) + return true; + + return false; +} + +int twl4030_power_probe(struct platform_device *pdev) +{ + struct twl4030_power_data *pdata = pdev->dev.platform_data; + struct device_node *node = pdev->dev.of_node; int err = 0; - int i; - struct twl4030_resconfig *resconfig; - u8 val, address = twl4030_start_script_address; + int err2 = 0; + u8 val; + + if (!pdata && !node) { + dev_err(&pdev->dev, "Platform data is missing\n"); + return -EINVAL; + } err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, TWL4030_PM_MASTER_PROTECT_KEY); - if (err) - goto unlock; - - err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2, + err |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, + TWL4030_PM_MASTER_KEY_CFG2, TWL4030_PM_MASTER_PROTECT_KEY); - if (err) - goto unlock; - for (i = 0; i < twl4030_scripts->num; i++) { - err = load_twl4030_script(twl4030_scripts->scripts[i], address); - if (err) - goto load; - address += twl4030_scripts->scripts[i]->size; + if (err) { + pr_err("TWL4030 Unable to unlock registers\n"); + return err; } - resconfig = twl4030_scripts->resource_config; - if (resconfig) { - while (resconfig->resource) { - err = twl4030_configure_resource(resconfig); - if (err) - goto resource; - resconfig++; - + if (pdata) { + /* TODO: convert to device tree */ + err = twl4030_power_configure_scripts(pdata); + if (err) { + pr_err("TWL4030 failed to load scripts\n"); + goto relock; + } + err = twl4030_power_configure_resources(pdata); + if (err) { + pr_err("TWL4030 failed to configure resource\n"); + goto relock; } } /* Board has to be wired properly to use this feature */ - if (twl4030_scripts->use_poweroff && !pm_power_off) { + if (twl4030_power_use_poweroff(pdata, node) && !pm_power_off) { /* Default for SEQ_OFFSYNC is set, lets ensure this */ err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val, TWL4030_PM_MASTER_CFG_P123_TRANSITION); @@ -564,22 +613,43 @@ void twl4030_power_init(struct twl4030_power_data *twl4030_scripts) } relock: - err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, + err2 = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, TWL4030_PM_MASTER_PROTECT_KEY); - if (err) + if (err2) { pr_err("TWL4030 Unable to relock registers\n"); - return; + return err2; + } -unlock: - if (err) - pr_err("TWL4030 Unable to unlock registers\n"); - return; -load: - if (err) - pr_err("TWL4030 failed to load scripts\n"); - return; -resource: - if (err) - pr_err("TWL4030 failed to configure resource\n"); - return; + return err; } + +static int twl4030_power_remove(struct platform_device *pdev) +{ + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id twl4030_power_of_match[] = { + {.compatible = "ti,twl4030-power", }, + { }, +}; +MODULE_DEVICE_TABLE(of, twl4030_power_of_match); +#endif + +static struct platform_driver twl4030_power_driver = { + .driver = { + .name = "twl4030_power", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(twl4030_power_of_match), + }, + .probe = twl4030_power_probe, + .remove = twl4030_power_remove, +}; + +module_platform_driver(twl4030_power_driver); + +MODULE_AUTHOR("Nokia Corporation"); +MODULE_AUTHOR("Texas Instruments, Inc."); +MODULE_DESCRIPTION("Power management for TWL4030"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:twl4030_power"); diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index 96a020b..981bef4 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c @@ -351,6 +351,8 @@ void __init vexpress_sysreg_of_early_init(void) } +#ifdef CONFIG_GPIOLIB + #define VEXPRESS_SYSREG_GPIO(_name, _reg, _value) \ [VEXPRESS_GPIO_##_name] = { \ .reg = _reg, \ @@ -445,6 +447,8 @@ struct gpio_led_platform_data vexpress_sysreg_leds_pdata = { .leds = vexpress_sysreg_leds, }; +#endif + static ssize_t vexpress_sysreg_sys_id_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -480,6 +484,9 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) setup_timer(&vexpress_sysreg_config_timer, vexpress_sysreg_config_complete, 0); + vexpress_sysreg_dev = &pdev->dev; + +#ifdef CONFIG_GPIOLIB vexpress_sysreg_gpio_chip.dev = &pdev->dev; err = gpiochip_add(&vexpress_sysreg_gpio_chip); if (err) { @@ -490,11 +497,10 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) return err; } - vexpress_sysreg_dev = &pdev->dev; - platform_device_register_data(vexpress_sysreg_dev, "leds-gpio", PLATFORM_DEVID_AUTO, &vexpress_sysreg_leds_pdata, sizeof(vexpress_sysreg_leds_pdata)); +#endif device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id); diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 00e4fe2..781115e 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -259,20 +259,6 @@ static int wm8994_suspend(struct device *dev) break; } - switch (wm8994->type) { - case WM1811: - ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2); - if (ret < 0) { - dev_err(dev, "Failed to read jackdet: %d\n", ret); - } else if (ret & WM1811_JACKDET_MODE_MASK) { - dev_dbg(dev, "CODEC still active, ignoring suspend\n"); - return 0; - } - break; - default: - break; - } - /* Disable LDO pulldowns while the device is suspended if we * don't know that something will be driving them. */ if (!wm8994->ldo_ena_always_driven) @@ -652,6 +638,17 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) return ret; } + /* Explicitly put the device into reset in case regulators + * don't get disabled in order to ensure we know the device + * state. + */ + ret = wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, + wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET)); + if (ret != 0) { + dev_err(wm8994->dev, "Failed to reset device: %d\n", ret); + return ret; + } + if (regmap_patch) { ret = regmap_register_patch(wm8994->regmap, regmap_patch, patch_regs); diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c index a050e56..d3a184a 100644 --- a/drivers/mfd/wm8994-irq.c +++ b/drivers/mfd/wm8994-irq.c @@ -14,10 +14,12 @@ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/gpio.h> #include <linux/i2c.h> #include <linux/irq.h> #include <linux/mfd/core.h> #include <linux/interrupt.h> +#include <linux/irqdomain.h> #include <linux/regmap.h> #include <linux/mfd/wm8994/core.h> @@ -138,6 +140,55 @@ static struct regmap_irq_chip wm8994_irq_chip = { .runtime_pm = true, }; +static void wm8994_edge_irq_enable(struct irq_data *data) +{ +} + +static void wm8994_edge_irq_disable(struct irq_data *data) +{ +} + +static struct irq_chip wm8994_edge_irq_chip = { + .name = "wm8994_edge", + .irq_disable = wm8994_edge_irq_disable, + .irq_enable = wm8994_edge_irq_enable, +}; + +static irqreturn_t wm8994_edge_irq(int irq, void *data) +{ + struct wm8994 *wm8994 = data; + + while (gpio_get_value_cansleep(wm8994->pdata.irq_gpio)) + handle_nested_irq(irq_create_mapping(wm8994->edge_irq, 0)); + + return IRQ_HANDLED; +} + +static int wm8994_edge_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct wm8994 *wm8994 = h->host_data; + + irq_set_chip_data(virq, wm8994); + irq_set_chip_and_handler(virq, &wm8994_edge_irq_chip, handle_edge_irq); + irq_set_nested_thread(virq, 1); + + /* ARM needs us to explicitly flag the IRQ as valid + * and will set them noprobe when we do so. */ +#ifdef CONFIG_ARM + set_irq_flags(virq, IRQF_VALID); +#else + irq_set_noprobe(virq); +#endif + + return 0; +} + +static struct irq_domain_ops wm8994_edge_irq_ops = { + .map = wm8994_edge_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + int wm8994_irq_init(struct wm8994 *wm8994) { int ret; @@ -156,10 +207,51 @@ int wm8994_irq_init(struct wm8994 *wm8994) if (pdata->irq_flags) irqflags = pdata->irq_flags; - ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq, - irqflags, - wm8994->irq_base, &wm8994_irq_chip, - &wm8994->irq_data); + /* use a GPIO for edge triggered controllers */ + if (irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { + if (gpio_to_irq(pdata->irq_gpio) != wm8994->irq) { + dev_warn(wm8994->dev, "IRQ %d is not GPIO %d (%d)\n", + wm8994->irq, pdata->irq_gpio, + gpio_to_irq(pdata->irq_gpio)); + wm8994->irq = gpio_to_irq(pdata->irq_gpio); + } + + ret = devm_gpio_request_one(wm8994->dev, pdata->irq_gpio, + GPIOF_IN, "WM8994 IRQ"); + + if (ret != 0) { + dev_err(wm8994->dev, "Failed to get IRQ GPIO: %d\n", + ret); + return ret; + } + + wm8994->edge_irq = irq_domain_add_linear(NULL, 1, + &wm8994_edge_irq_ops, + wm8994); + + ret = regmap_add_irq_chip(wm8994->regmap, + irq_create_mapping(wm8994->edge_irq, + 0), + IRQF_ONESHOT, + wm8994->irq_base, &wm8994_irq_chip, + &wm8994->irq_data); + if (ret != 0) { + dev_err(wm8994->dev, "Failed to get IRQ: %d\n", + ret); + return ret; + } + + ret = request_threaded_irq(wm8994->irq, + NULL, wm8994_edge_irq, + irqflags, + "WM8994 edge", wm8994); + } else { + ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq, + irqflags, + wm8994->irq_base, &wm8994_irq_chip, + &wm8994->irq_data); + } + if (ret != 0) { dev_err(wm8994->dev, "Failed to register IRQ chip: %d\n", ret); return ret; diff --git a/drivers/mfd/wm8997-tables.c b/drivers/mfd/wm8997-tables.c new file mode 100644 index 0000000..5aa8076 --- /dev/null +++ b/drivers/mfd/wm8997-tables.c @@ -0,0 +1,1525 @@ +/* + * wm8997-tables.c -- WM8997 data tables + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.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/module.h> + +#include <linux/mfd/arizona/core.h> +#include <linux/mfd/arizona/registers.h> + +#include "arizona.h" + +static const struct reg_default wm8997_reva_patch[] = { + { 0x80, 0x0003 }, + { 0x214, 0x0008 }, + { 0x458, 0x0000 }, + { 0x0081, 0xE022 }, + { 0x294, 0x0000 }, + { 0x80, 0x0000 }, + { 0x171, 0x0000 }, +}; + +/* We use a function so we can use ARRAY_SIZE() */ +int wm8997_patch(struct arizona *arizona) +{ + switch (arizona->rev) { + case 0: + return regmap_register_patch(arizona->regmap, + wm8997_reva_patch, + ARRAY_SIZE(wm8997_reva_patch)); + default: + return 0; + } +} +EXPORT_SYMBOL_GPL(wm8997_patch); + +static const struct regmap_irq wm8997_aod_irqs[ARIZONA_NUM_IRQ] = { + [ARIZONA_IRQ_GP5_FALL] = { .mask = ARIZONA_GP5_FALL_EINT1 }, + [ARIZONA_IRQ_GP5_RISE] = { .mask = ARIZONA_GP5_RISE_EINT1 }, + [ARIZONA_IRQ_JD_FALL] = { .mask = ARIZONA_JD1_FALL_EINT1 }, + [ARIZONA_IRQ_JD_RISE] = { .mask = ARIZONA_JD1_RISE_EINT1 }, +}; + +const struct regmap_irq_chip wm8997_aod = { + .name = "wm8997 AOD", + .status_base = ARIZONA_AOD_IRQ1, + .mask_base = ARIZONA_AOD_IRQ_MASK_IRQ1, + .ack_base = ARIZONA_AOD_IRQ1, + .num_regs = 1, + .irqs = wm8997_aod_irqs, + .num_irqs = ARRAY_SIZE(wm8997_aod_irqs), +}; +EXPORT_SYMBOL_GPL(wm8997_aod); + +static const struct regmap_irq wm8997_irqs[ARIZONA_NUM_IRQ] = { + [ARIZONA_IRQ_GP4] = { .reg_offset = 0, .mask = ARIZONA_GP4_EINT1 }, + [ARIZONA_IRQ_GP3] = { .reg_offset = 0, .mask = ARIZONA_GP3_EINT1 }, + [ARIZONA_IRQ_GP2] = { .reg_offset = 0, .mask = ARIZONA_GP2_EINT1 }, + [ARIZONA_IRQ_GP1] = { .reg_offset = 0, .mask = ARIZONA_GP1_EINT1 }, + + [ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = { + .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1 + }, + [ARIZONA_IRQ_SPK_SHUTDOWN] = { + .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1 + }, + [ARIZONA_IRQ_HPDET] = { + .reg_offset = 2, .mask = ARIZONA_HPDET_EINT1 + }, + [ARIZONA_IRQ_MICDET] = { + .reg_offset = 2, .mask = ARIZONA_MICDET_EINT1 + }, + [ARIZONA_IRQ_WSEQ_DONE] = { + .reg_offset = 2, .mask = ARIZONA_WSEQ_DONE_EINT1 + }, + [ARIZONA_IRQ_DRC1_SIG_DET] = { + .reg_offset = 2, .mask = ARIZONA_DRC1_SIG_DET_EINT1 + }, + [ARIZONA_IRQ_UNDERCLOCKED] = { + .reg_offset = 2, .mask = ARIZONA_UNDERCLOCKED_EINT1 + }, + [ARIZONA_IRQ_OVERCLOCKED] = { + .reg_offset = 2, .mask = ARIZONA_OVERCLOCKED_EINT1 + }, + [ARIZONA_IRQ_FLL2_LOCK] = { + .reg_offset = 2, .mask = ARIZONA_FLL2_LOCK_EINT1 + }, + [ARIZONA_IRQ_FLL1_LOCK] = { + .reg_offset = 2, .mask = ARIZONA_FLL1_LOCK_EINT1 + }, + [ARIZONA_IRQ_CLKGEN_ERR] = { + .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_EINT1 + }, + [ARIZONA_IRQ_CLKGEN_ERR_ASYNC] = { + .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_ASYNC_EINT1 + }, + + [ARIZONA_IRQ_AIF2_ERR] = { + .reg_offset = 3, .mask = ARIZONA_AIF2_ERR_EINT1 + }, + [ARIZONA_IRQ_AIF1_ERR] = { + .reg_offset = 3, .mask = ARIZONA_AIF1_ERR_EINT1 + }, + [ARIZONA_IRQ_CTRLIF_ERR] = { + .reg_offset = 3, .mask = ARIZONA_CTRLIF_ERR_EINT1 + }, + [ARIZONA_IRQ_MIXER_DROPPED_SAMPLES] = { + .reg_offset = 3, .mask = ARIZONA_MIXER_DROPPED_SAMPLE_EINT1 + }, + [ARIZONA_IRQ_ASYNC_CLK_ENA_LOW] = { + .reg_offset = 3, .mask = ARIZONA_ASYNC_CLK_ENA_LOW_EINT1 + }, + [ARIZONA_IRQ_SYSCLK_ENA_LOW] = { + .reg_offset = 3, .mask = ARIZONA_SYSCLK_ENA_LOW_EINT1 + }, + [ARIZONA_IRQ_ISRC1_CFG_ERR] = { + .reg_offset = 3, .mask = ARIZONA_ISRC1_CFG_ERR_EINT1 + }, + [ARIZONA_IRQ_ISRC2_CFG_ERR] = { + .reg_offset = 3, .mask = ARIZONA_ISRC2_CFG_ERR_EINT1 + }, + + [ARIZONA_IRQ_BOOT_DONE] = { + .reg_offset = 4, .mask = ARIZONA_BOOT_DONE_EINT1 + }, + [ARIZONA_IRQ_DCS_DAC_DONE] = { + .reg_offset = 4, .mask = ARIZONA_DCS_DAC_DONE_EINT1 + }, + [ARIZONA_IRQ_DCS_HP_DONE] = { + .reg_offset = 4, .mask = ARIZONA_DCS_HP_DONE_EINT1 + }, + [ARIZONA_IRQ_FLL2_CLOCK_OK] = { + .reg_offset = 4, .mask = ARIZONA_FLL2_CLOCK_OK_EINT1 + }, + [ARIZONA_IRQ_FLL1_CLOCK_OK] = { + .reg_offset = 4, .mask = ARIZONA_FLL1_CLOCK_OK_EINT1 + }, +}; + +const struct regmap_irq_chip wm8997_irq = { + .name = "wm8997 IRQ", + .status_base = ARIZONA_INTERRUPT_STATUS_1, + .mask_base = ARIZONA_INTERRUPT_STATUS_1_MASK, + .ack_base = ARIZONA_INTERRUPT_STATUS_1, + .num_regs = 5, + .irqs = wm8997_irqs, + .num_irqs = ARRAY_SIZE(wm8997_irqs), +}; +EXPORT_SYMBOL_GPL(wm8997_irq); + +static const struct reg_default wm8997_reg_default[] = { + { 0x00000009, 0x0001 }, /* R9 - Ctrl IF I2C1 CFG 1 */ + { 0x00000016, 0x0000 }, /* R22 - Write Sequencer Ctrl 0 */ + { 0x00000017, 0x0000 }, /* R23 - Write Sequencer Ctrl 1 */ + { 0x00000018, 0x0000 }, /* R24 - Write Sequencer Ctrl 2 */ + { 0x00000020, 0x0000 }, /* R32 - Tone Generator 1 */ + { 0x00000021, 0x1000 }, /* R33 - Tone Generator 2 */ + { 0x00000022, 0x0000 }, /* R34 - Tone Generator 3 */ + { 0x00000023, 0x1000 }, /* R35 - Tone Generator 4 */ + { 0x00000024, 0x0000 }, /* R36 - Tone Generator 5 */ + { 0x00000030, 0x0000 }, /* R48 - PWM Drive 1 */ + { 0x00000031, 0x0100 }, /* R49 - PWM Drive 2 */ + { 0x00000032, 0x0100 }, /* R50 - PWM Drive 3 */ + { 0x00000040, 0x0000 }, /* R64 - Wake control */ + { 0x00000041, 0x0000 }, /* R65 - Sequence control */ + { 0x00000061, 0x01FF }, /* R97 - Sample Rate Sequence Select 1 */ + { 0x00000062, 0x01FF }, /* R98 - Sample Rate Sequence Select 2 */ + { 0x00000063, 0x01FF }, /* R99 - Sample Rate Sequence Select 3 */ + { 0x00000064, 0x01FF }, /* R100 - Sample Rate Sequence Select 4 */ + { 0x00000068, 0x01FF }, /* R104 - Always On Triggers Sequence Select 1 */ + { 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 2 */ + { 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 3 */ + { 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 4 */ + { 0x00000070, 0x0000 }, /* R112 - Comfort Noise Generator */ + { 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */ + { 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */ + { 0x00000092, 0x0000 }, /* R146 - Haptics phase 1 intensity */ + { 0x00000093, 0x0000 }, /* R147 - Haptics phase 1 duration */ + { 0x00000094, 0x0000 }, /* R148 - Haptics phase 2 intensity */ + { 0x00000095, 0x0000 }, /* R149 - Haptics phase 2 duration */ + { 0x00000096, 0x0000 }, /* R150 - Haptics phase 3 intensity */ + { 0x00000097, 0x0000 }, /* R151 - Haptics phase 3 duration */ + { 0x00000100, 0x0002 }, /* R256 - Clock 32k 1 */ + { 0x00000101, 0x0304 }, /* R257 - System Clock 1 */ + { 0x00000102, 0x0011 }, /* R258 - Sample rate 1 */ + { 0x00000103, 0x0011 }, /* R259 - Sample rate 2 */ + { 0x00000104, 0x0011 }, /* R260 - Sample rate 3 */ + { 0x00000112, 0x0305 }, /* R274 - Async clock 1 */ + { 0x00000113, 0x0011 }, /* R275 - Async sample rate 1 */ + { 0x00000149, 0x0000 }, /* R329 - Output system clock */ + { 0x0000014A, 0x0000 }, /* R330 - Output async clock */ + { 0x00000152, 0x0000 }, /* R338 - Rate Estimator 1 */ + { 0x00000153, 0x0000 }, /* R339 - Rate Estimator 2 */ + { 0x00000154, 0x0000 }, /* R340 - Rate Estimator 3 */ + { 0x00000155, 0x0000 }, /* R341 - Rate Estimator 4 */ + { 0x00000156, 0x0000 }, /* R342 - Rate Estimator 5 */ + { 0x00000161, 0x0000 }, /* R353 - Dynamic Frequency Scaling 1 */ + { 0x00000171, 0x0000 }, /* R369 - FLL1 Control 1 */ + { 0x00000172, 0x0008 }, /* R370 - FLL1 Control 2 */ + { 0x00000173, 0x0018 }, /* R371 - FLL1 Control 3 */ + { 0x00000174, 0x007D }, /* R372 - FLL1 Control 4 */ + { 0x00000175, 0x0004 }, /* R373 - FLL1 Control 5 */ + { 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */ + { 0x00000177, 0x0181 }, /* R375 - FLL1 Loop Filter Test 1 */ + { 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */ + { 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */ + { 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */ + { 0x00000184, 0x0000 }, /* R388 - FLL1 Synchroniser 4 */ + { 0x00000185, 0x0000 }, /* R389 - FLL1 Synchroniser 5 */ + { 0x00000186, 0x0000 }, /* R390 - FLL1 Synchroniser 6 */ + { 0x00000189, 0x0000 }, /* R393 - FLL1 Spread Spectrum */ + { 0x0000018A, 0x0004 }, /* R394 - FLL1 GPIO Clock */ + { 0x00000191, 0x0000 }, /* R401 - FLL2 Control 1 */ + { 0x00000192, 0x0008 }, /* R402 - FLL2 Control 2 */ + { 0x00000193, 0x0018 }, /* R403 - FLL2 Control 3 */ + { 0x00000194, 0x007D }, /* R404 - FLL2 Control 4 */ + { 0x00000195, 0x0004 }, /* R405 - FLL2 Control 5 */ + { 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */ + { 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */ + { 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */ + { 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */ + { 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */ + { 0x000001A4, 0x0000 }, /* R420 - FLL2 Synchroniser 4 */ + { 0x000001A5, 0x0000 }, /* R421 - FLL2 Synchroniser 5 */ + { 0x000001A6, 0x0000 }, /* R422 - FLL2 Synchroniser 6 */ + { 0x000001A9, 0x0000 }, /* R425 - FLL2 Spread Spectrum */ + { 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */ + { 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */ + { 0x00000210, 0x00D4 }, /* R528 - LDO1 Control 1 */ + { 0x00000212, 0x0000 }, /* R530 - LDO1 Control 2 */ + { 0x00000213, 0x0344 }, /* R531 - LDO2 Control 1 */ + { 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */ + { 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */ + { 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */ + { 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */ + { 0x0000029B, 0x0020 }, /* R667 - Headphone Detect 1 */ + { 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */ + { 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */ + { 0x000002A5, 0x0000 }, /* R677 - Mic Detect 3 */ + { 0x000002C3, 0x0000 }, /* R707 - Mic noise mix control 1 */ + { 0x000002CB, 0x0000 }, /* R715 - Isolation control */ + { 0x000002D3, 0x0000 }, /* R723 - Jack detect analogue */ + { 0x00000300, 0x0000 }, /* R768 - Input Enables */ + { 0x00000308, 0x0000 }, /* R776 - Input Rate */ + { 0x00000309, 0x0022 }, /* R777 - Input Volume Ramp */ + { 0x00000310, 0x2080 }, /* R784 - IN1L Control */ + { 0x00000311, 0x0180 }, /* R785 - ADC Digital Volume 1L */ + { 0x00000312, 0x0000 }, /* R786 - DMIC1L Control */ + { 0x00000314, 0x0080 }, /* R788 - IN1R Control */ + { 0x00000315, 0x0180 }, /* R789 - ADC Digital Volume 1R */ + { 0x00000316, 0x0000 }, /* R790 - DMIC1R Control */ + { 0x00000318, 0x2080 }, /* R792 - IN2L Control */ + { 0x00000319, 0x0180 }, /* R793 - ADC Digital Volume 2L */ + { 0x0000031A, 0x0000 }, /* R794 - DMIC2L Control */ + { 0x0000031C, 0x0080 }, /* R796 - IN2R Control */ + { 0x0000031D, 0x0180 }, /* R797 - ADC Digital Volume 2R */ + { 0x0000031E, 0x0000 }, /* R798 - DMIC2R Control */ + { 0x00000400, 0x0000 }, /* R1024 - Output Enables 1 */ + { 0x00000408, 0x0000 }, /* R1032 - Output Rate 1 */ + { 0x00000409, 0x0022 }, /* R1033 - Output Volume Ramp */ + { 0x00000410, 0x0080 }, /* R1040 - Output Path Config 1L */ + { 0x00000411, 0x0180 }, /* R1041 - DAC Digital Volume 1L */ + { 0x00000412, 0x0080 }, /* R1042 - DAC Volume Limit 1L */ + { 0x00000413, 0x0001 }, /* R1043 - Noise Gate Select 1L */ + { 0x00000414, 0x0080 }, /* R1044 - Output Path Config 1R */ + { 0x00000415, 0x0180 }, /* R1045 - DAC Digital Volume 1R */ + { 0x00000416, 0x0080 }, /* R1046 - DAC Volume Limit 1R */ + { 0x00000417, 0x0002 }, /* R1047 - Noise Gate Select 1R */ + { 0x00000420, 0x0080 }, /* R1056 - Output Path Config 3L */ + { 0x00000421, 0x0180 }, /* R1057 - DAC Digital Volume 3L */ + { 0x00000422, 0x0080 }, /* R1058 - DAC Volume Limit 3L */ + { 0x00000423, 0x0010 }, /* R1059 - Noise Gate Select 3L */ + { 0x00000428, 0x0000 }, /* R1064 - Output Path Config 4L */ + { 0x00000429, 0x0180 }, /* R1065 - DAC Digital Volume 4L */ + { 0x0000042A, 0x0080 }, /* R1066 - Out Volume 4L */ + { 0x0000042B, 0x0040 }, /* R1067 - Noise Gate Select 4L */ + { 0x00000430, 0x0000 }, /* R1072 - Output Path Config 5L */ + { 0x00000431, 0x0180 }, /* R1073 - DAC Digital Volume 5L */ + { 0x00000432, 0x0080 }, /* R1074 - DAC Volume Limit 5L */ + { 0x00000433, 0x0100 }, /* R1075 - Noise Gate Select 5L */ + { 0x00000435, 0x0180 }, /* R1077 - DAC Digital Volume 5R */ + { 0x00000436, 0x0080 }, /* R1078 - DAC Volume Limit 5R */ + { 0x00000437, 0x0200 }, /* R1079 - Noise Gate Select 5R */ + { 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */ + { 0x00000458, 0x0000 }, /* R1112 - Noise Gate Control */ + { 0x00000490, 0x0069 }, /* R1168 - PDM SPK1 CTRL 1 */ + { 0x00000491, 0x0000 }, /* R1169 - PDM SPK1 CTRL 2 */ + { 0x00000500, 0x000C }, /* R1280 - AIF1 BCLK Ctrl */ + { 0x00000501, 0x0008 }, /* R1281 - AIF1 Tx Pin Ctrl */ + { 0x00000502, 0x0000 }, /* R1282 - AIF1 Rx Pin Ctrl */ + { 0x00000503, 0x0000 }, /* R1283 - AIF1 Rate Ctrl */ + { 0x00000504, 0x0000 }, /* R1284 - AIF1 Format */ + { 0x00000505, 0x0040 }, /* R1285 - AIF1 Tx BCLK Rate */ + { 0x00000506, 0x0040 }, /* R1286 - AIF1 Rx BCLK Rate */ + { 0x00000507, 0x1818 }, /* R1287 - AIF1 Frame Ctrl 1 */ + { 0x00000508, 0x1818 }, /* R1288 - AIF1 Frame Ctrl 2 */ + { 0x00000509, 0x0000 }, /* R1289 - AIF1 Frame Ctrl 3 */ + { 0x0000050A, 0x0001 }, /* R1290 - AIF1 Frame Ctrl 4 */ + { 0x0000050B, 0x0002 }, /* R1291 - AIF1 Frame Ctrl 5 */ + { 0x0000050C, 0x0003 }, /* R1292 - AIF1 Frame Ctrl 6 */ + { 0x0000050D, 0x0004 }, /* R1293 - AIF1 Frame Ctrl 7 */ + { 0x0000050E, 0x0005 }, /* R1294 - AIF1 Frame Ctrl 8 */ + { 0x0000050F, 0x0006 }, /* R1295 - AIF1 Frame Ctrl 9 */ + { 0x00000510, 0x0007 }, /* R1296 - AIF1 Frame Ctrl 10 */ + { 0x00000511, 0x0000 }, /* R1297 - AIF1 Frame Ctrl 11 */ + { 0x00000512, 0x0001 }, /* R1298 - AIF1 Frame Ctrl 12 */ + { 0x00000513, 0x0002 }, /* R1299 - AIF1 Frame Ctrl 13 */ + { 0x00000514, 0x0003 }, /* R1300 - AIF1 Frame Ctrl 14 */ + { 0x00000515, 0x0004 }, /* R1301 - AIF1 Frame Ctrl 15 */ + { 0x00000516, 0x0005 }, /* R1302 - AIF1 Frame Ctrl 16 */ + { 0x00000517, 0x0006 }, /* R1303 - AIF1 Frame Ctrl 17 */ + { 0x00000518, 0x0007 }, /* R1304 - AIF1 Frame Ctrl 18 */ + { 0x00000519, 0x0000 }, /* R1305 - AIF1 Tx Enables */ + { 0x0000051A, 0x0000 }, /* R1306 - AIF1 Rx Enables */ + { 0x00000540, 0x000C }, /* R1344 - AIF2 BCLK Ctrl */ + { 0x00000541, 0x0008 }, /* R1345 - AIF2 Tx Pin Ctrl */ + { 0x00000542, 0x0000 }, /* R1346 - AIF2 Rx Pin Ctrl */ + { 0x00000543, 0x0000 }, /* R1347 - AIF2 Rate Ctrl */ + { 0x00000544, 0x0000 }, /* R1348 - AIF2 Format */ + { 0x00000545, 0x0040 }, /* R1349 - AIF2 Tx BCLK Rate */ + { 0x00000546, 0x0040 }, /* R1350 - AIF2 Rx BCLK Rate */ + { 0x00000547, 0x1818 }, /* R1351 - AIF2 Frame Ctrl 1 */ + { 0x00000548, 0x1818 }, /* R1352 - AIF2 Frame Ctrl 2 */ + { 0x00000549, 0x0000 }, /* R1353 - AIF2 Frame Ctrl 3 */ + { 0x0000054A, 0x0001 }, /* R1354 - AIF2 Frame Ctrl 4 */ + { 0x00000551, 0x0000 }, /* R1361 - AIF2 Frame Ctrl 11 */ + { 0x00000552, 0x0001 }, /* R1362 - AIF2 Frame Ctrl 12 */ + { 0x00000559, 0x0000 }, /* R1369 - AIF2 Tx Enables */ + { 0x0000055A, 0x0000 }, /* R1370 - AIF2 Rx Enables */ + { 0x000005E3, 0x0004 }, /* R1507 - SLIMbus Framer Ref Gear */ + { 0x000005E5, 0x0000 }, /* R1509 - SLIMbus Rates 1 */ + { 0x000005E6, 0x0000 }, /* R1510 - SLIMbus Rates 2 */ + { 0x000005E7, 0x0000 }, /* R1511 - SLIMbus Rates 3 */ + { 0x000005E8, 0x0000 }, /* R1512 - SLIMbus Rates 4 */ + { 0x000005E9, 0x0000 }, /* R1513 - SLIMbus Rates 5 */ + { 0x000005EA, 0x0000 }, /* R1514 - SLIMbus Rates 6 */ + { 0x000005EB, 0x0000 }, /* R1515 - SLIMbus Rates 7 */ + { 0x000005EC, 0x0000 }, /* R1516 - SLIMbus Rates 8 */ + { 0x000005F5, 0x0000 }, /* R1525 - SLIMbus RX Channel Enable */ + { 0x000005F6, 0x0000 }, /* R1526 - SLIMbus TX Channel Enable */ + { 0x00000640, 0x0000 }, /* R1600 - PWM1MIX Input 1 Source */ + { 0x00000641, 0x0080 }, /* R1601 - PWM1MIX Input 1 Volume */ + { 0x00000642, 0x0000 }, /* R1602 - PWM1MIX Input 2 Source */ + { 0x00000643, 0x0080 }, /* R1603 - PWM1MIX Input 2 Volume */ + { 0x00000644, 0x0000 }, /* R1604 - PWM1MIX Input 3 Source */ + { 0x00000645, 0x0080 }, /* R1605 - PWM1MIX Input 3 Volume */ + { 0x00000646, 0x0000 }, /* R1606 - PWM1MIX Input 4 Source */ + { 0x00000647, 0x0080 }, /* R1607 - PWM1MIX Input 4 Volume */ + { 0x00000648, 0x0000 }, /* R1608 - PWM2MIX Input 1 Source */ + { 0x00000649, 0x0080 }, /* R1609 - PWM2MIX Input 1 Volume */ + { 0x0000064A, 0x0000 }, /* R1610 - PWM2MIX Input 2 Source */ + { 0x0000064B, 0x0080 }, /* R1611 - PWM2MIX Input 2 Volume */ + { 0x0000064C, 0x0000 }, /* R1612 - PWM2MIX Input 3 Source */ + { 0x0000064D, 0x0080 }, /* R1613 - PWM2MIX Input 3 Volume */ + { 0x0000064E, 0x0000 }, /* R1614 - PWM2MIX Input 4 Source */ + { 0x0000064F, 0x0080 }, /* R1615 - PWM2MIX Input 4 Volume */ + { 0x00000660, 0x0000 }, /* R1632 - MICMIX Input 1 Source */ + { 0x00000661, 0x0080 }, /* R1633 - MICMIX Input 1 Volume */ + { 0x00000662, 0x0000 }, /* R1634 - MICMIX Input 2 Source */ + { 0x00000663, 0x0080 }, /* R1635 - MICMIX Input 2 Volume */ + { 0x00000664, 0x0000 }, /* R1636 - MICMIX Input 3 Source */ + { 0x00000665, 0x0080 }, /* R1637 - MICMIX Input 3 Volume */ + { 0x00000666, 0x0000 }, /* R1638 - MICMIX Input 4 Source */ + { 0x00000667, 0x0080 }, /* R1639 - MICMIX Input 4 Volume */ + { 0x00000668, 0x0000 }, /* R1640 - NOISEMIX Input 1 Source */ + { 0x00000669, 0x0080 }, /* R1641 - NOISEMIX Input 1 Volume */ + { 0x0000066A, 0x0000 }, /* R1642 - NOISEMIX Input 2 Source */ + { 0x0000066B, 0x0080 }, /* R1643 - NOISEMIX Input 2 Volume */ + { 0x0000066C, 0x0000 }, /* R1644 - NOISEMIX Input 3 Source */ + { 0x0000066D, 0x0080 }, /* R1645 - NOISEMIX Input 3 Volume */ + { 0x0000066E, 0x0000 }, /* R1646 - NOISEMIX Input 4 Source */ + { 0x0000066F, 0x0080 }, /* R1647 - NOISEMIX Input 4 Volume */ + { 0x00000680, 0x0000 }, /* R1664 - OUT1LMIX Input 1 Source */ + { 0x00000681, 0x0080 }, /* R1665 - OUT1LMIX Input 1 Volume */ + { 0x00000682, 0x0000 }, /* R1666 - OUT1LMIX Input 2 Source */ + { 0x00000683, 0x0080 }, /* R1667 - OUT1LMIX Input 2 Volume */ + { 0x00000684, 0x0000 }, /* R1668 - OUT1LMIX Input 3 Source */ + { 0x00000685, 0x0080 }, /* R1669 - OUT1LMIX Input 3 Volume */ + { 0x00000686, 0x0000 }, /* R1670 - OUT1LMIX Input 4 Source */ + { 0x00000687, 0x0080 }, /* R1671 - OUT1LMIX Input 4 Volume */ + { 0x00000688, 0x0000 }, /* R1672 - OUT1RMIX Input 1 Source */ + { 0x00000689, 0x0080 }, /* R1673 - OUT1RMIX Input 1 Volume */ + { 0x0000068A, 0x0000 }, /* R1674 - OUT1RMIX Input 2 Source */ + { 0x0000068B, 0x0080 }, /* R1675 - OUT1RMIX Input 2 Volume */ + { 0x0000068C, 0x0000 }, /* R1676 - OUT1RMIX Input 3 Source */ + { 0x0000068D, 0x0080 }, /* R1677 - OUT1RMIX Input 3 Volume */ + { 0x0000068E, 0x0000 }, /* R1678 - OUT1RMIX Input 4 Source */ + { 0x0000068F, 0x0080 }, /* R1679 - OUT1RMIX Input 4 Volume */ + { 0x000006A0, 0x0000 }, /* R1696 - OUT3LMIX Input 1 Source */ + { 0x000006A1, 0x0080 }, /* R1697 - OUT3LMIX Input 1 Volume */ + { 0x000006A2, 0x0000 }, /* R1698 - OUT3LMIX Input 2 Source */ + { 0x000006A3, 0x0080 }, /* R1699 - OUT3LMIX Input 2 Volume */ + { 0x000006A4, 0x0000 }, /* R1700 - OUT3LMIX Input 3 Source */ + { 0x000006A5, 0x0080 }, /* R1701 - OUT3LMIX Input 3 Volume */ + { 0x000006A6, 0x0000 }, /* R1702 - OUT3LMIX Input 4 Source */ + { 0x000006A7, 0x0080 }, /* R1703 - OUT3LMIX Input 4 Volume */ + { 0x000006B0, 0x0000 }, /* R1712 - OUT4LMIX Input 1 Source */ + { 0x000006B1, 0x0080 }, /* R1713 - OUT4LMIX Input 1 Volume */ + { 0x000006B2, 0x0000 }, /* R1714 - OUT4LMIX Input 2 Source */ + { 0x000006B3, 0x0080 }, /* R1715 - OUT4LMIX Input 2 Volume */ + { 0x000006B4, 0x0000 }, /* R1716 - OUT4LMIX Input 3 Source */ + { 0x000006B5, 0x0080 }, /* R1717 - OUT4LMIX Input 3 Volume */ + { 0x000006B6, 0x0000 }, /* R1718 - OUT4LMIX Input 4 Source */ + { 0x000006B7, 0x0080 }, /* R1719 - OUT4LMIX Input 4 Volume */ + { 0x000006C0, 0x0000 }, /* R1728 - OUT5LMIX Input 1 Source */ + { 0x000006C1, 0x0080 }, /* R1729 - OUT5LMIX Input 1 Volume */ + { 0x000006C2, 0x0000 }, /* R1730 - OUT5LMIX Input 2 Source */ + { 0x000006C3, 0x0080 }, /* R1731 - OUT5LMIX Input 2 Volume */ + { 0x000006C4, 0x0000 }, /* R1732 - OUT5LMIX Input 3 Source */ + { 0x000006C5, 0x0080 }, /* R1733 - OUT5LMIX Input 3 Volume */ + { 0x000006C6, 0x0000 }, /* R1734 - OUT5LMIX Input 4 Source */ + { 0x000006C7, 0x0080 }, /* R1735 - OUT5LMIX Input 4 Volume */ + { 0x000006C8, 0x0000 }, /* R1736 - OUT5RMIX Input 1 Source */ + { 0x000006C9, 0x0080 }, /* R1737 - OUT5RMIX Input 1 Volume */ + { 0x000006CA, 0x0000 }, /* R1738 - OUT5RMIX Input 2 Source */ + { 0x000006CB, 0x0080 }, /* R1739 - OUT5RMIX Input 2 Volume */ + { 0x000006CC, 0x0000 }, /* R1740 - OUT5RMIX Input 3 Source */ + { 0x000006CD, 0x0080 }, /* R1741 - OUT5RMIX Input 3 Volume */ + { 0x000006CE, 0x0000 }, /* R1742 - OUT5RMIX Input 4 Source */ + { 0x000006CF, 0x0080 }, /* R1743 - OUT5RMIX Input 4 Volume */ + { 0x00000700, 0x0000 }, /* R1792 - AIF1TX1MIX Input 1 Source */ + { 0x00000701, 0x0080 }, /* R1793 - AIF1TX1MIX Input 1 Volume */ + { 0x00000702, 0x0000 }, /* R1794 - AIF1TX1MIX Input 2 Source */ + { 0x00000703, 0x0080 }, /* R1795 - AIF1TX1MIX Input 2 Volume */ + { 0x00000704, 0x0000 }, /* R1796 - AIF1TX1MIX Input 3 Source */ + { 0x00000705, 0x0080 }, /* R1797 - AIF1TX1MIX Input 3 Volume */ + { 0x00000706, 0x0000 }, /* R1798 - AIF1TX1MIX Input 4 Source */ + { 0x00000707, 0x0080 }, /* R1799 - AIF1TX1MIX Input 4 Volume */ + { 0x00000708, 0x0000 }, /* R1800 - AIF1TX2MIX Input 1 Source */ + { 0x00000709, 0x0080 }, /* R1801 - AIF1TX2MIX Input 1 Volume */ + { 0x0000070A, 0x0000 }, /* R1802 - AIF1TX2MIX Input 2 Source */ + { 0x0000070B, 0x0080 }, /* R1803 - AIF1TX2MIX Input 2 Volume */ + { 0x0000070C, 0x0000 }, /* R1804 - AIF1TX2MIX Input 3 Source */ + { 0x0000070D, 0x0080 }, /* R1805 - AIF1TX2MIX Input 3 Volume */ + { 0x0000070E, 0x0000 }, /* R1806 - AIF1TX2MIX Input 4 Source */ + { 0x0000070F, 0x0080 }, /* R1807 - AIF1TX2MIX Input 4 Volume */ + { 0x00000710, 0x0000 }, /* R1808 - AIF1TX3MIX Input 1 Source */ + { 0x00000711, 0x0080 }, /* R1809 - AIF1TX3MIX Input 1 Volume */ + { 0x00000712, 0x0000 }, /* R1810 - AIF1TX3MIX Input 2 Source */ + { 0x00000713, 0x0080 }, /* R1811 - AIF1TX3MIX Input 2 Volume */ + { 0x00000714, 0x0000 }, /* R1812 - AIF1TX3MIX Input 3 Source */ + { 0x00000715, 0x0080 }, /* R1813 - AIF1TX3MIX Input 3 Volume */ + { 0x00000716, 0x0000 }, /* R1814 - AIF1TX3MIX Input 4 Source */ + { 0x00000717, 0x0080 }, /* R1815 - AIF1TX3MIX Input 4 Volume */ + { 0x00000718, 0x0000 }, /* R1816 - AIF1TX4MIX Input 1 Source */ + { 0x00000719, 0x0080 }, /* R1817 - AIF1TX4MIX Input 1 Volume */ + { 0x0000071A, 0x0000 }, /* R1818 - AIF1TX4MIX Input 2 Source */ + { 0x0000071B, 0x0080 }, /* R1819 - AIF1TX4MIX Input 2 Volume */ + { 0x0000071C, 0x0000 }, /* R1820 - AIF1TX4MIX Input 3 Source */ + { 0x0000071D, 0x0080 }, /* R1821 - AIF1TX4MIX Input 3 Volume */ + { 0x0000071E, 0x0000 }, /* R1822 - AIF1TX4MIX Input 4 Source */ + { 0x0000071F, 0x0080 }, /* R1823 - AIF1TX4MIX Input 4 Volume */ + { 0x00000720, 0x0000 }, /* R1824 - AIF1TX5MIX Input 1 Source */ + { 0x00000721, 0x0080 }, /* R1825 - AIF1TX5MIX Input 1 Volume */ + { 0x00000722, 0x0000 }, /* R1826 - AIF1TX5MIX Input 2 Source */ + { 0x00000723, 0x0080 }, /* R1827 - AIF1TX5MIX Input 2 Volume */ + { 0x00000724, 0x0000 }, /* R1828 - AIF1TX5MIX Input 3 Source */ + { 0x00000725, 0x0080 }, /* R1829 - AIF1TX5MIX Input 3 Volume */ + { 0x00000726, 0x0000 }, /* R1830 - AIF1TX5MIX Input 4 Source */ + { 0x00000727, 0x0080 }, /* R1831 - AIF1TX5MIX Input 4 Volume */ + { 0x00000728, 0x0000 }, /* R1832 - AIF1TX6MIX Input 1 Source */ + { 0x00000729, 0x0080 }, /* R1833 - AIF1TX6MIX Input 1 Volume */ + { 0x0000072A, 0x0000 }, /* R1834 - AIF1TX6MIX Input 2 Source */ + { 0x0000072B, 0x0080 }, /* R1835 - AIF1TX6MIX Input 2 Volume */ + { 0x0000072C, 0x0000 }, /* R1836 - AIF1TX6MIX Input 3 Source */ + { 0x0000072D, 0x0080 }, /* R1837 - AIF1TX6MIX Input 3 Volume */ + { 0x0000072E, 0x0000 }, /* R1838 - AIF1TX6MIX Input 4 Source */ + { 0x0000072F, 0x0080 }, /* R1839 - AIF1TX6MIX Input 4 Volume */ + { 0x00000730, 0x0000 }, /* R1840 - AIF1TX7MIX Input 1 Source */ + { 0x00000731, 0x0080 }, /* R1841 - AIF1TX7MIX Input 1 Volume */ + { 0x00000732, 0x0000 }, /* R1842 - AIF1TX7MIX Input 2 Source */ + { 0x00000733, 0x0080 }, /* R1843 - AIF1TX7MIX Input 2 Volume */ + { 0x00000734, 0x0000 }, /* R1844 - AIF1TX7MIX Input 3 Source */ + { 0x00000735, 0x0080 }, /* R1845 - AIF1TX7MIX Input 3 Volume */ + { 0x00000736, 0x0000 }, /* R1846 - AIF1TX7MIX Input 4 Source */ + { 0x00000737, 0x0080 }, /* R1847 - AIF1TX7MIX Input 4 Volume */ + { 0x00000738, 0x0000 }, /* R1848 - AIF1TX8MIX Input 1 Source */ + { 0x00000739, 0x0080 }, /* R1849 - AIF1TX8MIX Input 1 Volume */ + { 0x0000073A, 0x0000 }, /* R1850 - AIF1TX8MIX Input 2 Source */ + { 0x0000073B, 0x0080 }, /* R1851 - AIF1TX8MIX Input 2 Volume */ + { 0x0000073C, 0x0000 }, /* R1852 - AIF1TX8MIX Input 3 Source */ + { 0x0000073D, 0x0080 }, /* R1853 - AIF1TX8MIX Input 3 Volume */ + { 0x0000073E, 0x0000 }, /* R1854 - AIF1TX8MIX Input 4 Source */ + { 0x0000073F, 0x0080 }, /* R1855 - AIF1TX8MIX Input 4 Volume */ + { 0x00000740, 0x0000 }, /* R1856 - AIF2TX1MIX Input 1 Source */ + { 0x00000741, 0x0080 }, /* R1857 - AIF2TX1MIX Input 1 Volume */ + { 0x00000742, 0x0000 }, /* R1858 - AIF2TX1MIX Input 2 Source */ + { 0x00000743, 0x0080 }, /* R1859 - AIF2TX1MIX Input 2 Volume */ + { 0x00000744, 0x0000 }, /* R1860 - AIF2TX1MIX Input 3 Source */ + { 0x00000745, 0x0080 }, /* R1861 - AIF2TX1MIX Input 3 Volume */ + { 0x00000746, 0x0000 }, /* R1862 - AIF2TX1MIX Input 4 Source */ + { 0x00000747, 0x0080 }, /* R1863 - AIF2TX1MIX Input 4 Volume */ + { 0x00000748, 0x0000 }, /* R1864 - AIF2TX2MIX Input 1 Source */ + { 0x00000749, 0x0080 }, /* R1865 - AIF2TX2MIX Input 1 Volume */ + { 0x0000074A, 0x0000 }, /* R1866 - AIF2TX2MIX Input 2 Source */ + { 0x0000074B, 0x0080 }, /* R1867 - AIF2TX2MIX Input 2 Volume */ + { 0x0000074C, 0x0000 }, /* R1868 - AIF2TX2MIX Input 3 Source */ + { 0x0000074D, 0x0080 }, /* R1869 - AIF2TX2MIX Input 3 Volume */ + { 0x0000074E, 0x0000 }, /* R1870 - AIF2TX2MIX Input 4 Source */ + { 0x0000074F, 0x0080 }, /* R1871 - AIF2TX2MIX Input 4 Volume */ + { 0x000007C0, 0x0000 }, /* R1984 - SLIMTX1MIX Input 1 Source */ + { 0x000007C1, 0x0080 }, /* R1985 - SLIMTX1MIX Input 1 Volume */ + { 0x000007C2, 0x0000 }, /* R1986 - SLIMTX1MIX Input 2 Source */ + { 0x000007C3, 0x0080 }, /* R1987 - SLIMTX1MIX Input 2 Volume */ + { 0x000007C4, 0x0000 }, /* R1988 - SLIMTX1MIX Input 3 Source */ + { 0x000007C5, 0x0080 }, /* R1989 - SLIMTX1MIX Input 3 Volume */ + { 0x000007C6, 0x0000 }, /* R1990 - SLIMTX1MIX Input 4 Source */ + { 0x000007C7, 0x0080 }, /* R1991 - SLIMTX1MIX Input 4 Volume */ + { 0x000007C8, 0x0000 }, /* R1992 - SLIMTX2MIX Input 1 Source */ + { 0x000007C9, 0x0080 }, /* R1993 - SLIMTX2MIX Input 1 Volume */ + { 0x000007CA, 0x0000 }, /* R1994 - SLIMTX2MIX Input 2 Source */ + { 0x000007CB, 0x0080 }, /* R1995 - SLIMTX2MIX Input 2 Volume */ + { 0x000007CC, 0x0000 }, /* R1996 - SLIMTX2MIX Input 3 Source */ + { 0x000007CD, 0x0080 }, /* R1997 - SLIMTX2MIX Input 3 Volume */ + { 0x000007CE, 0x0000 }, /* R1998 - SLIMTX2MIX Input 4 Source */ + { 0x000007CF, 0x0080 }, /* R1999 - SLIMTX2MIX Input 4 Volume */ + { 0x000007D0, 0x0000 }, /* R2000 - SLIMTX3MIX Input 1 Source */ + { 0x000007D1, 0x0080 }, /* R2001 - SLIMTX3MIX Input 1 Volume */ + { 0x000007D2, 0x0000 }, /* R2002 - SLIMTX3MIX Input 2 Source */ + { 0x000007D3, 0x0080 }, /* R2003 - SLIMTX3MIX Input 2 Volume */ + { 0x000007D4, 0x0000 }, /* R2004 - SLIMTX3MIX Input 3 Source */ + { 0x000007D5, 0x0080 }, /* R2005 - SLIMTX3MIX Input 3 Volume */ + { 0x000007D6, 0x0000 }, /* R2006 - SLIMTX3MIX Input 4 Source */ + { 0x000007D7, 0x0080 }, /* R2007 - SLIMTX3MIX Input 4 Volume */ + { 0x000007D8, 0x0000 }, /* R2008 - SLIMTX4MIX Input 1 Source */ + { 0x000007D9, 0x0080 }, /* R2009 - SLIMTX4MIX Input 1 Volume */ + { 0x000007DA, 0x0000 }, /* R2010 - SLIMTX4MIX Input 2 Source */ + { 0x000007DB, 0x0080 }, /* R2011 - SLIMTX4MIX Input 2 Volume */ + { 0x000007DC, 0x0000 }, /* R2012 - SLIMTX4MIX Input 3 Source */ + { 0x000007DD, 0x0080 }, /* R2013 - SLIMTX4MIX Input 3 Volume */ + { 0x000007DE, 0x0000 }, /* R2014 - SLIMTX4MIX Input 4 Source */ + { 0x000007DF, 0x0080 }, /* R2015 - SLIMTX4MIX Input 4 Volume */ + { 0x000007E0, 0x0000 }, /* R2016 - SLIMTX5MIX Input 1 Source */ + { 0x000007E1, 0x0080 }, /* R2017 - SLIMTX5MIX Input 1 Volume */ + { 0x000007E2, 0x0000 }, /* R2018 - SLIMTX5MIX Input 2 Source */ + { 0x000007E3, 0x0080 }, /* R2019 - SLIMTX5MIX Input 2 Volume */ + { 0x000007E4, 0x0000 }, /* R2020 - SLIMTX5MIX Input 3 Source */ + { 0x000007E5, 0x0080 }, /* R2021 - SLIMTX5MIX Input 3 Volume */ + { 0x000007E6, 0x0000 }, /* R2022 - SLIMTX5MIX Input 4 Source */ + { 0x000007E7, 0x0080 }, /* R2023 - SLIMTX5MIX Input 4 Volume */ + { 0x000007E8, 0x0000 }, /* R2024 - SLIMTX6MIX Input 1 Source */ + { 0x000007E9, 0x0080 }, /* R2025 - SLIMTX6MIX Input 1 Volume */ + { 0x000007EA, 0x0000 }, /* R2026 - SLIMTX6MIX Input 2 Source */ + { 0x000007EB, 0x0080 }, /* R2027 - SLIMTX6MIX Input 2 Volume */ + { 0x000007EC, 0x0000 }, /* R2028 - SLIMTX6MIX Input 3 Source */ + { 0x000007ED, 0x0080 }, /* R2029 - SLIMTX6MIX Input 3 Volume */ + { 0x000007EE, 0x0000 }, /* R2030 - SLIMTX6MIX Input 4 Source */ + { 0x000007EF, 0x0080 }, /* R2031 - SLIMTX6MIX Input 4 Volume */ + { 0x000007F0, 0x0000 }, /* R2032 - SLIMTX7MIX Input 1 Source */ + { 0x000007F1, 0x0080 }, /* R2033 - SLIMTX7MIX Input 1 Volume */ + { 0x000007F2, 0x0000 }, /* R2034 - SLIMTX7MIX Input 2 Source */ + { 0x000007F3, 0x0080 }, /* R2035 - SLIMTX7MIX Input 2 Volume */ + { 0x000007F4, 0x0000 }, /* R2036 - SLIMTX7MIX Input 3 Source */ + { 0x000007F5, 0x0080 }, /* R2037 - SLIMTX7MIX Input 3 Volume */ + { 0x000007F6, 0x0000 }, /* R2038 - SLIMTX7MIX Input 4 Source */ + { 0x000007F7, 0x0080 }, /* R2039 - SLIMTX7MIX Input 4 Volume */ + { 0x000007F8, 0x0000 }, /* R2040 - SLIMTX8MIX Input 1 Source */ + { 0x000007F9, 0x0080 }, /* R2041 - SLIMTX8MIX Input 1 Volume */ + { 0x000007FA, 0x0000 }, /* R2042 - SLIMTX8MIX Input 2 Source */ + { 0x000007FB, 0x0080 }, /* R2043 - SLIMTX8MIX Input 2 Volume */ + { 0x000007FC, 0x0000 }, /* R2044 - SLIMTX8MIX Input 3 Source */ + { 0x000007FD, 0x0080 }, /* R2045 - SLIMTX8MIX Input 3 Volume */ + { 0x000007FE, 0x0000 }, /* R2046 - SLIMTX8MIX Input 4 Source */ + { 0x000007FF, 0x0080 }, /* R2047 - SLIMTX8MIX Input 4 Volume */ + { 0x00000880, 0x0000 }, /* R2176 - EQ1MIX Input 1 Source */ + { 0x00000881, 0x0080 }, /* R2177 - EQ1MIX Input 1 Volume */ + { 0x00000882, 0x0000 }, /* R2178 - EQ1MIX Input 2 Source */ + { 0x00000883, 0x0080 }, /* R2179 - EQ1MIX Input 2 Volume */ + { 0x00000884, 0x0000 }, /* R2180 - EQ1MIX Input 3 Source */ + { 0x00000885, 0x0080 }, /* R2181 - EQ1MIX Input 3 Volume */ + { 0x00000886, 0x0000 }, /* R2182 - EQ1MIX Input 4 Source */ + { 0x00000887, 0x0080 }, /* R2183 - EQ1MIX Input 4 Volume */ + { 0x00000888, 0x0000 }, /* R2184 - EQ2MIX Input 1 Source */ + { 0x00000889, 0x0080 }, /* R2185 - EQ2MIX Input 1 Volume */ + { 0x0000088A, 0x0000 }, /* R2186 - EQ2MIX Input 2 Source */ + { 0x0000088B, 0x0080 }, /* R2187 - EQ2MIX Input 2 Volume */ + { 0x0000088C, 0x0000 }, /* R2188 - EQ2MIX Input 3 Source */ + { 0x0000088D, 0x0080 }, /* R2189 - EQ2MIX Input 3 Volume */ + { 0x0000088E, 0x0000 }, /* R2190 - EQ2MIX Input 4 Source */ + { 0x0000088F, 0x0080 }, /* R2191 - EQ2MIX Input 4 Volume */ + { 0x00000890, 0x0000 }, /* R2192 - EQ3MIX Input 1 Source */ + { 0x00000891, 0x0080 }, /* R2193 - EQ3MIX Input 1 Volume */ + { 0x00000892, 0x0000 }, /* R2194 - EQ3MIX Input 2 Source */ + { 0x00000893, 0x0080 }, /* R2195 - EQ3MIX Input 2 Volume */ + { 0x00000894, 0x0000 }, /* R2196 - EQ3MIX Input 3 Source */ + { 0x00000895, 0x0080 }, /* R2197 - EQ3MIX Input 3 Volume */ + { 0x00000896, 0x0000 }, /* R2198 - EQ3MIX Input 4 Source */ + { 0x00000897, 0x0080 }, /* R2199 - EQ3MIX Input 4 Volume */ + { 0x00000898, 0x0000 }, /* R2200 - EQ4MIX Input 1 Source */ + { 0x00000899, 0x0080 }, /* R2201 - EQ4MIX Input 1 Volume */ + { 0x0000089A, 0x0000 }, /* R2202 - EQ4MIX Input 2 Source */ + { 0x0000089B, 0x0080 }, /* R2203 - EQ4MIX Input 2 Volume */ + { 0x0000089C, 0x0000 }, /* R2204 - EQ4MIX Input 3 Source */ + { 0x0000089D, 0x0080 }, /* R2205 - EQ4MIX Input 3 Volume */ + { 0x0000089E, 0x0000 }, /* R2206 - EQ4MIX Input 4 Source */ + { 0x0000089F, 0x0080 }, /* R2207 - EQ4MIX Input 4 Volume */ + { 0x000008C0, 0x0000 }, /* R2240 - DRC1LMIX Input 1 Source */ + { 0x000008C1, 0x0080 }, /* R2241 - DRC1LMIX Input 1 Volume */ + { 0x000008C2, 0x0000 }, /* R2242 - DRC1LMIX Input 2 Source */ + { 0x000008C3, 0x0080 }, /* R2243 - DRC1LMIX Input 2 Volume */ + { 0x000008C4, 0x0000 }, /* R2244 - DRC1LMIX Input 3 Source */ + { 0x000008C5, 0x0080 }, /* R2245 - DRC1LMIX Input 3 Volume */ + { 0x000008C6, 0x0000 }, /* R2246 - DRC1LMIX Input 4 Source */ + { 0x000008C7, 0x0080 }, /* R2247 - DRC1LMIX Input 4 Volume */ + { 0x000008C8, 0x0000 }, /* R2248 - DRC1RMIX Input 1 Source */ + { 0x000008C9, 0x0080 }, /* R2249 - DRC1RMIX Input 1 Volume */ + { 0x000008CA, 0x0000 }, /* R2250 - DRC1RMIX Input 2 Source */ + { 0x000008CB, 0x0080 }, /* R2251 - DRC1RMIX Input 2 Volume */ + { 0x000008CC, 0x0000 }, /* R2252 - DRC1RMIX Input 3 Source */ + { 0x000008CD, 0x0080 }, /* R2253 - DRC1RMIX Input 3 Volume */ + { 0x000008CE, 0x0000 }, /* R2254 - DRC1RMIX Input 4 Source */ + { 0x000008CF, 0x0080 }, /* R2255 - DRC1RMIX Input 4 Volume */ + { 0x00000900, 0x0000 }, /* R2304 - HPLP1MIX Input 1 Source */ + { 0x00000901, 0x0080 }, /* R2305 - HPLP1MIX Input 1 Volume */ + { 0x00000902, 0x0000 }, /* R2306 - HPLP1MIX Input 2 Source */ + { 0x00000903, 0x0080 }, /* R2307 - HPLP1MIX Input 2 Volume */ + { 0x00000904, 0x0000 }, /* R2308 - HPLP1MIX Input 3 Source */ + { 0x00000905, 0x0080 }, /* R2309 - HPLP1MIX Input 3 Volume */ + { 0x00000906, 0x0000 }, /* R2310 - HPLP1MIX Input 4 Source */ + { 0x00000907, 0x0080 }, /* R2311 - HPLP1MIX Input 4 Volume */ + { 0x00000908, 0x0000 }, /* R2312 - HPLP2MIX Input 1 Source */ + { 0x00000909, 0x0080 }, /* R2313 - HPLP2MIX Input 1 Volume */ + { 0x0000090A, 0x0000 }, /* R2314 - HPLP2MIX Input 2 Source */ + { 0x0000090B, 0x0080 }, /* R2315 - HPLP2MIX Input 2 Volume */ + { 0x0000090C, 0x0000 }, /* R2316 - HPLP2MIX Input 3 Source */ + { 0x0000090D, 0x0080 }, /* R2317 - HPLP2MIX Input 3 Volume */ + { 0x0000090E, 0x0000 }, /* R2318 - HPLP2MIX Input 4 Source */ + { 0x0000090F, 0x0080 }, /* R2319 - HPLP2MIX Input 4 Volume */ + { 0x00000910, 0x0000 }, /* R2320 - HPLP3MIX Input 1 Source */ + { 0x00000911, 0x0080 }, /* R2321 - HPLP3MIX Input 1 Volume */ + { 0x00000912, 0x0000 }, /* R2322 - HPLP3MIX Input 2 Source */ + { 0x00000913, 0x0080 }, /* R2323 - HPLP3MIX Input 2 Volume */ + { 0x00000914, 0x0000 }, /* R2324 - HPLP3MIX Input 3 Source */ + { 0x00000915, 0x0080 }, /* R2325 - HPLP3MIX Input 3 Volume */ + { 0x00000916, 0x0000 }, /* R2326 - HPLP3MIX Input 4 Source */ + { 0x00000917, 0x0080 }, /* R2327 - HPLP3MIX Input 4 Volume */ + { 0x00000918, 0x0000 }, /* R2328 - HPLP4MIX Input 1 Source */ + { 0x00000919, 0x0080 }, /* R2329 - HPLP4MIX Input 1 Volume */ + { 0x0000091A, 0x0000 }, /* R2330 - HPLP4MIX Input 2 Source */ + { 0x0000091B, 0x0080 }, /* R2331 - HPLP4MIX Input 2 Volume */ + { 0x0000091C, 0x0000 }, /* R2332 - HPLP4MIX Input 3 Source */ + { 0x0000091D, 0x0080 }, /* R2333 - HPLP4MIX Input 3 Volume */ + { 0x0000091E, 0x0000 }, /* R2334 - HPLP4MIX Input 4 Source */ + { 0x0000091F, 0x0080 }, /* R2335 - HPLP4MIX Input 4 Volume */ + { 0x00000B00, 0x0000 }, /* R2816 - ISRC1DEC1MIX Input 1 Source */ + { 0x00000B08, 0x0000 }, /* R2824 - ISRC1DEC2MIX Input 1 Source */ + { 0x00000B20, 0x0000 }, /* R2848 - ISRC1INT1MIX Input 1 Source */ + { 0x00000B28, 0x0000 }, /* R2856 - ISRC1INT2MIX Input 1 Source */ + { 0x00000B40, 0x0000 }, /* R2880 - ISRC2DEC1MIX Input 1 Source */ + { 0x00000B48, 0x0000 }, /* R2888 - ISRC2DEC2MIX Input 1 Source */ + { 0x00000B60, 0x0000 }, /* R2912 - ISRC2INT1MIX Input 1 Source */ + { 0x00000B68, 0x0000 }, /* R2920 - ISRC2INT2MIX Input 1 Source */ + { 0x00000C00, 0xA101 }, /* R3072 - GPIO1 CTRL */ + { 0x00000C01, 0xA101 }, /* R3073 - GPIO2 CTRL */ + { 0x00000C02, 0xA101 }, /* R3074 - GPIO3 CTRL */ + { 0x00000C03, 0xA101 }, /* R3075 - GPIO4 CTRL */ + { 0x00000C04, 0xA101 }, /* R3076 - GPIO5 CTRL */ + { 0x00000C0F, 0x0400 }, /* R3087 - IRQ CTRL 1 */ + { 0x00000C10, 0x1000 }, /* R3088 - GPIO Debounce Config */ + { 0x00000C20, 0x8002 }, /* R3104 - Misc Pad Ctrl 1 */ + { 0x00000C21, 0x0001 }, /* R3105 - Misc Pad Ctrl 2 */ + { 0x00000C22, 0x0000 }, /* R3106 - Misc Pad Ctrl 3 */ + { 0x00000C23, 0x0000 }, /* R3107 - Misc Pad Ctrl 4 */ + { 0x00000C24, 0x0000 }, /* R3108 - Misc Pad Ctrl 5 */ + { 0x00000D08, 0xFFFF }, /* R3336 - Interrupt Status 1 Mask */ + { 0x00000D0A, 0xFFFF }, /* R3338 - Interrupt Status 3 Mask */ + { 0x00000D0B, 0xFFFF }, /* R3339 - Interrupt Status 4 Mask */ + { 0x00000D0C, 0xFEFF }, /* R3340 - Interrupt Status 5 Mask */ + { 0x00000D0F, 0x0000 }, /* R3343 - Interrupt Control */ + { 0x00000D18, 0xFFFF }, /* R3352 - IRQ2 Status 1 Mask */ + { 0x00000D1A, 0xFFFF }, /* R3354 - IRQ2 Status 3 Mask */ + { 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */ + { 0x00000D1C, 0xFFFF }, /* R3356 - IRQ2 Status 5 Mask */ + { 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */ + { 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */ + { 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */ + { 0x00000D56, 0x0000 }, /* R3414 - Jack detect debounce */ + { 0x00000E00, 0x0000 }, /* R3584 - FX_Ctrl1 */ + { 0x00000E01, 0x0000 }, /* R3585 - FX_Ctrl2 */ + { 0x00000E10, 0x6318 }, /* R3600 - EQ1_1 */ + { 0x00000E11, 0x6300 }, /* R3601 - EQ1_2 */ + { 0x00000E12, 0x0FC8 }, /* R3602 - EQ1_3 */ + { 0x00000E13, 0x03FE }, /* R3603 - EQ1_4 */ + { 0x00000E14, 0x00E0 }, /* R3604 - EQ1_5 */ + { 0x00000E15, 0x1EC4 }, /* R3605 - EQ1_6 */ + { 0x00000E16, 0xF136 }, /* R3606 - EQ1_7 */ + { 0x00000E17, 0x0409 }, /* R3607 - EQ1_8 */ + { 0x00000E18, 0x04CC }, /* R3608 - EQ1_9 */ + { 0x00000E19, 0x1C9B }, /* R3609 - EQ1_10 */ + { 0x00000E1A, 0xF337 }, /* R3610 - EQ1_11 */ + { 0x00000E1B, 0x040B }, /* R3611 - EQ1_12 */ + { 0x00000E1C, 0x0CBB }, /* R3612 - EQ1_13 */ + { 0x00000E1D, 0x16F8 }, /* R3613 - EQ1_14 */ + { 0x00000E1E, 0xF7D9 }, /* R3614 - EQ1_15 */ + { 0x00000E1F, 0x040A }, /* R3615 - EQ1_16 */ + { 0x00000E20, 0x1F14 }, /* R3616 - EQ1_17 */ + { 0x00000E21, 0x058C }, /* R3617 - EQ1_18 */ + { 0x00000E22, 0x0563 }, /* R3618 - EQ1_19 */ + { 0x00000E23, 0x4000 }, /* R3619 - EQ1_20 */ + { 0x00000E24, 0x0B75 }, /* R3620 - EQ1_21 */ + { 0x00000E26, 0x6318 }, /* R3622 - EQ2_1 */ + { 0x00000E27, 0x6300 }, /* R3623 - EQ2_2 */ + { 0x00000E28, 0x0FC8 }, /* R3624 - EQ2_3 */ + { 0x00000E29, 0x03FE }, /* R3625 - EQ2_4 */ + { 0x00000E2A, 0x00E0 }, /* R3626 - EQ2_5 */ + { 0x00000E2B, 0x1EC4 }, /* R3627 - EQ2_6 */ + { 0x00000E2C, 0xF136 }, /* R3628 - EQ2_7 */ + { 0x00000E2D, 0x0409 }, /* R3629 - EQ2_8 */ + { 0x00000E2E, 0x04CC }, /* R3630 - EQ2_9 */ + { 0x00000E2F, 0x1C9B }, /* R3631 - EQ2_10 */ + { 0x00000E30, 0xF337 }, /* R3632 - EQ2_11 */ + { 0x00000E31, 0x040B }, /* R3633 - EQ2_12 */ + { 0x00000E32, 0x0CBB }, /* R3634 - EQ2_13 */ + { 0x00000E33, 0x16F8 }, /* R3635 - EQ2_14 */ + { 0x00000E34, 0xF7D9 }, /* R3636 - EQ2_15 */ + { 0x00000E35, 0x040A }, /* R3637 - EQ2_16 */ + { 0x00000E36, 0x1F14 }, /* R3638 - EQ2_17 */ + { 0x00000E37, 0x058C }, /* R3639 - EQ2_18 */ + { 0x00000E38, 0x0563 }, /* R3640 - EQ2_19 */ + { 0x00000E39, 0x4000 }, /* R3641 - EQ2_20 */ + { 0x00000E3A, 0x0B75 }, /* R3642 - EQ2_21 */ + { 0x00000E3C, 0x6318 }, /* R3644 - EQ3_1 */ + { 0x00000E3D, 0x6300 }, /* R3645 - EQ3_2 */ + { 0x00000E3E, 0x0FC8 }, /* R3646 - EQ3_3 */ + { 0x00000E3F, 0x03FE }, /* R3647 - EQ3_4 */ + { 0x00000E40, 0x00E0 }, /* R3648 - EQ3_5 */ + { 0x00000E41, 0x1EC4 }, /* R3649 - EQ3_6 */ + { 0x00000E42, 0xF136 }, /* R3650 - EQ3_7 */ + { 0x00000E43, 0x0409 }, /* R3651 - EQ3_8 */ + { 0x00000E44, 0x04CC }, /* R3652 - EQ3_9 */ + { 0x00000E45, 0x1C9B }, /* R3653 - EQ3_10 */ + { 0x00000E46, 0xF337 }, /* R3654 - EQ3_11 */ + { 0x00000E47, 0x040B }, /* R3655 - EQ3_12 */ + { 0x00000E48, 0x0CBB }, /* R3656 - EQ3_13 */ + { 0x00000E49, 0x16F8 }, /* R3657 - EQ3_14 */ + { 0x00000E4A, 0xF7D9 }, /* R3658 - EQ3_15 */ + { 0x00000E4B, 0x040A }, /* R3659 - EQ3_16 */ + { 0x00000E4C, 0x1F14 }, /* R3660 - EQ3_17 */ + { 0x00000E4D, 0x058C }, /* R3661 - EQ3_18 */ + { 0x00000E4E, 0x0563 }, /* R3662 - EQ3_19 */ + { 0x00000E4F, 0x4000 }, /* R3663 - EQ3_20 */ + { 0x00000E50, 0x0B75 }, /* R3664 - EQ3_21 */ + { 0x00000E52, 0x6318 }, /* R3666 - EQ4_1 */ + { 0x00000E53, 0x6300 }, /* R3667 - EQ4_2 */ + { 0x00000E54, 0x0FC8 }, /* R3668 - EQ4_3 */ + { 0x00000E55, 0x03FE }, /* R3669 - EQ4_4 */ + { 0x00000E56, 0x00E0 }, /* R3670 - EQ4_5 */ + { 0x00000E57, 0x1EC4 }, /* R3671 - EQ4_6 */ + { 0x00000E58, 0xF136 }, /* R3672 - EQ4_7 */ + { 0x00000E59, 0x0409 }, /* R3673 - EQ4_8 */ + { 0x00000E5A, 0x04CC }, /* R3674 - EQ4_9 */ + { 0x00000E5B, 0x1C9B }, /* R3675 - EQ4_10 */ + { 0x00000E5C, 0xF337 }, /* R3676 - EQ4_11 */ + { 0x00000E5D, 0x040B }, /* R3677 - EQ4_12 */ + { 0x00000E5E, 0x0CBB }, /* R3678 - EQ4_13 */ + { 0x00000E5F, 0x16F8 }, /* R3679 - EQ4_14 */ + { 0x00000E60, 0xF7D9 }, /* R3680 - EQ4_15 */ + { 0x00000E61, 0x040A }, /* R3681 - EQ4_16 */ + { 0x00000E62, 0x1F14 }, /* R3682 - EQ4_17 */ + { 0x00000E63, 0x058C }, /* R3683 - EQ4_18 */ + { 0x00000E64, 0x0563 }, /* R3684 - EQ4_19 */ + { 0x00000E65, 0x4000 }, /* R3685 - EQ4_20 */ + { 0x00000E66, 0x0B75 }, /* R3686 - EQ4_21 */ + { 0x00000E80, 0x0018 }, /* R3712 - DRC1 ctrl1 */ + { 0x00000E81, 0x0933 }, /* R3713 - DRC1 ctrl2 */ + { 0x00000E82, 0x0018 }, /* R3714 - DRC1 ctrl3 */ + { 0x00000E83, 0x0000 }, /* R3715 - DRC1 ctrl4 */ + { 0x00000E84, 0x0000 }, /* R3716 - DRC1 ctrl5 */ + { 0x00000EC0, 0x0000 }, /* R3776 - HPLPF1_1 */ + { 0x00000EC1, 0x0000 }, /* R3777 - HPLPF1_2 */ + { 0x00000EC4, 0x0000 }, /* R3780 - HPLPF2_1 */ + { 0x00000EC5, 0x0000 }, /* R3781 - HPLPF2_2 */ + { 0x00000EC8, 0x0000 }, /* R3784 - HPLPF3_1 */ + { 0x00000EC9, 0x0000 }, /* R3785 - HPLPF3_2 */ + { 0x00000ECC, 0x0000 }, /* R3788 - HPLPF4_1 */ + { 0x00000ECD, 0x0000 }, /* R3789 - HPLPF4_2 */ + { 0x00000EF0, 0x0000 }, /* R3824 - ISRC 1 CTRL 1 */ + { 0x00000EF1, 0x0000 }, /* R3825 - ISRC 1 CTRL 2 */ + { 0x00000EF2, 0x0000 }, /* R3826 - ISRC 1 CTRL 3 */ + { 0x00000EF3, 0x0000 }, /* R3827 - ISRC 2 CTRL 1 */ + { 0x00000EF4, 0x0000 }, /* R3828 - ISRC 2 CTRL 2 */ + { 0x00000EF5, 0x0000 }, /* R3829 - ISRC 2 CTRL 3 */ + { 0x00001100, 0x0010 }, /* R4352 - DSP1 Control 1 */ + { 0x00001101, 0x0000 }, /* R4353 - DSP1 Clocking 1 */ +}; + +static bool wm8997_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ARIZONA_SOFTWARE_RESET: + case ARIZONA_DEVICE_REVISION: + case ARIZONA_CTRL_IF_I2C1_CFG_1: + case ARIZONA_WRITE_SEQUENCER_CTRL_0: + case ARIZONA_WRITE_SEQUENCER_CTRL_1: + case ARIZONA_WRITE_SEQUENCER_CTRL_2: + case ARIZONA_TONE_GENERATOR_1: + case ARIZONA_TONE_GENERATOR_2: + case ARIZONA_TONE_GENERATOR_3: + case ARIZONA_TONE_GENERATOR_4: + case ARIZONA_TONE_GENERATOR_5: + case ARIZONA_PWM_DRIVE_1: + case ARIZONA_PWM_DRIVE_2: + case ARIZONA_PWM_DRIVE_3: + case ARIZONA_WAKE_CONTROL: + case ARIZONA_SEQUENCE_CONTROL: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_1: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_2: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_3: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_4: + case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1: + case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2: + case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_3: + case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_4: + case ARIZONA_COMFORT_NOISE_GENERATOR: + case ARIZONA_HAPTICS_CONTROL_1: + case ARIZONA_HAPTICS_CONTROL_2: + case ARIZONA_HAPTICS_PHASE_1_INTENSITY: + case ARIZONA_HAPTICS_PHASE_1_DURATION: + case ARIZONA_HAPTICS_PHASE_2_INTENSITY: + case ARIZONA_HAPTICS_PHASE_2_DURATION: + case ARIZONA_HAPTICS_PHASE_3_INTENSITY: + case ARIZONA_HAPTICS_PHASE_3_DURATION: + case ARIZONA_HAPTICS_STATUS: + case ARIZONA_CLOCK_32K_1: + case ARIZONA_SYSTEM_CLOCK_1: + case ARIZONA_SAMPLE_RATE_1: + case ARIZONA_SAMPLE_RATE_2: + case ARIZONA_SAMPLE_RATE_3: + case ARIZONA_SAMPLE_RATE_1_STATUS: + case ARIZONA_SAMPLE_RATE_2_STATUS: + case ARIZONA_SAMPLE_RATE_3_STATUS: + case ARIZONA_ASYNC_CLOCK_1: + case ARIZONA_ASYNC_SAMPLE_RATE_1: + case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: + case ARIZONA_OUTPUT_SYSTEM_CLOCK: + case ARIZONA_OUTPUT_ASYNC_CLOCK: + case ARIZONA_RATE_ESTIMATOR_1: + case ARIZONA_RATE_ESTIMATOR_2: + case ARIZONA_RATE_ESTIMATOR_3: + case ARIZONA_RATE_ESTIMATOR_4: + case ARIZONA_RATE_ESTIMATOR_5: + case ARIZONA_FLL1_CONTROL_1: + case ARIZONA_FLL1_CONTROL_2: + case ARIZONA_FLL1_CONTROL_3: + case ARIZONA_FLL1_CONTROL_4: + case ARIZONA_FLL1_CONTROL_5: + case ARIZONA_FLL1_CONTROL_6: + case ARIZONA_FLL1_LOOP_FILTER_TEST_1: + case ARIZONA_FLL1_NCO_TEST_0: + case ARIZONA_FLL1_SYNCHRONISER_1: + case ARIZONA_FLL1_SYNCHRONISER_2: + case ARIZONA_FLL1_SYNCHRONISER_3: + case ARIZONA_FLL1_SYNCHRONISER_4: + case ARIZONA_FLL1_SYNCHRONISER_5: + case ARIZONA_FLL1_SYNCHRONISER_6: + case ARIZONA_FLL1_SPREAD_SPECTRUM: + case ARIZONA_FLL1_GPIO_CLOCK: + case ARIZONA_FLL2_CONTROL_1: + case ARIZONA_FLL2_CONTROL_2: + case ARIZONA_FLL2_CONTROL_3: + case ARIZONA_FLL2_CONTROL_4: + case ARIZONA_FLL2_CONTROL_5: + case ARIZONA_FLL2_CONTROL_6: + case ARIZONA_FLL2_LOOP_FILTER_TEST_1: + case ARIZONA_FLL2_NCO_TEST_0: + case ARIZONA_FLL2_SYNCHRONISER_1: + case ARIZONA_FLL2_SYNCHRONISER_2: + case ARIZONA_FLL2_SYNCHRONISER_3: + case ARIZONA_FLL2_SYNCHRONISER_4: + case ARIZONA_FLL2_SYNCHRONISER_5: + case ARIZONA_FLL2_SYNCHRONISER_6: + case ARIZONA_FLL2_SPREAD_SPECTRUM: + case ARIZONA_FLL2_GPIO_CLOCK: + case ARIZONA_MIC_CHARGE_PUMP_1: + case ARIZONA_LDO1_CONTROL_1: + case ARIZONA_LDO2_CONTROL_1: + case ARIZONA_MIC_BIAS_CTRL_1: + case ARIZONA_MIC_BIAS_CTRL_2: + case ARIZONA_MIC_BIAS_CTRL_3: + case ARIZONA_ACCESSORY_DETECT_MODE_1: + case ARIZONA_HEADPHONE_DETECT_1: + case ARIZONA_HEADPHONE_DETECT_2: + case ARIZONA_MIC_DETECT_1: + case ARIZONA_MIC_DETECT_2: + case ARIZONA_MIC_DETECT_3: + case ARIZONA_MIC_NOISE_MIX_CONTROL_1: + case ARIZONA_ISOLATION_CONTROL: + case ARIZONA_JACK_DETECT_ANALOGUE: + case ARIZONA_INPUT_ENABLES: + case ARIZONA_INPUT_ENABLES_STATUS: + case ARIZONA_INPUT_RATE: + case ARIZONA_INPUT_VOLUME_RAMP: + case ARIZONA_IN1L_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_1L: + case ARIZONA_DMIC1L_CONTROL: + case ARIZONA_IN1R_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_1R: + case ARIZONA_DMIC1R_CONTROL: + case ARIZONA_IN2L_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_2L: + case ARIZONA_DMIC2L_CONTROL: + case ARIZONA_IN2R_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_2R: + case ARIZONA_DMIC2R_CONTROL: + case ARIZONA_OUTPUT_ENABLES_1: + case ARIZONA_OUTPUT_STATUS_1: + case ARIZONA_RAW_OUTPUT_STATUS_1: + case ARIZONA_OUTPUT_RATE_1: + case ARIZONA_OUTPUT_VOLUME_RAMP: + case ARIZONA_OUTPUT_PATH_CONFIG_1L: + case ARIZONA_DAC_DIGITAL_VOLUME_1L: + case ARIZONA_DAC_VOLUME_LIMIT_1L: + case ARIZONA_NOISE_GATE_SELECT_1L: + case ARIZONA_OUTPUT_PATH_CONFIG_1R: + case ARIZONA_DAC_DIGITAL_VOLUME_1R: + case ARIZONA_DAC_VOLUME_LIMIT_1R: + case ARIZONA_NOISE_GATE_SELECT_1R: + case ARIZONA_OUTPUT_PATH_CONFIG_3L: + case ARIZONA_DAC_DIGITAL_VOLUME_3L: + case ARIZONA_DAC_VOLUME_LIMIT_3L: + case ARIZONA_NOISE_GATE_SELECT_3L: + case ARIZONA_OUTPUT_PATH_CONFIG_4L: + case ARIZONA_DAC_DIGITAL_VOLUME_4L: + case ARIZONA_OUT_VOLUME_4L: + case ARIZONA_NOISE_GATE_SELECT_4L: + case ARIZONA_OUTPUT_PATH_CONFIG_5L: + case ARIZONA_DAC_DIGITAL_VOLUME_5L: + case ARIZONA_DAC_VOLUME_LIMIT_5L: + case ARIZONA_NOISE_GATE_SELECT_5L: + case ARIZONA_DAC_DIGITAL_VOLUME_5R: + case ARIZONA_DAC_VOLUME_LIMIT_5R: + case ARIZONA_NOISE_GATE_SELECT_5R: + case ARIZONA_DAC_AEC_CONTROL_1: + case ARIZONA_NOISE_GATE_CONTROL: + case ARIZONA_PDM_SPK1_CTRL_1: + case ARIZONA_PDM_SPK1_CTRL_2: + case ARIZONA_AIF1_BCLK_CTRL: + case ARIZONA_AIF1_TX_PIN_CTRL: + case ARIZONA_AIF1_RX_PIN_CTRL: + case ARIZONA_AIF1_RATE_CTRL: + case ARIZONA_AIF1_FORMAT: + case ARIZONA_AIF1_TX_BCLK_RATE: + case ARIZONA_AIF1_RX_BCLK_RATE: + case ARIZONA_AIF1_FRAME_CTRL_1: + case ARIZONA_AIF1_FRAME_CTRL_2: + case ARIZONA_AIF1_FRAME_CTRL_3: + case ARIZONA_AIF1_FRAME_CTRL_4: + case ARIZONA_AIF1_FRAME_CTRL_5: + case ARIZONA_AIF1_FRAME_CTRL_6: + case ARIZONA_AIF1_FRAME_CTRL_7: + case ARIZONA_AIF1_FRAME_CTRL_8: + case ARIZONA_AIF1_FRAME_CTRL_9: + case ARIZONA_AIF1_FRAME_CTRL_10: + case ARIZONA_AIF1_FRAME_CTRL_11: + case ARIZONA_AIF1_FRAME_CTRL_12: + case ARIZONA_AIF1_FRAME_CTRL_13: + case ARIZONA_AIF1_FRAME_CTRL_14: + case ARIZONA_AIF1_FRAME_CTRL_15: + case ARIZONA_AIF1_FRAME_CTRL_16: + case ARIZONA_AIF1_FRAME_CTRL_17: + case ARIZONA_AIF1_FRAME_CTRL_18: + case ARIZONA_AIF1_TX_ENABLES: + case ARIZONA_AIF1_RX_ENABLES: + case ARIZONA_AIF2_BCLK_CTRL: + case ARIZONA_AIF2_TX_PIN_CTRL: + case ARIZONA_AIF2_RX_PIN_CTRL: + case ARIZONA_AIF2_RATE_CTRL: + case ARIZONA_AIF2_FORMAT: + case ARIZONA_AIF2_TX_BCLK_RATE: + case ARIZONA_AIF2_RX_BCLK_RATE: + case ARIZONA_AIF2_FRAME_CTRL_1: + case ARIZONA_AIF2_FRAME_CTRL_2: + case ARIZONA_AIF2_FRAME_CTRL_3: + case ARIZONA_AIF2_FRAME_CTRL_4: + case ARIZONA_AIF2_FRAME_CTRL_11: + case ARIZONA_AIF2_FRAME_CTRL_12: + case ARIZONA_AIF2_TX_ENABLES: + case ARIZONA_AIF2_RX_ENABLES: + case ARIZONA_SLIMBUS_FRAMER_REF_GEAR: + case ARIZONA_SLIMBUS_RATES_1: + case ARIZONA_SLIMBUS_RATES_2: + case ARIZONA_SLIMBUS_RATES_3: + case ARIZONA_SLIMBUS_RATES_4: + case ARIZONA_SLIMBUS_RATES_5: + case ARIZONA_SLIMBUS_RATES_6: + case ARIZONA_SLIMBUS_RATES_7: + case ARIZONA_SLIMBUS_RATES_8: + case ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE: + case ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE: + case ARIZONA_SLIMBUS_RX_PORT_STATUS: + case ARIZONA_SLIMBUS_TX_PORT_STATUS: + case ARIZONA_PWM1MIX_INPUT_1_SOURCE: + case ARIZONA_PWM1MIX_INPUT_1_VOLUME: + case ARIZONA_PWM1MIX_INPUT_2_SOURCE: + case ARIZONA_PWM1MIX_INPUT_2_VOLUME: + case ARIZONA_PWM1MIX_INPUT_3_SOURCE: + case ARIZONA_PWM1MIX_INPUT_3_VOLUME: + case ARIZONA_PWM1MIX_INPUT_4_SOURCE: + case ARIZONA_PWM1MIX_INPUT_4_VOLUME: + case ARIZONA_PWM2MIX_INPUT_1_SOURCE: + case ARIZONA_PWM2MIX_INPUT_1_VOLUME: + case ARIZONA_PWM2MIX_INPUT_2_SOURCE: + case ARIZONA_PWM2MIX_INPUT_2_VOLUME: + case ARIZONA_PWM2MIX_INPUT_3_SOURCE: + case ARIZONA_PWM2MIX_INPUT_3_VOLUME: + case ARIZONA_PWM2MIX_INPUT_4_SOURCE: + case ARIZONA_PWM2MIX_INPUT_4_VOLUME: + case ARIZONA_MICMIX_INPUT_1_SOURCE: + case ARIZONA_MICMIX_INPUT_1_VOLUME: + case ARIZONA_MICMIX_INPUT_2_SOURCE: + case ARIZONA_MICMIX_INPUT_2_VOLUME: + case ARIZONA_MICMIX_INPUT_3_SOURCE: + case ARIZONA_MICMIX_INPUT_3_VOLUME: + case ARIZONA_MICMIX_INPUT_4_SOURCE: + case ARIZONA_MICMIX_INPUT_4_VOLUME: + case ARIZONA_NOISEMIX_INPUT_1_SOURCE: + case ARIZONA_NOISEMIX_INPUT_1_VOLUME: + case ARIZONA_NOISEMIX_INPUT_2_SOURCE: + case ARIZONA_NOISEMIX_INPUT_2_VOLUME: + case ARIZONA_NOISEMIX_INPUT_3_SOURCE: + case ARIZONA_NOISEMIX_INPUT_3_VOLUME: + case ARIZONA_NOISEMIX_INPUT_4_SOURCE: + case ARIZONA_NOISEMIX_INPUT_4_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_4_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_4_VOLUME: + case ARIZONA_EQ1MIX_INPUT_1_SOURCE: + case ARIZONA_EQ1MIX_INPUT_1_VOLUME: + case ARIZONA_EQ1MIX_INPUT_2_SOURCE: + case ARIZONA_EQ1MIX_INPUT_2_VOLUME: + case ARIZONA_EQ1MIX_INPUT_3_SOURCE: + case ARIZONA_EQ1MIX_INPUT_3_VOLUME: + case ARIZONA_EQ1MIX_INPUT_4_SOURCE: + case ARIZONA_EQ1MIX_INPUT_4_VOLUME: + case ARIZONA_EQ2MIX_INPUT_1_SOURCE: + case ARIZONA_EQ2MIX_INPUT_1_VOLUME: + case ARIZONA_EQ2MIX_INPUT_2_SOURCE: + case ARIZONA_EQ2MIX_INPUT_2_VOLUME: + case ARIZONA_EQ2MIX_INPUT_3_SOURCE: + case ARIZONA_EQ2MIX_INPUT_3_VOLUME: + case ARIZONA_EQ2MIX_INPUT_4_SOURCE: + case ARIZONA_EQ2MIX_INPUT_4_VOLUME: + case ARIZONA_EQ3MIX_INPUT_1_SOURCE: + case ARIZONA_EQ3MIX_INPUT_1_VOLUME: + case ARIZONA_EQ3MIX_INPUT_2_SOURCE: + case ARIZONA_EQ3MIX_INPUT_2_VOLUME: + case ARIZONA_EQ3MIX_INPUT_3_SOURCE: + case ARIZONA_EQ3MIX_INPUT_3_VOLUME: + case ARIZONA_EQ3MIX_INPUT_4_SOURCE: + case ARIZONA_EQ3MIX_INPUT_4_VOLUME: + case ARIZONA_EQ4MIX_INPUT_1_SOURCE: + case ARIZONA_EQ4MIX_INPUT_1_VOLUME: + case ARIZONA_EQ4MIX_INPUT_2_SOURCE: + case ARIZONA_EQ4MIX_INPUT_2_VOLUME: + case ARIZONA_EQ4MIX_INPUT_3_SOURCE: + case ARIZONA_EQ4MIX_INPUT_3_VOLUME: + case ARIZONA_EQ4MIX_INPUT_4_SOURCE: + case ARIZONA_EQ4MIX_INPUT_4_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_1_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_1_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_2_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_2_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_3_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_3_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_4_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_4_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_1_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_1_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_2_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_2_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_3_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_3_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_4_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_4_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_4_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_4_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_4_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_4_VOLUME: + case ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE: + case ARIZONA_GPIO1_CTRL: + case ARIZONA_GPIO2_CTRL: + case ARIZONA_GPIO3_CTRL: + case ARIZONA_GPIO4_CTRL: + case ARIZONA_GPIO5_CTRL: + case ARIZONA_IRQ_CTRL_1: + case ARIZONA_GPIO_DEBOUNCE_CONFIG: + case ARIZONA_MISC_PAD_CTRL_1: + case ARIZONA_MISC_PAD_CTRL_2: + case ARIZONA_MISC_PAD_CTRL_3: + case ARIZONA_MISC_PAD_CTRL_4: + case ARIZONA_MISC_PAD_CTRL_5: + case ARIZONA_INTERRUPT_STATUS_1: + case ARIZONA_INTERRUPT_STATUS_2: + case ARIZONA_INTERRUPT_STATUS_3: + case ARIZONA_INTERRUPT_STATUS_4: + case ARIZONA_INTERRUPT_STATUS_5: + case ARIZONA_INTERRUPT_STATUS_1_MASK: + case ARIZONA_INTERRUPT_STATUS_3_MASK: + case ARIZONA_INTERRUPT_STATUS_4_MASK: + case ARIZONA_INTERRUPT_STATUS_5_MASK: + case ARIZONA_INTERRUPT_CONTROL: + case ARIZONA_IRQ2_STATUS_1: + case ARIZONA_IRQ2_STATUS_3: + case ARIZONA_IRQ2_STATUS_4: + case ARIZONA_IRQ2_STATUS_5: + case ARIZONA_IRQ2_STATUS_1_MASK: + case ARIZONA_IRQ2_STATUS_3_MASK: + case ARIZONA_IRQ2_STATUS_4_MASK: + case ARIZONA_IRQ2_STATUS_5_MASK: + case ARIZONA_IRQ2_CONTROL: + case ARIZONA_INTERRUPT_RAW_STATUS_3: + case ARIZONA_INTERRUPT_RAW_STATUS_4: + case ARIZONA_INTERRUPT_RAW_STATUS_5: + case ARIZONA_INTERRUPT_RAW_STATUS_6: + case ARIZONA_INTERRUPT_RAW_STATUS_7: + case ARIZONA_INTERRUPT_RAW_STATUS_8: + case ARIZONA_IRQ_PIN_STATUS: + case ARIZONA_AOD_WKUP_AND_TRIG: + case ARIZONA_AOD_IRQ1: + case ARIZONA_AOD_IRQ2: + case ARIZONA_AOD_IRQ_MASK_IRQ1: + case ARIZONA_AOD_IRQ_MASK_IRQ2: + case ARIZONA_AOD_IRQ_RAW_STATUS: + case ARIZONA_JACK_DETECT_DEBOUNCE: + case ARIZONA_FX_CTRL1: + case ARIZONA_FX_CTRL2: + case ARIZONA_EQ1_1: + case ARIZONA_EQ1_2: + case ARIZONA_EQ1_3: + case ARIZONA_EQ1_4: + case ARIZONA_EQ1_5: + case ARIZONA_EQ1_6: + case ARIZONA_EQ1_7: + case ARIZONA_EQ1_8: + case ARIZONA_EQ1_9: + case ARIZONA_EQ1_10: + case ARIZONA_EQ1_11: + case ARIZONA_EQ1_12: + case ARIZONA_EQ1_13: + case ARIZONA_EQ1_14: + case ARIZONA_EQ1_15: + case ARIZONA_EQ1_16: + case ARIZONA_EQ1_17: + case ARIZONA_EQ1_18: + case ARIZONA_EQ1_19: + case ARIZONA_EQ1_20: + case ARIZONA_EQ1_21: + case ARIZONA_EQ2_1: + case ARIZONA_EQ2_2: + case ARIZONA_EQ2_3: + case ARIZONA_EQ2_4: + case ARIZONA_EQ2_5: + case ARIZONA_EQ2_6: + case ARIZONA_EQ2_7: + case ARIZONA_EQ2_8: + case ARIZONA_EQ2_9: + case ARIZONA_EQ2_10: + case ARIZONA_EQ2_11: + case ARIZONA_EQ2_12: + case ARIZONA_EQ2_13: + case ARIZONA_EQ2_14: + case ARIZONA_EQ2_15: + case ARIZONA_EQ2_16: + case ARIZONA_EQ2_17: + case ARIZONA_EQ2_18: + case ARIZONA_EQ2_19: + case ARIZONA_EQ2_20: + case ARIZONA_EQ2_21: + case ARIZONA_EQ3_1: + case ARIZONA_EQ3_2: + case ARIZONA_EQ3_3: + case ARIZONA_EQ3_4: + case ARIZONA_EQ3_5: + case ARIZONA_EQ3_6: + case ARIZONA_EQ3_7: + case ARIZONA_EQ3_8: + case ARIZONA_EQ3_9: + case ARIZONA_EQ3_10: + case ARIZONA_EQ3_11: + case ARIZONA_EQ3_12: + case ARIZONA_EQ3_13: + case ARIZONA_EQ3_14: + case ARIZONA_EQ3_15: + case ARIZONA_EQ3_16: + case ARIZONA_EQ3_17: + case ARIZONA_EQ3_18: + case ARIZONA_EQ3_19: + case ARIZONA_EQ3_20: + case ARIZONA_EQ3_21: + case ARIZONA_EQ4_1: + case ARIZONA_EQ4_2: + case ARIZONA_EQ4_3: + case ARIZONA_EQ4_4: + case ARIZONA_EQ4_5: + case ARIZONA_EQ4_6: + case ARIZONA_EQ4_7: + case ARIZONA_EQ4_8: + case ARIZONA_EQ4_9: + case ARIZONA_EQ4_10: + case ARIZONA_EQ4_11: + case ARIZONA_EQ4_12: + case ARIZONA_EQ4_13: + case ARIZONA_EQ4_14: + case ARIZONA_EQ4_15: + case ARIZONA_EQ4_16: + case ARIZONA_EQ4_17: + case ARIZONA_EQ4_18: + case ARIZONA_EQ4_19: + case ARIZONA_EQ4_20: + case ARIZONA_EQ4_21: + case ARIZONA_DRC1_CTRL1: + case ARIZONA_DRC1_CTRL2: + case ARIZONA_DRC1_CTRL3: + case ARIZONA_DRC1_CTRL4: + case ARIZONA_DRC1_CTRL5: + case ARIZONA_HPLPF1_1: + case ARIZONA_HPLPF1_2: + case ARIZONA_HPLPF2_1: + case ARIZONA_HPLPF2_2: + case ARIZONA_HPLPF3_1: + case ARIZONA_HPLPF3_2: + case ARIZONA_HPLPF4_1: + case ARIZONA_HPLPF4_2: + case ARIZONA_ISRC_1_CTRL_1: + case ARIZONA_ISRC_1_CTRL_2: + case ARIZONA_ISRC_1_CTRL_3: + case ARIZONA_ISRC_2_CTRL_1: + case ARIZONA_ISRC_2_CTRL_2: + case ARIZONA_ISRC_2_CTRL_3: + return true; + default: + return false; + } +} + +static bool wm8997_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ARIZONA_SOFTWARE_RESET: + case ARIZONA_DEVICE_REVISION: + case ARIZONA_HAPTICS_STATUS: + case ARIZONA_SAMPLE_RATE_1_STATUS: + case ARIZONA_SAMPLE_RATE_2_STATUS: + case ARIZONA_SAMPLE_RATE_3_STATUS: + case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: + case ARIZONA_MIC_DETECT_3: + case ARIZONA_HEADPHONE_DETECT_2: + case ARIZONA_INPUT_ENABLES_STATUS: + case ARIZONA_OUTPUT_STATUS_1: + case ARIZONA_RAW_OUTPUT_STATUS_1: + case ARIZONA_SLIMBUS_RX_PORT_STATUS: + case ARIZONA_SLIMBUS_TX_PORT_STATUS: + case ARIZONA_INTERRUPT_STATUS_1: + case ARIZONA_INTERRUPT_STATUS_2: + case ARIZONA_INTERRUPT_STATUS_3: + case ARIZONA_INTERRUPT_STATUS_4: + case ARIZONA_INTERRUPT_STATUS_5: + case ARIZONA_IRQ2_STATUS_1: + case ARIZONA_IRQ2_STATUS_3: + case ARIZONA_IRQ2_STATUS_4: + case ARIZONA_IRQ2_STATUS_5: + case ARIZONA_INTERRUPT_RAW_STATUS_3: + case ARIZONA_INTERRUPT_RAW_STATUS_4: + case ARIZONA_INTERRUPT_RAW_STATUS_5: + case ARIZONA_INTERRUPT_RAW_STATUS_6: + case ARIZONA_INTERRUPT_RAW_STATUS_7: + case ARIZONA_INTERRUPT_RAW_STATUS_8: + case ARIZONA_IRQ_PIN_STATUS: + case ARIZONA_AOD_WKUP_AND_TRIG: + case ARIZONA_AOD_IRQ1: + case ARIZONA_AOD_IRQ2: + case ARIZONA_AOD_IRQ_RAW_STATUS: + case ARIZONA_FX_CTRL2: + return true; + default: + return false; + } +} + +#define WM8997_MAX_REGISTER 0x31ff + +const struct regmap_config wm8997_i2c_regmap = { + .reg_bits = 32, + .val_bits = 16, + + .max_register = WM8997_MAX_REGISTER, + .readable_reg = wm8997_readable_register, + .volatile_reg = wm8997_volatile_register, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = wm8997_reg_default, + .num_reg_defaults = ARRAY_SIZE(wm8997_reg_default), +}; +EXPORT_SYMBOL_GPL(wm8997_i2c_regmap); |