1 /* 2 * OF helpers for regulator framework 3 * 4 * Copyright (C) 2011 Texas Instruments, Inc. 5 * Rajendra Nayak <rnayak@ti.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 */ 12 13 #include <linux/module.h> 14 #include <linux/slab.h> 15 #include <linux/of.h> 16 #include <linux/regulator/machine.h> 17 #include <linux/regulator/of_regulator.h> 18 19 static void of_get_regulation_constraints(struct device_node *np, 20 struct regulator_init_data **init_data) 21 { 22 const __be32 *min_uV, *max_uV; 23 struct regulation_constraints *constraints = &(*init_data)->constraints; 24 int ret; 25 u32 pval; 26 27 constraints->name = of_get_property(np, "regulator-name", NULL); 28 29 min_uV = of_get_property(np, "regulator-min-microvolt", NULL); 30 if (min_uV) 31 constraints->min_uV = be32_to_cpu(*min_uV); 32 max_uV = of_get_property(np, "regulator-max-microvolt", NULL); 33 if (max_uV) 34 constraints->max_uV = be32_to_cpu(*max_uV); 35 36 /* Voltage change possible? */ 37 if (constraints->min_uV != constraints->max_uV) 38 constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; 39 /* Only one voltage? Then make sure it's set. */ 40 if (min_uV && max_uV && constraints->min_uV == constraints->max_uV) 41 constraints->apply_uV = true; 42 43 if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval)) 44 constraints->uV_offset = pval; 45 if (!of_property_read_u32(np, "regulator-min-microamp", &pval)) 46 constraints->min_uA = pval; 47 if (!of_property_read_u32(np, "regulator-max-microamp", &pval)) 48 constraints->max_uA = pval; 49 50 /* Current change possible? */ 51 if (constraints->min_uA != constraints->max_uA) 52 constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; 53 54 constraints->boot_on = of_property_read_bool(np, "regulator-boot-on"); 55 constraints->always_on = of_property_read_bool(np, "regulator-always-on"); 56 if (!constraints->always_on) /* status change should be possible. */ 57 constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; 58 59 if (of_property_read_bool(np, "regulator-allow-bypass")) 60 constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS; 61 62 ret = of_property_read_u32(np, "regulator-ramp-delay", &pval); 63 if (!ret) { 64 if (pval) 65 constraints->ramp_delay = pval; 66 else 67 constraints->ramp_disable = true; 68 } 69 70 ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval); 71 if (!ret) 72 constraints->enable_time = pval; 73 } 74 75 /** 76 * of_get_regulator_init_data - extract regulator_init_data structure info 77 * @dev: device requesting for regulator_init_data 78 * 79 * Populates regulator_init_data structure by extracting data from device 80 * tree node, returns a pointer to the populated struture or NULL if memory 81 * alloc fails. 82 */ 83 struct regulator_init_data *of_get_regulator_init_data(struct device *dev, 84 struct device_node *node) 85 { 86 struct regulator_init_data *init_data; 87 88 if (!node) 89 return NULL; 90 91 init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL); 92 if (!init_data) 93 return NULL; /* Out of memory? */ 94 95 of_get_regulation_constraints(node, &init_data); 96 return init_data; 97 } 98 EXPORT_SYMBOL_GPL(of_get_regulator_init_data); 99 100 struct devm_of_regulator_matches { 101 struct of_regulator_match *matches; 102 unsigned int num_matches; 103 }; 104 105 static void devm_of_regulator_put_matches(struct device *dev, void *res) 106 { 107 struct devm_of_regulator_matches *devm_matches = res; 108 int i; 109 110 for (i = 0; i < devm_matches->num_matches; i++) 111 of_node_put(devm_matches->matches[i].of_node); 112 } 113 114 /** 115 * of_regulator_match - extract multiple regulator init data from device tree. 116 * @dev: device requesting the data 117 * @node: parent device node of the regulators 118 * @matches: match table for the regulators 119 * @num_matches: number of entries in match table 120 * 121 * This function uses a match table specified by the regulator driver to 122 * parse regulator init data from the device tree. @node is expected to 123 * contain a set of child nodes, each providing the init data for one 124 * regulator. The data parsed from a child node will be matched to a regulator 125 * based on either the deprecated property regulator-compatible if present, 126 * or otherwise the child node's name. Note that the match table is modified 127 * in place and an additional of_node reference is taken for each matched 128 * regulator. 129 * 130 * Returns the number of matches found or a negative error code on failure. 131 */ 132 int of_regulator_match(struct device *dev, struct device_node *node, 133 struct of_regulator_match *matches, 134 unsigned int num_matches) 135 { 136 unsigned int count = 0; 137 unsigned int i; 138 const char *name; 139 struct device_node *child; 140 struct devm_of_regulator_matches *devm_matches; 141 142 if (!dev || !node) 143 return -EINVAL; 144 145 devm_matches = devres_alloc(devm_of_regulator_put_matches, 146 sizeof(struct devm_of_regulator_matches), 147 GFP_KERNEL); 148 if (!devm_matches) 149 return -ENOMEM; 150 151 devm_matches->matches = matches; 152 devm_matches->num_matches = num_matches; 153 154 devres_add(dev, devm_matches); 155 156 for (i = 0; i < num_matches; i++) { 157 struct of_regulator_match *match = &matches[i]; 158 match->init_data = NULL; 159 match->of_node = NULL; 160 } 161 162 for_each_child_of_node(node, child) { 163 name = of_get_property(child, 164 "regulator-compatible", NULL); 165 if (!name) 166 name = child->name; 167 for (i = 0; i < num_matches; i++) { 168 struct of_regulator_match *match = &matches[i]; 169 if (match->of_node) 170 continue; 171 172 if (strcmp(match->name, name)) 173 continue; 174 175 match->init_data = 176 of_get_regulator_init_data(dev, child); 177 if (!match->init_data) { 178 dev_err(dev, 179 "failed to parse DT for regulator %s\n", 180 child->name); 181 return -EINVAL; 182 } 183 match->of_node = of_node_get(child); 184 count++; 185 break; 186 } 187 } 188 189 return count; 190 } 191 EXPORT_SYMBOL_GPL(of_regulator_match); 192