mc13xxx-regulator-core.c revision 4b2f67d756cf4a5ed8e8d11caa7dcea06c41a09e
1/* 2 * Regulator Driver for Freescale MC13xxx PMIC 3 * 4 * Copyright 2010 Yong Shen <yong.shen@linaro.org> 5 * 6 * Based on mc13783 regulator driver : 7 * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> 8 * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 * 14 * Regs infos taken from mc13xxx drivers from freescale and mc13xxx.pdf file 15 * from freescale 16 */ 17 18#include <linux/mfd/mc13xxx.h> 19#include <linux/regulator/machine.h> 20#include <linux/regulator/driver.h> 21#include <linux/platform_device.h> 22#include <linux/kernel.h> 23#include <linux/slab.h> 24#include <linux/init.h> 25#include <linux/err.h> 26#include "mc13xxx.h" 27 28static int mc13xxx_regulator_enable(struct regulator_dev *rdev) 29{ 30 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 31 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 32 int id = rdev_get_id(rdev); 33 int ret; 34 35 dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 36 37 mc13xxx_lock(priv->mc13xxx); 38 ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg, 39 mc13xxx_regulators[id].enable_bit, 40 mc13xxx_regulators[id].enable_bit); 41 mc13xxx_unlock(priv->mc13xxx); 42 43 return ret; 44} 45 46static int mc13xxx_regulator_disable(struct regulator_dev *rdev) 47{ 48 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 49 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 50 int id = rdev_get_id(rdev); 51 int ret; 52 53 dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 54 55 mc13xxx_lock(priv->mc13xxx); 56 ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg, 57 mc13xxx_regulators[id].enable_bit, 0); 58 mc13xxx_unlock(priv->mc13xxx); 59 60 return ret; 61} 62 63static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev) 64{ 65 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 66 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 67 int ret, id = rdev_get_id(rdev); 68 unsigned int val; 69 70 mc13xxx_lock(priv->mc13xxx); 71 ret = mc13xxx_reg_read(priv->mc13xxx, mc13xxx_regulators[id].reg, &val); 72 mc13xxx_unlock(priv->mc13xxx); 73 74 if (ret) 75 return ret; 76 77 return (val & mc13xxx_regulators[id].enable_bit) != 0; 78} 79 80int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev, 81 unsigned selector) 82{ 83 int id = rdev_get_id(rdev); 84 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 85 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 86 87 if (selector >= mc13xxx_regulators[id].desc.n_voltages) 88 return -EINVAL; 89 90 return mc13xxx_regulators[id].voltages[selector]; 91} 92EXPORT_SYMBOL_GPL(mc13xxx_regulator_list_voltage); 93 94int mc13xxx_get_best_voltage_index(struct regulator_dev *rdev, 95 int min_uV, int max_uV) 96{ 97 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 98 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 99 int reg_id = rdev_get_id(rdev); 100 int i; 101 int bestmatch; 102 int bestindex; 103 104 /* 105 * Locate the minimum voltage fitting the criteria on 106 * this regulator. The switchable voltages are not 107 * in strict falling order so we need to check them 108 * all for the best match. 109 */ 110 bestmatch = INT_MAX; 111 bestindex = -1; 112 for (i = 0; i < mc13xxx_regulators[reg_id].desc.n_voltages; i++) { 113 if (mc13xxx_regulators[reg_id].voltages[i] >= min_uV && 114 mc13xxx_regulators[reg_id].voltages[i] < bestmatch) { 115 bestmatch = mc13xxx_regulators[reg_id].voltages[i]; 116 bestindex = i; 117 } 118 } 119 120 if (bestindex < 0 || bestmatch > max_uV) { 121 dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n", 122 min_uV, max_uV); 123 return -EINVAL; 124 } 125 return bestindex; 126} 127EXPORT_SYMBOL_GPL(mc13xxx_get_best_voltage_index); 128 129static int mc13xxx_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, 130 int max_uV, unsigned *selector) 131{ 132 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 133 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 134 int value, id = rdev_get_id(rdev); 135 int ret; 136 137 dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", 138 __func__, id, min_uV, max_uV); 139 140 /* Find the best index */ 141 value = mc13xxx_get_best_voltage_index(rdev, min_uV, max_uV); 142 dev_dbg(rdev_get_dev(rdev), "%s best value: %d\n", __func__, value); 143 if (value < 0) 144 return value; 145 146 mc13xxx_lock(priv->mc13xxx); 147 ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg, 148 mc13xxx_regulators[id].vsel_mask, 149 value << mc13xxx_regulators[id].vsel_shift); 150 mc13xxx_unlock(priv->mc13xxx); 151 152 return ret; 153} 154 155static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev) 156{ 157 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 158 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 159 int ret, id = rdev_get_id(rdev); 160 unsigned int val; 161 162 dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 163 164 mc13xxx_lock(priv->mc13xxx); 165 ret = mc13xxx_reg_read(priv->mc13xxx, 166 mc13xxx_regulators[id].vsel_reg, &val); 167 mc13xxx_unlock(priv->mc13xxx); 168 169 if (ret) 170 return ret; 171 172 val = (val & mc13xxx_regulators[id].vsel_mask) 173 >> mc13xxx_regulators[id].vsel_shift; 174 175 dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); 176 177 BUG_ON(val > mc13xxx_regulators[id].desc.n_voltages); 178 179 return mc13xxx_regulators[id].voltages[val]; 180} 181 182struct regulator_ops mc13xxx_regulator_ops = { 183 .enable = mc13xxx_regulator_enable, 184 .disable = mc13xxx_regulator_disable, 185 .is_enabled = mc13xxx_regulator_is_enabled, 186 .list_voltage = mc13xxx_regulator_list_voltage, 187 .set_voltage = mc13xxx_regulator_set_voltage, 188 .get_voltage = mc13xxx_regulator_get_voltage, 189}; 190EXPORT_SYMBOL_GPL(mc13xxx_regulator_ops); 191 192int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, 193 int max_uV, unsigned *selector) 194{ 195 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 196 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 197 int id = rdev_get_id(rdev); 198 199 dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", 200 __func__, id, min_uV, max_uV); 201 202 if (min_uV >= mc13xxx_regulators[id].voltages[0] && 203 max_uV <= mc13xxx_regulators[id].voltages[0]) 204 return 0; 205 else 206 return -EINVAL; 207} 208EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage); 209 210int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev) 211{ 212 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 213 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 214 int id = rdev_get_id(rdev); 215 216 dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 217 218 return mc13xxx_regulators[id].voltages[0]; 219} 220EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_get_voltage); 221 222struct regulator_ops mc13xxx_fixed_regulator_ops = { 223 .enable = mc13xxx_regulator_enable, 224 .disable = mc13xxx_regulator_disable, 225 .is_enabled = mc13xxx_regulator_is_enabled, 226 .list_voltage = mc13xxx_regulator_list_voltage, 227 .set_voltage = mc13xxx_fixed_regulator_set_voltage, 228 .get_voltage = mc13xxx_fixed_regulator_get_voltage, 229}; 230EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops); 231 232int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev) 233{ 234 return 1; 235} 236EXPORT_SYMBOL_GPL(mc13xxx_sw_regulator_is_enabled); 237 238MODULE_LICENSE("GPL v2"); 239MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>"); 240MODULE_DESCRIPTION("Regulator Driver for Freescale MC13xxx PMIC"); 241MODULE_ALIAS("mc13xxx-regulator-core"); 242