From 9032eabdd3fcfc00aa513a9eef54002cbabb8c9a Mon Sep 17 00:00:00 2001 From: Roger Tseng Date: Fri, 19 Apr 2013 21:52:42 +0800 Subject: mfd: rtsx: Add support for RTL8411B Adding support of model RTL8411B. Since the model is similar to RTL8411, differences are implemented in rtl8411.c. Signed-off-by: Roger Tseng Signed-off-by: Samuel Ortiz --- include/linux/mfd/rtsx_pci.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index 86bc635f8385..7a9f7089435d 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -575,6 +575,7 @@ #define CARD_PWR_CTL 0xFD50 #define CARD_CLK_SWITCH 0xFD51 +#define RTL8411B_PACKAGE_MODE 0xFD51 #define CARD_SHARE_MODE 0xFD52 #define CARD_DRIVE_SEL 0xFD53 #define CARD_STOP 0xFD54 -- cgit v1.2.3 From 7c8844481a1c16c10fa9be4ce95be5725aed6ce3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 6 May 2013 16:12:56 +0100 Subject: mfd: wm8994: Emulate level triggered interrupts if required The interrupt controller on the wm8994 series of devices requires a level triggered parent. If one is not available but a GPIO is available for the interrupt then emulate. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8994-irq.c | 100 +++++++++++++++++++++++++++++++++++++-- include/linux/mfd/wm8994/core.h | 2 + include/linux/mfd/wm8994/pdata.h | 5 ++ 3 files changed, 103 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c index a050e56a9bbd..d3a184a240f5 100644 --- a/drivers/mfd/wm8994-irq.c +++ b/drivers/mfd/wm8994-irq.c @@ -14,10 +14,12 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -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/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h index ae5c249530b4..40854ac0ba3d 100644 --- a/include/linux/mfd/wm8994/core.h +++ b/include/linux/mfd/wm8994/core.h @@ -29,6 +29,7 @@ enum wm8994_type { struct regulator_dev; struct regulator_bulk_data; +struct irq_domain; #define WM8994_NUM_GPIO_REGS 11 #define WM8994_NUM_LDO_REGS 2 @@ -73,6 +74,7 @@ struct wm8994 { int irq; struct regmap_irq_chip_data *irq_data; + struct irq_domain *edge_irq; /* Used over suspend/resume */ bool suspended; diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h index 68e776594889..90e9bf86e643 100644 --- a/include/linux/mfd/wm8994/pdata.h +++ b/include/linux/mfd/wm8994/pdata.h @@ -223,6 +223,11 @@ struct wm8994_pdata { * lines is mastered. */ int max_channels_clocked[WM8994_NUM_AIF]; + + /** + * GPIO for the IRQ pin if host only supports edge triggering + */ + int irq_gpio; }; #endif -- cgit v1.2.3 From a9bce1b03c2199e66d36cda8aac675338bc074a7 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 5 Jun 2013 16:13:47 +0200 Subject: mfd: input: iio: ti_am335x_adc: use one structure for ti_tscadc_dev The mfd driver creates platform data for the child devices and it is the ti_tscadc_dev struct. This struct is copied for the two devices. The copy of the structure makes a common lock in this structure a little less usefull. Therefore the platform data is not a pointer to the structure and the same structure is used. While doing the change I noticed that the suspend/resume code assumes the wrong pointer for ti_tscadc_dev and this has been fixed as well. Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 5 +++-- drivers/input/touchscreen/ti_am335x_tsc.c | 16 +++++++++------- drivers/mfd/ti_am335x_tscadc.c | 8 ++++---- include/linux/mfd/ti_am335x_tscadc.h | 7 +++++++ 4 files changed, 23 insertions(+), 13 deletions(-) (limited to 'include/linux') diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 5f9a7e7d3135..9db352e413e4 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -140,7 +140,7 @@ static int tiadc_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; struct tiadc_device *adc_dev; - struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; + struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); struct mfd_tscadc_board *pdata; int err; @@ -205,9 +205,10 @@ static int tiadc_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct tiadc_device *adc_dev = iio_priv(indio_dev); - struct ti_tscadc_dev *tscadc_dev = dev->platform_data; + struct ti_tscadc_dev *tscadc_dev; unsigned int idle; + tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); if (!device_may_wakeup(tscadc_dev->dev)) { idle = tiadc_readl(adc_dev, REG_CTRL); idle &= ~(CNTRLREG_TSCSSENB); diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 51e7b87827a4..16077d3d80ba 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -262,7 +262,7 @@ static int titsc_probe(struct platform_device *pdev) { struct titsc *ts_dev; struct input_dev *input_dev; - struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; + struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); struct mfd_tscadc_board *pdata; int err; @@ -329,8 +329,8 @@ err_free_mem: static int titsc_remove(struct platform_device *pdev) { - struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; - struct titsc *ts_dev = tscadc_dev->tsc; + struct titsc *ts_dev = platform_get_drvdata(pdev); + u32 steps; free_irq(ts_dev->irq, ts_dev); @@ -344,10 +344,11 @@ static int titsc_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int titsc_suspend(struct device *dev) { - struct ti_tscadc_dev *tscadc_dev = dev->platform_data; - struct titsc *ts_dev = tscadc_dev->tsc; + struct titsc *ts_dev = dev_get_drvdata(dev); + struct ti_tscadc_dev *tscadc_dev; unsigned int idle; + tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); if (device_may_wakeup(tscadc_dev->dev)) { idle = titsc_readl(ts_dev, REG_IRQENABLE); titsc_writel(ts_dev, REG_IRQENABLE, @@ -359,9 +360,10 @@ static int titsc_suspend(struct device *dev) static int titsc_resume(struct device *dev) { - struct ti_tscadc_dev *tscadc_dev = dev->platform_data; - struct titsc *ts_dev = tscadc_dev->tsc; + struct titsc *ts_dev = dev_get_drvdata(dev); + struct ti_tscadc_dev *tscadc_dev; + tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); if (device_may_wakeup(tscadc_dev->dev)) { titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00); diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index e9f3fb510b44..772ea2adb539 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -176,14 +176,14 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* TSC Cell */ cell = &tscadc->cells[TSC_CELL]; cell->name = "tsc"; - cell->platform_data = tscadc; - cell->pdata_size = sizeof(*tscadc); + 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); + cell->platform_data = &tscadc; + cell->pdata_size = sizeof(tscadc); err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells, TSCADC_CELLS, NULL, 0, NULL); diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index c79ad5d2f271..8114e4e8b91b 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -149,4 +149,11 @@ struct ti_tscadc_dev { struct adc_device *adc; }; +static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p) +{ + struct ti_tscadc_dev **tscadc_dev = p->dev.platform_data; + + return *tscadc_dev; +} + #endif -- cgit v1.2.3 From abeccee40320245a2a6a006dc8466a703cbd1d5e Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:05 +0000 Subject: input: ti_am33x_tsc: Step enable bits made configurable Current code has hard coded value written to step enable bits. Now the bits are updated based on how many steps are needed to be configured got from platform data. The user needs to take care not to exceed the count more than 16. While using ADC and TSC one should take care to set this parameter correctly. Sebastian added the common lock and moved the code, that manipulates the steps, from into the mfd module. Signed-off-by: Patil, Rachna Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 20 ++++++++++++++++++-- drivers/input/touchscreen/ti_am335x_tsc.c | 12 ++++++++++-- drivers/mfd/ti_am335x_tscadc.c | 29 ++++++++++++++++++++++++++++- include/linux/mfd/ti_am335x_tscadc.h | 8 ++++++-- 4 files changed, 62 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 9db352e413e4..543b9c42ac5f 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -42,10 +42,20 @@ static void tiadc_writel(struct tiadc_device *adc, unsigned int reg, writel(val, adc->mfd_tscadc->tscadc_base + reg); } +static u32 get_adc_step_mask(struct tiadc_device *adc_dev) +{ + u32 step_en; + + step_en = ((1 << adc_dev->channels) - 1); + step_en <<= TOTAL_STEPS - adc_dev->channels + 1; + return step_en; +} + static void tiadc_step_config(struct tiadc_device *adc_dev) { unsigned int stepconfig; int i, channels = 0, steps; + u32 step_en; /* * There are 16 configurable steps and 8 analog input @@ -69,7 +79,8 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) STEPCONFIG_OPENDLY); channels++; } - tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB); + step_en = get_adc_step_mask(adc_dev); + am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); } static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) @@ -127,7 +138,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, if (i == chan->channel) *val = readx1 & 0xfff; } - tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB); + am335x_tsc_se_update(adc_dev->mfd_tscadc); return IIO_VAL_INT; } @@ -191,10 +202,15 @@ err_ret: static int tiadc_remove(struct platform_device *pdev) { struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct tiadc_device *adc_dev = iio_priv(indio_dev); + u32 step_en; iio_device_unregister(indio_dev); tiadc_channels_remove(indio_dev); + step_en = get_adc_step_mask(adc_dev); + am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en); + iio_device_free(indio_dev); return 0; diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 16077d3d80ba..23d6a4dacc88 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -57,6 +57,7 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg, static void titsc_step_config(struct titsc *ts_dev) { unsigned int config; + unsigned int stepenable = 0; int i, total_steps; /* Configure the Step registers */ @@ -128,7 +129,9 @@ static void titsc_step_config(struct titsc *ts_dev) titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), STEPCONFIG_OPENDLY); - titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); + /* The steps1 … end and bit 0 for TS_Charge */ + stepenable = (1 << (total_steps + 2)) - 1; + am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable); } static void titsc_read_coordinates(struct titsc *ts_dev, @@ -250,7 +253,7 @@ static irqreturn_t titsc_irq(int irq, void *dev) titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); - titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); + am335x_tsc_se_update(ts_dev->mfd_tscadc); return IRQ_HANDLED; } @@ -334,6 +337,11 @@ static int titsc_remove(struct platform_device *pdev) free_irq(ts_dev->irq, ts_dev); + /* total steps followed by the enable mask */ + steps = 2 * ts_dev->steps_to_configure + 2; + steps = (1 << steps) - 1; + am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps); + input_unregister_device(ts_dev->input); platform_set_drvdata(pdev, NULL); diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 772ea2adb539..90ccfc07e16b 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -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; @@ -129,6 +155,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); @@ -239,7 +266,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)); diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 8114e4e8b91b..4258627d076a 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -46,8 +46,6 @@ /* Step Enable */ #define STEPENB_MASK (0x1FFFF << 0) #define STEPENB(val) ((val) << 0) -#define STPENB_STEPENB STEPENB(0x1FFFF) -#define STPENB_STEPENB_TC STEPENB(0x1FFF) /* IRQ enable */ #define IRQENB_HW_PEN BIT(0) @@ -141,6 +139,8 @@ struct ti_tscadc_dev { void __iomem *tscadc_base; int irq; struct mfd_cell cells[TSCADC_CELLS]; + u32 reg_se_cache; + spinlock_t reg_lock; /* tsc device */ struct titsc *tsc; @@ -156,4 +156,8 @@ static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p) return *tscadc_dev; } +void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc); +void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val); +void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val); + #endif -- cgit v1.2.3 From bb76dc09ddfc135c6c5e8eb7d3c583bfa8bdd439 Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:06 +0000 Subject: input: ti_am33x_tsc: Order of TSC wires, made configurable The current driver expected touchscreen input wires(XP,XN,YP,YN) to be connected in a particular order. Making changes to accept this as platform data. Sebastian reworked the original patch and removed a lot of the not required pieces. Signed-off-by: Patil, Rachna Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 102 +++++++++++++++++++++++++----- include/linux/input/ti_am335x_tsc.h | 12 ++++ include/linux/mfd/ti_am335x_tscadc.h | 3 - 3 files changed, 98 insertions(+), 19 deletions(-) (limited to 'include/linux') diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 23d6a4dacc88..2bdd66cd76a7 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -33,6 +33,13 @@ #define SEQ_SETTLE 275 #define MAX_12BIT ((1 << 12) - 1) +static const int config_pins[] = { + STEPCONFIG_XPP, + STEPCONFIG_XNN, + STEPCONFIG_YPP, + STEPCONFIG_YNN, +}; + struct titsc { struct input_dev *input; struct ti_tscadc_dev *mfd_tscadc; @@ -41,6 +48,9 @@ struct titsc { unsigned int x_plate_resistance; bool pen_down; int steps_to_configure; + u32 config_inp[4]; + u32 bit_xp, bit_xn, bit_yp, bit_yn; + u32 inp_xp, inp_xn, inp_yp, inp_yn; }; static unsigned int titsc_readl(struct titsc *ts, unsigned int reg) @@ -54,6 +64,58 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg, writel(val, tsc->mfd_tscadc->tscadc_base + reg); } +static int titsc_config_wires(struct titsc *ts_dev) +{ + u32 analog_line[4]; + u32 wire_order[4]; + int i, bit_cfg; + + for (i = 0; i < 4; i++) { + /* + * Get the order in which TSC wires are attached + * w.r.t. each of the analog input lines on the EVM. + */ + analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4; + wire_order[i] = ts_dev->config_inp[i] & 0x0F; + if (WARN_ON(analog_line[i] > 7)) + return -EINVAL; + if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins))) + return -EINVAL; + } + + for (i = 0; i < 4; i++) { + int an_line; + int wi_order; + + an_line = analog_line[i]; + wi_order = wire_order[i]; + bit_cfg = config_pins[wi_order]; + if (bit_cfg == 0) + return -EINVAL; + switch (wi_order) { + case 0: + ts_dev->bit_xp = bit_cfg; + ts_dev->inp_xp = an_line; + break; + + case 1: + ts_dev->bit_xn = bit_cfg; + ts_dev->inp_xn = an_line; + break; + + case 2: + ts_dev->bit_yp = bit_cfg; + ts_dev->inp_yp = an_line; + break; + case 3: + ts_dev->bit_yn = bit_cfg; + ts_dev->inp_yn = an_line; + break; + } + } + return 0; +} + static void titsc_step_config(struct titsc *ts_dev) { unsigned int config; @@ -64,18 +126,18 @@ static void titsc_step_config(struct titsc *ts_dev) total_steps = 2 * ts_dev->steps_to_configure; config = STEPCONFIG_MODE_HWSYNC | - STEPCONFIG_AVG_16 | STEPCONFIG_XPP; + STEPCONFIG_AVG_16 | ts_dev->bit_xp; switch (ts_dev->wires) { case 4: - config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; + config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; break; case 5: - config |= STEPCONFIG_YNN | - STEPCONFIG_INP_AN4 | STEPCONFIG_XNN | - STEPCONFIG_YPP; + config |= ts_dev->bit_yn | + STEPCONFIG_INP_AN4 | ts_dev->bit_xn | + ts_dev->bit_yp; break; case 8: - config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; + config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; break; } @@ -86,18 +148,18 @@ static void titsc_step_config(struct titsc *ts_dev) config = 0; config = STEPCONFIG_MODE_HWSYNC | - STEPCONFIG_AVG_16 | STEPCONFIG_YNN | + STEPCONFIG_AVG_16 | ts_dev->bit_yn | STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1; switch (ts_dev->wires) { case 4: - config |= STEPCONFIG_YPP; + config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); break; case 5: - config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 | - STEPCONFIG_XNP | STEPCONFIG_YPN; + config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 | + ts_dev->bit_xn | ts_dev->bit_yp; break; case 8: - config |= STEPCONFIG_YPP; + config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); break; } @@ -108,9 +170,9 @@ static void titsc_step_config(struct titsc *ts_dev) config = 0; /* Charge step configuration */ - config = STEPCONFIG_XPP | STEPCONFIG_YNN | + config = ts_dev->bit_xp | ts_dev->bit_yn | STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | - STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1; + STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp); titsc_writel(ts_dev, REG_CHARGECONFIG, config); titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); @@ -118,13 +180,14 @@ static void titsc_step_config(struct titsc *ts_dev) config = 0; /* Configure to calculate pressure */ config = STEPCONFIG_MODE_HWSYNC | - STEPCONFIG_AVG_16 | STEPCONFIG_YPP | - STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM; + STEPCONFIG_AVG_16 | ts_dev->bit_yp | + ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM | + STEPCONFIG_INP(ts_dev->inp_xp); titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config); titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1), STEPCONFIG_OPENDLY); - config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1; + config |= STEPCONFIG_INP(ts_dev->inp_yn) | STEPCONFIG_FIFO1; titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config); titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), STEPCONFIG_OPENDLY); @@ -292,6 +355,8 @@ static int titsc_probe(struct platform_device *pdev) ts_dev->wires = pdata->tsc_init->wires; ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance; ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure; + memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config, + sizeof(pdata->tsc_init->wire_config)); err = request_irq(ts_dev->irq, titsc_irq, 0, pdev->dev.driver->name, ts_dev); @@ -301,6 +366,11 @@ static int titsc_probe(struct platform_device *pdev) } titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); + err = titsc_config_wires(ts_dev); + if (err) { + dev_err(&pdev->dev, "wrong i/p wire configuration\n"); + goto err_free_irq; + } titsc_step_config(ts_dev); titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure); diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h index 49269a2aa329..6a66b4d1ac2c 100644 --- a/include/linux/input/ti_am335x_tsc.h +++ b/include/linux/input/ti_am335x_tsc.h @@ -12,12 +12,24 @@ * A step configured to read a single * co-ordinate value, can be applied * more number of times for better results. + * @wire_config: Different EVM's could have a different order + * for connecting wires on touchscreen. + * We need to provide an 8 bit number where in + * the 1st four bits represent the analog lines + * and the next 4 bits represent positive/ + * negative terminal on that input line. + * Notations to represent the input lines and + * terminals resoectively is as follows: + * AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7. + * XP = 0, XN = 1, YP = 2, YN = 3. + * */ struct tsc_data { int wires; int x_plate_resistance; int steps_to_configure; + int wire_config[10]; }; #endif diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 4258627d076a..e36ae4184917 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -71,8 +71,6 @@ #define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8) #define STEPCONFIG_INP_MASK (0xF << 19) #define STEPCONFIG_INP(val) ((val) << 19) -#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2) -#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3) #define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4) #define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8) #define STEPCONFIG_FIFO1 BIT(26) @@ -94,7 +92,6 @@ #define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1) #define STEPCHARGE_INP_MASK (0xF << 19) #define STEPCHARGE_INP(val) ((val) << 19) -#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1) #define STEPCHARGE_RFM_MASK (3 << 23) #define STEPCHARGE_RFM(val) ((val) << 23) #define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1) -- cgit v1.2.3 From 24d5c82f8227d4dedf177df3f062eb35db15aaf6 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Sat, 13 Oct 2012 16:37:24 +0300 Subject: mfd: ti_tscadc: deal with partial activation Fix the mfd device in the case where a subdevice might not be activated. Signed-off-by: Pantelis Antoniou Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/mfd/ti_am335x_tscadc.c | 38 ++++++++++++++++++++++++------------ include/linux/mfd/ti_am335x_tscadc.h | 8 +++----- 2 files changed, 28 insertions(+), 18 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index e78b9df590c0..d05fcba6f13a 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -107,11 +107,14 @@ static int ti_tscadc_probe(struct platform_device *pdev) of_property_read_u32(node, "ti,adc-channels", &adc_channels); 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; + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -202,28 +205,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->of_compatible = "ti,am3359-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 = "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->of_compatible = "ti,am3359-adc"; - 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 = "tiadc"; + 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: diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index e36ae4184917..fe54ba4a3b2f 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -120,11 +120,6 @@ #define TSCADC_CELLS 2 -enum tscadc_cells { - TSC_CELL, - ADC_CELL, -}; - struct mfd_tscadc_board { struct tsc_data *tsc_init; struct adc_data *adc_init; @@ -135,6 +130,9 @@ struct ti_tscadc_dev { struct regmap *regmap_tscadc; void __iomem *tscadc_base; int irq; + int used_cells; /* 1-2 */ + int tsc_cell; /* -1 if not used */ + int adc_cell; /* -1 if not used */ struct mfd_cell cells[TSCADC_CELLS]; u32 reg_se_cache; spinlock_t reg_lock; -- cgit v1.2.3 From a3e509bb328287beba05017037e505bc53b62724 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 21 May 2013 18:49:58 +0200 Subject: input: mfd: ti_am335x_tsc remove remaining platform data pieces The two header files removed here are unused and have no users as this platform was never used with platform devices. Signed-off-by: Sebastian Andrzej Siewior --- include/linux/input/ti_am335x_tsc.h | 35 ----------------------------- include/linux/mfd/ti_am335x_tscadc.h | 5 ----- include/linux/platform_data/ti_am335x_adc.h | 14 ------------ 3 files changed, 54 deletions(-) delete mode 100644 include/linux/input/ti_am335x_tsc.h delete mode 100644 include/linux/platform_data/ti_am335x_adc.h (limited to 'include/linux') diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h deleted file mode 100644 index 6a66b4d1ac2c..000000000000 --- a/include/linux/input/ti_am335x_tsc.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __LINUX_TI_AM335X_TSC_H -#define __LINUX_TI_AM335X_TSC_H - -/** - * struct tsc_data Touchscreen wire configuration - * @wires: Wires refer to application modes - * i.e. 4/5/8 wire touchscreen support - * on the platform. - * @x_plate_resistance: X plate resistance. - * @steps_to_configure: The sequencer supports a total of - * 16 programmable steps. - * A step configured to read a single - * co-ordinate value, can be applied - * more number of times for better results. - * @wire_config: Different EVM's could have a different order - * for connecting wires on touchscreen. - * We need to provide an 8 bit number where in - * the 1st four bits represent the analog lines - * and the next 4 bits represent positive/ - * negative terminal on that input line. - * Notations to represent the input lines and - * terminals resoectively is as follows: - * AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7. - * XP = 0, XN = 1, YP = 2, YN = 3. - * - */ - -struct tsc_data { - int wires; - int x_plate_resistance; - int steps_to_configure; - int wire_config[10]; -}; - -#endif diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index fe54ba4a3b2f..533f200e6d0e 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -120,11 +120,6 @@ #define TSCADC_CELLS 2 -struct mfd_tscadc_board { - struct tsc_data *tsc_init; - struct adc_data *adc_init; -}; - struct ti_tscadc_dev { struct device *dev; struct regmap *regmap_tscadc; diff --git a/include/linux/platform_data/ti_am335x_adc.h b/include/linux/platform_data/ti_am335x_adc.h deleted file mode 100644 index e41d5834cb84..000000000000 --- a/include/linux/platform_data/ti_am335x_adc.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __LINUX_TI_AM335X_ADC_H -#define __LINUX_TI_AM335X_ADC_H - -/** - * struct adc_data ADC Input information - * @adc_channels: Number of analog inputs - * available for ADC. - */ - -struct adc_data { - unsigned int adc_channels; -}; - -#endif -- cgit v1.2.3 From 8c896308feae7fb2e8da4ae4c09fe2d2ca18ad7b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 29 May 2013 14:46:21 +0200 Subject: input: ti_am335x_adc: use only FIFO0 and clean up a little The driver programs a threshold of "coordinate_readouts" say 5. The REG_FIFO0THR registers says it should it be programmed to "threshold minus one". The driver does not expect just 5 coordinates but 5 * 2 + 2. Multiplied by two because 5 for X and 5 for Y and plus 2 because we have two Z. The whole thing kind of works because It reads the 5 coordinates for X and Y from FIFO0 and FIFO1 and the last element in each FIFO is ignored within the loop and read later. Nothing guaranties that FIFO1 is ready by the time it is read. In fact I could see that that FIFO1 reaturns for Y channels 8,9, 10, 12, 6 and for Y channel 7 for Z. The problem is that channel 7 and channel 12 got somehow mixed up. The other Problem is that FIFO1 is also used by the IIO part leading to wrong results if both (tsc & adc) are used. The patch tries to clean up the whole thing a little: - Remove the +1 and -1 in REG_STEPCONFIG, REG_STEPDELAY and its counter part in the for loop. This is just confusing. - Use only FIFO0 in TSC. The fifo has space for 64 entries so should be fine. - Read the whole FIFO in one function and check the channel. - in case we dawdle around, make sure we only read a multiple of our coordinate set. On the second interrupt we will cleanup the remaining enties. Acked-by: Dmitry Torokhov Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 2 +- drivers/input/touchscreen/ti_am335x_tsc.c | 78 ++++++++++++++++--------------- include/linux/mfd/ti_am335x_tscadc.h | 4 +- 3 files changed, 44 insertions(+), 40 deletions(-) (limited to 'include/linux') diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 4bec91e40bf7..307a7c07be47 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -75,7 +75,7 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; - for (i = (steps + 1); i <= TOTAL_STEPS; i++) { + for (i = steps; i < TOTAL_STEPS; i++) { tiadc_writel(adc_dev, REG_STEPCONFIG(i), stepconfig | STEPCONFIG_INP(channels)); tiadc_writel(adc_dev, REG_STEPDELAY(i), diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index ff3215ddf9f5..1bceb2591fc7 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -120,11 +120,9 @@ static int titsc_config_wires(struct titsc *ts_dev) static void titsc_step_config(struct titsc *ts_dev) { unsigned int config; - unsigned int stepenable = 0; - int i, total_steps; - - /* Configure the Step registers */ - total_steps = 2 * ts_dev->coordinate_readouts; + int i; + int end_step; + u32 stepenable; config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | ts_dev->bit_xp; @@ -142,7 +140,9 @@ static void titsc_step_config(struct titsc *ts_dev) break; } - for (i = 1; i <= ts_dev->coordinate_readouts; i++) { + /* 1 … coordinate_readouts is for X */ + end_step = ts_dev->coordinate_readouts; + for (i = 0; i < end_step; i++) { titsc_writel(ts_dev, REG_STEPCONFIG(i), config); titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); } @@ -150,7 +150,7 @@ static void titsc_step_config(struct titsc *ts_dev) config = 0; config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | ts_dev->bit_yn | - STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1; + STEPCONFIG_INM_ADCREFM; switch (ts_dev->wires) { case 4: config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); @@ -164,12 +164,13 @@ static void titsc_step_config(struct titsc *ts_dev) break; } - for (i = (ts_dev->coordinate_readouts + 1); i <= total_steps; i++) { + /* coordinate_readouts … coordinate_readouts * 2 is for Y */ + end_step = ts_dev->coordinate_readouts * 2; + for (i = ts_dev->coordinate_readouts; i < end_step; i++) { titsc_writel(ts_dev, REG_STEPCONFIG(i), config); titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); } - config = 0; /* Charge step configuration */ config = ts_dev->bit_xp | ts_dev->bit_yn | STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | @@ -178,35 +179,39 @@ static void titsc_step_config(struct titsc *ts_dev) titsc_writel(ts_dev, REG_CHARGECONFIG, config); titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); - config = 0; - /* Configure to calculate pressure */ + /* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */ config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | ts_dev->bit_yp | ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM | STEPCONFIG_INP(ts_dev->inp_xp); - titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config); - titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1), + titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config); + titsc_writel(ts_dev, REG_STEPDELAY(end_step), STEPCONFIG_OPENDLY); - config |= STEPCONFIG_INP(ts_dev->inp_yn) | STEPCONFIG_FIFO1; - titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config); - titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), + end_step++; + config |= STEPCONFIG_INP(ts_dev->inp_yn); + titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config); + titsc_writel(ts_dev, REG_STEPDELAY(end_step), STEPCONFIG_OPENDLY); /* The steps1 … end and bit 0 for TS_Charge */ - stepenable = (1 << (total_steps + 2)) - 1; + stepenable = (1 << (end_step + 2)) - 1; am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable); } static void titsc_read_coordinates(struct titsc *ts_dev, - unsigned int *x, unsigned int *y) + u32 *x, u32 *y, u32 *z1, u32 *z2) { unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT); unsigned int prev_val_x = ~0, prev_val_y = ~0; unsigned int prev_diff_x = ~0, prev_diff_y = ~0; unsigned int read, diff; unsigned int i, channel; + unsigned int creads = ts_dev->coordinate_readouts; + *z1 = *z2 = 0; + if (fifocount % (creads * 2 + 2)) + fifocount -= fifocount % (creads * 2 + 2); /* * Delta filter is used to remove large variations in sampled * values from ADC. The filter tries to predict where the next @@ -215,32 +220,32 @@ static void titsc_read_coordinates(struct titsc *ts_dev, * algorithm compares the difference with that of a present value, * if true the value is reported to the sub system. */ - for (i = 0; i < fifocount - 1; i++) { + for (i = 0; i < fifocount; i++) { read = titsc_readl(ts_dev, REG_FIFO0); - channel = read & 0xf0000; - channel = channel >> 0x10; - if ((channel >= 0) && (channel < ts_dev->coordinate_readouts)) { - read &= 0xfff; + + channel = (read & 0xf0000) >> 16; + read &= 0xfff; + if (channel < creads) { diff = abs(read - prev_val_x); if (diff < prev_diff_x) { prev_diff_x = diff; *x = read; } prev_val_x = read; - } - read = titsc_readl(ts_dev, REG_FIFO1); - channel = read & 0xf0000; - channel = channel >> 0x10; - if ((channel >= ts_dev->coordinate_readouts) && - (channel < (2 * ts_dev->coordinate_readouts - 1))) { - read &= 0xfff; + } else if (channel < creads * 2) { diff = abs(read - prev_val_y); if (diff < prev_diff_y) { prev_diff_y = diff; *y = read; } prev_val_y = read; + + } else if (channel < creads * 2 + 1) { + *z1 = read; + + } else if (channel < creads * 2 + 2) { + *z2 = read; } } } @@ -256,10 +261,8 @@ static irqreturn_t titsc_irq(int irq, void *dev) status = titsc_readl(ts_dev, REG_IRQSTATUS); if (status & IRQENB_FIFO0THRES) { - titsc_read_coordinates(ts_dev, &x, &y); - z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff; - z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff; + titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2); if (ts_dev->pen_down && z1 != 0 && z2 != 0) { /* @@ -267,10 +270,10 @@ static irqreturn_t titsc_irq(int irq, void *dev) * Resistance(touch) = x plate resistance * * x postion/4096 * ((z2 / z1) - 1) */ - z = z2 - z1; + z = z1 - z2; z *= x; z *= ts_dev->x_plate_resistance; - z /= z1; + z /= z2; z = (z + 2047) >> 12; if (z <= MAX_12BIT) { @@ -391,7 +394,8 @@ static int titsc_probe(struct platform_device *pdev) goto err_free_irq; } titsc_step_config(ts_dev); - titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->coordinate_readouts); + titsc_writel(ts_dev, REG_FIFO0THR, + ts_dev->coordinate_readouts * 2 + 2 - 1); input_dev->name = "ti-tsc"; input_dev->dev.parent = &pdev->dev; @@ -468,7 +472,7 @@ static int titsc_resume(struct device *dev) } titsc_step_config(ts_dev); titsc_writel(ts_dev, REG_FIFO0THR, - ts_dev->coordinate_readouts); + ts_dev->coordinate_readouts * 2 + 2 - 1); return 0; } diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 533f200e6d0e..8d73fe29796a 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -30,8 +30,8 @@ #define REG_IDLECONFIG 0x058 #define REG_CHARGECONFIG 0x05C #define REG_CHARGEDELAY 0x060 -#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8)) -#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8)) +#define REG_STEPCONFIG(n) (0x64 + ((n) * 8)) +#define REG_STEPDELAY(n) (0x68 + ((n) * 8)) #define REG_FIFO0CNT 0xE4 #define REG_FIFO0THR 0xE8 #define REG_FIFO1CNT 0xF0 -- cgit v1.2.3 From 9c717cf3fa16f8ae8c6ccb8f4f8e784404ac9689 Mon Sep 17 00:00:00 2001 From: Alexandre Torgue Date: Fri, 24 May 2013 11:59:47 +0200 Subject: mfd: ab8500-core: Add device for new RTC version for AB8540 cut2 AB8540 RTC have changed between AB8540_cut1 and AB8540_cut2.Different ressources to define for those two version. Acked-by: Linus Walleij Signed-off-by: Julien Delacou Signed-off-by: Alexandre Torgue Signed-off-by: Lee Jones --- drivers/mfd/ab8500-core.c | 55 +++++++++++++++++++++++++++++++++------ include/linux/mfd/abx500/ab8500.h | 2 ++ 2 files changed, 49 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 1863985df615..02698da00b78 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", @@ -1276,11 +1291,6 @@ static struct mfd_cell ab8540_devs[] = { .num_resources = ARRAY_SIZE(ab8505_gpadc_resources), .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), @@ -1318,6 +1328,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) { @@ -1721,11 +1749,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/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index 0390d5943ed6..f4acd898dac9 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -291,6 +291,8 @@ enum ab8500_version { #define AB8540_INT_FSYNC2R 213 #define AB8540_INT_BITCLK2F 214 #define AB8540_INT_BITCLK2R 215 +/* ab8540_irq_regoffset[27] -> IT[Source|Latch|Mask]33 */ +#define AB8540_INT_RTC_1S 216 /* * AB8500_AB9540_NR_IRQS is used when configuring the IRQ numbers for the -- cgit v1.2.3 From dc7d48635dd3c3fd5360238f7d2c697ff13abe7b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 13 Jun 2013 09:43:29 +0100 Subject: mfd: arizona: Integrate wm8997 into Arizona mfd The wm8997 is a compact, high-performance audio hub CODEC with SLIMbus interfacing, for smartphones, tablets and other portable audio devices based on the Arizona platform. This patch integrates the wm8997 into the Arizona mfd. Signed-off-by: Charles Keepax Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 6 + drivers/mfd/Makefile | 3 + drivers/mfd/arizona-core.c | 27 + drivers/mfd/arizona-i2c.c | 6 + drivers/mfd/arizona-irq.c | 8 + drivers/mfd/arizona.h | 5 + drivers/mfd/wm8997-tables.c | 1525 ++++++++++++++++++++++++++++++++++++++ include/linux/mfd/arizona/core.h | 2 + 8 files changed, 1582 insertions(+) create mode 100644 drivers/mfd/wm8997-tables.c (limited to 'include/linux') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index c6eb930fb54d..29f7363f6bc4 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1047,6 +1047,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 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 31d0f97d6e50..4d70cdb044e0 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 diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 74b4481754fd..89a115301a0c 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); @@ -767,6 +779,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); @@ -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 deb267ebf84e..51dbabf7c021 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c @@ -44,6 +44,11 @@ static int arizona_i2c_probe(struct i2c_client *i2c, case WM5110: 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", @@ -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 64cd9b6dac92..88758ab9402b 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 db55d9854a55..b4cef777df73 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/wm8997-tables.c b/drivers/mfd/wm8997-tables.c new file mode 100644 index 000000000000..5aa807687777 --- /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 + * + * 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 + +#include +#include + +#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); diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h index f797bb9b8b56..5cf8b91ce996 100644 --- a/include/linux/mfd/arizona/core.h +++ b/include/linux/mfd/arizona/core.h @@ -23,6 +23,7 @@ enum arizona_type { WM5102 = 1, WM5110 = 2, + WM8997 = 3, }; #define ARIZONA_IRQ_GP1 0 @@ -121,5 +122,6 @@ int arizona_set_irq_wake(struct arizona *arizona, int irq, int on); int wm5102_patch(struct arizona *arizona); int wm5110_patch(struct arizona *arizona); +int wm8997_patch(struct arizona *arizona); #endif -- cgit v1.2.3 From c750d8e053c08ccb82d814d695e64d1eb602a91a Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 14 Jun 2013 01:21:49 -0400 Subject: mfd: 88pm800: Remove the power and gpadc page addr from platform data 88pm800 has two addtional pages - power and gpadc. The address of the pages depends on the address of 88pm800. So do not need pass the address of the power and gpadc in platform data. Signed-off-by: Chao Xie Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 5 +++-- include/linux/mfd/88pm80x.h | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index d2951d749bf3..6b607adebce1 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -525,8 +525,9 @@ 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 = pm800_pages_init(chip); diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h index e94537befabd..023e6395da87 100644 --- a/include/linux/mfd/88pm80x.h +++ b/include/linux/mfd/88pm80x.h @@ -309,8 +309,6 @@ struct pm80x_chip { struct pm80x_platform_data { struct pm80x_rtc_pdata *rtc; - unsigned short power_page_addr; /* power page I2C address */ - unsigned short gpadc_page_addr; /* gpadc page I2C address */ int irq_mode; /* Clear interrupt by read/write(0/1) */ int batt_det; /* enable/disable */ int (*plat_config)(struct pm80x_chip *chip, -- cgit v1.2.3 From 03dcc544bff9ff36b9ac5e2b992a7a4890e6edc4 Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 14 Jun 2013 01:21:51 -0400 Subject: mfd: 88pm80x: Change chip id definition and detection Change the chip id definition and detection and then: 1. We no longer need to add PM800_CHIP_XXX for the coming revision. 2. We no longer need to pass driver_data in i2c_device_id as we can distinguish the chips from the CHIP_ID register. Signed-off-by: Chao Xie Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 42 ++++++---------------------------------- drivers/mfd/88pm805.c | 16 +++------------ drivers/mfd/88pm80x.c | 47 ++++++++++++++++++++++++++++++++++++++------- include/linux/mfd/88pm80x.h | 7 ++----- 4 files changed, 51 insertions(+), 61 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index 4ebb2e215bac..2c0b4155181f 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -28,8 +28,6 @@ #include #include -#define PM800_CHIP_ID (0x00) - /* Interrupt Registers */ #define PM800_INT_STATUS1 (0x05) #define PM800_ONKEY_INT_STS1 (1 << 0) @@ -114,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); @@ -434,28 +423,9 @@ static void pm800_pages_exit(struct pm80x_chip *chip) 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 @@ -523,7 +493,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; @@ -553,7 +523,7 @@ static int pm800_probe(struct i2c_client *client, ret = device_800_init(chip, pdata); if (ret) { - dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); + dev_err(chip->dev, "Failed to initialize 88pm800 devices\n"); goto err_device_init; } diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index 0e82c2a1e842..521602231c7b 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -29,10 +29,8 @@ #include #include -#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); @@ -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; } diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c index f736a46eb8c0..5e72f65ef94c 100644 --- a/drivers/mfd/88pm80x.c +++ b/drivers/mfd/88pm80x.c @@ -18,6 +18,23 @@ #include #include +/* 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/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h index 023e6395da87..4a66a5633031 100644 --- a/include/linux/mfd/88pm80x.h +++ b/include/linux/mfd/88pm80x.h @@ -17,7 +17,6 @@ #include #include -#define PM80X_VERSION_MASK (0xFF) /* 80X chip ID mask */ enum { CHIP_INVALID = 0, CHIP_PM800, @@ -299,8 +298,7 @@ struct pm80x_chip { struct regmap *regmap; struct regmap_irq_chip *regmap_irq_chip; struct regmap_irq_chip_data *irq_data; - unsigned char version; - int id; + int type; int irq; int irq_mode; unsigned long wu_flag; @@ -361,7 +359,6 @@ static inline int pm80x_dev_resume(struct device *dev) } #endif -extern int pm80x_init(struct i2c_client *client, - const struct i2c_device_id *id); +extern int pm80x_init(struct i2c_client *client); extern int pm80x_deinit(void); #endif /* __LINUX_MFD_88PM80X_H */ -- cgit v1.2.3 From 2d3aa0569cc111b7567cb082c2f8ab32e2245e49 Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 14 Jun 2013 01:21:53 -0400 Subject: mfd: 88pm800: Add regulator sub device Signed-off-by: Chao Xie Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 28 ++++++++++++++++++++++++++++ include/linux/mfd/88pm80x.h | 8 ++++++++ 2 files changed, 36 insertions(+) (limited to 'include/linux') diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index a475fb3c2d0c..6c954835d61e 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -157,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] = { @@ -339,6 +346,21 @@ static int device_rtc_init(struct pm80x_chip *chip, 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; @@ -500,6 +522,12 @@ static int device_800_init(struct pm80x_chip *chip, goto out; } + ret = device_regulator_init(chip, pdata); + if (ret) { + dev_err(chip->dev, "Failed to add regulators subdev\n"); + goto out; + } + return 0; out_dev: mfd_remove_devices(chip->dev); diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h index 4a66a5633031..97cb283cc8e1 100644 --- a/include/linux/mfd/88pm80x.h +++ b/include/linux/mfd/88pm80x.h @@ -307,6 +307,14 @@ struct pm80x_chip { struct pm80x_platform_data { struct pm80x_rtc_pdata *rtc; + /* + * For the regulator not defined, set regulators[not_defined] to be + * NULL. num_regulators are the number of regulators supposed to be + * initialized. If all regulators are not defined, set num_regulators + * to be 0. + */ + struct regulator_init_data *regulators[PM800_ID_RG_MAX]; + unsigned int num_regulators; int irq_mode; /* Clear interrupt by read/write(0/1) */ int batt_det; /* enable/disable */ int (*plat_config)(struct pm80x_chip *chip, -- cgit v1.2.3 From 637d6895f8f5ecc041ca6f521f544bb3d5699416 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 18 Jun 2013 15:17:56 +0200 Subject: mfd: twl4030-power: Split from twl-core into a dedicated module For now, the call to twl4030-power is hard-wired inside twl-core. To ease the future transition to DT, make twl4030-power as a separate module, like what is already done for twl4030-audio and others. Signed-off-by: Florian Vaussard Signed-off-by: Samuel Ortiz --- drivers/mfd/twl-core.c | 12 ++++++++---- drivers/mfd/twl4030-power.c | 43 +++++++++++++++++++++++++++++++++---------- include/linux/i2c/twl.h | 1 - 3 files changed, 41 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 8d9bc10c5312..dbd52b373b27 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -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; } @@ -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()) { diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index dd362c1078e1..94bcbeed1d62 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -507,8 +507,9 @@ void twl4030_power_off(void) pr_err("TWL4030 Unable to power off\n"); } -void twl4030_power_init(struct twl4030_power_data *twl4030_scripts) +int twl4030_power_probe(struct platform_device *pdev) { + struct twl4030_power_data *pdata = pdev->dev.platform_data; int err = 0; int i; struct twl4030_resconfig *resconfig; @@ -524,14 +525,14 @@ void twl4030_power_init(struct twl4030_power_data *twl4030_scripts) if (err) goto unlock; - for (i = 0; i < twl4030_scripts->num; i++) { - err = load_twl4030_script(twl4030_scripts->scripts[i], address); + for (i = 0; i < pdata->num; i++) { + err = load_twl4030_script(pdata->scripts[i], address); if (err) goto load; - address += twl4030_scripts->scripts[i]->size; + address += pdata->scripts[i]->size; } - resconfig = twl4030_scripts->resource_config; + resconfig = pdata->resource_config; if (resconfig) { while (resconfig->resource) { err = twl4030_configure_resource(resconfig); @@ -543,7 +544,7 @@ void twl4030_power_init(struct twl4030_power_data *twl4030_scripts) } /* Board has to be wired properly to use this feature */ - if (twl4030_scripts->use_poweroff && !pm_power_off) { + if (pdata->use_poweroff && !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); @@ -568,18 +569,40 @@ relock: TWL4030_PM_MASTER_PROTECT_KEY); if (err) pr_err("TWL4030 Unable to relock registers\n"); - return; + return err; unlock: if (err) pr_err("TWL4030 Unable to unlock registers\n"); - return; + return err; load: if (err) pr_err("TWL4030 failed to load scripts\n"); - return; + return err; 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; } + +static struct platform_driver twl4030_power_driver = { + .driver = { + .name = "twl4030_power", + .owner = THIS_MODULE, + }, + .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/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 488debbef895..2167c0d00abf 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -658,7 +658,6 @@ struct twl4030_power_data { bool use_poweroff; /* Board is wired for TWL poweroff */ }; -extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts); extern int twl4030_remove_script(u8 flags); extern void twl4030_power_off(void); -- cgit v1.2.3 From c8eaed458e2cfbd906dbbe1af49aa028f59cc132 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 18 Jun 2013 15:35:40 +0530 Subject: mfd: davinci_voicecodec: Convert to use devm_* APIs devm_* APIs are device managed and make code simpler. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/davinci_voicecodec.c | 48 +++++++--------------------------- include/linux/mfd/davinci_voicecodec.h | 2 -- 2 files changed, 10 insertions(+), 40 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index b6e297363946..fb64398506e9 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c @@ -46,7 +46,7 @@ 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; @@ -58,7 +58,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev) 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"); @@ -67,35 +67,18 @@ static int __init davinci_vc_probe(struct platform_device *pdev) 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,19 +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; return ret; } @@ -155,12 +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; return 0; } diff --git a/include/linux/mfd/davinci_voicecodec.h b/include/linux/mfd/davinci_voicecodec.h index 0ab61320ffa8..94c53d4819c7 100644 --- a/include/linux/mfd/davinci_voicecodec.h +++ b/include/linux/mfd/davinci_voicecodec.h @@ -112,8 +112,6 @@ struct davinci_vc { /* Memory resources */ void __iomem *base; - resource_size_t pbase; - size_t base_size; /* MFD cells */ struct mfd_cell cells[DAVINCI_VC_CELLS]; -- cgit v1.2.3 From 997174705458d2abdbc31ba1594bf2a4503cb41a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 18 Jun 2013 15:35:39 +0530 Subject: mfd: davinci_voicecodec: Fix build breakage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include the missing header file to fix the following build error: drivers/mfd/davinci_voicecodec.c: In function ‘davinci_vc_probe’: drivers/mfd/davinci_voicecodec.c:86:3: error: implicit declaration of function ‘io_v2p’ [-Werror=implicit-function-declaration] (dma_addr_t)(io_v2p(davinci_vc->base) + DAVINCI_VC_WFIFO); Signed-off-by: Sachin Kamat Signed-off-by: Samuel Ortiz --- include/linux/mfd/davinci_voicecodec.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/mfd/davinci_voicecodec.h b/include/linux/mfd/davinci_voicecodec.h index 94c53d4819c7..810aee7e53eb 100644 --- a/include/linux/mfd/davinci_voicecodec.h +++ b/include/linux/mfd/davinci_voicecodec.h @@ -28,6 +28,7 @@ #include #include +#include /* * Register values. -- cgit v1.2.3 From 89ce43fbbce525f99991ed060b1302bd3fdae9c6 Mon Sep 17 00:00:00 2001 From: Graeme Gregory Date: Wed, 19 Jun 2013 15:24:02 +0300 Subject: mfd: twl-core: Change TWL6025 references to TWL6032 The TWL6025 was never released beyond sample form and was replaced by the PhoenixLite range of chips - TWL6032. Change the references to reference the TWL6032 class and name the registers to twl6032 in line with an actual released chip name to avoid confusion. Currently there are no users of TWL6025 in the code. Signed-off-by: Graeme Gregory Signed-off-by: Oleksandr Kozaruk Acked-by: Lee Jones Reviwed-by: Mark Brown Signed-off-by: Samuel Ortiz --- .../bindings/regulator/twl-regulator.txt | 26 ++++---- .../devicetree/bindings/usb/twlxxxx-usb.txt | 2 +- drivers/mfd/twl-core.c | 46 ++++++------- drivers/regulator/twl-regulator.c | 76 +++++++++++----------- drivers/usb/phy/phy-twl6030-usb.c | 2 +- include/linux/i2c/twl.h | 30 ++++----- 6 files changed, 91 insertions(+), 91 deletions(-) (limited to 'include/linux') diff --git a/Documentation/devicetree/bindings/regulator/twl-regulator.txt b/Documentation/devicetree/bindings/regulator/twl-regulator.txt index 658749b90b97..75b0c1669504 100644 --- a/Documentation/devicetree/bindings/regulator/twl-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/twl-regulator.txt @@ -18,20 +18,20 @@ For twl6030 regulators/LDOs - "ti,twl6030-vdd1" for VDD1 SMPS - "ti,twl6030-vdd2" for VDD2 SMPS - "ti,twl6030-vdd3" for VDD3 SMPS -For twl6025 regulators/LDOs +For twl6032 regulators/LDOs - compatible: - - "ti,twl6025-ldo1" for LDO1 LDO - - "ti,twl6025-ldo2" for LDO2 LDO - - "ti,twl6025-ldo3" for LDO3 LDO - - "ti,twl6025-ldo4" for LDO4 LDO - - "ti,twl6025-ldo5" for LDO5 LDO - - "ti,twl6025-ldo6" for LDO6 LDO - - "ti,twl6025-ldo7" for LDO7 LDO - - "ti,twl6025-ldoln" for LDOLN LDO - - "ti,twl6025-ldousb" for LDOUSB LDO - - "ti,twl6025-smps3" for SMPS3 SMPS - - "ti,twl6025-smps4" for SMPS4 SMPS - - "ti,twl6025-vio" for VIO SMPS + - "ti,twl6032-ldo1" for LDO1 LDO + - "ti,twl6032-ldo2" for LDO2 LDO + - "ti,twl6032-ldo3" for LDO3 LDO + - "ti,twl6032-ldo4" for LDO4 LDO + - "ti,twl6032-ldo5" for LDO5 LDO + - "ti,twl6032-ldo6" for LDO6 LDO + - "ti,twl6032-ldo7" for LDO7 LDO + - "ti,twl6032-ldoln" for LDOLN LDO + - "ti,twl6032-ldousb" for LDOUSB LDO + - "ti,twl6032-smps3" for SMPS3 SMPS + - "ti,twl6032-smps4" for SMPS4 SMPS + - "ti,twl6032-vio" for VIO SMPS For twl4030 regulators/LDOs - compatible: - "ti,twl4030-vaux1" for VAUX1 LDO diff --git a/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt index 36b9aede3f40..0aee0ad3f035 100644 --- a/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt +++ b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt @@ -8,7 +8,7 @@ TWL6030 USB COMPARATOR usb interrupt number that raises VBUS interrupts when the controller has to act as device - usb-supply : phandle to the regulator device tree node. It should be vusb - if it is twl6030 or ldousb if it is twl6025 subclass. + if it is twl6030 or ldousb if it is twl6032 subclass. twl6030-usb { compatible = "ti,twl6030-usb"; diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index dbd52b373b27..7f150d94d295 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); @@ -1184,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; @@ -1296,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); diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index fb6e67d74ffb..93bc4f456da4 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -109,7 +109,7 @@ struct twlreg_info { #define SMPS_OFFSET_EN BIT(0) #define SMPS_EXTENDED_EN BIT(1) -/* twl6025 SMPS EPROM values */ +/* twl6032 SMPS EPROM values */ #define TWL6030_SMPS_OFFSET 0xB0 #define TWL6030_SMPS_MULT 0xB3 #define SMPS_MULTOFFSET_SMPS4 BIT(0) @@ -173,7 +173,7 @@ static int twl6030reg_is_enabled(struct regulator_dev *rdev) struct twlreg_info *info = rdev_get_drvdata(rdev); int grp = 0, val; - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) { + if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) { grp = twlreg_grp(rdev); if (grp < 0) return grp; @@ -211,7 +211,7 @@ static int twl6030reg_enable(struct regulator_dev *rdev) int grp = 0; int ret; - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) + if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) grp = twlreg_grp(rdev); if (grp < 0) return grp; @@ -245,7 +245,7 @@ static int twl6030reg_disable(struct regulator_dev *rdev) int grp = 0; int ret; - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) + if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030; /* For 6030, set the off state for all grps enabled */ @@ -339,7 +339,7 @@ static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode) int grp = 0; int val; - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) + if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) grp = twlreg_grp(rdev); if (grp < 0) @@ -899,14 +899,14 @@ static const struct twlreg_info TWL6030_INFO_##label = { \ }, \ } -#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \ -static const struct twlreg_info TWL6025_INFO_##label = { \ +#define TWL6032_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \ +static const struct twlreg_info TWL6032_INFO_##label = { \ .base = offset, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ .desc = { \ .name = #label, \ - .id = TWL6025_REG_##label, \ + .id = TWL6032_REG_##label, \ .n_voltages = 32, \ .ops = &twl6030ldo_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -933,14 +933,14 @@ static const struct twlreg_info TWLFIXED_INFO_##label = { \ }, \ } -#define TWL6025_ADJUSTABLE_SMPS(label, offset) \ +#define TWL6032_ADJUSTABLE_SMPS(label, offset) \ static const struct twlreg_info TWLSMPS_INFO_##label = { \ .base = offset, \ .min_mV = 600, \ .max_mV = 2100, \ .desc = { \ .name = #label, \ - .id = TWL6025_REG_##label, \ + .id = TWL6032_REG_##label, \ .n_voltages = 63, \ .ops = &twlsmps_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -981,15 +981,15 @@ TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300); TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300); TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300); /* 6025 are renamed compared to 6030 versions */ -TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300); TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08); TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08); TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08); @@ -1001,9 +1001,9 @@ TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0); TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0); TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0); TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0); -TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34); -TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10); -TWL6025_ADJUSTABLE_SMPS(VIO, 0x16); +TWL6032_ADJUSTABLE_SMPS(SMPS3, 0x34); +TWL6032_ADJUSTABLE_SMPS(SMPS4, 0x10); +TWL6032_ADJUSTABLE_SMPS(VIO, 0x16); static u8 twl_get_smps_offset(void) { @@ -1031,7 +1031,7 @@ static u8 twl_get_smps_mult(void) #define TWL4030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL4030, label) #define TWL6030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6030, label) -#define TWL6025_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6025, label) +#define TWL6032_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6032, label) #define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label) #define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label) @@ -1060,15 +1060,15 @@ static const struct of_device_id twl_of_match[] = { TWL6030_OF_MATCH("ti,twl6030-vmmc", VMMC), TWL6030_OF_MATCH("ti,twl6030-vpp", VPP), TWL6030_OF_MATCH("ti,twl6030-vusim", VUSIM), - TWL6025_OF_MATCH("ti,twl6025-ldo2", LDO2), - TWL6025_OF_MATCH("ti,twl6025-ldo4", LDO4), - TWL6025_OF_MATCH("ti,twl6025-ldo3", LDO3), - TWL6025_OF_MATCH("ti,twl6025-ldo5", LDO5), - TWL6025_OF_MATCH("ti,twl6025-ldo1", LDO1), - TWL6025_OF_MATCH("ti,twl6025-ldo7", LDO7), - TWL6025_OF_MATCH("ti,twl6025-ldo6", LDO6), - TWL6025_OF_MATCH("ti,twl6025-ldoln", LDOLN), - TWL6025_OF_MATCH("ti,twl6025-ldousb", LDOUSB), + TWL6032_OF_MATCH("ti,twl6032-ldo2", LDO2), + TWL6032_OF_MATCH("ti,twl6032-ldo4", LDO4), + TWL6032_OF_MATCH("ti,twl6032-ldo3", LDO3), + TWL6032_OF_MATCH("ti,twl6032-ldo5", LDO5), + TWL6032_OF_MATCH("ti,twl6032-ldo1", LDO1), + TWL6032_OF_MATCH("ti,twl6032-ldo7", LDO7), + TWL6032_OF_MATCH("ti,twl6032-ldo6", LDO6), + TWL6032_OF_MATCH("ti,twl6032-ldoln", LDOLN), + TWL6032_OF_MATCH("ti,twl6032-ldousb", LDOUSB), TWLFIXED_OF_MATCH("ti,twl4030-vintana1", VINTANA1), TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG), TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5), @@ -1080,9 +1080,9 @@ static const struct of_device_id twl_of_match[] = { TWLFIXED_OF_MATCH("ti,twl6030-vusb", VUSB), TWLFIXED_OF_MATCH("ti,twl6030-v1v8", V1V8), TWLFIXED_OF_MATCH("ti,twl6030-v2v1", V2V1), - TWLSMPS_OF_MATCH("ti,twl6025-smps3", SMPS3), - TWLSMPS_OF_MATCH("ti,twl6025-smps4", SMPS4), - TWLSMPS_OF_MATCH("ti,twl6025-vio", VIO), + TWLSMPS_OF_MATCH("ti,twl6032-smps3", SMPS3), + TWLSMPS_OF_MATCH("ti,twl6032-smps4", SMPS4), + TWLSMPS_OF_MATCH("ti,twl6032-vio", VIO), {}, }; MODULE_DEVICE_TABLE(of, twl_of_match); @@ -1163,19 +1163,19 @@ static int twlreg_probe(struct platform_device *pdev) } switch (id) { - case TWL6025_REG_SMPS3: + case TWL6032_REG_SMPS3: if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3) info->flags |= SMPS_OFFSET_EN; break; - case TWL6025_REG_SMPS4: + case TWL6032_REG_SMPS4: if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4) info->flags |= SMPS_OFFSET_EN; break; - case TWL6025_REG_VIO: + case TWL6032_REG_VIO: if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO) diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index 9de7ada90a8b..1753bd367e0a 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c @@ -347,7 +347,7 @@ static int twl6030_usb_probe(struct platform_device *pdev) if (np) { twl->regulator = "usb"; } else if (pdata) { - if (pdata->features & TWL6025_SUBCLASS) + if (pdata->features & TWL6032_SUBCLASS) twl->regulator = "ldousb"; else twl->regulator = "vusb"; diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 2167c0d00abf..81cbbdb96aae 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -725,7 +725,7 @@ struct twl4030_platform_data { struct regulator_init_data *clk32kg; struct regulator_init_data *v1v8; struct regulator_init_data *v2v1; - /* TWL6025 LDO regulators */ + /* TWL6032 LDO regulators */ struct regulator_init_data *ldo1; struct regulator_init_data *ldo2; struct regulator_init_data *ldo3; @@ -735,7 +735,7 @@ struct twl4030_platform_data { struct regulator_init_data *ldo7; struct regulator_init_data *ldoln; struct regulator_init_data *ldousb; - /* TWL6025 DCDC regulators */ + /* TWL6032 DCDC regulators */ struct regulator_init_data *smps3; struct regulator_init_data *smps4; struct regulator_init_data *vio6025; @@ -752,7 +752,7 @@ struct twl_regulator_driver_data { #define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */ #define TWL5031 BIT(2) /* twl5031 has different registers */ #define TWL6030_CLASS BIT(3) /* TWL6030 class */ -#define TWL6025_SUBCLASS BIT(4) /* TWL6025 has changed registers */ +#define TWL6032_SUBCLASS BIT(4) /* TWL6032 has changed registers */ #define TWL4030_ALLOW_UNSUPPORTED BIT(5) /* Some voltages are possible * but not officially supported. * This flag is necessary to @@ -839,20 +839,20 @@ static inline int twl4030charger_usb_en(int enable) { return 0; } #define TWL6030_REG_CLK32KG 48 /* LDOs on 6025 have different names */ -#define TWL6025_REG_LDO2 49 -#define TWL6025_REG_LDO4 50 -#define TWL6025_REG_LDO3 51 -#define TWL6025_REG_LDO5 52 -#define TWL6025_REG_LDO1 53 -#define TWL6025_REG_LDO7 54 -#define TWL6025_REG_LDO6 55 -#define TWL6025_REG_LDOLN 56 -#define TWL6025_REG_LDOUSB 57 +#define TWL6032_REG_LDO2 49 +#define TWL6032_REG_LDO4 50 +#define TWL6032_REG_LDO3 51 +#define TWL6032_REG_LDO5 52 +#define TWL6032_REG_LDO1 53 +#define TWL6032_REG_LDO7 54 +#define TWL6032_REG_LDO6 55 +#define TWL6032_REG_LDOLN 56 +#define TWL6032_REG_LDOUSB 57 /* 6025 DCDC supplies */ -#define TWL6025_REG_SMPS3 58 -#define TWL6025_REG_SMPS4 59 -#define TWL6025_REG_VIO 60 +#define TWL6032_REG_SMPS3 58 +#define TWL6032_REG_SMPS4 59 +#define TWL6032_REG_VIO 60 #endif /* End of __TWL4030_H */ -- cgit v1.2.3 From 1ffb0be3ad6186b421921de91092917f0b3ee3e2 Mon Sep 17 00:00:00 2001 From: J Keerthy Date: Wed, 19 Jun 2013 11:27:48 +0530 Subject: mfd: palmas: Add SMPS10_BOOST feature The SMPS10 regulator is not presesnt in all the variants of the PALMAS PMIC family. Hence adding a feature to distingush between them. Signed-off-by: J Keerthy Signed-off-by: Samuel Ortiz --- drivers/mfd/palmas.c | 29 +++++++++++++++++++++-------- drivers/regulator/palmas-regulator.c | 3 +++ include/linux/mfd/palmas.h | 14 ++++++++++++++ 3 files changed, 38 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index b24bee3d00b4..a4e53caa76cd 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = { { @@ -231,6 +231,16 @@ 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 const struct of_device_id of_palmas_match_tbl[] = { + { + .compatible = "ti,palmas", + .data = &palmas_features, + }, + { }, +}; + static int palmas_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -238,8 +248,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; + const struct of_device_id *match; pdata = dev_get_platdata(&i2c->dev); @@ -261,9 +272,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; @@ -433,11 +451,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/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 3ae44ac12a94..1ae1e83448cf 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -838,6 +838,9 @@ static int palmas_regulators_probe(struct platform_device *pdev) continue; ramp_delay_support = true; break; + case PALMAS_REG_SMPS10: + if (!PALMAS_PMIC_HAS(palmas, SMPS10_BOOST)) + continue; } if ((id == PALMAS_REG_SMPS6) || (id == PALMAS_REG_SMPS8)) diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h index 8f21daf62fb5..98058caa7aca 100644 --- a/include/linux/mfd/palmas.h +++ b/include/linux/mfd/palmas.h @@ -32,6 +32,19 @@ ((a) == PALMAS_CHIP_ID)) #define is_palmas_charger(a) ((a) == PALMAS_CHIP_CHARGER_ID) +/** + * Palmas PMIC feature types + * + * PALMAS_PMIC_FEATURE_SMPS10_BOOST - used when the PMIC provides SMPS10_BOOST + * regulator. + * + * PALMAS_PMIC_HAS(b, f) - macro to check if a bandgap device is capable of a + * specific feature (above) or not. Return non-zero, if yes. + */ +#define PALMAS_PMIC_FEATURE_SMPS10_BOOST BIT(0) +#define PALMAS_PMIC_HAS(b, f) \ + ((b)->features & PALMAS_PMIC_FEATURE_ ## f) + struct palmas_pmic; struct palmas_gpadc; struct palmas_resource; @@ -46,6 +59,7 @@ struct palmas { /* Stored chip id */ int id; + unsigned int features; /* IRQ Data */ int irq; u32 irq_mask; -- cgit v1.2.3 From 43620a17945b598e707ef897b3866914f9f9056c Mon Sep 17 00:00:00 2001 From: Kevin Strasser Date: Sun, 23 Jun 2013 21:00:03 -0700 Subject: mfd: Kontron PLD mfd driver Add core MFD driver for the on-board PLD found on some Kontron embedded 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 Originally-From: Michael Brunner Signed-off-by: Kevin Strasser Acked-by: Guenter Roeck Acked-by: Darren Hart Acked-by: Thomas Gleixner Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 21 ++ drivers/mfd/Makefile | 1 + drivers/mfd/kempld-core.c | 641 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/kempld.h | 125 +++++++++ 4 files changed, 788 insertions(+) create mode 100644 drivers/mfd/kempld-core.c create mode 100644 include/linux/mfd/kempld.h (limited to 'include/linux') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3e3be603cf82..3bb2932eafb1 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -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 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 4d70cdb044e0..3c90051ffa5a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -129,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 diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c new file mode 100644 index 000000000000..686a4565acb6 --- /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 + * + * 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 +#include +#include +#include +#include +#include +#include + +#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 "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:kempld-core"); diff --git a/include/linux/mfd/kempld.h b/include/linux/mfd/kempld.h new file mode 100644 index 000000000000..b911ef3add03 --- /dev/null +++ b/include/linux/mfd/kempld.h @@ -0,0 +1,125 @@ +/* + * Kontron PLD driver definitions + * + * Copyright (c) 2010-2012 Kontron Europe GmbH + * Author: Michael Brunner + * + * 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. + */ + +#ifndef _LINUX_MFD_KEMPLD_H_ +#define _LINUX_MFD_KEMPLD_H_ + +/* kempld register definitions */ +#define KEMPLD_IOINDEX 0xa80 +#define KEMPLD_IODATA 0xa81 +#define KEMPLD_MUTEX_KEY 0x80 +#define KEMPLD_VERSION 0x00 +#define KEMPLD_VERSION_LSB 0x00 +#define KEMPLD_VERSION_MSB 0x01 +#define KEMPLD_VERSION_GET_MINOR(x) (x & 0x1f) +#define KEMPLD_VERSION_GET_MAJOR(x) ((x >> 5) & 0x1f) +#define KEMPLD_VERSION_GET_NUMBER(x) ((x >> 10) & 0xf) +#define KEMPLD_VERSION_GET_TYPE(x) ((x >> 14) & 0x3) +#define KEMPLD_BUILDNR 0x02 +#define KEMPLD_BUILDNR_LSB 0x02 +#define KEMPLD_BUILDNR_MSB 0x03 +#define KEMPLD_FEATURE 0x04 +#define KEMPLD_FEATURE_LSB 0x04 +#define KEMPLD_FEATURE_MSB 0x05 +#define KEMPLD_FEATURE_BIT_I2C (1 << 0) +#define KEMPLD_FEATURE_BIT_WATCHDOG (1 << 1) +#define KEMPLD_FEATURE_BIT_GPIO (1 << 2) +#define KEMPLD_FEATURE_MASK_UART (7 << 3) +#define KEMPLD_FEATURE_BIT_NMI (1 << 8) +#define KEMPLD_FEATURE_BIT_SMI (1 << 9) +#define KEMPLD_FEATURE_BIT_SCI (1 << 10) +#define KEMPLD_SPEC 0x06 +#define KEMPLD_SPEC_GET_MINOR(x) (x & 0x0f) +#define KEMPLD_SPEC_GET_MAJOR(x) ((x >> 4) & 0x0f) +#define KEMPLD_IRQ_GPIO 0x35 +#define KEMPLD_IRQ_I2C 0x36 +#define KEMPLD_CFG 0x37 +#define KEMPLD_CFG_GPIO_I2C_MUX (1 << 0) +#define KEMPLD_CFG_BIOS_WP (1 << 7) + +#define KEMPLD_CLK 33333333 + +#define KEMPLD_TYPE_RELEASE 0x0 +#define KEMPLD_TYPE_DEBUG 0x1 +#define KEMPLD_TYPE_CUSTOM 0x2 + +/** + * struct kempld_info - PLD device information structure + * @major: PLD major revision + * @minor: PLD minor revision + * @buildnr: PLD build number + * @number: PLD board specific index + * @type: PLD type + * @spec_major: PLD FW specification major revision + * @spec_minor: PLD FW specification minor revision + */ +struct kempld_info { + unsigned int major; + unsigned int minor; + unsigned int buildnr; + unsigned int number; + unsigned int type; + unsigned int spec_major; + unsigned int spec_minor; +}; + +/** + * struct kempld_device_data - Internal representation of the PLD device + * @io_base: Pointer to the IO memory + * @io_index: Pointer to the IO index register + * @io_data: Pointer to the IO data register + * @pld_clock: PLD clock frequency + * @feature_mask: PLD feature mask + * @dev: Pointer to kernel device structure + * @info: KEMPLD info structure + * @lock: PLD mutex + */ +struct kempld_device_data { + void __iomem *io_base; + void __iomem *io_index; + void __iomem *io_data; + u32 pld_clock; + u32 feature_mask; + struct device *dev; + struct kempld_info info; + struct mutex lock; +}; + +/** + * struct kempld_platform_data - PLD hardware configuration structure + * @pld_clock: PLD clock frequency + * @gpio_base GPIO base pin number + * @ioresource: IO addresses of the PLD + * @get_mutex: PLD specific get_mutex callback + * @release_mutex: PLD specific release_mutex callback + * @get_info: PLD specific get_info callback + * @register_cells: PLD specific register_cells callback + */ +struct kempld_platform_data { + u32 pld_clock; + int gpio_base; + struct resource *ioresource; + void (*get_hardware_mutex) (struct kempld_device_data *); + void (*release_hardware_mutex) (struct kempld_device_data *); + int (*get_info) (struct kempld_device_data *); + int (*register_cells) (struct kempld_device_data *); +}; + +extern void kempld_get_mutex(struct kempld_device_data *pld); +extern void kempld_release_mutex(struct kempld_device_data *pld); +extern u8 kempld_read8(struct kempld_device_data *pld, u8 index); +extern void kempld_write8(struct kempld_device_data *pld, u8 index, u8 data); +extern u16 kempld_read16(struct kempld_device_data *pld, u8 index); +extern void kempld_write16(struct kempld_device_data *pld, u8 index, u16 data); +extern u32 kempld_read32(struct kempld_device_data *pld, u8 index); +extern void kempld_write32(struct kempld_device_data *pld, u8 index, u32 data); + +#endif /* _LINUX_MFD_KEMPLD_H_ */ -- cgit v1.2.3 From 443c6ae253e96db9a5800a28d7c61131e81c2dee Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 24 Jun 2013 14:39:52 +0200 Subject: mfd: max8998: Add irq domain support This patch adds irq domain support for max8998 interrupts. To keep both non-DT and DT worlds happy, simple domain is used, which is linear when no explicit IRQ base is specified and legacy, with static mapping, otherwise. Signed-off-by: Tomasz Figa Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 1 + drivers/mfd/max8998-irq.c | 65 +++++++++++++++++++++++-------------- drivers/rtc/rtc-max8998.c | 12 ++++++- include/linux/mfd/max8998-private.h | 5 ++- include/linux/mfd/max8998.h | 2 +- 5 files changed, 57 insertions(+), 28 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3bb2932eafb1..aecd6ddcbbbf 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -363,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. diff --git a/drivers/mfd/max8998-irq.c b/drivers/mfd/max8998-irq.c index 5919710dc9ed..c469477eb778 100644 --- a/drivers/mfd/max8998-irq.c +++ b/drivers/mfd/max8998-irq.c @@ -14,6 +14,7 @@ #include #include #include +#include #include 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/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c index d5af7baa48b5..46f23014759b 100644 --- a/drivers/rtc/rtc-max8998.c +++ b/drivers/rtc/rtc-max8998.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -264,7 +265,6 @@ static int max8998_rtc_probe(struct platform_device *pdev) info->dev = &pdev->dev; info->max8998 = max8998; info->rtc = max8998->rtc; - info->irq = max8998->irq_base + MAX8998_IRQ_ALARM0; platform_set_drvdata(pdev, info); @@ -277,6 +277,15 @@ static int max8998_rtc_probe(struct platform_device *pdev) goto out_rtc; } + if (!max8998->irq_domain) + goto no_irq; + + info->irq = irq_create_mapping(max8998->irq_domain, MAX8998_IRQ_ALARM0); + if (!info->irq) { + dev_warn(&pdev->dev, "Failed to map alarm IRQ\n"); + goto no_irq; + } + ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, max8998_rtc_alarm_irq, 0, "rtc-alarm0", info); @@ -284,6 +293,7 @@ static int max8998_rtc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", info->irq, ret); +no_irq: dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name); if (pdata && pdata->rtc_delay) { info->lp3974_bug_workaround = true; diff --git a/include/linux/mfd/max8998-private.h b/include/linux/mfd/max8998-private.h index effa5d3b96ae..bfb48b6fcc74 100644 --- a/include/linux/mfd/max8998-private.h +++ b/include/linux/mfd/max8998-private.h @@ -132,6 +132,8 @@ enum { #define MAX8998_ENRAMP (1 << 4) +struct irq_domain; + /** * struct max8998_dev - max8998 master device for sub-drivers * @dev: master device of the chip (can be used to access platform data) @@ -153,7 +155,8 @@ struct max8998_dev { struct mutex iolock; struct mutex irqlock; - int irq_base; + unsigned int irq_base; + struct irq_domain *irq_domain; int irq; int ono; u8 irq_masks_cur[MAX8998_NUM_IRQ_REGS]; diff --git a/include/linux/mfd/max8998.h b/include/linux/mfd/max8998.h index 6823548d0c0a..75471183b87a 100644 --- a/include/linux/mfd/max8998.h +++ b/include/linux/mfd/max8998.h @@ -100,7 +100,7 @@ struct max8998_regulator_data { struct max8998_platform_data { struct max8998_regulator_data *regulators; int num_regulators; - int irq_base; + unsigned int irq_base; int ono; bool buck_voltage_lock; int buck1_voltage1; -- cgit v1.2.3 From 4280e0b42bd590316a048d66ea356e78c5d0464e Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 24 Jun 2013 14:39:53 +0200 Subject: regulator: max8998: Use arrays for specifying voltages in platform data This patch modifies the platform data of max8998 to use arrays for specifying predefined voltages of buck1 and buck2 instead of separate field for each voltage. This allows to simplify the code a bit and will help in adding support for Device Tree, which will be introduced in further patch. Signed-off-by: Tomasz Figa Acked-by: Mark Brown Signed-off-by: Samuel Ortiz --- arch/arm/mach-exynos/mach-universal_c210.c | 8 +-- arch/arm/mach-s5pv210/mach-aquila.c | 8 +-- arch/arm/mach-s5pv210/mach-goni.c | 8 +-- drivers/regulator/max8998.c | 96 +++++++++--------------------- include/linux/mfd/max8998.h | 16 ++--- 5 files changed, 39 insertions(+), 97 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c index 74ddb2b55614..f912444cae33 100644 --- a/arch/arm/mach-exynos/mach-universal_c210.c +++ b/arch/arm/mach-exynos/mach-universal_c210.c @@ -540,15 +540,11 @@ static struct max8998_regulator_data lp3974_regulators[] = { static struct max8998_platform_data universal_lp3974_pdata = { .num_regulators = ARRAY_SIZE(lp3974_regulators), .regulators = lp3974_regulators, - .buck1_voltage1 = 1100000, /* INT */ - .buck1_voltage2 = 1000000, - .buck1_voltage3 = 1100000, - .buck1_voltage4 = 1000000, + .buck1_voltage = { 1100000, 1000000, 1100000, 1000000 }, .buck1_set1 = EXYNOS4_GPX0(5), .buck1_set2 = EXYNOS4_GPX0(6), - .buck2_voltage1 = 1200000, /* G3D */ - .buck2_voltage2 = 1100000, .buck1_default_idx = 0, + .buck2_voltage = { 1200000, 1100000 }, .buck2_set3 = EXYNOS4_GPE2(0), .buck2_default_idx = 0, .wakeup = true, diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index ed2b85485b9d..ad40ab0f5dbd 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -377,12 +377,8 @@ static struct max8998_platform_data aquila_max8998_pdata = { .buck1_set1 = S5PV210_GPH0(3), .buck1_set2 = S5PV210_GPH0(4), .buck2_set3 = S5PV210_GPH0(5), - .buck1_voltage1 = 1200000, - .buck1_voltage2 = 1200000, - .buck1_voltage3 = 1200000, - .buck1_voltage4 = 1200000, - .buck2_voltage1 = 1200000, - .buck2_voltage2 = 1200000, + .buck1_voltage = { 1200000, 1200000, 1200000, 1200000 }, + .buck2_voltage = { 1200000, 1200000 }, }; #endif diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index 30b24ad84f49..e5cd9fbf19e9 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -580,12 +580,8 @@ static struct max8998_platform_data goni_max8998_pdata = { .buck1_set1 = S5PV210_GPH0(3), .buck1_set2 = S5PV210_GPH0(4), .buck2_set3 = S5PV210_GPH0(5), - .buck1_voltage1 = 1200000, - .buck1_voltage2 = 1200000, - .buck1_voltage3 = 1200000, - .buck1_voltage4 = 1200000, - .buck2_voltage1 = 1200000, - .buck2_voltage2 = 1200000, + .buck1_voltage = { 1200000, 1200000, 1200000, 1200000 }, + .buck2_voltage = { 1200000, 1200000 }, }; #endif diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index a57a1b15cdba..8c45b93b7334 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -630,6 +630,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) struct max8998_data *max8998; struct i2c_client *i2c; int i, ret, size; + unsigned int v; if (!pdata) { dev_err(pdev->dev.parent, "No platform init data supplied\n"); @@ -688,53 +689,21 @@ static int max8998_pmic_probe(struct platform_device *pdev) gpio_request(pdata->buck1_set2, "MAX8998 BUCK1_SET2"); gpio_direction_output(pdata->buck1_set2, (max8998->buck1_idx >> 1) & 0x1); - /* Set predefined value for BUCK1 register 1 */ - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i - < pdata->buck1_voltage1) - i++; - max8998->buck1_vol[0] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); - if (ret) - goto err_out; - - /* Set predefined value for BUCK1 register 2 */ - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i - < pdata->buck1_voltage2) - i++; - - max8998->buck1_vol[1] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i); - if (ret) - goto err_out; - - /* Set predefined value for BUCK1 register 3 */ - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i - < pdata->buck1_voltage3) - i++; - - max8998->buck1_vol[2] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i); - if (ret) - goto err_out; - - /* Set predefined value for BUCK1 register 4 */ - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i - < pdata->buck1_voltage4) - i++; - - max8998->buck1_vol[3] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i); - if (ret) - goto err_out; + /* Set predefined values for BUCK1 registers */ + for (v = 0; v < ARRAY_SIZE(pdata->buck1_voltage); ++v) { + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i + < pdata->buck1_voltage[v]) + i++; + + max8998->buck1_vol[v] = i; + ret = max8998_write_reg(i2c, + MAX8998_REG_BUCK1_VOLTAGE1 + v, i); + if (ret) + goto err_out; + } } if (gpio_is_valid(pdata->buck2_set3)) { @@ -750,27 +719,20 @@ static int max8998_pmic_probe(struct platform_device *pdev) gpio_direction_output(pdata->buck2_set3, max8998->buck2_idx & 0x1); - /* BUCK2 register 1 */ - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i - < pdata->buck2_voltage1) - i++; - max8998->buck2_vol[0] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); - if (ret) - goto err_out; - - /* BUCK2 register 2 */ - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i - < pdata->buck2_voltage2) - i++; - max8998->buck2_vol[1] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); - if (ret) - goto err_out; + /* Set predefined values for BUCK2 registers */ + for (v = 0; v < ARRAY_SIZE(pdata->buck2_voltage); ++v) { + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i + < pdata->buck2_voltage[v]) + i++; + + max8998->buck2_vol[v] = i; + ret = max8998_write_reg(i2c, + MAX8998_REG_BUCK2_VOLTAGE1 + v, i); + if (ret) + goto err_out; + } } for (i = 0; i < pdata->num_regulators; i++) { diff --git a/include/linux/mfd/max8998.h b/include/linux/mfd/max8998.h index 75471183b87a..ca56bb03bc69 100644 --- a/include/linux/mfd/max8998.h +++ b/include/linux/mfd/max8998.h @@ -73,12 +73,8 @@ struct max8998_regulator_data { * @buck_voltage_lock: Do NOT change the values of the following six * registers set by buck?_voltage?. The voltage of BUCK1/2 cannot * be other than the preset values. - * @buck1_voltage1: BUCK1 DVS mode 1 voltage register - * @buck1_voltage2: BUCK1 DVS mode 2 voltage register - * @buck1_voltage3: BUCK1 DVS mode 3 voltage register - * @buck1_voltage4: BUCK1 DVS mode 4 voltage register - * @buck2_voltage1: BUCK2 DVS mode 1 voltage register - * @buck2_voltage2: BUCK2 DVS mode 2 voltage register + * @buck1_voltage: BUCK1 DVS mode 1 voltage registers + * @buck2_voltage: BUCK2 DVS mode 2 voltage registers * @buck1_set1: BUCK1 gpio pin 1 to set output voltage * @buck1_set2: BUCK1 gpio pin 2 to set output voltage * @buck1_default_idx: Default for BUCK1 gpio pin 1, 2 @@ -103,12 +99,8 @@ struct max8998_platform_data { unsigned int irq_base; int ono; bool buck_voltage_lock; - int buck1_voltage1; - int buck1_voltage2; - int buck1_voltage3; - int buck1_voltage4; - int buck2_voltage1; - int buck2_voltage2; + int buck1_voltage[4]; + int buck2_voltage[2]; int buck1_set1; int buck1_set2; int buck1_default_idx; -- cgit v1.2.3 From ee999fb3f17faa3af6028bf7130707fe0d4157a4 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 25 Jun 2013 16:08:10 +0200 Subject: mfd: max8998: Add support for Device Tree This patch adds Device Tree support to max8998 driver. Signed-off-by: Tomasz Figa Acked-by: Mark Brown Signed-off-by: Samuel Ortiz --- Documentation/devicetree/bindings/mfd/max8998.txt | 119 ++++++++++++++++++++ drivers/mfd/max8998.c | 67 ++++++++++- drivers/regulator/max8998.c | 131 +++++++++++++++++++++- drivers/rtc/rtc-max8998.c | 2 +- include/linux/mfd/max8998-private.h | 2 + include/linux/mfd/max8998.h | 2 + 6 files changed, 316 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/mfd/max8998.txt (limited to 'include/linux') diff --git a/Documentation/devicetree/bindings/mfd/max8998.txt b/Documentation/devicetree/bindings/mfd/max8998.txt new file mode 100644 index 000000000000..23a3650ff2a2 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/max8998.txt @@ -0,0 +1,119 @@ +* Maxim MAX8998, National/TI LP3974 multi-function device + +The Maxim MAX8998 is a multi-function device which includes voltage/current +regulators, real time clock, battery charging controller and several +other sub-blocks. It is interfaced using an I2C interface. Each sub-block +is addressed by the host system using different i2c slave address. + +PMIC sub-block +-------------- + +The PMIC sub-block contains a number of voltage and current regulators, +with controllable parameters and dynamic voltage scaling capability. +In addition, it includes a real time clock and battery charging controller +as well. It is accessible at I2C address 0x66. + +Required properties: +- compatible: Should be one of the following: + - "maxim,max8998" for Maxim MAX8998 + - "national,lp3974" or "ti,lp3974" for National/TI LP3974. +- reg: Specifies the i2c slave address of the pmic block. It should be 0x66. + +Optional properties: +- interrupt-parent: Specifies the phandle of the interrupt controller to which + the interrupts from MAX8998 are routed to. +- interrupts: Interrupt specifiers for two interrupt sources. + - First interrupt specifier is for main interrupt. + - Second interrupt specifier is for power-on/-off interrupt. +- max8998,pmic-buck1-dvs-gpios: GPIO specifiers for two host gpios used + for buck 1 dvs. The format of the gpio specifier depends on the gpio + controller. +- max8998,pmic-buck2-dvs-gpio: GPIO specifier for host gpio used + for buck 2 dvs. The format of the gpio specifier depends on the gpio + controller. +- max8998,pmic-buck1-default-dvs-idx: Default voltage setting selected from + the possible 4 options selectable by the dvs gpios. The value of this + property should be 0, 1, 2 or 3. If not specified or out of range, + a default value of 0 is taken. +- max8998,pmic-buck2-default-dvs-idx: Default voltage setting selected from + the possible 2 options selectable by the dvs gpios. The value of this + property should be 0 or 1. If not specified or out of range, a default + value of 0 is taken. +- max8998,pmic-buck-voltage-lock: If present, disallows changing of + preprogrammed buck dvfs voltages. + +Additional properties required if max8998,pmic-buck1-dvs-gpios is defined: +- max8998,pmic-buck1-dvs-voltage: An array of 4 voltage values in microvolts + for buck1 regulator that can be selected using dvs gpio. + +Additional properties required if max8998,pmic-buck2-dvs-gpio is defined: +- max8998,pmic-buck2-dvs-voltage: An array of 2 voltage values in microvolts + for buck2 regulator that can be selected using dvs gpio. + +Regulators: All the regulators of MAX8998 to be instantiated shall be +listed in a child node named 'regulators'. Each regulator is represented +by a child node of the 'regulators' node. + + regulator-name { + /* standard regulator bindings here */ + }; + +Following regulators of the MAX8998 PMIC block are supported. Note that +the 'n' in regulator name, as in LDOn or BUCKn, represents the LDO or BUCK +number as described in MAX8998 datasheet. + + - LDOn + - valid values for n are 2 to 17 + - Example: LDO2, LDO10, LDO17 + - BUCKn + - valid values for n are 1 to 4. + - Example: BUCK1, BUCK2, BUCK3, BUCK4 + + - ENVICHG: Battery Charging Current Monitor Output. This is a fixed + voltage type regulator + + - ESAFEOUT1: (ldo19) + - ESAFEOUT2: (ld020) + +Standard regulator bindings are used inside regulator subnodes. Check + Documentation/devicetree/bindings/regulator/regulator.txt +for more details. + +Example: + + pmic@66 { + compatible = "maxim,max8998-pmic"; + reg = <0x66>; + interrupt-parent = <&wakeup_eint>; + interrupts = <4 0>, <3 0>; + + /* Buck 1 DVS settings */ + max8998,pmic-buck1-default-dvs-idx = <0>; + max8998,pmic-buck1-dvs-gpios = <&gpx0 0 1 0 0>, /* SET1 */ + <&gpx0 1 1 0 0>; /* SET2 */ + max8998,pmic-buck1-dvs-voltage = <1350000>, <1300000>, + <1000000>, <950000>; + + /* Buck 2 DVS settings */ + max8998,pmic-buck2-default-dvs-idx = <0>; + max8998,pmic-buck2-dvs-gpio = <&gpx0 0 3 0 0>; /* SET3 */ + max8998,pmic-buck2-dvs-voltage = <1350000>, <1300000>; + + /* Regulators to instantiate */ + regulators { + ldo2_reg: LDO2 { + regulator-name = "VDD_ALIVE_1.1V"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + }; + + buck1_reg: BUCK1 { + regulator-name = "VDD_ARM_1.2V"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + }; + }; + }; diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index d7218cc90945..21af51a499f4 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 #include #include #include #include #include #include +#include +#include #include #include #include @@ -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/regulator/max8998.c b/drivers/regulator/max8998.c index 8c45b93b7334..a4c53b2d1aaf 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -28,8 +28,11 @@ #include #include #include +#include +#include #include #include +#include #include #include @@ -589,13 +592,13 @@ static struct regulator_desc regulators[] = { .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, { - .name = "EN32KHz AP", + .name = "EN32KHz-AP", .id = MAX8998_EN32KHZ_AP, .ops = &max8998_others_ops, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, { - .name = "EN32KHz CP", + .name = "EN32KHz-CP", .id = MAX8998_EN32KHZ_CP, .ops = &max8998_others_ops, .type = REGULATOR_VOLTAGE, @@ -621,10 +624,122 @@ static struct regulator_desc regulators[] = { } }; +static int max8998_pmic_dt_parse_dvs_gpio(struct max8998_dev *iodev, + struct max8998_platform_data *pdata, + struct device_node *pmic_np) +{ + int gpio; + + gpio = of_get_named_gpio(pmic_np, "max8998,pmic-buck1-dvs-gpios", 0); + if (!gpio_is_valid(gpio)) { + dev_err(iodev->dev, "invalid buck1 gpio[0]: %d\n", gpio); + return -EINVAL; + } + pdata->buck1_set1 = gpio; + + gpio = of_get_named_gpio(pmic_np, "max8998,pmic-buck1-dvs-gpios", 1); + if (!gpio_is_valid(gpio)) { + dev_err(iodev->dev, "invalid buck1 gpio[1]: %d\n", gpio); + return -EINVAL; + } + pdata->buck1_set2 = gpio; + + gpio = of_get_named_gpio(pmic_np, "max8998,pmic-buck2-dvs-gpio", 0); + if (!gpio_is_valid(gpio)) { + dev_err(iodev->dev, "invalid buck 2 gpio: %d\n", gpio); + return -EINVAL; + } + pdata->buck2_set3 = gpio; + + return 0; +} + +static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev, + struct max8998_platform_data *pdata) +{ + struct device_node *pmic_np = iodev->dev->of_node; + struct device_node *regulators_np, *reg_np; + struct max8998_regulator_data *rdata; + unsigned int i; + int ret; + + regulators_np = of_get_child_by_name(pmic_np, "regulators"); + if (!regulators_np) { + dev_err(iodev->dev, "could not find regulators sub-node\n"); + return -EINVAL; + } + + /* count the number of regulators to be supported in pmic */ + pdata->num_regulators = of_get_child_count(regulators_np); + + rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * + pdata->num_regulators, GFP_KERNEL); + if (!rdata) + return -ENOMEM; + + pdata->regulators = rdata; + for (i = 0; i < ARRAY_SIZE(regulators); ++i) { + reg_np = of_get_child_by_name(regulators_np, + regulators[i].name); + if (!reg_np) + continue; + + rdata->id = regulators[i].id; + rdata->initdata = of_get_regulator_init_data( + iodev->dev, reg_np); + rdata->reg_node = reg_np; + ++rdata; + } + pdata->num_regulators = rdata - pdata->regulators; + + ret = max8998_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np); + if (ret) + return -EINVAL; + + if (of_find_property(pmic_np, "max8998,pmic-buck-voltage-lock", NULL)) + pdata->buck_voltage_lock = true; + + ret = of_property_read_u32(pmic_np, + "max8998,pmic-buck1-default-dvs-idx", + &pdata->buck1_default_idx); + if (!ret && pdata->buck1_default_idx >= 4) { + pdata->buck1_default_idx = 0; + dev_warn(iodev->dev, "invalid value for default dvs index, using 0 instead\n"); + } + + ret = of_property_read_u32(pmic_np, + "max8998,pmic-buck2-default-dvs-idx", + &pdata->buck2_default_idx); + if (!ret && pdata->buck2_default_idx >= 2) { + pdata->buck2_default_idx = 0; + dev_warn(iodev->dev, "invalid value for default dvs index, using 0 instead\n"); + } + + ret = of_property_read_u32_array(pmic_np, + "max8998,pmic-buck1-dvs-voltage", + pdata->buck1_voltage, + ARRAY_SIZE(pdata->buck1_voltage)); + if (ret) { + dev_err(iodev->dev, "buck1 voltages not specified\n"); + return -EINVAL; + } + + ret = of_property_read_u32_array(pmic_np, + "max8998,pmic-buck2-dvs-voltage", + pdata->buck2_voltage, + ARRAY_SIZE(pdata->buck2_voltage)); + if (ret) { + dev_err(iodev->dev, "buck2 voltages not specified\n"); + return -EINVAL; + } + + return 0; +} + static int max8998_pmic_probe(struct platform_device *pdev) { struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev); + struct max8998_platform_data *pdata = iodev->pdata; struct regulator_config config = { }; struct regulator_dev **rdev; struct max8998_data *max8998; @@ -637,6 +752,12 @@ static int max8998_pmic_probe(struct platform_device *pdev) return -ENODEV; } + if (IS_ENABLED(CONFIG_OF) && iodev->dev->of_node) { + ret = max8998_pmic_dt_parse_pdata(iodev, pdata); + if (ret) + return ret; + } + max8998 = devm_kzalloc(&pdev->dev, sizeof(struct max8998_data), GFP_KERNEL); if (!max8998) @@ -750,13 +871,15 @@ static int max8998_pmic_probe(struct platform_device *pdev) } config.dev = max8998->dev; + config.of_node = pdata->regulators[i].reg_node; config.init_data = pdata->regulators[i].initdata; config.driver_data = max8998; rdev[i] = regulator_register(®ulators[index], &config); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); - dev_err(max8998->dev, "regulator init failed\n"); + dev_err(max8998->dev, "regulator %s init failed (%d)\n", + regulators[index].name, ret); rdev[i] = NULL; goto err; } diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c index 46f23014759b..042a8734bd28 100644 --- a/drivers/rtc/rtc-max8998.c +++ b/drivers/rtc/rtc-max8998.c @@ -253,7 +253,7 @@ static const struct rtc_class_ops max8998_rtc_ops = { static int max8998_rtc_probe(struct platform_device *pdev) { struct max8998_dev *max8998 = dev_get_drvdata(pdev->dev.parent); - struct max8998_platform_data *pdata = dev_get_platdata(max8998->dev); + struct max8998_platform_data *pdata = max8998->pdata; struct max8998_rtc_info *info; int ret; diff --git a/include/linux/mfd/max8998-private.h b/include/linux/mfd/max8998-private.h index bfb48b6fcc74..84844e0a5704 100644 --- a/include/linux/mfd/max8998-private.h +++ b/include/linux/mfd/max8998-private.h @@ -137,6 +137,7 @@ struct irq_domain; /** * struct max8998_dev - max8998 master device for sub-drivers * @dev: master device of the chip (can be used to access platform data) + * @pdata: platform data for the driver and subdrivers * @i2c: i2c client private data for regulator * @rtc: i2c client private data for rtc * @iolock: mutex for serializing io access @@ -150,6 +151,7 @@ struct irq_domain; */ struct max8998_dev { struct device *dev; + struct max8998_platform_data *pdata; struct i2c_client *i2c; struct i2c_client *rtc; struct mutex iolock; diff --git a/include/linux/mfd/max8998.h b/include/linux/mfd/max8998.h index ca56bb03bc69..e3956a654cbc 100644 --- a/include/linux/mfd/max8998.h +++ b/include/linux/mfd/max8998.h @@ -58,10 +58,12 @@ enum { * max8998_regulator_data - regulator data * @id: regulator id * @initdata: regulator init data (contraints, supplies, ...) + * @reg_node: DT node of regulator (unused on non-DT platforms) */ struct max8998_regulator_data { int id; struct regulator_init_data *initdata; + struct device_node *reg_node; }; /** -- cgit v1.2.3 From dc6641822e412ff527e022ec752707ebb034add4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 28 Jun 2013 15:12:23 +0100 Subject: mfd: sec: Remove fields not used since regmap conversion These were all used by the open coded I/O and IRQ implementations and are no longer referenced now that the regmap core variants are used instead. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- include/linux/mfd/samsung/core.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index f0f4de3b4ccc..378ae8a04c6a 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -14,8 +14,6 @@ #ifndef __LINUX_MFD_SEC_CORE_H #define __LINUX_MFD_SEC_CORE_H -#define NUM_IRQ_REGS 4 - enum sec_device_type { S5M8751X, S5M8763X, @@ -44,8 +42,6 @@ struct sec_pmic_dev { struct regmap *regmap; struct i2c_client *i2c; struct i2c_client *rtc; - struct mutex iolock; - struct mutex irqlock; int device_type; int irq_base; @@ -53,8 +49,6 @@ struct sec_pmic_dev { struct regmap_irq_chip_data *irq_data; int ono; - u8 irq_masks_cur[NUM_IRQ_REGS]; - u8 irq_masks_cache[NUM_IRQ_REGS]; int type; bool wakeup; }; -- cgit v1.2.3