1/* 2 * max77843.c - Regulator driver for the Maxim MAX77843 3 * 4 * Copyright (C) 2015 Samsung Electronics 5 * Author: Jaewon Kim <jaewon02.kim@samsung.com> 6 * Author: Beomho Seo <beomho.seo@samsung.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 */ 13 14#include <linux/module.h> 15#include <linux/platform_device.h> 16#include <linux/regulator/driver.h> 17#include <linux/regulator/machine.h> 18#include <linux/mfd/max77843-private.h> 19#include <linux/regulator/of_regulator.h> 20 21enum max77843_regulator_type { 22 MAX77843_SAFEOUT1 = 0, 23 MAX77843_SAFEOUT2, 24 MAX77843_CHARGER, 25 26 MAX77843_NUM, 27}; 28 29static const unsigned int max77843_safeout_voltage_table[] = { 30 4850000, 31 4900000, 32 4950000, 33 3300000, 34}; 35 36static int max77843_reg_is_enabled(struct regulator_dev *rdev) 37{ 38 struct regmap *regmap = rdev->regmap; 39 int ret; 40 unsigned int reg; 41 42 ret = regmap_read(regmap, rdev->desc->enable_reg, ®); 43 if (ret) { 44 dev_err(&rdev->dev, "Fialed to read charger register\n"); 45 return ret; 46 } 47 48 return (reg & rdev->desc->enable_mask) == rdev->desc->enable_mask; 49} 50 51static int max77843_reg_get_current_limit(struct regulator_dev *rdev) 52{ 53 struct regmap *regmap = rdev->regmap; 54 unsigned int chg_min_uA = rdev->constraints->min_uA; 55 unsigned int chg_max_uA = rdev->constraints->max_uA; 56 unsigned int val; 57 int ret; 58 unsigned int reg, sel; 59 60 ret = regmap_read(regmap, MAX77843_CHG_REG_CHG_CNFG_02, ®); 61 if (ret) { 62 dev_err(&rdev->dev, "Failed to read charger register\n"); 63 return ret; 64 } 65 66 sel = reg & MAX77843_CHG_FAST_CHG_CURRENT_MASK; 67 68 if (sel < 0x03) 69 sel = 0; 70 else 71 sel -= 2; 72 73 val = chg_min_uA + MAX77843_CHG_FAST_CHG_CURRENT_STEP * sel; 74 if (val > chg_max_uA) 75 return -EINVAL; 76 77 return val; 78} 79 80static int max77843_reg_set_current_limit(struct regulator_dev *rdev, 81 int min_uA, int max_uA) 82{ 83 struct regmap *regmap = rdev->regmap; 84 unsigned int chg_min_uA = rdev->constraints->min_uA; 85 int sel = 0; 86 87 while (chg_min_uA + MAX77843_CHG_FAST_CHG_CURRENT_STEP * sel < min_uA) 88 sel++; 89 90 if (chg_min_uA + MAX77843_CHG_FAST_CHG_CURRENT_STEP * sel > max_uA) 91 return -EINVAL; 92 93 sel += 2; 94 95 return regmap_write(regmap, MAX77843_CHG_REG_CHG_CNFG_02, sel); 96} 97 98static struct regulator_ops max77843_charger_ops = { 99 .is_enabled = max77843_reg_is_enabled, 100 .enable = regulator_enable_regmap, 101 .disable = regulator_disable_regmap, 102 .get_current_limit = max77843_reg_get_current_limit, 103 .set_current_limit = max77843_reg_set_current_limit, 104}; 105 106static struct regulator_ops max77843_regulator_ops = { 107 .is_enabled = regulator_is_enabled_regmap, 108 .enable = regulator_enable_regmap, 109 .disable = regulator_disable_regmap, 110 .list_voltage = regulator_list_voltage_table, 111 .get_voltage_sel = regulator_get_voltage_sel_regmap, 112 .set_voltage_sel = regulator_set_voltage_sel_regmap, 113}; 114 115static const struct regulator_desc max77843_supported_regulators[] = { 116 [MAX77843_SAFEOUT1] = { 117 .name = "SAFEOUT1", 118 .id = MAX77843_SAFEOUT1, 119 .ops = &max77843_regulator_ops, 120 .of_match = of_match_ptr("SAFEOUT1"), 121 .regulators_node = of_match_ptr("regulators"), 122 .type = REGULATOR_VOLTAGE, 123 .owner = THIS_MODULE, 124 .n_voltages = ARRAY_SIZE(max77843_safeout_voltage_table), 125 .volt_table = max77843_safeout_voltage_table, 126 .enable_reg = MAX77843_SYS_REG_SAFEOUTCTRL, 127 .enable_mask = MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT1, 128 .vsel_reg = MAX77843_SYS_REG_SAFEOUTCTRL, 129 .vsel_mask = MAX77843_REG_SAFEOUTCTRL_SAFEOUT1_MASK, 130 }, 131 [MAX77843_SAFEOUT2] = { 132 .name = "SAFEOUT2", 133 .id = MAX77843_SAFEOUT2, 134 .ops = &max77843_regulator_ops, 135 .of_match = of_match_ptr("SAFEOUT2"), 136 .regulators_node = of_match_ptr("regulators"), 137 .type = REGULATOR_VOLTAGE, 138 .owner = THIS_MODULE, 139 .n_voltages = ARRAY_SIZE(max77843_safeout_voltage_table), 140 .volt_table = max77843_safeout_voltage_table, 141 .enable_reg = MAX77843_SYS_REG_SAFEOUTCTRL, 142 .enable_mask = MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT2, 143 .vsel_reg = MAX77843_SYS_REG_SAFEOUTCTRL, 144 .vsel_mask = MAX77843_REG_SAFEOUTCTRL_SAFEOUT2_MASK, 145 }, 146 [MAX77843_CHARGER] = { 147 .name = "CHARGER", 148 .id = MAX77843_CHARGER, 149 .ops = &max77843_charger_ops, 150 .of_match = of_match_ptr("CHARGER"), 151 .regulators_node = of_match_ptr("regulators"), 152 .type = REGULATOR_CURRENT, 153 .owner = THIS_MODULE, 154 .enable_reg = MAX77843_CHG_REG_CHG_CNFG_00, 155 .enable_mask = MAX77843_CHG_MASK, 156 }, 157}; 158 159static struct regmap *max77843_get_regmap(struct max77843 *max77843, int reg_id) 160{ 161 switch (reg_id) { 162 case MAX77843_SAFEOUT1: 163 case MAX77843_SAFEOUT2: 164 return max77843->regmap; 165 case MAX77843_CHARGER: 166 return max77843->regmap_chg; 167 default: 168 return max77843->regmap; 169 } 170} 171 172static int max77843_regulator_probe(struct platform_device *pdev) 173{ 174 struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent); 175 struct regulator_config config = {}; 176 int i; 177 178 config.dev = max77843->dev; 179 config.driver_data = max77843; 180 181 for (i = 0; i < ARRAY_SIZE(max77843_supported_regulators); i++) { 182 struct regulator_dev *regulator; 183 184 config.regmap = max77843_get_regmap(max77843, 185 max77843_supported_regulators[i].id); 186 187 regulator = devm_regulator_register(&pdev->dev, 188 &max77843_supported_regulators[i], &config); 189 if (IS_ERR(regulator)) { 190 dev_err(&pdev->dev, 191 "Failed to regiser regulator-%d\n", i); 192 return PTR_ERR(regulator); 193 } 194 } 195 196 return 0; 197} 198 199static const struct platform_device_id max77843_regulator_id[] = { 200 { "max77843-regulator", }, 201 { /* sentinel */ }, 202}; 203 204static struct platform_driver max77843_regulator_driver = { 205 .driver = { 206 .name = "max77843-regulator", 207 }, 208 .probe = max77843_regulator_probe, 209 .id_table = max77843_regulator_id, 210}; 211 212static int __init max77843_regulator_init(void) 213{ 214 return platform_driver_register(&max77843_regulator_driver); 215} 216subsys_initcall(max77843_regulator_init); 217 218static void __exit max77843_regulator_exit(void) 219{ 220 platform_driver_unregister(&max77843_regulator_driver); 221} 222module_exit(max77843_regulator_exit); 223 224MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>"); 225MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>"); 226MODULE_DESCRIPTION("Maxim MAX77843 regulator driver"); 227MODULE_LICENSE("GPL"); 228