diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c index 91431284f8b7..4f507d89c6f0 100644 --- a/drivers/mfd/wcd9xxx-core.c +++ b/drivers/mfd/wcd9xxx-core.c @@ -1120,6 +1120,41 @@ static int wcd9xxx_regmap_init_cache(struct wcd9xxx *wcd9xxx) return rc; } +static void wcd9xxx_core_res_update_irq_regs( + struct wcd9xxx_core_resource *core_res, + u16 id_major) +{ + switch (id_major) { + case TASHA_MAJOR: + core_res->intr_reg[WCD9XXX_INTR_STATUS_BASE] = + WCD9335_INTR_PIN1_STATUS0; + core_res->intr_reg[WCD9XXX_INTR_CLEAR_BASE] = + WCD9335_INTR_PIN1_CLEAR0; + core_res->intr_reg[WCD9XXX_INTR_MASK_BASE] = + WCD9335_INTR_PIN1_MASK0; + core_res->intr_reg[WCD9XXX_INTR_LEVEL_BASE] = + WCD9335_INTR_LEVEL0; + core_res->intr_reg[WCD9XXX_INTR_CLR_COMMIT] = + WCD9335_INTR_CLR_COMMIT; + break; + case TABLA_MAJOR: + case TOMTOM_MAJOR: + case TAIKO_MAJOR: + default: + core_res->intr_reg[WCD9XXX_INTR_STATUS_BASE] = + WCD9XXX_A_INTR_STATUS0; + core_res->intr_reg[WCD9XXX_INTR_CLEAR_BASE] = + WCD9XXX_A_INTR_CLEAR0; + core_res->intr_reg[WCD9XXX_INTR_MASK_BASE] = + WCD9XXX_A_INTR_MASK0; + core_res->intr_reg[WCD9XXX_INTR_LEVEL_BASE] = + WCD9XXX_A_INTR_LEVEL0; + core_res->intr_reg[WCD9XXX_INTR_CLR_COMMIT] = + WCD9XXX_A_INTR_MODE; + break; + }; +} + static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx) { int ret = 0; @@ -1159,6 +1194,8 @@ static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx) core_res->intr_table = intr_tbl_v2; core_res->intr_table_size = ARRAY_SIZE(intr_tbl_v2); } + wcd9xxx_core_res_update_irq_regs(&wcd9xxx->core_res, + wcd9xxx->codec_type->id_major); wcd9xxx_core_res_init(&wcd9xxx->core_res, wcd9xxx->codec_type->num_irqs, diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c index 1f264cb7a45d..573f81124829 100644 --- a/drivers/mfd/wcd9xxx-irq.c +++ b/drivers/mfd/wcd9xxx-irq.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -90,8 +90,8 @@ static void wcd9xxx_irq_sync_unlock(struct irq_data *data) wcd9xxx_res->irq_masks_cache[i] = wcd9xxx_res->irq_masks_cur[i]; wcd9xxx_res->codec_reg_write(wcd9xxx_res, - WCD9XXX_A_INTR_MASK0 + i, - wcd9xxx_res->irq_masks_cur[i]); + wcd9xxx_res->intr_reg[WCD9XXX_INTR_MASK_BASE] + i, + wcd9xxx_res->irq_masks_cur[i]); } } @@ -252,23 +252,27 @@ static void wcd9xxx_irq_dispatch(struct wcd9xxx_core_resource *wcd9xxx_res, if (irqdata->clear_first) { wcd9xxx_nested_irq_lock(wcd9xxx_res); wcd9xxx_res->codec_reg_write(wcd9xxx_res, - WCD9XXX_A_INTR_CLEAR0 + BIT_BYTE(irqbit), - BYTE_BIT_MASK(irqbit)); + wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLEAR_BASE] + + BIT_BYTE(irqbit), + BYTE_BIT_MASK(irqbit)); if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C) wcd9xxx_res->codec_reg_write(wcd9xxx_res, - WCD9XXX_A_INTR_MODE, 0x02); + wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLR_COMMIT], + 0x02); handle_nested_irq(phyirq_to_virq(wcd9xxx_res, irqbit)); wcd9xxx_nested_irq_unlock(wcd9xxx_res); } else { wcd9xxx_nested_irq_lock(wcd9xxx_res); handle_nested_irq(phyirq_to_virq(wcd9xxx_res, irqbit)); wcd9xxx_res->codec_reg_write(wcd9xxx_res, - WCD9XXX_A_INTR_CLEAR0 + BIT_BYTE(irqbit), - BYTE_BIT_MASK(irqbit)); + wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLEAR_BASE] + + BIT_BYTE(irqbit), + BYTE_BIT_MASK(irqbit)); if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C) wcd9xxx_res->codec_reg_write(wcd9xxx_res, - WCD9XXX_A_INTR_MODE, 0x02); + wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLR_COMMIT], + 0x02); wcd9xxx_nested_irq_unlock(wcd9xxx_res); } @@ -298,8 +302,8 @@ static irqreturn_t wcd9xxx_irq_thread(int irq, void *data) } ret = wcd9xxx_res->codec_bulk_read(wcd9xxx_res, - WCD9XXX_A_INTR_STATUS0, - num_irq_regs, status); + wcd9xxx_res->intr_reg[WCD9XXX_INTR_STATUS_BASE], + num_irq_regs, status); if (ret < 0) { dev_err(wcd9xxx_res->dev, @@ -354,11 +358,12 @@ static irqreturn_t wcd9xxx_irq_thread(int irq, void *data) memset(status, 0xff, num_irq_regs); ret = wcd9xxx_res->codec_bulk_write(wcd9xxx_res, - WCD9XXX_A_INTR_CLEAR0, - num_irq_regs, status); + wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLEAR_BASE], + num_irq_regs, status); if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C) wcd9xxx_res->codec_reg_write(wcd9xxx_res, - WCD9XXX_A_INTR_MODE, 0x02); + wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLR_COMMIT], + 0x02); } wcd9xxx_unlock_sleep(wcd9xxx_res); @@ -485,11 +490,11 @@ int wcd9xxx_irq_init(struct wcd9xxx_core_resource *wcd9xxx_res) for (i = 0; i < wcd9xxx_res->num_irq_regs; i++) { /* Initialize interrupt mask and level registers */ wcd9xxx_res->codec_reg_write(wcd9xxx_res, - WCD9XXX_A_INTR_LEVEL0 + i, + wcd9xxx_res->intr_reg[WCD9XXX_INTR_LEVEL_BASE] + i, irq_level[i]); wcd9xxx_res->codec_reg_write(wcd9xxx_res, - WCD9XXX_A_INTR_MASK0 + i, - wcd9xxx_res->irq_masks_cur[i]); + wcd9xxx_res->intr_reg[WCD9XXX_INTR_MASK_BASE] + i, + wcd9xxx_res->irq_masks_cur[i]); } ret = request_threaded_irq(wcd9xxx_res->irq, NULL, wcd9xxx_irq_thread, diff --git a/include/linux/mfd/wcd9xxx/core-resource.h b/include/linux/mfd/wcd9xxx/core-resource.h index 6e4fae40a168..fa32fd4b13ee 100644 --- a/include/linux/mfd/wcd9xxx/core-resource.h +++ b/include/linux/mfd/wcd9xxx/core-resource.h @@ -31,6 +31,15 @@ enum wcd9xxx_pm_state { WCD9XXX_PM_ASLEEP, }; +enum { + WCD9XXX_INTR_STATUS_BASE = 0, + WCD9XXX_INTR_CLEAR_BASE, + WCD9XXX_INTR_MASK_BASE, + WCD9XXX_INTR_LEVEL_BASE, + WCD9XXX_INTR_CLR_COMMIT, + WCD9XXX_INTR_REG_MAX, +}; + enum wcd9xxx_intf_status { WCD9XXX_INTERFACE_TYPE_PROBING, WCD9XXX_INTERFACE_TYPE_SLIMBUS, @@ -59,6 +68,7 @@ struct wcd9xxx_core_resource { bool irq_level_high[WCD9XXX_MAX_NUM_IRQS]; int num_irqs; int num_irq_regs; + u16 intr_reg[WCD9XXX_INTR_REG_MAX]; /* Callback functions to read/write codec registers */ int (*codec_reg_read) (struct wcd9xxx_core_resource *,