From 9787f5e28b50774f1d5672e33b277ba1e9aa0753 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Thu, 2 Jun 2016 12:52:23 -0500 Subject: mfd: altr_a10sr: Add Altera Arria10 DevKit System Resource Chip Add support for the Altera Arria10 Development Kit System Resource chip which is implemented using a MAX5 as a external gpio extender with the regmap framework over a SPI bus. Signed-off-by: Thor Thayer Signed-off-by: Lee Jones --- include/linux/mfd/altera-a10sr.h | 85 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 include/linux/mfd/altera-a10sr.h (limited to 'include') diff --git a/include/linux/mfd/altera-a10sr.h b/include/linux/mfd/altera-a10sr.h new file mode 100644 index 000000000000..45a5e6e7db54 --- /dev/null +++ b/include/linux/mfd/altera-a10sr.h @@ -0,0 +1,85 @@ +/* + * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * Declarations for Altera Arria10 MAX5 System Resource Chip + * + * Adapted from DA9052 + */ + +#ifndef __MFD_ALTERA_A10SR_H +#define __MFD_ALTERA_A10SR_H + +#include +#include +#include +#include +#include + +/* Write registers are always on even addresses */ +#define WRITE_REG_MASK 0xFE +/* Odd registers are always on odd addresses */ +#define READ_REG_MASK 0x01 + +#define ALTR_A10SR_BITS_PER_REGISTER 8 +/* + * To find the correct register, we divide the input GPIO by + * the number of GPIO in each register. We then need to multiply + * by 2 because the reads are at odd addresses. + */ +#define ALTR_A10SR_REG_OFFSET(X) (((X) / ALTR_A10SR_BITS_PER_REGISTER) << 1) +#define ALTR_A10SR_REG_BIT(X) ((X) % ALTR_A10SR_BITS_PER_REGISTER) +#define ALTR_A10SR_REG_BIT_CHG(X, Y) ((X) << ALTR_A10SR_REG_BIT(Y)) +#define ALTR_A10SR_REG_BIT_MASK(X) (1 << ALTR_A10SR_REG_BIT(X)) + +/* Arria10 System Controller Register Defines */ +#define ALTR_A10SR_NOP 0x00 /* No Change */ +#define ALTR_A10SR_VERSION_READ 0x00 /* MAX5 Version Read */ + +#define ALTR_A10SR_LED_REG 0x02 /* LED - Upper 4 bits */ +/* LED register Bit Definitions */ +#define ALTR_A10SR_LED_VALID_SHIFT 4 /* LED - Upper 4 bits valid */ +#define ALTR_A10SR_OUT_VALID_RANGE_LO ALTR_A10SR_LED_VALID_SHIFT +#define ALTR_A10SR_OUT_VALID_RANGE_HI 7 + +#define ALTR_A10SR_PBDSW_REG 0x04 /* PB & DIP SW - Input only */ +#define ALTR_A10SR_PBDSW_IRQ_REG 0x06 /* PB & DIP SW Flag Clear */ +/* Pushbutton & DIP Switch Bit Definitions */ +#define ALTR_A10SR_IN_VALID_RANGE_LO 8 +#define ALTR_A10SR_IN_VALID_RANGE_HI 15 + +#define ALTR_A10SR_PWR_GOOD1_REG 0x08 /* Power Good1 Read */ +#define ALTR_A10SR_PWR_GOOD2_REG 0x0A /* Power Good2 Read */ +#define ALTR_A10SR_PWR_GOOD3_REG 0x0C /* Power Good3 Read */ +#define ALTR_A10SR_FMCAB_REG 0x0E /* FMCA/B & PCIe Pwr Enable */ +#define ALTR_A10SR_HPS_RST_REG 0x10 /* HPS Reset */ +#define ALTR_A10SR_USB_QSPI_REG 0x12 /* USB, BQSPI, FILE Reset */ +#define ALTR_A10SR_SFPA_REG 0x14 /* SFPA Control Reg */ +#define ALTR_A10SR_SFPB_REG 0x16 /* SFPB Control Reg */ +#define ALTR_A10SR_I2C_M_REG 0x18 /* I2C Master Select */ +#define ALTR_A10SR_WARM_RST_REG 0x1A /* HPS Warm Reset */ +#define ALTR_A10SR_WR_KEY_REG 0x1C /* HPS Warm Reset Key */ +#define ALTR_A10SR_PMBUS_REG 0x1E /* HPS PM Bus */ + +/** + * struct altr_a10sr - Altera Max5 MFD device private data structure + * @dev: : this device + * @regmap: the regmap assigned to the parent device. + */ +struct altr_a10sr { + struct device *dev; + struct regmap *regmap; +}; + +#endif /* __MFD_ALTERA_A10SR_H */ -- cgit v1.2.3 From 0d3a7cce3e8bc5c060b1f038984c10cb70289e1d Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Wed, 8 Jun 2016 10:54:35 -0500 Subject: mfd: ti_am335x_tscadc: Rename regmap_tscadc to regmap The regmap structure pointer is named regmap_tscadc, this is not consistent with other drivers and is redundant, it also contributes to several checkpatch warnings involving long lines. Rename this. Signed-off-by: Andrew F. Davis Signed-off-by: Lee Jones --- drivers/mfd/ti_am335x_tscadc.c | 36 ++++++++++++++++++------------------ include/linux/mfd/ti_am335x_tscadc.h | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index e71f6092be61..c8f027b4ea4c 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -43,7 +43,7 @@ void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tscadc, u32 val) if (tscadc->adc_waiting) wake_up(&tscadc->reg_se_wait); else if (!tscadc->adc_in_use) - regmap_write(tscadc->regmap_tscadc, REG_SE, tscadc->reg_se_cache); + regmap_write(tscadc->regmap, REG_SE, tscadc->reg_se_cache); spin_unlock_irqrestore(&tscadc->reg_lock, flags); } @@ -54,7 +54,7 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tscadc) DEFINE_WAIT(wait); u32 reg; - regmap_read(tscadc->regmap_tscadc, REG_ADCFSM, ®); + regmap_read(tscadc->regmap, REG_ADCFSM, ®); if (reg & SEQ_STATUS) { tscadc->adc_waiting = true; prepare_to_wait(&tscadc->reg_se_wait, &wait, @@ -70,7 +70,7 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tscadc) * Sequencer should either be idle or * busy applying the charge step. */ - regmap_read(tscadc->regmap_tscadc, REG_ADCFSM, ®); + regmap_read(tscadc->regmap, REG_ADCFSM, ®); WARN_ON((reg & SEQ_STATUS) && !(reg & CHARGE_STEP)); tscadc->adc_waiting = false; } @@ -82,7 +82,7 @@ void am335x_tsc_se_set_once(struct ti_tscadc_dev *tscadc, u32 val) spin_lock_irq(&tscadc->reg_lock); am335x_tscadc_need_adc(tscadc); - regmap_write(tscadc->regmap_tscadc, REG_SE, val); + regmap_write(tscadc->regmap, REG_SE, val); spin_unlock_irq(&tscadc->reg_lock); } EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once); @@ -93,7 +93,7 @@ void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tscadc) spin_lock_irqsave(&tscadc->reg_lock, flags); tscadc->adc_in_use = false; - regmap_write(tscadc->regmap_tscadc, REG_SE, tscadc->reg_se_cache); + regmap_write(tscadc->regmap, REG_SE, tscadc->reg_se_cache); spin_unlock_irqrestore(&tscadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done); @@ -104,7 +104,7 @@ void am335x_tsc_se_clr(struct ti_tscadc_dev *tscadc, u32 val) spin_lock_irqsave(&tscadc->reg_lock, flags); tscadc->reg_se_cache &= ~val; - regmap_write(tscadc->regmap_tscadc, REG_SE, tscadc->reg_se_cache); + regmap_write(tscadc->regmap, REG_SE, tscadc->reg_se_cache); spin_unlock_irqrestore(&tscadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); @@ -116,7 +116,7 @@ static void tscadc_idle_config(struct ti_tscadc_dev *tscadc) idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM | STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN; - regmap_write(tscadc->regmap_tscadc, REG_IDLECONFIG, idleconfig); + regmap_write(tscadc->regmap, REG_IDLECONFIG, idleconfig); } static int ti_tscadc_probe(struct platform_device *pdev) @@ -187,11 +187,11 @@ static int ti_tscadc_probe(struct platform_device *pdev) if (IS_ERR(tscadc->tscadc_base)) return PTR_ERR(tscadc->tscadc_base); - tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev, + tscadc->regmap = devm_regmap_init_mmio(&pdev->dev, tscadc->tscadc_base, &tscadc_regmap_config); - if (IS_ERR(tscadc->regmap_tscadc)) { + if (IS_ERR(tscadc->regmap)) { dev_err(&pdev->dev, "regmap init failed\n"); - err = PTR_ERR(tscadc->regmap_tscadc); + err = PTR_ERR(tscadc->regmap); goto ret; } @@ -221,11 +221,11 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* TSCADC_CLKDIV needs to be configured to the value minus 1 */ tscadc->clk_div--; - regmap_write(tscadc->regmap_tscadc, REG_CLKDIV, tscadc->clk_div); + regmap_write(tscadc->regmap, REG_CLKDIV, tscadc->clk_div); /* Set the control register bits */ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; - regmap_write(tscadc->regmap_tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap, REG_CTRL, ctrl); /* Set register bits for Idle Config Mode */ if (tsc_wires > 0) { @@ -239,7 +239,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* Enable the TSC module enable bit */ ctrl |= CNTRLREG_TSCSSENB; - regmap_write(tscadc->regmap_tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap, REG_CTRL, ctrl); tscadc->used_cells = 0; tscadc->tsc_cell = -1; @@ -285,7 +285,7 @@ static int ti_tscadc_remove(struct platform_device *pdev) { struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev); - regmap_write(tscadc->regmap_tscadc, REG_SE, 0x00); + regmap_write(tscadc->regmap, REG_SE, 0x00); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -299,7 +299,7 @@ static int __maybe_unused tscadc_suspend(struct device *dev) { struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev); - regmap_write(tscadc->regmap_tscadc, REG_SE, 0x00); + regmap_write(tscadc->regmap, REG_SE, 0x00); pm_runtime_put_sync(dev); return 0; @@ -314,7 +314,7 @@ static int __maybe_unused tscadc_resume(struct device *dev) /* context restore */ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; - regmap_write(tscadc->regmap_tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap, REG_CTRL, ctrl); if (tscadc->tsc_cell != -1) { if (tscadc->tsc_wires == 5) @@ -324,9 +324,9 @@ static int __maybe_unused tscadc_resume(struct device *dev) tscadc_idle_config(tscadc); } ctrl |= CNTRLREG_TSCSSENB; - regmap_write(tscadc->regmap_tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap, REG_CTRL, ctrl); - regmap_write(tscadc->regmap_tscadc, REG_CLKDIV, tscadc->clk_div); + regmap_write(tscadc->regmap, REG_CLKDIV, tscadc->clk_div); return 0; } diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 1fd50dcfe47c..2567a87872b0 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -153,7 +153,7 @@ struct ti_tscadc_dev { struct device *dev; - struct regmap *regmap_tscadc; + struct regmap *regmap; void __iomem *tscadc_base; int irq; int used_cells; /* 1-2 */ -- cgit v1.2.3 From 9e3d5c996b340c1572afabe5ff2f0dd8ced1583a Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 14 Jun 2016 15:43:31 -0700 Subject: mfd: hi655x-pmic: Rename some interrupt macro names Currently the hi655x-pmic driver has names for interrupt mask values, but not for the interrupt numbers themselves. So to allow for interrupt numbers to have sane names, rename the mask values with the _MASK postfix and use the existing names as the interrupt name Signed-off-by: John Stultz Signed-off-by: Lee Jones --- drivers/mfd/hi655x-pmic.c | 16 ++++++++-------- include/linux/mfd/hi655x-pmic.h | 25 +++++++++++++++++-------- 2 files changed, 25 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c index 68ab3701cbf3..072e6feab6e9 100644 --- a/drivers/mfd/hi655x-pmic.c +++ b/drivers/mfd/hi655x-pmic.c @@ -29,14 +29,14 @@ static const struct mfd_cell hi655x_pmic_devs[] = { }; static const struct regmap_irq hi655x_irqs[] = { - { .reg_offset = 0, .mask = OTMP_D1R_INT }, - { .reg_offset = 0, .mask = VSYS_2P5_R_INT }, - { .reg_offset = 0, .mask = VSYS_UV_D3R_INT }, - { .reg_offset = 0, .mask = VSYS_6P0_D200UR_INT }, - { .reg_offset = 0, .mask = PWRON_D4SR_INT }, - { .reg_offset = 0, .mask = PWRON_D20F_INT }, - { .reg_offset = 0, .mask = PWRON_D20R_INT }, - { .reg_offset = 0, .mask = RESERVE_INT }, + { .reg_offset = 0, .mask = OTMP_D1R_INT_MASK }, + { .reg_offset = 0, .mask = VSYS_2P5_R_INT_MASK }, + { .reg_offset = 0, .mask = VSYS_UV_D3R_INT_MASK }, + { .reg_offset = 0, .mask = VSYS_6P0_D200UR_INT_MASK }, + { .reg_offset = 0, .mask = PWRON_D4SR_INT_MASK }, + { .reg_offset = 0, .mask = PWRON_D20F_INT_MASK }, + { .reg_offset = 0, .mask = PWRON_D20R_INT_MASK }, + { .reg_offset = 0, .mask = RESERVE_INT_MASK }, }; static const struct regmap_irq_chip hi655x_irq_chip = { diff --git a/include/linux/mfd/hi655x-pmic.h b/include/linux/mfd/hi655x-pmic.h index dbbe9a644622..62f03c2b1bb0 100644 --- a/include/linux/mfd/hi655x-pmic.h +++ b/include/linux/mfd/hi655x-pmic.h @@ -34,14 +34,23 @@ #define PMU_VER_START 0x10 #define PMU_VER_END 0x38 -#define RESERVE_INT BIT(7) -#define PWRON_D20R_INT BIT(6) -#define PWRON_D20F_INT BIT(5) -#define PWRON_D4SR_INT BIT(4) -#define VSYS_6P0_D200UR_INT BIT(3) -#define VSYS_UV_D3R_INT BIT(2) -#define VSYS_2P5_R_INT BIT(1) -#define OTMP_D1R_INT BIT(0) +#define RESERVE_INT 7 +#define PWRON_D20R_INT 6 +#define PWRON_D20F_INT 5 +#define PWRON_D4SR_INT 4 +#define VSYS_6P0_D200UR_INT 3 +#define VSYS_UV_D3R_INT 2 +#define VSYS_2P5_R_INT 1 +#define OTMP_D1R_INT 0 + +#define RESERVE_INT_MASK BIT(RESERVE_INT) +#define PWRON_D20R_INT_MASK BIT(PWRON_D20R_INT) +#define PWRON_D20F_INT_MASK BIT(PWRON_D20F_INT) +#define PWRON_D4SR_INT_MASK BIT(PWRON_D4SR_INT) +#define VSYS_6P0_D200UR_INT_MASK BIT(VSYS_6P0_D200UR_INT) +#define VSYS_UV_D3R_INT_MASK BIT(VSYS_UV_D3R_INT) +#define VSYS_2P5_R_INT_MASK BIT(VSYS_2P5_R_INT) +#define OTMP_D1R_INT_MASK BIT(OTMP_D1R_INT) struct hi655x_pmic { struct resource *res; -- cgit v1.2.3 From 698adfc968f3625a50853157ee5dbd208b6408a8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 13 Jun 2016 13:37:51 +0100 Subject: mfd: arizona: Remove some duplicate defines Some duplicate defines seem to have snuck into the registers file, this patch simply removes them. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- include/linux/mfd/arizona/registers.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'include') diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index cd7e78eae006..0d06c5d0af93 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h @@ -856,12 +856,6 @@ #define ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE 0xB38 #define ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE 0xB40 #define ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE 0xB48 -#define ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE 0xB60 -#define ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE 0xB68 -#define ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE 0xB30 -#define ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE 0xB38 -#define ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE 0xB40 -#define ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE 0xB48 #define ARIZONA_ISRC2DEC3MIX_INPUT_1_SOURCE 0xB50 #define ARIZONA_ISRC2DEC4MIX_INPUT_1_SOURCE 0xB58 #define ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE 0xB60 -- cgit v1.2.3 From fc1882dcb5031953169a38260a0e653910825e46 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 25 May 2016 14:22:02 +0200 Subject: mfd: stmpe: Move platform data into MFD driver The STMPE platform data is only populated from the device tree in all existing users, so push the struct and make the OF case the norm. Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/stmpe.c | 40 ++++++++++++++++++++++++++++------------ include/linux/mfd/stmpe.h | 22 +--------------------- 2 files changed, 29 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index fb8f9e8b75df..94c7cc02fdab 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -23,6 +23,27 @@ #include #include "stmpe.h" +/** + * struct stmpe_platform_data - STMPE platform data + * @id: device id to distinguish between multiple STMPEs on the same board + * @blocks: bitmask of blocks to enable (use STMPE_BLOCK_*) + * @irq_trigger: IRQ trigger to use for the interrupt to the host + * @autosleep: bool to enable/disable stmpe autosleep + * @autosleep_timeout: inactivity timeout in milliseconds for autosleep + * @irq_over_gpio: true if gpio is used to get irq + * @irq_gpio: gpio number over which irq will be requested (significant only if + * irq_over_gpio is true) + */ +struct stmpe_platform_data { + int id; + unsigned int blocks; + unsigned int irq_trigger; + bool autosleep; + bool irq_over_gpio; + int irq_gpio; + int autosleep_timeout; +}; + static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks) { return stmpe->variant->enable(stmpe, blocks, true); @@ -1187,24 +1208,19 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata, /* Called from client specific probe routines */ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) { - struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev); + struct stmpe_platform_data *pdata; struct device_node *np = ci->dev->of_node; struct stmpe *stmpe; int ret; - if (!pdata) { - if (!np) - return -EINVAL; - - pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; + pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; - stmpe_of_probe(pdata, np); + stmpe_of_probe(pdata, np); - if (of_find_property(np, "interrupts", NULL) == NULL) - ci->irq = -1; - } + if (of_find_property(np, "interrupts", NULL) == NULL) + ci->irq = -1; stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL); if (!stmpe) diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h index cb83883918a7..de748bc7525e 100644 --- a/include/linux/mfd/stmpe.h +++ b/include/linux/mfd/stmpe.h @@ -62,6 +62,7 @@ enum { struct stmpe_variant_info; struct stmpe_client_info; +struct stmpe_platform_data; /** * struct stmpe - STMPE MFD structure @@ -117,25 +118,4 @@ extern int stmpe_disable(struct stmpe *stmpe, unsigned int blocks); #define STMPE_GPIO_NOREQ_811_TOUCH (0xf0) -/** - * struct stmpe_platform_data - STMPE platform data - * @id: device id to distinguish between multiple STMPEs on the same board - * @blocks: bitmask of blocks to enable (use STMPE_BLOCK_*) - * @irq_trigger: IRQ trigger to use for the interrupt to the host - * @autosleep: bool to enable/disable stmpe autosleep - * @autosleep_timeout: inactivity timeout in milliseconds for autosleep - * @irq_over_gpio: true if gpio is used to get irq - * @irq_gpio: gpio number over which irq will be requested (significant only if - * irq_over_gpio is true) - */ -struct stmpe_platform_data { - int id; - unsigned int blocks; - unsigned int irq_trigger; - bool autosleep; - bool irq_over_gpio; - int irq_gpio; - int autosleep_timeout; -}; - #endif -- cgit v1.2.3 From 0a58da1e2f25f213fb72d7d6a18dff9562621215 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 20 Jun 2016 17:07:18 +0300 Subject: mfd: twl6040: Handle mclk used for HPPLL and optional internal clock source On some boards, like omap5-uevm the MCLK is gated by default and in order to be able to use the High performance modes of twl6040 it need to be enabled by SW. Add support for handling the MCLK source clock via CCF. At the same time lower the print priority of the notification that the 32K clock is not provided and it is not going to be handled by the driver. Signed-off-by: Peter Ujfalusi Acked-by: Rob Herring Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/mfd/twl6040.txt | 4 +-- drivers/mfd/twl6040.c | 41 ++++++++++++++++------- include/linux/mfd/twl6040.h | 5 +-- 3 files changed, 34 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/Documentation/devicetree/bindings/mfd/twl6040.txt b/Documentation/devicetree/bindings/mfd/twl6040.txt index a41157b5d930..e6afdfa3543d 100644 --- a/Documentation/devicetree/bindings/mfd/twl6040.txt +++ b/Documentation/devicetree/bindings/mfd/twl6040.txt @@ -19,8 +19,8 @@ Required properties: Optional properties, nodes: - enable-active-high: To power on the twl6040 during boot. -- clocks: phandle to the clk32k clock provider -- clock-names: Must be "clk32k" +- clocks: phandle to the clk32k and/or to mclk clock provider +- clock-names: Must be "clk32k" for the 32K clock and "mclk" for the MCLK. Vibra functionality Required properties: diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index 852d5874aabb..ab328ec49353 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -323,8 +323,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) /* Default PLL configuration after power up */ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; - twl6040->sysclk = 19200000; - twl6040->mclk = 32768; + twl6040->sysclk_rate = 19200000; } else { /* already powered-down */ if (!twl6040->power_count) { @@ -352,8 +351,12 @@ int twl6040_power(struct twl6040 *twl6040, int on) regcache_cache_only(twl6040->regmap, true); regcache_mark_dirty(twl6040->regmap); - twl6040->sysclk = 0; - twl6040->mclk = 0; + twl6040->sysclk_rate = 0; + + if (twl6040->pll == TWL6040_SYSCLK_SEL_HPPLL) { + clk_disable_unprepare(twl6040->mclk); + twl6040->mclk_rate = 0; + } clk_disable_unprepare(twl6040->clk32k); } @@ -377,15 +380,15 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, /* Force full reconfiguration when switching between PLL */ if (pll_id != twl6040->pll) { - twl6040->sysclk = 0; - twl6040->mclk = 0; + twl6040->sysclk_rate = 0; + twl6040->mclk_rate = 0; } switch (pll_id) { case TWL6040_SYSCLK_SEL_LPPLL: /* low-power PLL divider */ /* Change the sysclk configuration only if it has been canged */ - if (twl6040->sysclk != freq_out) { + if (twl6040->sysclk_rate != freq_out) { switch (freq_out) { case 17640000: lppllctl |= TWL6040_LPLLFIN; @@ -427,6 +430,8 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, ret = -EINVAL; goto pll_out; } + + clk_disable_unprepare(twl6040->mclk); break; case TWL6040_SYSCLK_SEL_HPPLL: /* high-performance PLL can provide only 19.2 MHz */ @@ -437,7 +442,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, goto pll_out; } - if (twl6040->mclk != freq_in) { + if (twl6040->mclk_rate != freq_in) { hppllctl &= ~TWL6040_MCLK_MSK; switch (freq_in) { @@ -468,6 +473,9 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, goto pll_out; } + /* When switching to HPPLL, enable the mclk first */ + if (pll_id != twl6040->pll) + clk_prepare_enable(twl6040->mclk); /* * enable clock slicer to ensure input waveform is * square @@ -483,6 +491,8 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, lppllctl &= ~TWL6040_LPLLENA; twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); + + twl6040->mclk_rate = freq_in; } break; default: @@ -491,8 +501,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, goto pll_out; } - twl6040->sysclk = freq_out; - twl6040->mclk = freq_in; + twl6040->sysclk_rate = freq_out; twl6040->pll = pll_id; pll_out: @@ -512,7 +521,7 @@ EXPORT_SYMBOL(twl6040_get_pll); unsigned int twl6040_get_sysclk(struct twl6040 *twl6040) { - return twl6040->sysclk; + return twl6040->sysclk_rate; } EXPORT_SYMBOL(twl6040_get_sysclk); @@ -655,10 +664,18 @@ static int twl6040_probe(struct i2c_client *client, if (IS_ERR(twl6040->clk32k)) { if (PTR_ERR(twl6040->clk32k) == -EPROBE_DEFER) return -EPROBE_DEFER; - dev_info(&client->dev, "clk32k is not handled\n"); + dev_dbg(&client->dev, "clk32k is not handled\n"); twl6040->clk32k = NULL; } + twl6040->mclk = devm_clk_get(&client->dev, "mclk"); + if (IS_ERR(twl6040->mclk)) { + if (PTR_ERR(twl6040->mclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_dbg(&client->dev, "mclk is not handled\n"); + twl6040->mclk = NULL; + } + twl6040->supplies[0].supply = "vio"; twl6040->supplies[1].supply = "v2v1"; ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES, diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 8e95cd87cd74..36795a1be479 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h @@ -226,6 +226,7 @@ struct twl6040 { struct regmap_irq_chip_data *irq_data; struct regulator_bulk_data supplies[2]; /* supplies for vio, v2v1 */ struct clk *clk32k; + struct clk *mclk; struct mutex mutex; struct mutex irq_mutex; struct mfd_cell cells[TWL6040_CELLS]; @@ -237,8 +238,8 @@ struct twl6040 { /* PLL configuration */ int pll; - unsigned int sysclk; - unsigned int mclk; + unsigned int sysclk_rate; + unsigned int mclk_rate; unsigned int irq; unsigned int irq_ready; -- cgit v1.2.3