2011-11-18 16:47:17 +05:30
/*
* 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 18:50:58 +08:00
# include <linux/module.h>
2011-11-18 16:47:17 +05:30
# include <linux/slab.h>
# include <linux/of.h>
# include <linux/regulator/machine.h>
2012-04-26 16:52:20 +02:00
# include <linux/regulator/of_regulator.h>
2011-11-18 16:47:17 +05:30
static void of_get_regulation_constraints ( struct device_node * np ,
struct regulator_init_data * * init_data )
{
const __be32 * min_uV , * max_uV , * uV_offset ;
2012-06-11 17:41:08 +05:30
const __be32 * min_uA , * max_uA , * ramp_delay ;
2011-11-18 16:47:17 +05:30
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 10:58:41 +00:00
/* Only one voltage? Then make sure it's set. */
2012-01-25 10:31:45 +01:00
if ( min_uV & & max_uV & & constraints - > min_uV = = constraints - > max_uV )
2011-12-05 10:58:41 +00:00
constraints - > apply_uV = true ;
2011-11-18 16:47:17 +05:30
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 ;
2012-06-11 17:41:08 +05:30
ramp_delay = of_get_property ( np , " regulator-ramp-delay " , NULL ) ;
if ( ramp_delay )
2012-06-18 13:59:02 +08:00
constraints - > ramp_delay = be32_to_cpu ( * ramp_delay ) ;
2011-11-18 16:47:17 +05:30
}
/**
* 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 17:21:06 +08:00
struct regulator_init_data * of_get_regulator_init_data ( struct device * dev ,
struct device_node * node )
2011-11-18 16:47:17 +05:30
{
struct regulator_init_data * init_data ;
2011-12-01 17:21:06 +08:00
if ( ! node )
2011-11-18 16:47:17 +05:30
return NULL ;
init_data = devm_kzalloc ( dev , sizeof ( * init_data ) , GFP_KERNEL ) ;
if ( ! init_data )
return NULL ; /* Out of memory? */
2011-12-01 17:21:06 +08:00
of_get_regulation_constraints ( node , & init_data ) ;
2011-11-18 16:47:17 +05:30
return init_data ;
}
2011-11-26 18:50:58 +08:00
EXPORT_SYMBOL_GPL ( of_get_regulator_init_data ) ;
2012-04-26 16:52:20 +02:00
/**
2012-06-20 17:53:06 +05:30
* of_regulator_match - extract regulator init data when node
* property " regulator-compatible " matches with the regulator name .
2012-04-26 16:52:20 +02:00
* @ 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
2012-06-20 17:53:06 +05:30
* looks up the corresponding init data in the device tree if
* regulator - compatible matches . Note that the match table is modified
* in place .
2012-04-26 16:52:20 +02:00
*
* 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 ;
2012-06-20 17:53:06 +05:30
const char * regulator_comp ;
struct device_node * child ;
2012-04-26 16:52:20 +02:00
if ( ! dev | | ! node )
return - EINVAL ;
2012-06-20 17:53:06 +05:30
for_each_child_of_node ( node , child ) {
regulator_comp = of_get_property ( child ,
" regulator-compatible " , NULL ) ;
if ( ! regulator_comp ) {
dev_err ( dev , " regulator-compatible is missing for node %s \n " ,
2012-04-26 16:52:20 +02:00
child - > name ) ;
2012-06-20 17:53:06 +05:30
continue ;
}
for ( i = 0 ; i < num_matches ; i + + ) {
struct of_regulator_match * match = & matches [ i ] ;
if ( match - > of_node )
continue ;
if ( strcmp ( match - > name , regulator_comp ) )
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 + + ;
break ;
2012-04-26 16:52:20 +02:00
}
}
return count ;
}
EXPORT_SYMBOL_GPL ( of_regulator_match ) ;