Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 296855
b: refs/heads/master
c: 23de435
h: refs/heads/master
i:
  296853: 942aae0
  296851: 1d87e2c
  296847: 6c0b1cf
v: v3
  • Loading branch information
Jett.Zhou authored and Samuel Ortiz committed Mar 6, 2012
1 parent b42a977 commit 65cae13
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fe2afaa5412126f7a41aec811228a1f439d232a0
refs/heads/master: 23de435a59b37eda468472ac67179eee5ef10a07
95 changes: 95 additions & 0 deletions trunk/drivers/mfd/88pm860x-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,99 @@ static void device_irq_exit(struct pm860x_chip *chip)
free_irq(chip->core_irq, chip);
}

int pm8606_osc_enable(struct pm860x_chip *chip, unsigned short client)
{
int ret = -EIO;
struct i2c_client *i2c = (chip->id == CHIP_PM8606) ?
chip->client : chip->companion;

dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client);
dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n",
__func__, chip->osc_vote,
chip->osc_status);

mutex_lock(&chip->osc_lock);
/* Update voting status */
chip->osc_vote |= client;
/* If reference group is off - turn on*/
if (chip->osc_status != PM8606_REF_GP_OSC_ON) {
chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN;
/* Enable Reference group Vsys */
if (pm860x_set_bits(i2c, PM8606_VSYS,
PM8606_VSYS_EN, PM8606_VSYS_EN))
goto out;

/*Enable Internal Oscillator */
if (pm860x_set_bits(i2c, PM8606_MISC,
PM8606_MISC_OSC_EN, PM8606_MISC_OSC_EN))
goto out;
/* Update status (only if writes succeed) */
chip->osc_status = PM8606_REF_GP_OSC_ON;
}
mutex_unlock(&chip->osc_lock);

dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n",
__func__, chip->osc_vote,
chip->osc_status, ret);
return 0;
out:
mutex_unlock(&chip->osc_lock);
return ret;
}

int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client)
{
int ret = -EIO;
struct i2c_client *i2c = (chip->id == CHIP_PM8606) ?
chip->client : chip->companion;

dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client);
dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n",
__func__, chip->osc_vote,
chip->osc_status);

mutex_lock(&chip->osc_lock);
/*Update voting status */
chip->osc_vote &= ~(client);
/* If reference group is off and this is the last client to release
* - turn off */
if ((chip->osc_status != PM8606_REF_GP_OSC_OFF) &&
(chip->osc_vote == REF_GP_NO_CLIENTS)) {
chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN;
/* Disable Reference group Vsys */
if (pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0))
goto out;
/* Disable Internal Oscillator */
if (pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0))
goto out;
chip->osc_status = PM8606_REF_GP_OSC_OFF;
}
mutex_unlock(&chip->osc_lock);

dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n",
__func__, chip->osc_vote,
chip->osc_status, ret);
return 0;
out:
mutex_unlock(&chip->osc_lock);
return ret;
}

static void __devinit device_osc_init(struct i2c_client *i2c)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);

mutex_init(&chip->osc_lock);
/* init portofino reference group voting and status */
/* Disable Reference group Vsys */
pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0);
/* Disable Internal Oscillator */
pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0);

chip->osc_vote = REF_GP_NO_CLIENTS;
chip->osc_status = PM8606_REF_GP_OSC_OFF;
}

static void __devinit device_bk_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
Expand Down Expand Up @@ -774,6 +867,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,

switch (chip->id) {
case CHIP_PM8606:
device_osc_init(chip->client);
device_bk_init(chip, pdata);
device_led_init(chip, pdata);
break;
Expand All @@ -785,6 +879,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
if (chip->companion) {
switch (chip->id) {
case CHIP_PM8607:
device_osc_init(chip->companion);
device_bk_init(chip, pdata);
device_led_init(chip, pdata);
break;
Expand Down
22 changes: 22 additions & 0 deletions trunk/include/linux/mfd/88pm860x.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,22 @@ enum {
#define PM8607_PD_PREBIAS_MASK (0x1F << 0)
#define PM8607_PD_PRECHG_MASK (7 << 5)

#define PM8606_REF_GP_OSC_OFF 0
#define PM8606_REF_GP_OSC_ON 1
#define PM8606_REF_GP_OSC_UNKNOWN 2

/* Clients of reference group and 8MHz oscillator in 88PM8606 */
enum pm8606_ref_gp_and_osc_clients {
REF_GP_NO_CLIENTS = 0,
WLED1_DUTY = (1<<0), /*PF 0x02.7:0*/
WLED2_DUTY = (1<<1), /*PF 0x04.7:0*/
WLED3_DUTY = (1<<2), /*PF 0x06.7:0*/
RGB1_ENABLE = (1<<3), /*PF 0x07.1*/
RGB2_ENABLE = (1<<4), /*PF 0x07.2*/
LDO_VBR_EN = (1<<5), /*PF 0x12.0*/
REF_GP_MAX_CLIENT = 0xFFFF
};

/* Interrupt Number in 88PM8607 */
enum {
PM8607_IRQ_ONKEY,
Expand Down Expand Up @@ -298,18 +314,21 @@ enum {
struct pm860x_chip {
struct device *dev;
struct mutex irq_lock;
struct mutex osc_lock;
struct i2c_client *client;
struct i2c_client *companion; /* companion chip client */
struct regmap *regmap;
struct regmap *regmap_companion;

int buck3_double; /* DVC ramp slope double */
unsigned short companion_addr;
unsigned short osc_vote;
int id;
int irq_mode;
int irq_base;
int core_irq;
unsigned char chip_version;
unsigned char osc_status;

unsigned int wakeup_flag;
};
Expand Down Expand Up @@ -370,6 +389,9 @@ struct pm860x_platform_data {
int num_regulators;
};

extern int pm8606_osc_enable(struct pm860x_chip *, unsigned short);
extern int pm8606_osc_disable(struct pm860x_chip *, unsigned short);

extern int pm860x_reg_read(struct i2c_client *, int);
extern int pm860x_reg_write(struct i2c_client *, int, unsigned char);
extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *);
Expand Down

0 comments on commit 65cae13

Please sign in to comment.