From 5af8792bd59d0ea7e1bdf2cf83fba38f40eaea26 Mon Sep 17 00:00:00 2001 From: Prasad Sodagudi Date: Wed, 5 Jun 2013 17:33:52 +0530 Subject: [PATCH] leds: pm8xxx: Enable PWM LPG banks based on max current The current design enables PWM LPG high bank with out checking the max current. So enable PWM LPG low bank when max current configured as 4mA and enable PWM LPG high bank when the max current configured as 8mA. Enabled both PWM LPG low bank and PWM LPG high bank when max current configure as 12mA. CRs-Fixed: 486318 Change-Id: Ib7177aafc63c4c33b8c144d665a11d5aaf0ef584 Signed-off-by: Prasad Sodagudi --- drivers/leds/leds-pm8xxx.c | 25 +++++++++++++-- drivers/mfd/pm8xxx-pwm.c | 56 ++++++++++++++++++++++++++-------- include/linux/mfd/pm8xxx/pwm.h | 5 ++- 3 files changed, 71 insertions(+), 15 deletions(-) diff --git a/drivers/leds/leds-pm8xxx.c b/drivers/leds/leds-pm8xxx.c index c3a55647080..aef6295db08 100644 --- a/drivers/leds/leds-pm8xxx.c +++ b/drivers/leds/leds-pm8xxx.c @@ -133,6 +133,11 @@ _rgb_led_blue << PM8XXX_ID_RGB_LED_BLUE, \ } +#define PM8XXX_PWM_CURRENT_4MA 4 +#define PM8XXX_PWM_CURRENT_8MA 8 +#define PM8XXX_PWM_CURRENT_12MA 12 + + /** * supported_leds - leds supported for each PMIC version * @version - version of PMIC @@ -795,7 +800,7 @@ static int __devinit get_init_value(struct pm8xxx_led_data *led, u8 *val) static int pm8xxx_led_pwm_configure(struct pm8xxx_led_data *led) { - int start_idx, idx_len, duty_us, rc; + int start_idx, idx_len, duty_us, rc, flags; led->pwm_dev = pwm_request(led->pwm_channel, led->cdev.name); @@ -808,6 +813,22 @@ static int pm8xxx_led_pwm_configure(struct pm8xxx_led_data *led) return -ENODEV; } + flags = PM8XXX_LED_PWM_FLAGS; + switch (led->max_current) { + case PM8XXX_PWM_CURRENT_4MA: + flags |= PM_PWM_BANK_LO; + break; + case PM8XXX_PWM_CURRENT_8MA: + flags |= PM_PWM_BANK_HI; + break; + case PM8XXX_PWM_CURRENT_12MA: + flags |= (PM_PWM_BANK_LO | PM_PWM_BANK_HI); + break; + default: + flags |= (PM_PWM_BANK_LO | PM_PWM_BANK_HI); + break; + } + if (led->pwm_duty_cycles != NULL) { start_idx = led->pwm_duty_cycles->start_idx; idx_len = led->pwm_duty_cycles->num_duty_pcts; @@ -825,7 +846,7 @@ static int pm8xxx_led_pwm_configure(struct pm8xxx_led_data *led) led->pwm_duty_cycles->duty_pcts, led->pwm_duty_cycles->duty_ms, start_idx, idx_len, 0, 0, - PM8XXX_LED_PWM_FLAGS); + flags); } else { duty_us = led->pwm_period_us; rc = pwm_config(led->pwm_dev, duty_us, led->pwm_period_us); diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c index caaba81cb5d..0388484e9b0 100644 --- a/drivers/mfd/pm8xxx-pwm.c +++ b/drivers/mfd/pm8xxx-pwm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -58,10 +58,11 @@ #define PM8XXX_PWM_DISABLE 0x3F /* PM8XXX LPG PWM */ +#define SSBI_REG_ADDR_LPG_BANK_LOW_EN 0x130 #define SSBI_REG_ADDR_LPG_CTL_BASE 0x13C #define SSBI_REG_ADDR_LPG_CTL(n) (SSBI_REG_ADDR_LPG_CTL_BASE + (n)) #define SSBI_REG_ADDR_LPG_BANK_SEL 0x143 -#define SSBI_REG_ADDR_LPG_BANK_EN 0x144 +#define SSBI_REG_ADDR_LPG_BANK_HIGH_EN 0x144 #define SSBI_REG_ADDR_LPG_LUT_CFG0 0x145 #define SSBI_REG_ADDR_LPG_LUT_CFG1 0x146 #define SSBI_REG_ADDR_LPG_TEST 0x147 @@ -206,13 +207,15 @@ struct pwm_device { struct pm8xxx_pwm_chip *chip; int bypass_lut; int dtest_mode_supported; + int banks; }; struct pm8xxx_pwm_chip { struct pwm_device *pwm_dev; u8 pwm_channels; u8 pwm_total_pre_divs; - u8 bank_mask; + u8 lo_bank_mask; + u8 hi_bank_mask; struct mutex pwm_mutex; struct device *dev; bool is_lpg_supported; @@ -259,18 +262,37 @@ static int pm8xxx_pwm_bank_enable(struct pwm_device *pwm, int enable) chip = pwm->chip; - if (enable) - reg = chip->bank_mask | (1 << pwm->pwm_id); - else - reg = chip->bank_mask & ~(1 << pwm->pwm_id); + if (pwm->banks & PM_PWM_BANK_LO) { + if (enable) + reg = chip->lo_bank_mask | (1 << pwm->pwm_id); + else + reg = chip->lo_bank_mask & ~(1 << pwm->pwm_id); - rc = pm8xxx_writeb(chip->dev->parent, SSBI_REG_ADDR_LPG_BANK_EN, reg); - if (rc) { - pr_err("pm8xxx_writeb(): rc=%d (Enable LPG Bank)\n", rc); - return rc; + rc = pm8xxx_writeb(chip->dev->parent, + SSBI_REG_ADDR_LPG_BANK_LOW_EN, reg); + if (rc) { + pr_err("pm8xxx_writeb(): Enable Bank Low =%d\n", rc); + return rc; + } + + chip->lo_bank_mask = reg; } - chip->bank_mask = reg; + if (pwm->banks & PM_PWM_BANK_HI) { + if (enable) + reg = chip->hi_bank_mask | (1 << pwm->pwm_id); + else + reg = chip->hi_bank_mask & ~(1 << pwm->pwm_id); + + rc = pm8xxx_writeb(chip->dev->parent, + SSBI_REG_ADDR_LPG_BANK_HIGH_EN, reg); + if (rc) { + pr_err("pm8xxx_writeb(): Enable Bank High =%d\n", rc); + return rc; + } + + chip->hi_bank_mask = reg; + } return 0; } @@ -1010,6 +1032,16 @@ int pm8xxx_pwm_lut_config(struct pwm_device *pwm, int period_us, period = &pwm->period; mutex_lock(&pwm->chip->pwm_mutex); + if (flags & PM_PWM_BANK_HI) + pwm->banks = PM_PWM_BANK_HI; + + if (flags & PM_PWM_BANK_LO) + pwm->banks |= PM_PWM_BANK_LO; + + /*Enable both banks if banks information is not shared.*/ + if (!pwm->banks) + pwm->banks |= (PM_PWM_BANK_LO | PM_PWM_BANK_HI); + if (!pwm->in_use) { pr_err("pwm_id: %d: stale handle?\n", pwm->pwm_id); rc = -EINVAL; diff --git a/include/linux/mfd/pm8xxx/pwm.h b/include/linux/mfd/pm8xxx/pwm.h index 6d95e3a4b57..47ebe06a16b 100644 --- a/include/linux/mfd/pm8xxx/pwm.h +++ b/include/linux/mfd/pm8xxx/pwm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,6 +32,9 @@ #define PM_PWM_LUT_NO_TABLE 0x100 +#define PM_PWM_BANK_LO 0x1000 +#define PM_PWM_BANK_HI 0x2000 + /** * PWM frequency/period control *