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/regulator/of_regulator.h> 22#include <linux/platform_device.h> 23#include <linux/kernel.h> 24#include <linux/slab.h> 25#include <linux/init.h> 26#include <linux/err.h> 27#include <linux/module.h> 28#include <linux/of.h> 29#include "mc13xxx.h" 30 31static int mc13xxx_regulator_enable(struct regulator_dev *rdev) 32{ 33 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 34 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 35 int id = rdev_get_id(rdev); 36 37 dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 38 39 return mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg, 40 mc13xxx_regulators[id].enable_bit, 41 mc13xxx_regulators[id].enable_bit); 42} 43 44static int mc13xxx_regulator_disable(struct regulator_dev *rdev) 45{ 46 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 47 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 48 int id = rdev_get_id(rdev); 49 50 dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 51 52 return mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg, 53 mc13xxx_regulators[id].enable_bit, 0); 54} 55 56static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev) 57{ 58 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 59 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 60 int ret, id = rdev_get_id(rdev); 61 unsigned int val; 62 63 ret = mc13xxx_reg_read(priv->mc13xxx, mc13xxx_regulators[id].reg, &val); 64 if (ret) 65 return ret; 66 67 return (val & mc13xxx_regulators[id].enable_bit) != 0; 68} 69 70static int mc13xxx_regulator_set_voltage_sel(struct regulator_dev *rdev, 71 unsigned selector) 72{ 73 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 74 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 75 int id = rdev_get_id(rdev); 76 77 return mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg, 78 mc13xxx_regulators[id].vsel_mask, 79 selector << mc13xxx_regulators[id].vsel_shift); 80} 81 82static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev) 83{ 84 struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 85 struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; 86 int ret, id = rdev_get_id(rdev); 87 unsigned int val; 88 89 dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 90 91 ret = mc13xxx_reg_read(priv->mc13xxx, 92 mc13xxx_regulators[id].vsel_reg, &val); 93 if (ret) 94 return ret; 95 96 val = (val & mc13xxx_regulators[id].vsel_mask) 97 >> mc13xxx_regulators[id].vsel_shift; 98 99 dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); 100 101 BUG_ON(val >= mc13xxx_regulators[id].desc.n_voltages); 102 103 return rdev->desc->volt_table[val]; 104} 105 106struct regulator_ops mc13xxx_regulator_ops = { 107 .enable = mc13xxx_regulator_enable, 108 .disable = mc13xxx_regulator_disable, 109 .is_enabled = mc13xxx_regulator_is_enabled, 110 .list_voltage = regulator_list_voltage_table, 111 .set_voltage_sel = mc13xxx_regulator_set_voltage_sel, 112 .get_voltage = mc13xxx_regulator_get_voltage, 113}; 114EXPORT_SYMBOL_GPL(mc13xxx_regulator_ops); 115 116int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, 117 int max_uV, unsigned *selector) 118{ 119 int id = rdev_get_id(rdev); 120 121 dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", 122 __func__, id, min_uV, max_uV); 123 124 if (min_uV <= rdev->desc->volt_table[0] && 125 rdev->desc->volt_table[0] <= max_uV) { 126 *selector = 0; 127 return 0; 128 } else { 129 return -EINVAL; 130 } 131} 132EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage); 133 134struct regulator_ops mc13xxx_fixed_regulator_ops = { 135 .enable = mc13xxx_regulator_enable, 136 .disable = mc13xxx_regulator_disable, 137 .is_enabled = mc13xxx_regulator_is_enabled, 138 .list_voltage = regulator_list_voltage_table, 139 .set_voltage = mc13xxx_fixed_regulator_set_voltage, 140}; 141EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops); 142 143#ifdef CONFIG_OF 144int mc13xxx_get_num_regulators_dt(struct platform_device *pdev) 145{ 146 struct device_node *parent; 147 int num; 148 149 if (!pdev->dev.parent->of_node) 150 return -ENODEV; 151 152 parent = of_get_child_by_name(pdev->dev.parent->of_node, "regulators"); 153 if (!parent) 154 return -ENODEV; 155 156 num = of_get_child_count(parent); 157 of_node_put(parent); 158 return num; 159} 160EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt); 161 162struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( 163 struct platform_device *pdev, struct mc13xxx_regulator *regulators, 164 int num_regulators) 165{ 166 struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); 167 struct mc13xxx_regulator_init_data *data, *p; 168 struct device_node *parent, *child; 169 int i, parsed = 0; 170 171 if (!pdev->dev.parent->of_node) 172 return NULL; 173 174 parent = of_get_child_by_name(pdev->dev.parent->of_node, "regulators"); 175 if (!parent) 176 return NULL; 177 178 data = devm_kzalloc(&pdev->dev, sizeof(*data) * priv->num_regulators, 179 GFP_KERNEL); 180 if (!data) { 181 of_node_put(parent); 182 return NULL; 183 } 184 185 p = data; 186 187 for_each_child_of_node(parent, child) { 188 int found = 0; 189 190 for (i = 0; i < num_regulators; i++) { 191 if (!regulators[i].desc.name) 192 continue; 193 if (!of_node_cmp(child->name, 194 regulators[i].desc.name)) { 195 p->id = i; 196 p->init_data = of_get_regulator_init_data( 197 &pdev->dev, child, 198 ®ulators[i].desc); 199 p->node = child; 200 p++; 201 202 parsed++; 203 found = 1; 204 break; 205 } 206 } 207 208 if (!found) 209 dev_warn(&pdev->dev, 210 "Unknown regulator: %s\n", child->name); 211 } 212 of_node_put(parent); 213 214 priv->num_regulators = parsed; 215 216 return data; 217} 218EXPORT_SYMBOL_GPL(mc13xxx_parse_regulators_dt); 219#endif 220 221MODULE_LICENSE("GPL v2"); 222MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>"); 223MODULE_DESCRIPTION("Regulator Driver for Freescale MC13xxx PMIC"); 224MODULE_ALIAS("mc13xxx-regulator-core"); 225