Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752487AbbGML3P (ORCPT ); Mon, 13 Jul 2015 07:29:15 -0400 Received: from mail-pa0-f52.google.com ([209.85.220.52]:33363 "EHLO mail-pa0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752117AbbGML22 (ORCPT ); Mon, 13 Jul 2015 07:28:28 -0400 From: Krzysztof Kozlowski To: David Woodhouse , Liam Girdwood , Mark Brown , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, linux-pm@vger.kernel.org, Bryan Wu , Richard Purdie , Jacek Anaszewski , linux-leds@vger.kernel.org Cc: Chanwoo Choi , MyungJoo Ham , Dmitry Torokhov , Samuel Ortiz , Lee Jones , Sebastian Reichel , Dmitry Eremin-Solenikov , Krzysztof Kozlowski Subject: [PATCH v4 8/9] regulator: max77693: Add support for MAX77843 device Date: Mon, 13 Jul 2015 20:26:57 +0900 Message-Id: <1436786818-14115-9-git-send-email-k.kozlowski.k@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1436786818-14115-1-git-send-email-k.kozlowski.k@gmail.com> References: <1436786818-14115-1-git-send-email-k.kozlowski.k@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 8615 Lines: 249 The charger and safeout parts of MAX77843 are almost the same as MAX77693. >From regulator point of view the only differences are the constraints and register values related to these constraints. Now the max77693 regulator driver can be used for MAX77843 device. Signed-off-by: Krzysztof Kozlowski Acked-by: Mark Brown --- drivers/regulator/Kconfig | 8 +-- drivers/regulator/max77693.c | 125 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 117 insertions(+), 16 deletions(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index bef3bde6971b..b1022c2fd877 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -407,13 +407,13 @@ config REGULATOR_MAX77686 Exynos-4 chips to control VARM and VINT voltages. config REGULATOR_MAX77693 - tristate "Maxim MAX77693 regulator" - depends on MFD_MAX77693 + tristate "Maxim 77693/77843 regulator" + depends on (MFD_MAX77693 || MFD_MAX77843) help - This driver controls a Maxim 77693 regulator via I2C bus. + This driver controls a Maxim 77693/77843 regulators via I2C bus. The regulators include two LDOs, 'SAFEOUT1', 'SAFEOUT2' and one current regulator 'CHARGER'. This is suitable for - Exynos-4x12 chips. + Exynos-4x12 (MAX77693) or Exynos5433 (MAX77843) SoC chips. config REGULATOR_MAX77802 tristate "Maxim 77802 regulator" diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c index 5b30dc42679c..918745d1c5e4 100644 --- a/drivers/regulator/max77693.c +++ b/drivers/regulator/max77693.c @@ -1,8 +1,9 @@ /* - * max77693.c - Regulator driver for the Maxim 77693 + * max77693.c - Regulator driver for the Maxim 77693 and 77843 * - * Copyright (C) 2013 Samsung Electronics + * Copyright (C) 2013-2015 Samsung Electronics * Jonghwa Lee + * Krzysztof Kozlowski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,11 +31,24 @@ #include #include #include +#include #include #include #include -/* Charger regulator differences between MAX77693 and MAX77843 */ +/* + * ID for MAX77843 regulators. + * There is no need for such for MAX77693. + */ +enum max77843_regulator_type { + MAX77843_SAFEOUT1 = 0, + MAX77843_SAFEOUT2, + MAX77843_CHARGER, + + MAX77843_NUM, +}; + +/* Register differences between chargers: MAX77693 and MAX77843 */ struct chg_reg_data { unsigned int linear_reg; unsigned int linear_mask; @@ -43,9 +57,14 @@ struct chg_reg_data { }; /* - * CHARGER regulator - Min : 20mA, Max : 2580mA, step : 20mA + * MAX77693 CHARGER regulator - Min : 20mA, Max : 2580mA, step : 20mA * 0x00, 0x01, 0x2, 0x03 = 60 mA * 0x04 ~ 0x7E = (60 + (X - 3) * 20) mA + * Actually for MAX77693 the driver manipulates the maximum input current, + * not the fast charge current (output). This should be fixed. + * + * On MAX77843 the calculation formula is the same (except values). + * Fortunately it properly manipulates the fast charge current. */ static int max77693_chg_get_current_limit(struct regulator_dev *rdev) { @@ -95,6 +114,26 @@ static int max77693_chg_set_current_limit(struct regulator_dev *rdev, } /* end of CHARGER regulator ops */ +/* Returns regmap suitable for given regulator on chosen device */ +static struct regmap *max77693_get_regmap(enum max77693_types type, + struct max77693_dev *max77693, + int reg_id) +{ + if (type == TYPE_MAX77693) + return max77693->regmap; + + /* Else: TYPE_MAX77843 */ + switch (reg_id) { + case MAX77843_SAFEOUT1: + case MAX77843_SAFEOUT2: + return max77693->regmap; + case MAX77843_CHARGER: + return max77693->regmap_chg; + default: + return max77693->regmap; + } +} + static const unsigned int max77693_safeout_table[] = { 4850000, 4900000, @@ -119,7 +158,7 @@ static struct regulator_ops max77693_charger_ops = { .set_current_limit = max77693_chg_set_current_limit, }; -#define regulator_desc_esafeout(_num) { \ +#define max77693_regulator_desc_esafeout(_num) { \ .name = "ESAFEOUT"#_num, \ .id = MAX77693_ESAFEOUT##_num, \ .of_match = of_match_ptr("ESAFEOUT"#_num), \ @@ -135,9 +174,9 @@ static struct regulator_ops max77693_charger_ops = { .enable_mask = SAFEOUT_CTRL_ENSAFEOUT##_num##_MASK , \ } -static const struct regulator_desc regulators[] = { - regulator_desc_esafeout(1), - regulator_desc_esafeout(2), +static const struct regulator_desc max77693_supported_regulators[] = { + max77693_regulator_desc_esafeout(1), + max77693_regulator_desc_esafeout(2), { .name = "CHARGER", .id = MAX77693_CHARGER, @@ -160,19 +199,79 @@ static const struct chg_reg_data max77693_chg_reg_data = { .min_sel = 3, }; +#define max77843_regulator_desc_esafeout(num) { \ + .name = "SAFEOUT" # num, \ + .id = MAX77843_SAFEOUT ## num, \ + .ops = &max77693_safeout_ops, \ + .of_match = of_match_ptr("SAFEOUT" # num), \ + .regulators_node = of_match_ptr("regulators"), \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(max77693_safeout_table), \ + .volt_table = max77693_safeout_table, \ + .enable_reg = MAX77843_SYS_REG_SAFEOUTCTRL, \ + .enable_mask = MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT ## num, \ + .vsel_reg = MAX77843_SYS_REG_SAFEOUTCTRL, \ + .vsel_mask = MAX77843_REG_SAFEOUTCTRL_SAFEOUT ## num ## _MASK, \ +} + +static const struct regulator_desc max77843_supported_regulators[] = { + [MAX77843_SAFEOUT1] = max77843_regulator_desc_esafeout(1), + [MAX77843_SAFEOUT2] = max77843_regulator_desc_esafeout(2), + [MAX77843_CHARGER] = { + .name = "CHARGER", + .id = MAX77843_CHARGER, + .ops = &max77693_charger_ops, + .of_match = of_match_ptr("CHARGER"), + .regulators_node = of_match_ptr("regulators"), + .type = REGULATOR_CURRENT, + .owner = THIS_MODULE, + .enable_reg = MAX77843_CHG_REG_CHG_CNFG_00, + .enable_mask = MAX77843_CHG_MASK, + .enable_val = MAX77843_CHG_MASK, + }, +}; + +static const struct chg_reg_data max77843_chg_reg_data = { + .linear_reg = MAX77843_CHG_REG_CHG_CNFG_02, + .linear_mask = MAX77843_CHG_FAST_CHG_CURRENT_MASK, + .uA_step = MAX77843_CHG_FAST_CHG_CURRENT_STEP, + .min_sel = 2, +}; + static int max77693_pmic_probe(struct platform_device *pdev) { + enum max77693_types type = platform_get_device_id(pdev)->driver_data; struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent); + const struct regulator_desc *regulators; + unsigned int regulators_size; int i; struct regulator_config config = { }; config.dev = iodev->dev; - config.regmap = iodev->regmap; - config.driver_data = (void *)&max77693_chg_reg_data; - for (i = 0; i < ARRAY_SIZE(regulators); i++) { + switch (type) { + case TYPE_MAX77693: + regulators = max77693_supported_regulators; + regulators_size = ARRAY_SIZE(max77693_supported_regulators); + config.driver_data = (void *)&max77693_chg_reg_data; + break; + case TYPE_MAX77843: + regulators = max77843_supported_regulators; + regulators_size = ARRAY_SIZE(max77843_supported_regulators); + config.driver_data = (void *)&max77843_chg_reg_data; + break; + default: + dev_err(&pdev->dev, "Unsupported device type: %u\n", type); + return -ENODEV; + } + + for (i = 0; i < regulators_size; i++) { struct regulator_dev *rdev; + config.regmap = max77693_get_regmap(type, iodev, + regulators[i].id); + rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); if (IS_ERR(rdev)) { @@ -187,6 +286,7 @@ static int max77693_pmic_probe(struct platform_device *pdev) static const struct platform_device_id max77693_pmic_id[] = { { "max77693-pmic", TYPE_MAX77693 }, + { "max77843-regulator", TYPE_MAX77843 }, {}, }; @@ -202,6 +302,7 @@ static struct platform_driver max77693_pmic_driver = { module_platform_driver(max77693_pmic_driver); -MODULE_DESCRIPTION("MAXIM MAX77693 regulator driver"); +MODULE_DESCRIPTION("MAXIM 77693/77843 regulator driver"); MODULE_AUTHOR("Jonghwa Lee "); +MODULE_AUTHOR("Krzysztof Kozlowski "); MODULE_LICENSE("GPL"); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/