2011-11-18 15:17:17 +04:00
/*
* OF helpers for regulator framework
*
* Copyright ( C ) 2011 Texas Instruments , Inc .
* Rajendra Nayak < rnayak @ ti . com >
*
* 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
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
2011-11-26 14:50:58 +04:00
# include <linux/module.h>
2011-11-18 15:17:17 +04:00
# include <linux/slab.h>
# include <linux/of.h>
# include <linux/regulator/machine.h>
2012-04-26 18:52:20 +04:00
# include <linux/regulator/of_regulator.h>
2011-11-18 15:17:17 +04:00
static void of_get_regulation_constraints ( struct device_node * np ,
struct regulator_init_data * * init_data )
{
const __be32 * min_uV , * max_uV , * uV_offset ;
const __be32 * min_uA , * max_uA ;
struct regulation_constraints * constraints = & ( * init_data ) - > constraints ;
constraints - > name = of_get_property ( np , " regulator-name " , NULL ) ;
min_uV = of_get_property ( np , " regulator-min-microvolt " , NULL ) ;
if ( min_uV )
constraints - > min_uV = be32_to_cpu ( * min_uV ) ;
max_uV = of_get_property ( np , " regulator-max-microvolt " , NULL ) ;
if ( max_uV )
constraints - > max_uV = be32_to_cpu ( * max_uV ) ;
/* Voltage change possible? */
if ( constraints - > min_uV ! = constraints - > max_uV )
constraints - > valid_ops_mask | = REGULATOR_CHANGE_VOLTAGE ;
2011-12-05 14:58:41 +04:00
/* Only one voltage? Then make sure it's set. */
2012-01-25 13:31:45 +04:00
if ( min_uV & & max_uV & & constraints - > min_uV = = constraints - > max_uV )
2011-12-05 14:58:41 +04:00
constraints - > apply_uV = true ;
2011-11-18 15:17:17 +04:00
uV_offset = of_get_property ( np , " regulator-microvolt-offset " , NULL ) ;
if ( uV_offset )
constraints - > uV_offset = be32_to_cpu ( * uV_offset ) ;
min_uA = of_get_property ( np , " regulator-min-microamp " , NULL ) ;
if ( min_uA )
constraints - > min_uA = be32_to_cpu ( * min_uA ) ;
max_uA = of_get_property ( np , " regulator-max-microamp " , NULL ) ;
if ( max_uA )
constraints - > max_uA = be32_to_cpu ( * max_uA ) ;
/* Current change possible? */
if ( constraints - > min_uA ! = constraints - > max_uA )
constraints - > valid_ops_mask | = REGULATOR_CHANGE_CURRENT ;
if ( of_find_property ( np , " regulator-boot-on " , NULL ) )
constraints - > boot_on = true ;
if ( of_find_property ( np , " regulator-always-on " , NULL ) )
constraints - > always_on = true ;
else /* status change should be possible if not always on. */
constraints - > valid_ops_mask | = REGULATOR_CHANGE_STATUS ;
}
/**
* of_get_regulator_init_data - extract regulator_init_data structure info
* @ dev : device requesting for regulator_init_data
*
* Populates regulator_init_data structure by extracting data from device
* tree node , returns a pointer to the populated struture or NULL if memory
* alloc fails .
*/
2011-12-01 13:21:06 +04:00
struct regulator_init_data * of_get_regulator_init_data ( struct device * dev ,
struct device_node * node )
2011-11-18 15:17:17 +04:00
{
struct regulator_init_data * init_data ;
2011-12-01 13:21:06 +04:00
if ( ! node )
2011-11-18 15:17:17 +04:00
return NULL ;
init_data = devm_kzalloc ( dev , sizeof ( * init_data ) , GFP_KERNEL ) ;
if ( ! init_data )
return NULL ; /* Out of memory? */
2011-12-01 13:21:06 +04:00
of_get_regulation_constraints ( node , & init_data ) ;
2011-11-18 15:17:17 +04:00
return init_data ;
}
2011-11-26 14:50:58 +04:00
EXPORT_SYMBOL_GPL ( of_get_regulator_init_data ) ;
2012-04-26 18:52:20 +04:00
/**
* of_regulator_match - extract regulator init data
* @ dev : device requesting the data
* @ node : parent device node of the regulators
* @ matches : match table for the regulators
* @ num_matches : number of entries in match table
*
* This function uses a match table specified by the regulator driver and
* looks up the corresponding init data in the device tree . Note that the
* match table is modified in place .
*
* Returns the number of matches found or a negative error code on failure .
*/
int of_regulator_match ( struct device * dev , struct device_node * node ,
struct of_regulator_match * matches ,
unsigned int num_matches )
{
unsigned int count = 0 ;
unsigned int i ;
if ( ! dev | | ! node )
return - EINVAL ;
for ( i = 0 ; i < num_matches ; i + + ) {
struct of_regulator_match * match = & matches [ i ] ;
struct device_node * child ;
child = of_find_node_by_name ( node , match - > name ) ;
if ( ! child )
continue ;
match - > init_data = of_get_regulator_init_data ( dev , child ) ;
if ( ! match - > init_data ) {
dev_err ( dev , " failed to parse DT for regulator %s \n " ,
child - > name ) ;
return - EINVAL ;
}
match - > of_node = child ;
count + + ;
}
return count ;
}
EXPORT_SYMBOL_GPL ( of_regulator_match ) ;