modified pmu_lp8725 and real kernel regulator interface function

This commit is contained in:
cym
2010-08-11 10:26:40 +08:00
parent 77d6dd51f9
commit 882ddc0c29
8 changed files with 1034 additions and 789 deletions

View File

@@ -49,7 +49,7 @@
#include "devices.h"
#include "../../../drivers/spi/rk2818_spim.h"
#include "../../../drivers/regulator/rk2818_lp8725.h"
/* --------------------------------------------------------------------
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>rk2818_gpioBank<6E><6B><EFBFBD><EFBFBD><E9A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>GPIO<49>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ID<49>ͼĴ<CDBC><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7>
* -------------------------------------------------------------------- */
@@ -264,6 +264,241 @@ struct pca9554_platform_data rk2818_pca9554_data={
};
#endif
/*****************************************************************************************
*regulator devices drivers/regulator/rk2818_lp8725.c linux/regulator/rk2818_lp8725.h
*author: cym
*****************************************************************************************/
#if defined (CONFIG_RK2818_REGULATOR_LP8725)
/*ldo1 2V8OUT USB2.5V LCD_VCC*/
static struct regulator_consumer_supply ldo1_consumers[] = {
{
.supply = "ldo1",
}
};
static struct regulator_init_data rk2818_lp8725_ldo1_data = {
.constraints = {
.name = "LDO1",
.min_uV = 1200000,
.max_uV = 3300000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE,
},
.num_consumer_supplies = ARRAY_SIZE(ldo1_consumers),
.consumer_supplies = ldo1_consumers,
};
/*ldo2 CAMERA_1V8 SD_CARD*/
static struct regulator_consumer_supply ldo2_consumers[] = {
{
.supply = "ldo2",
}
};
static struct regulator_init_data rk2818_lp8725_ldo2_data = {
.constraints = {
.name = "LDO2",
.min_uV = 1200000,
.max_uV = 3300000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE,
},
.num_consumer_supplies = ARRAY_SIZE(ldo2_consumers),
.consumer_supplies = ldo2_consumers,
};
/*ldo3 VCC_NAND WIFI/BT/FM_BCM4325*/
static struct regulator_consumer_supply ldo3_consumers[] = {
{
.supply = "ldo3",
}
};
static struct regulator_init_data rk2818_lp8725_ldo3_data = {
.constraints = {
.name = "LDO3",
.min_uV = 1200000,
.max_uV = 3300000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE,
},
.num_consumer_supplies = ARRAY_SIZE(ldo3_consumers),
.consumer_supplies = ldo3_consumers,
};
/*ldo4 VCCA CODEC_WM8994*/
static struct regulator_consumer_supply ldo4_consumers[] = {
{
.supply = "ldo4",
}
};
static struct regulator_init_data rk2818_lp8725_ldo4_data = {
.constraints = {
.name = "LDO4",
.min_uV = 1200000,
.max_uV = 3300000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE,
},
.num_consumer_supplies = ARRAY_SIZE(ldo4_consumers),
.consumer_supplies = ldo4_consumers,
};
/*ldo5 AVDD18 CODEC_WM8994*/
static struct regulator_consumer_supply ldo5_consumers[] = {
{
.supply = "ldo5",
}
};
static struct regulator_init_data rk2818_lp8725_ldo5_data = {
.constraints = {
.name = "LDO5",
.min_uV = 1200000,
.max_uV = 3300000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE,
},
.num_consumer_supplies = ARRAY_SIZE(ldo5_consumers),
.consumer_supplies = ldo5_consumers,
};
/*lilo1 VCCIO Sensor<6F><72>3M<33><4D>*/
static struct regulator_consumer_supply lilo1_consumers[] = {
{
.supply = "lilo1",
}
};
static struct regulator_init_data rk2818_lp8725_lilo1_data = {
.constraints = {
.name = "LILO1",
.min_uV = 800000,
.max_uV = 3300000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE,
},
.num_consumer_supplies = ARRAY_SIZE(lilo1_consumers),
.consumer_supplies = lilo1_consumers
};
/*lilo2 VCC33_SD Sensor<6F><72>3M<33><4D>*/
static struct regulator_consumer_supply lilo2_consumers[] = {
{
.supply = "lilo2",
}
};
static struct regulator_init_data rk2818_lp8725_lilo2_data = {
.constraints = {
.name = "LILO2",
.min_uV = 800000,
.max_uV = 3300000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE,
},
.num_consumer_supplies = ARRAY_SIZE(lilo2_consumers),
.consumer_supplies = lilo2_consumers
};
/*buck1 VDD12 Core*/
static struct regulator_consumer_supply buck1_consumers[] = {
{
.supply = "vdd12",
}
};
static struct regulator_init_data rk2818_lp8725_buck1_data = {
.constraints = {
.name = "VDD12",
.min_uV = 800000,
.max_uV = 1500000,
.apply_uV = 1,
.always_on = 1,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
},
.num_consumer_supplies = ARRAY_SIZE(buck1_consumers),
.consumer_supplies = buck1_consumers
};
/*buck2 VDDDR MobileDDR VCC*/
static struct regulator_consumer_supply buck2_consumers[] = {
{
.supply = "vccdr",
}
};
static struct regulator_init_data rk2818_lp8725_buck2_data = {
.constraints = {
.name = "VCCDR",
.min_uV = 1800000,
.max_uV = 1800000,
.apply_uV = 1,
.always_on = 1,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
},
.num_consumer_supplies = ARRAY_SIZE(buck2_consumers),
.consumer_supplies = buck2_consumers
};
struct lp8725_regulator_subdev rk2818_lp8725_regulator_subdev[] = {
{
.id=LP8725_LDO1,
.initdata=&rk2818_lp8725_ldo1_data,
},
{
.id=LP8725_LDO2,
.initdata=&rk2818_lp8725_ldo2_data,
},
{
.id=LP8725_LDO3,
.initdata=&rk2818_lp8725_ldo3_data,
},
{
.id=LP8725_LDO4,
.initdata=&rk2818_lp8725_ldo4_data,
},
{
.id=LP8725_LDO5,
.initdata=&rk2818_lp8725_ldo5_data,
},
{
.id=LP8725_LILO1,
.initdata=&rk2818_lp8725_lilo1_data,
},
{
.id=LP8725_LILO2,
.initdata=&rk2818_lp8725_lilo2_data,
},
{
.id=LP8725_DCDC1,
.initdata=&rk2818_lp8725_buck1_data,
},
{
.id=LP8725_DCDC2,
.initdata=&rk2818_lp8725_buck2_data,
},
};
struct lp8725_platform_data rk2818_lp8725_data={
.num_regulators=LP8725_NUM_REGULATORS,
.regulators=rk2818_lp8725_regulator_subdev,
};
#endif
/*****************************************************************************************
* I2C devices
*author: kfx
@@ -365,11 +600,12 @@ static struct i2c_board_info __initdata board_i2c1_devices[] = {
.platform_data=&rk2818_pca9554_data.gpio_base,
},
#endif
#if defined (CONFIG_PMIC_LP8725)
#if defined (CONFIG_RK2818_REGULATOR_LP8725)
{
.type = "lp8725",
.addr = 0x79,
.flags = 0,
.platform_data=&rk2818_lp8725_data,
},
#endif
#if defined (CONFIG_GS_MMA7660)

View File

@@ -115,10 +115,4 @@ config BATTERY_RK2818
depends on RK28_ADC
help
Say Y to enable support for the battery on the RK2818.
config PMIC_LP8725
tristate "pmic lp8725"
depends on I2C
help
Say Y to enable support for the pmic lp8725 on the RK2818.
endif # POWER_SUPPLY

View File

@@ -30,4 +30,3 @@ obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
obj-$(CONFIG_BATTERY_RK2818) += rk2818_battery.o
obj-$(CONFIG_PMIC_LP8725) += pmic_lp8725.o

View File

@@ -1,780 +0,0 @@
/* arch/arm/mach-rk2818/example.c
*
* Copyright (C) 2010 ROCKCHIP, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*******************************************************************/
/* COPYRIGHT (C) ROCK-CHIPS FUZHOU . ALL RIGHTS RESERVED. */
/*******************************************************************
FILE : PCA9554.C
DESC : <20><>չGPIO <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>س<EFBFBD><D8B3><EFBFBD>
AUTHOR : ZHONGYW
DATE : 2009-4-26
NOTES :
$LOG: GPIO.C,V $
REVISION 0.01
********************************************************************/
#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <asm/mach-types.h>
#include <linux/irq.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
#include <mach/rk2818_iomap.h>
#include <mach/iomux.h>
#include <linux/device.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include <linux/i2c.h>
#include <linux/workqueue.h>
#include <mach/board.h>
#include <linux/delay.h>
#if 1
#define DBG(x...) printk(KERN_INFO x)
#else
#define DBG(x...)
#endif
#if 1
#define DBGERR(x...) printk(KERN_INFO x)
#else
#define DBGERR(x...)
#endif
#define DEFSEL_VIN1
#define GENERAL_REG_ADDR 0x0
#define LDO1_REG_ADDR 0x01
#define LDO2_REG_ADDR 0x02
#define LDO3_REG_ADDR 0x03
#define LDO4_REG_ADDR 0x04
#define LDO5_REG_ADDR 0x05
#define LILO1_REG_ADDR 0x06
#define LILO2_REG_ADDR 0x07
#define BUCK1_V1_REG_ADDR 0x08
#define BUCK1_V2_REG_ADDR 0x09
#define BUCK2_V1_REG_ADDR 0x0a
#define BUCK2_V2_REG_ADDR 0x0b
#define BUCK_CTR_REG_ADDR 0x0c
#define LDO_CTR_REG_ADDR 0x0d
#define PULLDOWN_REG_ADDR 0x0e
#define STATUS_REG_ADDR 0x0f
#define LP8725_LDO_NUM 5
#define LP8725_LILO_NUM 2
#define LP8725_BUCK_NUM 2
#define LDO_BUCKV1_TIME 5 //<2F><>3
#define LDO_BUCKV_V 0 //<2F><>5
#define BUCKV2_CL_BIT 6 //<2F><>2
#ifdef DEFSEL_VIN1
#define GENERAL_REG_DEFAULT 0x59 //0101 1001 buck1output dependon dvs pin, dvs=1 v1 is used buck2v1 is output
#define LDO1_REG_T_DEFAULT 0x02 //1001 1001
#define LDO1_REG_V_DEFAULT 0x19
#define LDO2_REG_T_DEFAULT 0x04 //1001 1001
#define LDO2_REG_V_DEFAULT 0x19
#define LDO3_REG_T_DEFAULT 0x05 // 1011 1111
#define LDO3_REG_V_DEFAULT 0x1f
#define LDO4_REG_T_DEFAULT 0x04 // 1001 1101
#define LDO4_REG_V_DEFAULT 0x1d
#define LDO5_REG_T_DEFAULT 0x04 //1000 1100
#define LDO5_REG_V_DEFAULT 0x0c
#define LILO1_REG_T_DEFAULT 0x05 //1010 1000
#define LILO1_REG_V_DEFAULT 0x08
#define LILO2_REG_T_DEFAULT 0x02 // 0101 0000
#define LILO2_REG_V_DEFAULT 0x10
#define BUCK1_V1_REG_T_DEFAULT 0x00 // 0000 0100
#define BUCK1_V1_REG_V_DEFAULT 0x04
#define BUCK1_V2_REG_C_DEFAULT 0x03 //1100 1000 <20>߶<EFBFBD>
#define BUCK1_V2_REG_V_DEFAULT 0x08
#define BUCK2_V1_REG_T_DEFAULT 0x02 // 0101 0001
#define BUCK2_V1_REG_V_DEFAULT 0x11
#define BUCK2_V2_REG_C_DEFAULT 0x02//1001 0001 <20>߶<EFBFBD>
#define BUCK2_V2_REG_V_DEFAULT 0x11// <20><>5
#define BUCK2_CTR_REG_ADDR 0x11 // 0001 0001
#define LDO_CTR_REG_DEFAULT 0x7f //0111 1111
#define PULLDOWN_DEFAULT 0x7f //0111 1111
#define STATUS_REG_DEFAULT 0x00 //0000 0000
#else
#define GENERAL_REG_DEFAULT 0x59 //0101 1001
#define LDO1_REG_T_DEFAULT 0x01 // 0011 0101
#define LDO1_REG_V_DEFAULT 0x15
#define LDO2_REG_T_DEFAULT 0x01 // 0011 1001
#define LDO2_REG_V_DEFAULT 0x19
#define LDO3_REG_T_DEFAULT 0x02 // 0101 1001
#define LDO3_REG_V_DEFAULT 0x19
#define LDO4_REG_T_DEFAULT 0x02 // 0101 1001
#define LDO4_REG_V_DEFAULT 0x19
#define LDO5_REG_T_DEFAULT 0x01 // 0011 1001
#define LDO5_REG_V_DEFAULT 0x19
#define LILO1_REG_T_DEFAULT 0x01 //0011 1111
#define LILO1_REG_V_DEFAULT 0x1f
#define LILO2_REG_T_DEFAULT 0x00 // 0000 1000
#define LILO2_REG_V_DEFAULT 0x08
#define BUCK1_V1_REG_T_DEFAULT 0x00 // 0000 1000
#define BUCK1_V1_REG_V_DEFAULT 0x08
#define BUCK1_V2_REG_C_DEFAULT 0x03 //1100 0100 <20>߶<EFBFBD>
#define BUCK1_V2_REG_V_DEFAULT 0x04
#define BUCK2_V1_REG_T_DEFAULT 0x01 // 0011 0001
#define BUCK2_V1_REG_V_DEFAULT 0x11
#define BUCK2_V2_REG_C_DEFAULT 0x02 //1001 0001 <20>߶<EFBFBD>
#define BUCK2_V2_REG_V_DEFAULT 0x11// <20><>5
#define BUCK_CTR_REG_ADDR 0x11 // 0001 0001
#define LDO_CTR_REG_DEFAULT 0x7f //0111 1111
#define PULLDOWN_REG_DEFAULT 0x7f //0111 1111
#define STATUS_REG_DEFAULT 0x00 //0000 0000
#endif
struct i2c_client *lp8725_client;
#define lp8725getbit(a,num) (((a)>>(num))&0x01)
#define lp8725setbit(a,num) ((a)|(0x01<<(num)))
#define lp8725clearbit(a,num) ((a)&(~(0x01<<(num))))
static const struct i2c_device_id lp8725_id[] =
{
{ "lp8725", 0, },
{ }
};
MODULE_DEVICE_TABLE(i2c, lp8725_id);
struct lp8725_regs_s
{
uint8_t general_reg_val;
uint8_t ldo_reg_val[5];
uint8_t lilo_reg_val[2];
uint8_t buck_v1_reg_val[2];
uint8_t buck_v2_reg_val[2];
uint8_t buck_ctr_reg_val;
uint8_t ldo_ctr_reg_val;
uint8_t pulldown_reg_val;
uint8_t status_reg_val;
};
struct lp8725_vol_range_s
{
uint16_t vol_low;
uint16_t vol_high;
uint16_t rang;
};
static struct lp8725_regs_s lp8725_regs;
uint8_t ldo_reg_t_default[LP8725_LDO_NUM]={LDO1_REG_T_DEFAULT,LDO2_REG_T_DEFAULT,LDO3_REG_T_DEFAULT,LDO4_REG_T_DEFAULT,LDO5_REG_T_DEFAULT};
uint8_t ldo_reg_v_default[LP8725_LDO_NUM]={LDO1_REG_V_DEFAULT,LDO2_REG_V_DEFAULT,LDO3_REG_V_DEFAULT,LDO4_REG_V_DEFAULT,LDO5_REG_V_DEFAULT};
uint8_t lilo_reg_t_default[LP8725_LILO_NUM]={LILO1_REG_T_DEFAULT,LILO2_REG_T_DEFAULT};
uint8_t lilo_reg_v_default[LP8725_LILO_NUM]={LILO1_REG_V_DEFAULT,LILO2_REG_V_DEFAULT};
uint8_t buck_v1_reg_t_default[LP8725_BUCK_NUM]={BUCK1_V1_REG_T_DEFAULT,BUCK2_V1_REG_T_DEFAULT};
uint8_t buck_v1_reg_v_default[LP8725_BUCK_NUM]={BUCK1_V1_REG_V_DEFAULT,BUCK2_V1_REG_V_DEFAULT};
uint8_t buck_v2_reg_c_default[LP8725_BUCK_NUM]={BUCK1_V2_REG_C_DEFAULT,BUCK2_V2_REG_C_DEFAULT};
uint8_t buck_v2_reg_v_default[LP8725_BUCK_NUM]={BUCK1_V2_REG_V_DEFAULT,BUCK2_V2_REG_V_DEFAULT};
#define LDO_RANG 5
#define LILO_RANG 5
#define BULK_RANG 6
struct lp8725_vol_range_s ldo_vol_range[LDO_RANG]={{120,190,5},{190,260,10},{260,300,5},{300,310,10},{310,330,20}};
struct lp8725_vol_range_s lilo_vol_range[LILO_RANG]={{80,140,5},{140,280,10},{280,290,5},{290,310,10},{310,330,20}};
struct lp8725_vol_range_s buck_vol_range[BULK_RANG]={{80,140,5},{140,170,10},{170,190,5},{190,280,10},{280,290,5},{290,300,10}};
/* **********************************************************************
* д<>Ĵ<EFBFBD><C4B4><EFBFBD>
* return <0 failed
* * ***********************************************************************/
static int lp8725_write_reg(struct i2c_client *client, uint8_t reg, uint8_t val)
{
int ret=-1;
DBG("**run in %s**\n",__FUNCTION__);
struct i2c_adapter *adap;
struct i2c_msg msg;
char tx_buf[2];
if(!client)
return ret;
adap = client->adapter;
tx_buf[0] = reg;
tx_buf[1]=val;
//DBG("**run in %s**\n",__FUNCTION__);
msg.addr = client->addr;
msg.buf = &tx_buf[0];
msg.len = 1 +1;
msg.flags = client->flags;
msg.scl_rate = 200*1000;
//DBG("**run in %s**\n",__FUNCTION__);
ret = i2c_transfer(adap, &msg, 1);
//DBG("**run in %s**\n",__FUNCTION__);
return ret;
DBG("**run out %s**\n",__FUNCTION__);
}
/* **********************************************************************
* <20><><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>
* return <0 failed
* * ***********************************************************************/
#if 1
static int lp8725_read_reg(struct i2c_client *client, uint8_t reg, uint8_t *val)
{
int ret;
struct i2c_adapter *adap;
struct i2c_msg msgs[2];
if(!client)
return ret;
adap = client->adapter;
//<2F><><EFBFBD>ͼĴ<CDBC><C4B4><EFBFBD><EFBFBD><EFBFBD>ַ
msgs[0].addr = client->addr;
msgs[0].buf = &reg;
msgs[0].flags = client->flags;
msgs[0].len = 1;
msgs[0].scl_rate = 200*1000;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//msgs[1].buf = val;
DBG("msgs[1].buf = %d\n",*msgs[1].buf);
//msgs[1].buf = val;
msgs[1].buf = val;
msgs[1].addr = client->addr;
msgs[1].flags = client->flags | I2C_M_RD;
msgs[1].len = 1;
msgs[1].scl_rate = 200*1000;
ret = i2c_transfer(adap, msgs, 2);
//DBG("**has run at %s %d ret=%d**\n",__FUNCTION__,__LINE__,ret);
DBG("msgs[1].buf = %d\n",*(msgs[1].buf));
return ret;
}
#else
static int lp8725_read_reg(struct i2c_client *client, uint8_t reg)
{
int ret;
struct i2c_adapter *adap;
struct i2c_msg msgs[2];
if(!client)
return ret;
adap = client->adapter;
//<2F><><EFBFBD>ͼĴ<CDBC><C4B4><EFBFBD><EFBFBD><EFBFBD>ַ
msgs[0].addr = client->addr;
msgs[0].buf = &reg;
msgs[0].flags = client->flags;
msgs[0].len = 1;
msgs[0].scl_rate = 200*1000;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
msgs[1].buf;
msgs[1].addr = client->addr;
msgs[1].flags = client->flags | I2C_M_RD;
msgs[1].len = 1;
msgs[1].scl_rate = 200*1000;
ret = i2c_transfer(adap, msgs, 2);
//DBG("**has run at %s %d ret=%d**\n",__FUNCTION__,__LINE__,ret);
DBG("msgs[1].buf = %d\n",*msgs[1].buf);
return ret;
}
#endif
/* **********************************************************************
* <20><><EFBFBD><EFBFBD>ldo<64><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ
*ldon:ldo<64><6F><EFBFBD><EFBFBD> <20><>ldo1 ldon=1<><31>vol <20><>ѹ<EFBFBD><D1B9>λ10mv <20><>1.2v vol=120
*<2A><>ѹ<EFBFBD><D1B9>Χ:<3A><>1.2v<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>0.05v
* return <0 failed
* * ***********************************************************************/
int lp8725_set_ldo_vol(uint8_t ldon,uint16_t vol)
{
uint8_t val=0;
uint8_t reg_val=0;
int i;
if((vol>ldo_vol_range[LDO_RANG-1].vol_high)||(vol<ldo_vol_range[0].vol_low)||ldon>LP8725_LDO_NUM)
return -1;
for(i=0;i<LDO_RANG;i++)
{
if(vol<=ldo_vol_range[i].vol_high)
{
val+=(vol-ldo_vol_range[i].vol_low)/ldo_vol_range[i].rang;
break;
}
else
val+=(ldo_vol_range[i].vol_high-ldo_vol_range[i].vol_low)/ldo_vol_range[i].rang;
DBG("val=0x%x,vol=%d\n",val,vol);
}
DBG("val=0x%x,vol=%d\n",val,vol);
reg_val=(ldo_reg_t_default[ldon-1]<<LDO_BUCKV1_TIME)|val;
DBG("ldo_reg_t_default[ldon-1]=0x%x,LDO_BUCKV1_TIME=0x%x\n",ldo_reg_t_default[ldon-1],LDO_BUCKV1_TIME);
DBG("ldo_reg_t_default[ldon-1]<<LDO_BUCKV1_TIME=0x%x\n",ldo_reg_t_default[ldon-1]<<LDO_BUCKV1_TIME);
DBG("ADDR=0x%x,reg_val=0x%x\n",LDO1_REG_ADDR+ldon-1,reg_val);
if(lp8725_write_reg(lp8725_client,LDO1_REG_ADDR+ldon-1,reg_val)<0)
{
DBGERR("%s %d error\n",__FUNCTION__,__LINE__);
return -1;
}
lp8725_regs.ldo_reg_val[ldon-1]=reg_val;
return 0;
}
/* **********************************************************************
* <20><><EFBFBD><EFBFBD>lilo<6C><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ
*ldon:ldo<64><6F><EFBFBD><EFBFBD> <20><>lilo1 lilon=1<><31>vol <20><>ѹ<EFBFBD><D1B9>λ10mv <20><>0.8v vol=80
*<2A><>ѹ<EFBFBD><D1B9>Χ:<3A><>ѹ<EFBFBD><D1B9>[0.8,1.4]ʱ<><CAB1><EFBFBD><EFBFBD>0.05v<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD>[1.4,3.3]ʱ<><CAB1><EFBFBD><EFBFBD>0.1v
* return <0 failed
* * ***********************************************************************/
int lp8725_set_lilo_vol(uint8_t lilon,uint16_t vol)
{
uint8_t val=0;
uint8_t reg_val=0;
int i;
if((vol>lilo_vol_range[LILO_RANG-1].vol_high)||(vol<lilo_vol_range[0].vol_low)||lilon>LP8725_LILO_NUM)
return -1;
for(i=0;i<LILO_RANG;i++)
{
if(vol<=lilo_vol_range[i].vol_high)
{
val+=(vol-lilo_vol_range[i].vol_low)/lilo_vol_range[i].rang;
break;
}
else
val+=(lilo_vol_range[i].vol_high-lilo_vol_range[i].vol_low)/lilo_vol_range[i].rang;
}
reg_val=(lilo_reg_t_default[lilon-1]<<LDO_BUCKV1_TIME)|val;
if(lp8725_write_reg(lp8725_client,LILO1_REG_ADDR+lilon-1,reg_val)<0)
{
DBGERR("%s %d error\n",__FUNCTION__,__LINE__);
return -1;
}
lp8725_regs.lilo_reg_val[lilon-1]=reg_val;
return 0;
}
/* **********************************************************************
* <20><><EFBFBD><EFBFBD>buck<63><6B>v1 v2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD>ƼĴ<C6BC><C4B4><EFBFBD>
*ldon:ldo<64><6F><EFBFBD><EFBFBD> <20><>buck1 buckn=1<><31>vol <20><>ѹ<EFBFBD><D1B9>λ10mv <20><>0.8v vol=80 <20><>v2=1 <20><><EFBFBD><EFBFBD>ѹֵд<D6B5><D0B4>v2 reg<65><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>v1 reg
*<2A><>ѹ<EFBFBD><D1B9>Χ:<3A><>ѹ<EFBFBD><D1B9>[0.8,1.4]ʱ<><CAB1><EFBFBD><EFBFBD>0.05v<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD>[1.4,1.7]ʱ<><CAB1><EFBFBD><EFBFBD>0.1v<EFBFBD><EFBFBD>
*<2A><>ѹ<EFBFBD><D1B9>[1.7,1.9]ʱ<><CAB1><EFBFBD><EFBFBD>0.05v<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD>[1.9,3.0]ʱ<><CAB1><EFBFBD><EFBFBD>0.1v
* return <0 failed
* * ***********************************************************************/
static int lp8725_set_buck_vol_v1orv2(uint8_t buckn,uint16_t vol,uint8_t v2)
{
uint8_t val=0;
uint8_t reg_val=0;
uint8_t reg_addr=0;
int i;
if(vol>buck_vol_range[BULK_RANG-1].vol_high||vol<buck_vol_range[0].vol_low||buckn>LP8725_BUCK_NUM)
return -1;
for(i=0;i<BULK_RANG;i++)
{
if(vol<=buck_vol_range[i].vol_high)
{
val+=(vol-buck_vol_range[i].vol_low)/buck_vol_range[i].rang;
break;
}
else
val+=(buck_vol_range[i].vol_high-buck_vol_range[i].vol_low)/buck_vol_range[i].rang;
}
reg_addr=BUCK1_V1_REG_ADDR+(buckn-1)*2;
reg_val=(buck_v1_reg_t_default[buckn-1]<<LDO_BUCKV1_TIME)|val;
if(v2)
reg_addr=BUCK1_V2_REG_ADDR+(buckn-1)*2;
if(lp8725_write_reg(lp8725_client,reg_addr,reg_val)<0)
{
DBGERR("%s %d error\n",__FUNCTION__,__LINE__);
return -1;
}
if(v2)
lp8725_regs.buck_v2_reg_val[buckn-1]=reg_val;
else
lp8725_regs.buck_v1_reg_val[buckn-1]=reg_val;
return 0;
}
/***************************************************************
*
*
****************************************************************/
int lp8725_set_buck_dvsn_v_bit(uint8_t buckn,uint8_t dvs)
{
uint8_t reg_val=0;
if(dvs)
reg_val=lp8725_regs.general_reg_val|(0x01<<(2+buckn-1));
else
reg_val=lp8725_regs.general_reg_val&(~0x01<<(12+buckn-1));
if(lp8725_write_reg(lp8725_client,GENERAL_REG_ADDR,reg_val)<0)
{
DBGERR("%s %d error\n",__FUNCTION__,__LINE__);
return -1;
}
lp8725_regs.general_reg_val=reg_val;
return 0;
}
/* **********************************************************************
* <20><><EFBFBD><EFBFBD>buck<63><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ
*ldon:ldo<64><6F><EFBFBD><EFBFBD> <20><>buck1 buckn=1<><31>vol <20><>ѹ<EFBFBD><D1B9>λ10mv <20><>0.8v vol=80
*<2A><>ѹ<EFBFBD><D1B9>Χ:<3A><>ѹ<EFBFBD><D1B9>[0.8,1.4]ʱ<><CAB1><EFBFBD><EFBFBD>0.05v<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD>[1.4,1.7]ʱ<><CAB1><EFBFBD><EFBFBD>0.1v<EFBFBD><EFBFBD>
*<2A><>ѹ<EFBFBD><D1B9>[1.7,1.9]ʱ<><CAB1><EFBFBD><EFBFBD>0.05v<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD>[1.9,3.0]ʱ<><CAB1><EFBFBD><EFBFBD>0.1v
*ÿ<><C3BF>buck <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>v1<76><31>v2<76><32>buck <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*ѡ<><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǹ<EFBFBD><C7B8>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ
* buck1: dvs1_v=1 output vol depend on buck1_v1 reg,else depend on dvs pin. dvspin=1 output vol depend on buck1_v1,esle output vol depend on buck1_v2
*buck2:dvs1_v=1 output vol depend on buck2_v1 reg,else depend on buck2_v2.
* return <0 failed
* * ***********************************************************************/
int lp8725_set_buck_vol(uint8_t buckn,uint16_t vol)
{
if(lp8725_set_buck_vol_v1orv2(buckn,vol,0)<0)
return -1;
return lp8725_set_buck_vol_v1orv2(buckn,vol,1);
}
int get_dvs_pin_level(void)
{
// dvs pin is low return 0
}
int set_dvs_pin_level(uint8_t level)
{
}
/*******************************************************************************
*in sleep mode all pins val is low
*reg SLEEP_MODE=0,and pin DVS=0<><30>this ic enter into seelp mode
********************************************************************************/
int lp8725_setinto_sleep(uint8_t sleep)
{
uint8_t reg_val=0;
set_dvs_pin_level(0);
if(sleep)
reg_val=lp8725_regs.general_reg_val|(0x01<<1);
else
reg_val=lp8725_regs.general_reg_val&(~0x01<<1);
if(lp8725_write_reg(lp8725_client,GENERAL_REG_ADDR,reg_val)<0)
{
DBGERR("%s %d error\n",__FUNCTION__,__LINE__);
return -1;
}
lp8725_regs.general_reg_val=reg_val;
return 0;
}
/***************************************************************
*
*
****************************************************************/
int lp8725_buck_en(uint8_t buckn,uint8_t enble)
{
uint8_t reg_val=0;
if(buckn==1)
{
if(enble)
reg_val=lp8725_regs.general_reg_val|0x01;
else
reg_val=lp8725_regs.general_reg_val&(~0x01);
}
if(buckn==2)
{
if(enble)
reg_val=lp8725_regs.general_reg_val|(0x01<<4);
else
reg_val=lp8725_regs.general_reg_val&(~0x01<<4);
}
if(lp8725_write_reg(lp8725_client,GENERAL_REG_ADDR,reg_val)<0)
{
DBGERR("%s %d error\n",__FUNCTION__,__LINE__);
return -1;
}
lp8725_regs.general_reg_val=reg_val;
return 0;
}
int lp8725_lilo_en(uint8_t lilon,uint8_t enble)
{
uint8_t reg_val=0;
if(enble)
reg_val=lp8725_regs.ldo_ctr_reg_val|(0x01<<(5+lilon-1));
else
reg_val=lp8725_regs.ldo_ctr_reg_val&(~(0x01<<(5+lilon-1)));
if(lp8725_write_reg(lp8725_client,LDO_CTR_REG_ADDR,reg_val)<0)
{
DBGERR("%s %d error\n",__FUNCTION__,__LINE__);
return -1;
}
lp8725_regs.ldo_ctr_reg_val=reg_val;
return 0;
}
/***************************************************************
*ldo3 is enbale if pin LdO3_EN=1 or LDO3 enable reg=1
*
****************************************************************/
int lp8725_ldo_en(uint8_t ldo,uint8_t enble)
{
uint8_t reg_val=0;
if(enble)
reg_val=lp8725_regs.ldo_ctr_reg_val|(0x01<<(ldo-1));
else
reg_val=lp8725_regs.ldo_ctr_reg_val&(~(0x01<<(ldo-1)));
if(lp8725_write_reg(lp8725_client,LDO_CTR_REG_ADDR,reg_val)<0)
{
DBGERR("%s %d error\n",__FUNCTION__,__LINE__);
return -1;
}
lp8725_regs.ldo_ctr_reg_val=reg_val;
return 0;
}
void lp8725_set_init(void)
{
uint8_t reg_val=0;
uint8_t read_ret;
lp8725_regs.general_reg_val=GENERAL_REG_DEFAULT;
lp8725_regs.buck_ctr_reg_val=BUCK_CTR_REG_ADDR;
lp8725_regs.pulldown_reg_val=PULLDOWN_REG_ADDR;
lp8725_regs.status_reg_val=STATUS_REG_ADDR;
/*
<09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ldo 1<><31>2<EFBFBD><32>5 lilo2Ĭ<32><C4AC>Ϊ<EFBFBD>ر<EFBFBD>
*/
DBG("**run in %s**\n",__FUNCTION__);
//reg_val=LDO_CTR_REG_ADDR&&(~(1<<0))&&(~(1<<0))&&(~(1<<1))&&(~(1<<4))&&(~(1<<6));
reg_val=0x7f;
DBG("**lp8725_client=%s**LDO_CTR_REG_ADDR=%d**reg_val=%d\n",lp8725_client,LDO_CTR_REG_ADDR,reg_val);
if(lp8725_write_reg(lp8725_client,LDO_CTR_REG_ADDR,reg_val)<0)
{
DBG("%s %d error\n",__FUNCTION__,__LINE__);
return -1;
}
/*
**set ldo4 VCCA 3.3V;ldo5 AVDD18 1.8v
*/
lp8725_set_ldo_vol(4,330);
lp8725_set_ldo_vol(5,180);
#if 0
DBG("**begin lp8725_read_reg %s %d \n",__FUNCTION__,__LINE__);
if(lp8725_read_reg(lp8725_client,0x00,&read_ret)<0)
{
DBG("%s %d error\n",__FUNCTION__,__LINE__);
return -1;
}
DBG("**lp8725_read_reg %s %d return read_ret = %d\n",__FUNCTION__,__LINE__,read_ret);
#endif
lp8725_regs.ldo_ctr_reg_val=reg_val;
DBG("**run out %s**\n",__FUNCTION__);
}
#if 0
static __init int seqgen1_init(void)
{
uint8_t *read_val;
//uint8_t reg_val=0x98;
DBG("**************run in %s\n",__FUNCTION__);
//lp8725_set_ldo_vol(2,150);
//lp8725_set_lilo_vol(2,150);
//lp8725_set_buck_vol(2,170);
while(1)
{
DBG("\n***lp8725_lilo_en(2,0)\n");
lp8725_lilo_en(2,0);
mdelay(6000);
DBG("\n***lp8725_lilo_en(2,1)\n");
lp8725_lilo_en(2,1);
mdelay(6000);
}
#if 0
while(1)
{
int i;
for(i=180;i<=330;i=i-10)
{
DBG("\n\n**i=%d\n",i);
DBG("**************run in %s\n",__FUNCTION__);
lp8725_set_buck_vol(2,i);
mdelay(3000);
}
}
DBG("**************run out %s\n",__FUNCTION__);
if(lp8725_write_reg(lp8725_client,LDO2_REG_ADDR,reg_val)<0)
{
DBG("%s %d error\n",__FUNCTION__,__LINE__);
return -1;
}
while(1)
{
lp8725_read_reg(lp8725_client,LDO_CTR_REG_ADDR,read_val);
DBG("\n*****read_val = %d\n",read_val);
}
DBG("**************run out %s\n",__FUNCTION__);
#endif
return 0;
}
late_initcall(seqgen1_init);
#endif
static int __devinit lp8725_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
int ret;
DBG("**%s in %d line,dev adr is %x**\n",__FUNCTION__,__LINE__,client->addr);
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -EIO;
lp8725_client=client;
lp8725_set_init();
DBG("**run out %s**\n",__FUNCTION__);
return 0;
}
static int lp8725_remove(struct i2c_client *client)
{
return 0;
}
static struct i2c_driver lp8725_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "lp8725",
},
.probe = lp8725_probe,
.remove = lp8725_remove,
.id_table = lp8725_id,
};
static int __init lp8725_init(void)
{
int ret;
ret = i2c_add_driver(&lp8725_driver);
DBG("**lp8725_init return %d**\n",ret);
return ret;
}
static void __exit lp8725_exit(void)
{
i2c_del_driver(&lp8725_driver);
}
module_init(lp8725_init);
module_exit(lp8725_exit);
MODULE_AUTHOR(" XXX XXX@rock-chips.com");
MODULE_DESCRIPTION("Driver for rk2818 extend gpio device");
MODULE_LICENSE("GPL");

View File

@@ -157,5 +157,10 @@ config REGULATOR_TPS6507X
three step-down converters and two general-purpose LDO voltage regulators.
It supports TI's software based Class-2 SmartReflex implementation.
config RK2818_REGULATOR_LP8725
tristate "rk2818 pmic lp8725"
depends on I2C
help
Say Y to enable support for the voltage regulators pmic lp8725 on the RK2818.
endif

View File

@@ -22,6 +22,7 @@ obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
obj-$(CONFIG_REGULATOR_MC13783) += mc13783.o
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
obj-$(CONFIG_RK2818_REGULATOR_LP8725) += rk2818_lp8725.o
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o

View File

@@ -0,0 +1,746 @@
/* drivers/regulator/rk2818_lp8725.c
*
* Copyright (C) 2010 ROCKCHIP, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*******************************************************************/
/* COPYRIGHT (C) ROCK-CHIPS FUZHOU . ALL RIGHTS RESERVED. */
/*******************************************************************
FILE : rk2818_lp8725.c
DESC : LP8725 PMIC driver
AUTHOR : cym
DATE : 2010-08-06
NOTES :
$LOG: GPIO.C,V $
REVISION 0.01
********************************************************************/
#include <linux/bug.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/regulator/driver.h>
#include "rk2818_lp8725.h"
#if 0
#define DBG(x...) printk(KERN_INFO x)
#else
#define DBG(x...)
#endif
#if 1
#define DBG_INFO(x...) printk(KERN_INFO x)
#else
#define DBG_INFO(x...)
#endif
struct lp8725 {
struct device *dev;
struct mutex io_lock;
struct i2c_client *i2c;
int num_regulators;
struct regulator_dev **rdev;
};
static u8 lp8725_reg_read(struct lp8725 *lp8725, u8 reg);
static int lp8725_set_bits(struct lp8725 *lp8725, u8 reg, u16 mask, u16 val);
#define LP8725_BUCK_VOL_ENABLE_REG 0x00
#define LP8725_BUCK1_BASE 0x08
#define LP8725_BUCK2_BASE 0x0A
const static int buck_base_addr[] = {
LP8725_BUCK1_BASE,
LP8725_BUCK2_BASE,
};
#define LP8725_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x])
#define LP8725_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1)
const static int buck_voltage_map[] = {
800, 850, 900, 950, 1000, 1050, 1100, 1150,
1200, 1250, 1300, 1350, 1400, 1500, 1600, 1700,
1750, 1800, 1850, 1900, 2000, 2100, 2200, 2300,
2400, 2500, 2600, 2700, 2800, 2850, 2900, 3000,
};
#define BUCK_TARGET_VOL_MASK 0x1f
#define BUCK_TARGET_VOL_MIN_IDX 0x00
#define BUCK_TARGET_VOL_MAX_IDX 0x1f
#define LP8725_LDO_ENABLE_REG 0x0d
#define LP8725_LDO_VOL_CONTR_BASE 0x01
#define LP8725_LDO_VOL_CONTR_REG(x) (LP8725_LDO_VOL_CONTR_BASE + x)
const static int ldo_voltage_map[] = {
1200, 1250, 1300, 1350, 1400, 1450, 1500, 1550,
1600, 1650, 1700, 1750, 1800, 1850, 1900, 2000,
2100, 2200, 2300, 2400, 2500, 2600, 2650, 2700,
2750, 2800, 2850, 2900, 2950, 3000, 3100, 3300,
};
#define LDO_VOL_CONTR_MASK 0x1f
#define LDO_VOL_MIN_IDX 0x00
#define LDO_VOL_MAX_IDX 0x1f
#define LP8725_LILO_ENABLE_REG 0x0d
#define LP8725_LILO_VOL_CONTR_BASE 0x06
#define LP8725_LILO_VOL_CONTR_REG(x) (LP8725_LILO_VOL_CONTR_BASE + x)
const static int lilo_voltage_map[] = {
800, 850, 900, 950, 1000, 1050, 1100, 1150,
1200, 1250, 1300, 1350, 1400, 1500, 1600, 1700,
1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
2600, 2700, 2800, 2850, 2900, 3000, 3100, 3300,
};
#define LILO_VOL_CONTR_MASK 0x1f
#define LILO_VOL_MIN_IDX 0x00
#define LILO_VOL_MAX_IDX 0x1f
static int lp8725_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
{
return 1000 * ldo_voltage_map[index];
}
static int lp8725_ldo_is_enabled(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int ldo = rdev_get_id(dev) - LP8725_LDO1;
u16 mask = 1 << (ldo);
u16 val;
val = lp8725_reg_read(lp8725, LP8725_LDO_ENABLE_REG);
return (val & mask) != 0;
}
static int lp8725_ldo_enable(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int ldo = rdev_get_id(dev) - LP8725_LDO1;
u16 mask = 1 << (ldo);
return lp8725_set_bits(lp8725, LP8725_LDO_ENABLE_REG, mask, mask);
}
static int lp8725_ldo_disable(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int ldo = rdev_get_id(dev) - LP8725_LDO1;
u16 mask = 1 << (ldo);
return lp8725_set_bits(lp8725, LP8725_LDO_ENABLE_REG, mask, 0);
}
static int lp8725_ldo_get_voltage(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int ldo = rdev_get_id(dev) - LP8725_LDO1;
u16 reg;
u32 val;
reg = lp8725_reg_read(lp8725, LP8725_LDO_VOL_CONTR_REG(ldo));
reg &= BUCK_TARGET_VOL_MASK;
val = 1000 * ldo_voltage_map[reg];
return val;
}
static int lp8725_ldo_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int ldo = rdev_get_id(dev) - LP8725_LDO1;
int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
const int *vol_map = ldo_voltage_map;
u16 val;
if (min_vol < vol_map[LDO_VOL_MIN_IDX] ||
min_vol > vol_map[LDO_VOL_MAX_IDX])
return -EINVAL;
for (val = LDO_VOL_MIN_IDX; val <= LDO_VOL_MAX_IDX; val++)
if (vol_map[val] >= min_vol)
break;
if (vol_map[val] > max_vol)
return -EINVAL;
DBG("***run in %s %d reg=0x%x val=0x%x",__FUNCTION__,__LINE__,LP8725_LDO_VOL_CONTR_REG(ldo),val);
return lp8725_set_bits(lp8725, LP8725_LDO_VOL_CONTR_REG(ldo),
LDO_VOL_CONTR_MASK, val);
}
static struct regulator_ops lp8725_ldo_ops = {
.list_voltage = lp8725_ldo_list_voltage,
.is_enabled = lp8725_ldo_is_enabled,
.enable = lp8725_ldo_enable,
.disable = lp8725_ldo_disable,
.get_voltage = lp8725_ldo_get_voltage,
.set_voltage = lp8725_ldo_set_voltage,
};
static int lp8725_lilo_list_voltage(struct regulator_dev *dev, unsigned index)
{
return 1000 * lilo_voltage_map[index];
}
static int lp8725_lilo_is_enabled(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int lilo = rdev_get_id(dev) - LP8725_LILO1;
u16 mask = 1 << (lilo+4);
u16 val;
val = lp8725_reg_read(lp8725, LP8725_LILO_ENABLE_REG);
return (val & mask) != 0;
}
static int lp8725_lilo_enable(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int lilo = rdev_get_id(dev) - LP8725_LILO1;
u16 mask = 1 << (lilo+4);
return lp8725_set_bits(lp8725, LP8725_LILO_ENABLE_REG, mask, mask);
}
static int lp8725_lilo_disable(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int lilo = rdev_get_id(dev) - LP8725_LILO1;
u16 mask = 1 << (lilo+4);
return lp8725_set_bits(lp8725, LP8725_LILO_ENABLE_REG, mask, 0);
}
static int lp8725_lilo_get_voltage(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int lilo = rdev_get_id(dev) - LP8725_LILO1;
u16 reg;
u32 val;
reg = lp8725_reg_read(lp8725, LP8725_LILO_VOL_CONTR_REG(lilo));
reg &= BUCK_TARGET_VOL_MASK;
val = 1000 * lilo_voltage_map[reg];
return val;
}
static int lp8725_lilo_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int lilo = rdev_get_id(dev) - LP8725_LILO1;
int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
const int *vol_map = lilo_voltage_map;
u16 val;
if (min_vol < vol_map[LILO_VOL_MIN_IDX] ||
min_vol > vol_map[LILO_VOL_MAX_IDX])
return -EINVAL;
for (val = LILO_VOL_MIN_IDX; val <= LILO_VOL_MAX_IDX; val++)
if (vol_map[val] >= min_vol)
break;
if (vol_map[val] > max_vol)
return -EINVAL;
return lp8725_set_bits(lp8725, LP8725_LILO_VOL_CONTR_REG(lilo),
LILO_VOL_CONTR_MASK, val);
}
static struct regulator_ops lp8725_lilo_ops = {
.list_voltage = lp8725_lilo_list_voltage,
.is_enabled = lp8725_lilo_is_enabled,
.enable = lp8725_lilo_enable,
.disable = lp8725_lilo_disable,
.get_voltage = lp8725_lilo_get_voltage,
.set_voltage = lp8725_lilo_set_voltage,
};
static int lp8725_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
{
return 1000 * buck_voltage_map[index];
}
static int lp8725_dcdc_is_enabled(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int buck = rdev_get_id(dev) - LP8725_DCDC1;
u16 mask = 1 << (buck * 2);
u16 val;
val = lp8725_reg_read(lp8725, LP8725_BUCK_VOL_ENABLE_REG);
return (val & mask) != 0;
}
static int lp8725_dcdc_enable(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int buck = rdev_get_id(dev) - LP8725_DCDC1;
u16 mask = 1 << (buck * 2);
return lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, mask);
}
static int lp8725_dcdc_disable(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int buck = rdev_get_id(dev) - LP8725_DCDC1;
u16 mask = 1 << (buck * 2);
return lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, 0);
}
static int lp8725_dcdc_get_voltage(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int buck = rdev_get_id(dev) - LP8725_DCDC1;
u16 reg;
int val;
reg = lp8725_reg_read(lp8725, LP8725_BUCK_TARGET_VOL1_REG(buck));
reg &= BUCK_TARGET_VOL_MASK;
val = 1000 * buck_voltage_map[reg];
return val;
}
static int lp8725_dcdc_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int buck = rdev_get_id(dev) - LP8725_DCDC1;
int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
const int *vol_map = buck_voltage_map;
u16 val;
int ret;
if (min_vol < vol_map[BUCK_TARGET_VOL_MIN_IDX] ||
min_vol > vol_map[BUCK_TARGET_VOL_MAX_IDX])
return -EINVAL;
for (val = BUCK_TARGET_VOL_MIN_IDX; val <= BUCK_TARGET_VOL_MAX_IDX;
val++)
if (vol_map[val] >= min_vol)
break;
if (vol_map[val] > max_vol)
return -EINVAL;
ret = lp8725_set_bits(lp8725, LP8725_BUCK_TARGET_VOL1_REG(buck),
BUCK_TARGET_VOL_MASK, val);
if (ret)
return ret;
ret = lp8725_set_bits(lp8725, LP8725_BUCK_TARGET_VOL2_REG(buck),
BUCK_TARGET_VOL_MASK, val);
if (ret)
return ret;
return ret;
}
static struct regulator_ops lp8725_dcdc_ops = {
.list_voltage = lp8725_dcdc_list_voltage,
.is_enabled = lp8725_dcdc_is_enabled,
.enable = lp8725_dcdc_enable,
.disable = lp8725_dcdc_disable,
.get_voltage = lp8725_dcdc_get_voltage,
.set_voltage = lp8725_dcdc_set_voltage,
};
static struct regulator_desc regulators[] = {
{
.name = "LDO1",
.id = LP8725_LDO1,
.ops = &lp8725_ldo_ops,
.n_voltages = ARRAY_SIZE(ldo_voltage_map),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
{
.name = "LDO2",
.id = LP8725_LDO2,
.ops = &lp8725_ldo_ops,
.n_voltages = ARRAY_SIZE(ldo_voltage_map),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
{
.name = "LDO3",
.id = LP8725_LDO3,
.ops = &lp8725_ldo_ops,
.n_voltages = ARRAY_SIZE(ldo_voltage_map),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
{
.name = "LDO4",
.id = LP8725_LDO4,
.ops = &lp8725_ldo_ops,
.n_voltages = ARRAY_SIZE(ldo_voltage_map),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
{
.name = "LDO5",
.id = LP8725_LDO5,
.ops = &lp8725_ldo_ops,
.n_voltages = ARRAY_SIZE(ldo_voltage_map),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
{
.name = "LILO1",
.id = LP8725_LILO1,
.ops = &lp8725_lilo_ops,
.n_voltages = ARRAY_SIZE(lilo_voltage_map),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
{
.name = "LILO2",
.id = LP8725_LILO2,
.ops = &lp8725_lilo_ops,
.n_voltages = ARRAY_SIZE(lilo_voltage_map),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
{
.name = "DCDC1",
.id = LP8725_DCDC1,
.ops = &lp8725_dcdc_ops,
.n_voltages = ARRAY_SIZE(buck_voltage_map),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
{
.name = "DCDC2",
.id = LP8725_DCDC2,
.ops = &lp8725_dcdc_ops,
.n_voltages = ARRAY_SIZE(buck_voltage_map),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
};
static int lp8725_i2c_read(struct i2c_client *i2c, char reg, int count, u16 *dest)
{
int ret;
struct i2c_adapter *adap;
struct i2c_msg msgs[2];
if(!i2c)
return ret;
if (count != 1)
return -EIO;
adap = i2c->adapter;
msgs[0].addr = i2c->addr;
msgs[0].buf = &reg;
msgs[0].flags = i2c->flags;
msgs[0].len = 1;
msgs[0].scl_rate = 200*1000;
msgs[1].buf = dest;
msgs[1].addr = i2c->addr;
msgs[1].flags = i2c->flags | I2C_M_RD;
msgs[1].len = 1;
msgs[1].scl_rate = 200*1000;
ret = i2c_transfer(adap, msgs, 2);
DBG("***run in %s %d msgs[1].buf = %d\n",__FUNCTION__,__LINE__,*(msgs[1].buf));
return 0;
}
static int lp8725_i2c_write(struct i2c_client *i2c, char reg, int count, const u16 src)
{
int ret=-1;
struct i2c_adapter *adap;
struct i2c_msg msg;
char tx_buf[2];
if(!i2c)
return ret;
if (count != 1)
return -EIO;
adap = i2c->adapter;
tx_buf[0] = reg;
tx_buf[1] = src;
msg.addr = i2c->addr;
msg.buf = &tx_buf[0];
msg.len = 1 +1;
msg.flags = i2c->flags;
msg.scl_rate = 200*1000;
ret = i2c_transfer(adap, &msg, 1);
return ret;
}
static u8 lp8725_reg_read(struct lp8725 *lp8725, u8 reg)
{
u16 val = 0;
mutex_lock(&lp8725->io_lock);
lp8725_i2c_read(lp8725->i2c, reg, 1, &val);
DBG("reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff);
mutex_unlock(&lp8725->io_lock);
return val & 0xff;
}
static int lp8725_set_bits(struct lp8725 *lp8725, u8 reg, u16 mask, u16 val)
{
u16 tmp;
int ret;
mutex_lock(&lp8725->io_lock);
ret = lp8725_i2c_read(lp8725->i2c, reg, 1, &tmp);
tmp = (tmp & ~mask) | val;
if (ret == 0) {
ret = lp8725_i2c_write(lp8725->i2c, reg, 1, tmp);
DBG("reg write 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff);
}
mutex_unlock(&lp8725->io_lock);
return ret;
}
static int lp8725_set_init(void)
{
int ret;
int tmp = 0;
struct regulator *ldo1,*ldo2,*ldo3,*ldo4,*ldo5;
struct regulator *lilo1,*lilo2;
struct regulator *buck1,*buck2;
DBG_INFO("***run in %s %d ",__FUNCTION__,__LINE__);
/*init ldo1*/
DBG_INFO("***ldo1 vcc init\n");
ldo1 = regulator_get(NULL, "ldo1");
regulator_enable(ldo1);
// regulator_set_voltage(ldo1,2500000,2500000);
tmp = regulator_get_voltage(ldo1);
DBG_INFO("***regulator_set_init: ldo1 vcc =%d\n",tmp);
/*init ldo2*/
DBG_INFO("***ldo2 vcc init\n");
ldo2 = regulator_get(NULL, "ldo2");
regulator_enable(ldo2);
// regulator_set_voltage(ldo2,3000000,3000000);
tmp = regulator_get_voltage(ldo2);
DBG_INFO("***regulator_set_init: ldo2 vcc =%d\n",tmp);
/*init ldo3*/
DBG_INFO("***ldo3 vcc init\n");
ldo3 = regulator_get(NULL, "ldo3");
regulator_enable(ldo3);
// regulator_set_voltage(ldo3,3000000,3000000);
tmp = regulator_get_voltage(ldo3);
DBG_INFO("***regulator_set_init: ldo3 vcc =%d\n",tmp);
/*init ldo4*/
DBG_INFO("***ldo4 vcc init\n");
ldo4 = regulator_get(NULL, "ldo4");
regulator_enable(ldo4);
// regulator_set_voltage(ldo4,1900000,1900000);
tmp = regulator_get_voltage(ldo4);
DBG_INFO("***regulator_set_init: ldo4 vcc =%d\n",tmp);
/*init ldo5*/
DBG_INFO("***ldo5 vcc init\n");
ldo5 = regulator_get(NULL, "ldo5");
regulator_enable(ldo5);
// regulator_set_voltage(ldo5,1900000,1900000);
tmp = regulator_get_voltage(ldo5);
DBG_INFO("***regulator_set_init: ldo5 vcc =%d\n",tmp);
/*init lilo1*/
DBG_INFO("***lilo1 vcc init\n");
lilo1 = regulator_get(NULL, "lilo1");
regulator_enable(lilo1);
// regulator_set_voltage(lilo1,3300000,3300000);
tmp = regulator_get_voltage(lilo1);
DBG_INFO("***regulator_set_init: lilo1 vcc =%d\n",tmp);
/*init lilo2*/
DBG_INFO("***lilo2 vcc init\n");
lilo2 = regulator_get(NULL, "lilo2");
regulator_enable(lilo2);
// regulator_set_voltage(lilo2,3300000,3300000);
tmp = regulator_get_voltage(lilo2);
DBG_INFO("***regulator_set_init: lilo2 vcc =%d\n",tmp);
/*init buck1*/
DBG_INFO("***buck1 vcc init\n");
buck1 = regulator_get(NULL, "vdd12");
regulator_set_voltage(buck1,1200000,1200000);
tmp = regulator_get_voltage(buck1);
DBG_INFO("***regulator_set_init: buck1 vcc =%d\n",tmp);
/*init buck2*/
DBG_INFO("***buck2 vcc init\n");
buck2 = regulator_get(NULL, "vccdr");
// regulator_set_voltage(buck1,1800000,1800000);
tmp = regulator_get_voltage(buck2);
DBG_INFO("***regulator_set_init: buck2 vcc =%d\n",tmp);
return(0);
}
static int setup_regulators(struct lp8725 *lp8725, struct lp8725_platform_data *pdata)
{
int i, err;
int num_regulators = pdata->num_regulators;
lp8725->num_regulators = num_regulators;
lp8725->rdev = kzalloc(sizeof(struct regulator_dev *) * num_regulators,
GFP_KERNEL);
/* Instantiate the regulators */
for (i = 0; i < num_regulators; i++) {
int id = pdata->regulators[i].id;
lp8725->rdev[i] = regulator_register(&regulators[id],
lp8725->dev, pdata->regulators[i].initdata, lp8725);
err = IS_ERR(lp8725->rdev[i]);
if (err) {
dev_err(lp8725->dev, "regulator init failed: %d\n",
err);
goto error;
}
}
return 0;
error:
for (i = 0; i < num_regulators; i++)
if (lp8725->rdev[i])
regulator_unregister(lp8725->rdev[i]);
kfree(lp8725->rdev);
lp8725->rdev = NULL;
return err;
}
static int __devinit lp8725_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
struct lp8725 *lp8725;
struct lp8725_platform_data *pdata = i2c->dev.platform_data;
int ret;
lp8725 = kzalloc(sizeof(struct lp8725), GFP_KERNEL);
if (lp8725 == NULL) {
ret = -ENOMEM;
goto err;
}
lp8725->i2c = i2c;
lp8725->dev = &i2c->dev;
i2c_set_clientdata(i2c, lp8725);
mutex_init(&lp8725->io_lock);
if (pdata) {
ret = setup_regulators(lp8725, pdata);
if (ret < 0)
goto err;
} else
dev_warn(lp8725->dev, "No platform init data supplied\n");
lp8725_set_init();
return 0;
err:
return ret;
}
static int __devexit lp8725_i2c_remove(struct i2c_client *i2c)
{
struct lp8725 *lp8725 = i2c_get_clientdata(i2c);
int i;
for (i = 0; i < lp8725->num_regulators; i++)
if (lp8725->rdev[i])
regulator_unregister(lp8725->rdev[i]);
kfree(lp8725->rdev);
i2c_set_clientdata(i2c, NULL);
kfree(lp8725);
return 0;
}
static const struct i2c_device_id lp8725_i2c_id[] = {
{ "lp8725", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lp8725_i2c_id);
static struct i2c_driver lp8725_i2c_driver = {
.driver = {
.name = "lp8725",
.owner = THIS_MODULE,
},
.probe = lp8725_i2c_probe,
.remove = __devexit_p(lp8725_i2c_remove),
.id_table = lp8725_i2c_id,
};
static int __init lp8725_module_init(void)
{
int ret;
ret = i2c_add_driver(&lp8725_i2c_driver);
if (ret != 0)
pr_err("Failed to register I2C driver: %d\n", ret);
return ret;
}
module_init(lp8725_module_init);
static void __exit lp8725_module_exit(void)
{
i2c_del_driver(&lp8725_i2c_driver);
}
module_exit(lp8725_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("cym <cym@rock-chips.com>");
MODULE_DESCRIPTION("LP8725 PMIC driver");

View File

@@ -0,0 +1,44 @@
/* include/linux/regulator/rk2818_lp8725.h
*
* Copyright (C) 2010 ROCKCHIP, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __LINUX_REGULATOR_LP8725_H
#define __LINUX_REGULATOR_LP8725_H
#include <linux/regulator/machine.h>
#define LP8725_LDO1 0
#define LP8725_LDO2 1
#define LP8725_LDO3 2
#define LP8725_LDO4 3
#define LP8725_LDO5 4
#define LP8725_LILO1 5
#define LP8725_LILO2 6
#define LP8725_DCDC1 7
#define LP8725_DCDC2 8
#define LP8725_NUM_REGULATORS 9
struct lp8725_regulator_subdev {
int id;
struct regulator_init_data *initdata;
};
struct lp8725_platform_data {
int num_regulators;
struct lp8725_regulator_subdev *regulators;
};
#endif