From 3f7e82759c692df473675ed06fb90b20f1f225c3 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Tue, 8 May 2012 11:42:38 -0700 Subject: mfd: Commonize tps65910 regmap access through header This change removes the read/write callback functions in favor of common regmap accessors inside the header file. This change also makes use of regmap_read/write for single register access which maps better onto what this driver actually needs. Signed-off-by: Rhyland Klein Signed-off-by: Samuel Ortiz --- drivers/regulator/tps65910-regulator.c | 88 ++++++++++++++++------------------ 1 file changed, 42 insertions(+), 46 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 4a37c2b6367f..852b05b20de9 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -331,21 +331,16 @@ struct tps65910_reg { static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg) { - u8 val; + unsigned int val; int err; - err = pmic->mfd->read(pmic->mfd, reg, 1, &val); + err = tps65910_reg_read(pmic->mfd, reg, &val); if (err) return err; return val; } -static inline int tps65910_write(struct tps65910_reg *pmic, u8 reg, u8 val) -{ - return pmic->mfd->write(pmic->mfd, reg, 1, &val); -} - static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg, u8 set_mask, u8 clear_mask) { @@ -362,7 +357,7 @@ static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg, data &= ~clear_mask; data |= set_mask; - err = tps65910_write(pmic, reg, data); + err = tps65910_reg_write(pmic->mfd, reg, data); if (err) dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg); @@ -371,7 +366,7 @@ out: return err; } -static int tps65910_reg_read(struct tps65910_reg *pmic, u8 reg) +static int tps65910_reg_read_locked(struct tps65910_reg *pmic, u8 reg) { int data; @@ -385,13 +380,13 @@ static int tps65910_reg_read(struct tps65910_reg *pmic, u8 reg) return data; } -static int tps65910_reg_write(struct tps65910_reg *pmic, u8 reg, u8 val) +static int tps65910_reg_write_locked(struct tps65910_reg *pmic, u8 reg, u8 val) { int err; mutex_lock(&pmic->mutex); - err = tps65910_write(pmic, reg, val); + err = tps65910_reg_write(pmic->mfd, reg, val); if (err < 0) dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg); @@ -476,7 +471,7 @@ static int tps65910_is_enabled(struct regulator_dev *dev) if (reg < 0) return reg; - value = tps65910_reg_read(pmic, reg); + value = tps65910_reg_read_locked(pmic, reg); if (value < 0) return value; @@ -493,7 +488,7 @@ static int tps65910_enable(struct regulator_dev *dev) if (reg < 0) return reg; - return tps65910_set_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); + return tps65910_reg_set_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); } static int tps65910_disable(struct regulator_dev *dev) @@ -506,7 +501,7 @@ static int tps65910_disable(struct regulator_dev *dev) if (reg < 0) return reg; - return tps65910_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); + return tps65910_reg_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); } static int tps65910_enable_time(struct regulator_dev *dev) @@ -532,9 +527,9 @@ static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) LDO_ST_MODE_BIT); case REGULATOR_MODE_IDLE: value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT; - return tps65910_set_bits(mfd, reg, value); + return tps65910_reg_set_bits(mfd, reg, value); case REGULATOR_MODE_STANDBY: - return tps65910_clear_bits(mfd, reg, LDO_ST_ON_BIT); + return tps65910_reg_clear_bits(mfd, reg, LDO_ST_ON_BIT); } return -EINVAL; @@ -549,7 +544,7 @@ static unsigned int tps65910_get_mode(struct regulator_dev *dev) if (reg < 0) return reg; - value = tps65910_reg_read(pmic, reg); + value = tps65910_reg_read_locked(pmic, reg); if (value < 0) return value; @@ -569,28 +564,28 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev) switch (id) { case TPS65910_REG_VDD1: - opvsel = tps65910_reg_read(pmic, TPS65910_VDD1_OP); - mult = tps65910_reg_read(pmic, TPS65910_VDD1); + opvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD1_OP); + mult = tps65910_reg_read_locked(pmic, TPS65910_VDD1); mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT; - srvsel = tps65910_reg_read(pmic, TPS65910_VDD1_SR); + srvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD1_SR); sr = opvsel & VDD1_OP_CMD_MASK; opvsel &= VDD1_OP_SEL_MASK; srvsel &= VDD1_SR_SEL_MASK; vselmax = 75; break; case TPS65910_REG_VDD2: - opvsel = tps65910_reg_read(pmic, TPS65910_VDD2_OP); - mult = tps65910_reg_read(pmic, TPS65910_VDD2); + opvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD2_OP); + mult = tps65910_reg_read_locked(pmic, TPS65910_VDD2); mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT; - srvsel = tps65910_reg_read(pmic, TPS65910_VDD2_SR); + srvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD2_SR); sr = opvsel & VDD2_OP_CMD_MASK; opvsel &= VDD2_OP_SEL_MASK; srvsel &= VDD2_SR_SEL_MASK; vselmax = 75; break; case TPS65911_REG_VDDCTRL: - opvsel = tps65910_reg_read(pmic, TPS65911_VDDCTRL_OP); - srvsel = tps65910_reg_read(pmic, TPS65911_VDDCTRL_SR); + opvsel = tps65910_reg_read_locked(pmic, TPS65911_VDDCTRL_OP); + srvsel = tps65910_reg_read_locked(pmic, TPS65911_VDDCTRL_SR); sr = opvsel & VDDCTRL_OP_CMD_MASK; opvsel &= VDDCTRL_OP_SEL_MASK; srvsel &= VDDCTRL_SR_SEL_MASK; @@ -630,7 +625,7 @@ static int tps65910_get_voltage(struct regulator_dev *dev) if (reg < 0) return reg; - value = tps65910_reg_read(pmic, reg); + value = tps65910_reg_read_locked(pmic, reg); if (value < 0) return value; @@ -669,7 +664,7 @@ static int tps65911_get_voltage(struct regulator_dev *dev) reg = pmic->get_ctrl_reg(id); - value = tps65910_reg_read(pmic, reg); + value = tps65910_reg_read_locked(pmic, reg); switch (id) { case TPS65911_REG_LDO1: @@ -728,7 +723,7 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev, tps65910_modify_bits(pmic, TPS65910_VDD1, (dcdc_mult << VDD1_VGAIN_SEL_SHIFT), VDD1_VGAIN_SEL_MASK); - tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel); + tps65910_reg_write_locked(pmic, TPS65910_VDD1_OP, vsel); break; case TPS65910_REG_VDD2: dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1; @@ -739,11 +734,11 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev, tps65910_modify_bits(pmic, TPS65910_VDD2, (dcdc_mult << VDD2_VGAIN_SEL_SHIFT), VDD1_VGAIN_SEL_MASK); - tps65910_reg_write(pmic, TPS65910_VDD2_OP, vsel); + tps65910_reg_write_locked(pmic, TPS65910_VDD2_OP, vsel); break; case TPS65911_REG_VDDCTRL: vsel = selector + 3; - tps65910_reg_write(pmic, TPS65911_VDDCTRL_OP, vsel); + tps65910_reg_write_locked(pmic, TPS65911_VDDCTRL_OP, vsel); } return 0; @@ -994,10 +989,10 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, /* External EN1 control */ if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1) - ret = tps65910_set_bits(mfd, + ret = tps65910_reg_set_bits(mfd, TPS65910_EN1_LDO_ASS + regoffs, bit_pos); else - ret = tps65910_clear_bits(mfd, + ret = tps65910_reg_clear_bits(mfd, TPS65910_EN1_LDO_ASS + regoffs, bit_pos); if (ret < 0) { dev_err(mfd->dev, @@ -1007,10 +1002,10 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, /* External EN2 control */ if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2) - ret = tps65910_set_bits(mfd, + ret = tps65910_reg_set_bits(mfd, TPS65910_EN2_LDO_ASS + regoffs, bit_pos); else - ret = tps65910_clear_bits(mfd, + ret = tps65910_reg_clear_bits(mfd, TPS65910_EN2_LDO_ASS + regoffs, bit_pos); if (ret < 0) { dev_err(mfd->dev, @@ -1022,10 +1017,10 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, if ((tps65910_chip_id(mfd) == TPS65910) && (id >= TPS65910_REG_VDIG1)) { if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3) - ret = tps65910_set_bits(mfd, + ret = tps65910_reg_set_bits(mfd, TPS65910_EN3_LDO_ASS + regoffs, bit_pos); else - ret = tps65910_clear_bits(mfd, + ret = tps65910_reg_clear_bits(mfd, TPS65910_EN3_LDO_ASS + regoffs, bit_pos); if (ret < 0) { dev_err(mfd->dev, @@ -1037,10 +1032,10 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, /* Return if no external control is selected */ if (!(ext_sleep_config & EXT_SLEEP_CONTROL)) { /* Clear all sleep controls */ - ret = tps65910_clear_bits(mfd, + ret = tps65910_reg_clear_bits(mfd, TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos); if (!ret) - ret = tps65910_clear_bits(mfd, + ret = tps65910_reg_clear_bits(mfd, TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos); if (ret < 0) dev_err(mfd->dev, @@ -1059,32 +1054,33 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, (tps65910_chip_id(mfd) == TPS65911))) { int op_reg_add = pmic->get_ctrl_reg(id) + 1; int sr_reg_add = pmic->get_ctrl_reg(id) + 2; - int opvsel = tps65910_reg_read(pmic, op_reg_add); - int srvsel = tps65910_reg_read(pmic, sr_reg_add); + int opvsel = tps65910_reg_read_locked(pmic, op_reg_add); + int srvsel = tps65910_reg_read_locked(pmic, sr_reg_add); if (opvsel & VDD1_OP_CMD_MASK) { u8 reg_val = srvsel & VDD1_OP_SEL_MASK; - ret = tps65910_reg_write(pmic, op_reg_add, reg_val); + ret = tps65910_reg_write_locked(pmic, op_reg_add, + reg_val); if (ret < 0) { dev_err(mfd->dev, "Error in configuring op register\n"); return ret; } } - ret = tps65910_reg_write(pmic, sr_reg_add, 0); + ret = tps65910_reg_write_locked(pmic, sr_reg_add, 0); if (ret < 0) { dev_err(mfd->dev, "Error in settting sr register\n"); return ret; } } - ret = tps65910_clear_bits(mfd, + ret = tps65910_reg_clear_bits(mfd, TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos); if (!ret) { if (ext_sleep_config & TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP) - ret = tps65910_set_bits(mfd, + ret = tps65910_reg_set_bits(mfd, TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos); else - ret = tps65910_clear_bits(mfd, + ret = tps65910_reg_clear_bits(mfd, TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos); } if (ret < 0) @@ -1117,7 +1113,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pmic); /* Give control of all register to control port */ - tps65910_set_bits(pmic->mfd, TPS65910_DEVCTRL, + tps65910_reg_set_bits(pmic->mfd, TPS65910_DEVCTRL, DEVCTRL_SR_CTL_I2C_SEL_MASK); switch(tps65910_chip_id(tps65910)) { -- cgit v1.2.3 From cd99758ba3bde64347a8ece381cbae2fb5c745b2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 14 May 2012 23:14:24 +0200 Subject: mfd: Convert wm831x to irq_domain The modern idiom is to use irq_domain to allocate interrupts. This is useful partly to allow further infrastructure to be based on the domains and partly because it makes it much easier to allocate virtual interrupts to devices as we don't need to allocate a contiguous range of interrupt numbers. Convert the wm831x driver over to this infrastructure, using a legacy IRQ mapping if an irq_base is specified in platform data and otherwise using a linear mapping, always registering the interrupts even if they won't ever be used. Only boards which need to use the GPIOs as interrupts should need to use an irq_base. This means that we can't use the MFD irq_base management since the unless we're using an explicit irq_base from platform data we can't rely on a linear mapping of interrupts. Instead we need to map things via the irq_domain - provide a conveniencem function wm831x_irq() to save a small amount of typing when doing so. Looking at this I couldn't clearly see anything the MFD core could do to make this nicer. Since we're not supporting device tree yet there's no meaningful advantage if we don't do this conversion in one, the fact that the interrupt resources are used for repeated IP blocks makes accessor functions for the irq_domain more trouble to do than they're worth. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/gpio/gpio-wm831x.c | 6 +- drivers/input/misc/wm831x-on.c | 2 +- drivers/input/touchscreen/wm831x-ts.c | 9 +-- drivers/mfd/Kconfig | 2 + drivers/mfd/wm831x-auxadc.c | 6 +- drivers/mfd/wm831x-core.c | 19 +++---- drivers/mfd/wm831x-irq.c | 101 +++++++++++++++++++++------------- drivers/power/wm831x_power.c | 21 ++++--- drivers/regulator/wm831x-dcdc.c | 24 +++++--- drivers/regulator/wm831x-isink.c | 4 +- drivers/regulator/wm831x-ldo.c | 10 ++-- drivers/rtc/rtc-wm831x.c | 2 +- include/linux/mfd/wm831x/core.h | 9 ++- 13 files changed, 131 insertions(+), 84 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index deb949e75ec1..e56a2165641c 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c @@ -102,10 +102,8 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); struct wm831x *wm831x = wm831x_gpio->wm831x; - if (!wm831x->irq_base) - return -EINVAL; - - return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; + return irq_create_mapping(wm831x->irq_domain, + WM831X_IRQ_GPIO_1 + offset); } static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c index 47f18d6bce46..6790a812a1db 100644 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c @@ -73,7 +73,7 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_on *wm831x_on; - int irq = platform_get_irq(pdev, 0); + int irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0)); int ret; wm831x_on = kzalloc(sizeof(struct wm831x_on), GFP_KERNEL); diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c index 4bc851a9dc3d..e83410721e38 100644 --- a/drivers/input/touchscreen/wm831x-ts.c +++ b/drivers/input/touchscreen/wm831x-ts.c @@ -260,15 +260,16 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev) * If we have a direct IRQ use it, otherwise use the interrupt * from the WM831x IRQ controller. */ + wm831x_ts->data_irq = wm831x_irq(wm831x, + platform_get_irq_byname(pdev, + "TCHDATA")); if (pdata && pdata->data_irq) wm831x_ts->data_irq = pdata->data_irq; - else - wm831x_ts->data_irq = platform_get_irq_byname(pdev, "TCHDATA"); + wm831x_ts->pd_irq = wm831x_irq(wm831x, + platform_get_irq_byname(pdev, "TCHPD")); if (pdata && pdata->pd_irq) wm831x_ts->pd_irq = pdata->pd_irq; - else - wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD"); if (pdata) wm831x_ts->pressure = pdata->pressure; diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index a0e1b834af61..8325c44c04c6 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -496,6 +496,7 @@ config MFD_WM831X_I2C select MFD_CORE select MFD_WM831X select REGMAP_I2C + select IRQ_DOMAIN depends on I2C=y && GENERIC_HARDIRQS help Support for the Wolfson Microelecronics WM831x and WM832x PMICs @@ -508,6 +509,7 @@ config MFD_WM831X_SPI select MFD_CORE select MFD_WM831X select REGMAP_SPI + select IRQ_DOMAIN depends on SPI_MASTER && GENERIC_HARDIRQS help Support for the Wolfson Microelecronics WM831x and WM832x PMICs diff --git a/drivers/mfd/wm831x-auxadc.c b/drivers/mfd/wm831x-auxadc.c index 87210954a066..6ee3018d8653 100644 --- a/drivers/mfd/wm831x-auxadc.c +++ b/drivers/mfd/wm831x-auxadc.c @@ -280,11 +280,11 @@ void wm831x_auxadc_init(struct wm831x *wm831x) mutex_init(&wm831x->auxadc_lock); INIT_LIST_HEAD(&wm831x->auxadc_pending); - if (wm831x->irq && wm831x->irq_base) { + if (wm831x->irq) { wm831x->auxadc_read = wm831x_auxadc_read_irq; - ret = request_threaded_irq(wm831x->irq_base + - WM831X_IRQ_AUXADC_DATA, + ret = request_threaded_irq(wm831x_irq(wm831x, + WM831X_IRQ_AUXADC_DATA), NULL, wm831x_auxadc_irq, 0, "auxadc", wm831x); if (ret < 0) { diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 476e4d31a823..946698fd2dc6 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -1813,27 +1813,27 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8310: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8310_devs, ARRAY_SIZE(wm8310_devs), - NULL, wm831x->irq_base); + NULL, 0); break; case WM8311: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8311_devs, ARRAY_SIZE(wm8311_devs), - NULL, wm831x->irq_base); + NULL, 0); if (!pdata || !pdata->disable_touch) mfd_add_devices(wm831x->dev, wm831x_num, touch_devs, ARRAY_SIZE(touch_devs), - NULL, wm831x->irq_base); + NULL, 0); break; case WM8312: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8312_devs, ARRAY_SIZE(wm8312_devs), - NULL, wm831x->irq_base); + NULL, 0); if (!pdata || !pdata->disable_touch) mfd_add_devices(wm831x->dev, wm831x_num, touch_devs, ARRAY_SIZE(touch_devs), - NULL, wm831x->irq_base); + NULL, 0); break; case WM8320: @@ -1842,7 +1842,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8326: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8320_devs, ARRAY_SIZE(wm8320_devs), - NULL, wm831x->irq_base); + NULL, 0); break; default: @@ -1867,7 +1867,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) if (ret & WM831X_XTAL_ENA) { ret = mfd_add_devices(wm831x->dev, wm831x_num, rtc_devs, ARRAY_SIZE(rtc_devs), - NULL, wm831x->irq_base); + NULL, 0); if (ret != 0) { dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret); goto err_irq; @@ -1880,7 +1880,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) /* Treat errors as non-critical */ ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs, ARRAY_SIZE(backlight_devs), NULL, - wm831x->irq_base); + 0); if (ret < 0) dev_err(wm831x->dev, "Failed to add backlight: %d\n", ret); @@ -1909,8 +1909,7 @@ void wm831x_device_exit(struct wm831x *wm831x) { wm831x_otp_exit(wm831x); mfd_remove_devices(wm831x->dev); - if (wm831x->irq_base) - free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x); + free_irq(wm831x_irq(wm831x, WM831X_IRQ_AUXADC_DATA), wm831x); wm831x_irq_exit(wm831x); } diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index 2be9628074bd..ecc9d6d62fad 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -328,7 +329,7 @@ static inline int irq_data_to_status_reg(struct wm831x_irq_data *irq_data) static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x, int irq) { - return &wm831x_irqs[irq - wm831x->irq_base]; + return &wm831x_irqs[irq]; } static void wm831x_irq_lock(struct irq_data *data) @@ -374,7 +375,7 @@ static void wm831x_irq_enable(struct irq_data *data) { struct wm831x *wm831x = irq_data_get_irq_chip_data(data); struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, - data->irq); + data->hwirq); wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; } @@ -383,7 +384,7 @@ static void wm831x_irq_disable(struct irq_data *data) { struct wm831x *wm831x = irq_data_get_irq_chip_data(data); struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, - data->irq); + data->hwirq); wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; } @@ -393,7 +394,7 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type) struct wm831x *wm831x = irq_data_get_irq_chip_data(data); int irq; - irq = data->irq - wm831x->irq_base; + irq = data->hwirq; if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) { /* Ignore internal-only IRQs */ @@ -469,9 +470,11 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data) * descriptors. */ if (primary & WM831X_TCHPD_INT) - handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHPD); + handle_nested_irq(irq_find_mapping(wm831x->irq_domain, + WM831X_IRQ_TCHPD)); if (primary & WM831X_TCHDATA_INT) - handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHDATA); + handle_nested_irq(irq_find_mapping(wm831x->irq_domain, + WM831X_IRQ_TCHDATA)); primary &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT); for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) { @@ -507,7 +510,8 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data) } if (*status & wm831x_irqs[i].mask) - handle_nested_irq(wm831x->irq_base + i); + handle_nested_irq(irq_find_mapping(wm831x->irq_domain, + i)); /* Simulate an edge triggered IRQ by polling the input * status. This is sucky but improves interoperability. @@ -516,7 +520,8 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data) wm831x->gpio_level[i - WM831X_IRQ_GPIO_1]) { ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL); while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) { - handle_nested_irq(wm831x->irq_base + i); + handle_nested_irq(irq_find_mapping(wm831x->irq_domain, + i)); ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL); } @@ -527,10 +532,34 @@ out: return IRQ_HANDLED; } +static int wm831x_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + irq_set_chip_data(virq, h->host_data); + irq_set_chip_and_handler(virq, &wm831x_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 wm831x_irq_domain_ops = { + .map = wm831x_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + int wm831x_irq_init(struct wm831x *wm831x, int irq) { struct wm831x_pdata *pdata = wm831x->dev->platform_data; - int i, cur_irq, ret; + struct irq_domain *domain; + int i, ret, irq_base; mutex_init(&wm831x->irq_lock); @@ -543,18 +572,33 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) } /* Try to dynamically allocate IRQs if no base is specified */ - if (!pdata || !pdata->irq_base) - wm831x->irq_base = -1; + if (pdata && pdata->irq_base) { + irq_base = irq_alloc_descs(pdata->irq_base, 0, + WM831X_NUM_IRQS, 0); + if (irq_base < 0) { + dev_warn(wm831x->dev, "Failed to allocate IRQs: %d\n", + irq_base); + irq_base = 0; + } + } else { + irq_base = 0; + } + + if (irq_base) + domain = irq_domain_add_legacy(wm831x->dev->of_node, + ARRAY_SIZE(wm831x_irqs), + irq_base, 0, + &wm831x_irq_domain_ops, + wm831x); else - wm831x->irq_base = pdata->irq_base; + domain = irq_domain_add_linear(wm831x->dev->of_node, + ARRAY_SIZE(wm831x_irqs), + &wm831x_irq_domain_ops, + wm831x); - wm831x->irq_base = irq_alloc_descs(wm831x->irq_base, 0, - WM831X_NUM_IRQS, 0); - if (wm831x->irq_base < 0) { - dev_warn(wm831x->dev, "Failed to allocate IRQs: %d\n", - wm831x->irq_base); - wm831x->irq_base = 0; - return 0; + if (!domain) { + dev_warn(wm831x->dev, "Failed to allocate IRQ domain\n"); + return -EINVAL; } if (pdata && pdata->irq_cmos) @@ -566,24 +610,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) WM831X_IRQ_OD, i); wm831x->irq = irq; - - /* Register them with genirq */ - for (cur_irq = wm831x->irq_base; - cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base; - cur_irq++) { - irq_set_chip_data(cur_irq, wm831x); - irq_set_chip_and_handler(cur_irq, &wm831x_irq_chip, - handle_edge_irq); - irq_set_nested_thread(cur_irq, 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(cur_irq, IRQF_VALID); -#else - irq_set_noprobe(cur_irq); -#endif - } + wm831x->irq_domain = domain; if (irq) { /* Try to flag /IRQ as a wake source; there are a number of diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c index 987332b71d8d..fc1ad9551182 100644 --- a/drivers/power/wm831x_power.c +++ b/drivers/power/wm831x_power.c @@ -565,7 +565,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) goto err_usb; } - irq = platform_get_irq_byname(pdev, "SYSLO"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq, IRQF_TRIGGER_RISING, "System power low", power); @@ -575,7 +575,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) goto err_battery; } - irq = platform_get_irq_byname(pdev, "PWR SRC"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq, IRQF_TRIGGER_RISING, "Power source", power); @@ -586,7 +586,9 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) } for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { - irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); + irq = wm831x_irq(wm831x, + platform_get_irq_byname(pdev, + wm831x_bat_irqs[i])); ret = request_threaded_irq(irq, NULL, wm831x_bat_irq, IRQF_TRIGGER_RISING, wm831x_bat_irqs[i], @@ -606,10 +608,10 @@ err_bat_irq: irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); free_irq(irq, power); } - irq = platform_get_irq_byname(pdev, "PWR SRC"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); free_irq(irq, power); err_syslo: - irq = platform_get_irq_byname(pdev, "SYSLO"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); free_irq(irq, power); err_battery: if (power->have_battery) @@ -626,17 +628,20 @@ err_kmalloc: static __devexit int wm831x_power_remove(struct platform_device *pdev) { struct wm831x_power *wm831x_power = platform_get_drvdata(pdev); + struct wm831x *wm831x = wm831x_power->wm831x; int irq, i; for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { - irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); + irq = wm831x_irq(wm831x, + platform_get_irq_byname(pdev, + wm831x_bat_irqs[i])); free_irq(irq, wm831x_power); } - irq = platform_get_irq_byname(pdev, "PWR SRC"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); free_irq(irq, wm831x_power); - irq = platform_get_irq_byname(pdev, "SYSLO"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); free_irq(irq, wm831x_power); if (wm831x_power->have_battery) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index ff810e787eac..33b2f20a2932 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -565,7 +565,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) goto err; } - irq = platform_get_irq_byname(pdev, "UV"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq, IRQF_TRIGGER_RISING, dcdc->name, dcdc); if (ret != 0) { @@ -574,7 +574,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) goto err_regulator; } - irq = platform_get_irq_byname(pdev, "HC"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC")); ret = request_threaded_irq(irq, NULL, wm831x_dcdc_oc_irq, IRQF_TRIGGER_RISING, dcdc->name, dcdc); if (ret != 0) { @@ -588,7 +588,8 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) return 0; err_uv: - free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); + free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")), + dcdc); err_regulator: regulator_unregister(dcdc->regulator); err: @@ -600,11 +601,14 @@ err: static __devexit int wm831x_buckv_remove(struct platform_device *pdev) { struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); + struct wm831x *wm831x = dcdc->wm831x; platform_set_drvdata(pdev, NULL); - free_irq(platform_get_irq_byname(pdev, "HC"), dcdc); - free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); + free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC")), + dcdc); + free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")), + dcdc); regulator_unregister(dcdc->regulator); if (dcdc->dvs_gpio) gpio_free(dcdc->dvs_gpio); @@ -758,7 +762,7 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) goto err; } - irq = platform_get_irq_byname(pdev, "UV"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq, IRQF_TRIGGER_RISING, dcdc->name, dcdc); if (ret != 0) { @@ -783,7 +787,8 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); + free_irq(wm831x_irq(dcdc->wm831x, platform_get_irq_byname(pdev, "UV")), + dcdc); regulator_unregister(dcdc->regulator); return 0; @@ -883,7 +888,7 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) goto err; } - irq = platform_get_irq_byname(pdev, "UV"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq, IRQF_TRIGGER_RISING, dcdc->name, dcdc); @@ -910,7 +915,8 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); + free_irq(wm831x_irq(dcdc->wm831x, platform_get_irq_byname(pdev, "UV")), + dcdc); regulator_unregister(dcdc->regulator); kfree(dcdc); diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index b414e09c5620..1596947f603f 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c @@ -198,7 +198,7 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev) goto err; } - irq = platform_get_irq(pdev, 0); + irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0)); ret = request_threaded_irq(irq, NULL, wm831x_isink_irq, IRQF_TRIGGER_RISING, isink->name, isink); if (ret != 0) { @@ -223,7 +223,7 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - free_irq(platform_get_irq(pdev, 0), isink); + free_irq(wm831x_irq(isink->wm831x, platform_get_irq(pdev, 0)), isink); regulator_unregister(isink->regulator); diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 641e9f6499d1..b09ba05ada6d 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -359,7 +359,7 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) goto err; } - irq = platform_get_irq_byname(pdev, "UV"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq, IRQF_TRIGGER_RISING, ldo->name, ldo); @@ -385,7 +385,8 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - free_irq(platform_get_irq_byname(pdev, "UV"), ldo); + free_irq(wm831x_irq(ldo->wm831x, + platform_get_irq_byname(pdev, "UV")), ldo); regulator_unregister(ldo->regulator); return 0; @@ -624,7 +625,7 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) goto err; } - irq = platform_get_irq_byname(pdev, "UV"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq, IRQF_TRIGGER_RISING, ldo->name, ldo); if (ret != 0) { @@ -647,7 +648,8 @@ static __devexit int wm831x_aldo_remove(struct platform_device *pdev) { struct wm831x_ldo *ldo = platform_get_drvdata(pdev); - free_irq(platform_get_irq_byname(pdev, "UV"), ldo); + free_irq(wm831x_irq(ldo->wm831x, platform_get_irq_byname(pdev, "UV")), + ldo); regulator_unregister(ldo->regulator); return 0; diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 3b6e6a67e765..59c6245e0421 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c @@ -396,7 +396,7 @@ static int wm831x_rtc_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_rtc *wm831x_rtc; - int alm_irq = platform_get_irq_byname(pdev, "ALM"); + int alm_irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "ALM")); int ret = 0; wm831x_rtc = devm_kzalloc(&pdev->dev, sizeof(*wm831x_rtc), GFP_KERNEL); diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h index 4b1211859f74..736191cc7e00 100644 --- a/include/linux/mfd/wm831x/core.h +++ b/include/linux/mfd/wm831x/core.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -338,6 +339,7 @@ #define WM831X_FLL_CLK_SRC_WIDTH 2 /* FLL_CLK_SRC - [1:0] */ struct regulator_dev; +struct irq_domain; #define WM831X_NUM_IRQ_REGS 5 #define WM831X_NUM_GPIO_REGS 16 @@ -367,7 +369,7 @@ struct wm831x { int irq; /* Our chip IRQ */ struct mutex irq_lock; - int irq_base; + struct irq_domain *irq_domain; int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */ int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */ @@ -417,6 +419,11 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq); void wm831x_irq_exit(struct wm831x *wm831x); void wm831x_auxadc_init(struct wm831x *wm831x); +static inline int wm831x_irq(struct wm831x *wm831x, int irq) +{ + return irq_create_mapping(wm831x->irq_domain, irq); +} + extern struct regmap_config wm831x_regmap_config; #endif -- cgit v1.2.3 From b09530ef844f0bf29ed3677080c02b179be84818 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sun, 13 May 2012 09:18:02 +0800 Subject: mfd: Make anatop register accessor more flexible and rename meaningfully - rename to anatop_read_reg and anatop_write_reg - anatop_read_reg directly return reg value - anatop_write_reg write reg with mask Signed-off-by: Richard Zhao Reviewed-by: Ying-Chun Liu (PaulLiu) Signed-off-by: Samuel Ortiz --- drivers/mfd/anatop-mfd.c | 35 +++++++++++------------------------ drivers/regulator/anatop-regulator.c | 18 ++++++++---------- include/linux/mfd/anatop.h | 4 ++-- 3 files changed, 21 insertions(+), 36 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/mfd/anatop-mfd.c b/drivers/mfd/anatop-mfd.c index 2af42480635e..6da06341f6c9 100644 --- a/drivers/mfd/anatop-mfd.c +++ b/drivers/mfd/anatop-mfd.c @@ -41,39 +41,26 @@ #include #include -u32 anatop_get_bits(struct anatop *adata, u32 addr, int bit_shift, - int bit_width) +u32 anatop_read_reg(struct anatop *adata, u32 addr) { - u32 val, mask; - - if (bit_width == 32) - mask = ~0; - else - mask = (1 << bit_width) - 1; - - val = readl(adata->ioreg + addr); - val = (val >> bit_shift) & mask; - - return val; + return readl(adata->ioreg + addr); } -EXPORT_SYMBOL_GPL(anatop_get_bits); +EXPORT_SYMBOL_GPL(anatop_read_reg); -void anatop_set_bits(struct anatop *adata, u32 addr, int bit_shift, - int bit_width, u32 data) +void anatop_write_reg(struct anatop *adata, u32 addr, u32 data, u32 mask) { - u32 val, mask; + u32 val; - if (bit_width == 32) - mask = ~0; - else - mask = (1 << bit_width) - 1; + data &= mask; spin_lock(&adata->reglock); - val = readl(adata->ioreg + addr) & ~(mask << bit_shift); - writel((data << bit_shift) | val, adata->ioreg + addr); + val = readl(adata->ioreg + addr); + val &= ~mask; + val |= data; + writel(val, adata->ioreg + addr); spin_unlock(&adata->reglock); } -EXPORT_SYMBOL_GPL(anatop_set_bits); +EXPORT_SYMBOL_GPL(anatop_write_reg); static const struct of_device_id of_anatop_match[] = { { .compatible = "fsl,imx6q-anatop", }, diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 81fd606e47bc..0a3408570d0a 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -47,7 +47,7 @@ static int anatop_set_voltage(struct regulator_dev *reg, int min_uV, int max_uV, unsigned *selector) { struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); - u32 val, sel; + u32 val, sel, mask; int uv; uv = min_uV; @@ -71,11 +71,10 @@ static int anatop_set_voltage(struct regulator_dev *reg, int min_uV, val = anatop_reg->min_bit_val + sel; *selector = sel; dev_dbg(®->dev, "%s: calculated val %d\n", __func__, val); - anatop_set_bits(anatop_reg->mfd, - anatop_reg->control_reg, - anatop_reg->vol_bit_shift, - anatop_reg->vol_bit_width, - val); + mask = ((1 << anatop_reg->vol_bit_width) - 1) << + anatop_reg->vol_bit_shift; + val <<= anatop_reg->vol_bit_shift; + anatop_write_reg(anatop_reg->mfd, anatop_reg->control_reg, val, mask); return 0; } @@ -88,10 +87,9 @@ static int anatop_get_voltage_sel(struct regulator_dev *reg) if (!anatop_reg->control_reg) return -ENOTSUPP; - val = anatop_get_bits(anatop_reg->mfd, - anatop_reg->control_reg, - anatop_reg->vol_bit_shift, - anatop_reg->vol_bit_width); + val = anatop_read_reg(anatop_reg->mfd, anatop_reg->control_reg); + val = (val & ((1 << anatop_reg->vol_bit_width) - 1)) >> + anatop_reg->vol_bit_shift; return val - anatop_reg->min_bit_val; } diff --git a/include/linux/mfd/anatop.h b/include/linux/mfd/anatop.h index 22c1007d3ec5..7f92acf03d9e 100644 --- a/include/linux/mfd/anatop.h +++ b/include/linux/mfd/anatop.h @@ -34,7 +34,7 @@ struct anatop { spinlock_t reglock; }; -extern u32 anatop_get_bits(struct anatop *, u32, int, int); -extern void anatop_set_bits(struct anatop *, u32, int, int, u32); +extern u32 anatop_read_reg(struct anatop *, u32); +extern void anatop_write_reg(struct anatop *, u32, u32, u32); #endif /* __LINUX_MFD_ANATOP_H */ -- cgit v1.2.3