blob: 38700cbbb2b82d69b45ae6456bc769d5867556db [file] [log] [blame]
/* Copyright (c) 2011, Code Aurora Forum. 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
* only version 2 as published by the Free Software Foundation.
*
* 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 __MFD_PM8XXX_REGULATOR_H__
#define __MFD_PM8XXX_REGULATOR_H__
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/pm8xxx-regulator.h>
/**
* enum pm8xxx_regulator_type - possible PM8XXX voltage regulator types
* %PM8XXX_REGULATOR_TYPE_PLDO: PMOS low drop-out linear regulator
* %PM8XXX_REGULATOR_TYPE_NLDO: NMOS low drop-out linear regulator
* %PM8XXX_REGULATOR_TYPE_NLDO1200: NMOS low drop-out linear regulator
* capable of supplying up to 1200 mA
* %PM8XXX_REGULATOR_TYPE_SMPS: switched-mode power supply (buck)
* %PM8XXX_REGULATOR_TYPE_FTSMPS: fast transient switched-mode power
* supply (buck)
* %PM8XXX_REGULATOR_TYPE_VS: voltage switch capable of sourcing 100mA
* %PM8XXX_REGULATOR_TYPE_VS300: voltage switch capable of sourcing 300mA
* %PM8XXX_REGULATOR_TYPE_NCP: negative charge pump
* %PM8XXX_REGULATOR_TYPE_MAX: used internally for error checking; not
* a valid regulator type.
*
* Each of these has a different register control interface.
*/
enum pm8xxx_regulator_type {
PM8XXX_REGULATOR_TYPE_PLDO,
PM8XXX_REGULATOR_TYPE_NLDO,
PM8XXX_REGULATOR_TYPE_NLDO1200,
PM8XXX_REGULATOR_TYPE_SMPS,
PM8XXX_REGULATOR_TYPE_FTSMPS,
PM8XXX_REGULATOR_TYPE_VS,
PM8XXX_REGULATOR_TYPE_VS300,
PM8XXX_REGULATOR_TYPE_NCP,
PM8XXX_REGULATOR_TYPE_MAX,
};
/**
* struct pm8xxx_vreg - regulator configuration and state data used by the
* pm8xxx-regulator driver
* @rdesc: regulator description
* @rdesc_pc: pin control regulator description. rdesc_pc.name == NULL
* implies that there is no pin control version of this
* regulator.
* @type: regulator type
* @hpm_min_load: minimum load in uA that will result in the regulator
* being set to high power mode
* @ctrl_addr: control register SSBI address
* @test_addr: test register SSBI address (not needed for all types)
* @clk_ctrl_addr: clock control register SSBI address (only used by SMPS
* type regulators)
* @sleep_ctrl_addr: sleep control register SSBI address (only used by SMPS
* type regulators)
* @pfm_ctrl_addr: pulse-frequency modulation control register SSBI address
* (only used by FTSMPS type regulators)
* @pwr_cnfg_addr: power configuration register SSBI address (only used by
* FTSMPS type regulators)
* @pdata: this platform data struct is filled based using the
* platform data pointed to in a core platform data struct
* @rdev: pointer to regulator device which is created with
* regulator_register
* @rdev_pc: pointer to pin controlled regulator device which is
* created with regulator_register
* @dev: pointer to pm8xxx-regulator device
* @dev_pc: pointer to pin control pm8xxx-regulator device
* @pc_lock: mutex lock to handle sharing between pin controlled and
* non-pin controlled versions of a given regulator. Note,
* this lock must be initialized in the PMIC core driver.)
* @save_uV: current regulator voltage in uV
* @mode: current mode of the regulator
* @write_count: number of SSBI writes that have taken place for this
* regulator. This is used for debug printing to determine
* if a given operation is redundant.
* @prev_write_count: number of SSBI writes that have taken place for this
* regulator at the start of an operation. This is used for
* debug printing to determine if a given operation is
* redundant.
* @is_enabled: true if the regulator is currently enabled, false if not
* @is_enabled_pc: true if the pin controlled version of the regulator is
* currently enabled (i.e. pin control is active), false if
* not
* @test_reg: last value read from or written to each of the banks of
* the test register
* @ctrl_reg: last value read from or written to the control register
* @clk_ctrl_reg: last value read from or written to the clock control
* register
* @sleep_ctrl_reg: last value read from or written to the sleep control
* register
* @pfm_ctrl_reg: last value read from or written to the PFM control
* register
* @pwr_cnfg_reg: last value read from or written to the power
* configuration register
*
* This data structure should only need to be instantiated in a PMIC core driver
* It is used to specify PMIC specific as opposed to board specific
* configuration data. It is also used to hold all state variables needed by
* the pm8xxx-regulator driver as these variables need to be shared between
* pin controlled and non-pin controlled versions of a given regulator, which
* are probed separately.
*/
struct pm8xxx_vreg {
/* Configuration data */
struct regulator_desc rdesc;
struct regulator_desc rdesc_pc;
enum pm8xxx_regulator_type type;
const int hpm_min_load;
const u16 ctrl_addr;
const u16 test_addr;
const u16 clk_ctrl_addr;
const u16 sleep_ctrl_addr;
const u16 pfm_ctrl_addr;
const u16 pwr_cnfg_addr;
/* State data */
struct pm8xxx_regulator_platform_data pdata;
struct regulator_dev *rdev;
struct regulator_dev *rdev_pc;
struct device *dev;
struct device *dev_pc;
struct mutex pc_lock;
int save_uV;
int mode;
u32 write_count;
u32 prev_write_count;
bool is_enabled;
bool is_enabled_pc;
u8 test_reg[REGULATOR_TEST_BANKS_MAX];
u8 ctrl_reg;
u8 clk_ctrl_reg;
u8 sleep_ctrl_reg;
u8 pfm_ctrl_reg;
u8 pwr_cnfg_reg;
};
/**
* struct pm8xxx_regulator_core_platform_data - platform data specified in a
* PMIC core driver and utilized in the pm8xxx-regulator driver
* @vreg: pointer to pm8xxx_vreg data structure that may be shared
* between pin controlled and non-pin controlled versions
* of a given regulator. Note that this data must persist
* as long as the regulator device is in use.
* @pdata: pointer to platform data passed in from a board file
* @is_pin_controlled: true if the regulator driver represents the pin control
* portion of a regulator, false if not.
*
* This data structure should only be needed in a PMIC core driver.
*/
struct pm8xxx_regulator_core_platform_data {
struct pm8xxx_vreg *vreg;
struct pm8xxx_regulator_platform_data *pdata;
bool is_pin_controlled;
};
/* Helper macros */
#define PLDO(_name, _pc_name, _ctrl_addr, _test_addr, _hpm_min_load) \
{ \
.type = PM8XXX_REGULATOR_TYPE_PLDO, \
.ctrl_addr = _ctrl_addr, \
.test_addr = _test_addr, \
.hpm_min_load = PM8XXX_VREG_##_hpm_min_load##_HPM_MIN_LOAD, \
.rdesc.name = _name, \
.rdesc_pc.name = _pc_name, \
.write_count = 0, \
.prev_write_count = -1, \
}
#define NLDO(_name, _pc_name, _ctrl_addr, _test_addr, _hpm_min_load) \
{ \
.type = PM8XXX_REGULATOR_TYPE_NLDO, \
.ctrl_addr = _ctrl_addr, \
.test_addr = _test_addr, \
.hpm_min_load = PM8XXX_VREG_##_hpm_min_load##_HPM_MIN_LOAD, \
.rdesc.name = _name, \
.rdesc_pc.name = _pc_name, \
.write_count = 0, \
.prev_write_count = -1, \
}
#define NLDO1200(_name, _ctrl_addr, _test_addr, _hpm_min_load) \
{ \
.type = PM8XXX_REGULATOR_TYPE_NLDO1200, \
.ctrl_addr = _ctrl_addr, \
.test_addr = _test_addr, \
.hpm_min_load = PM8XXX_VREG_##_hpm_min_load##_HPM_MIN_LOAD, \
.rdesc.name = _name, \
.write_count = 0, \
.prev_write_count = -1, \
}
#define SMPS(_name, _pc_name, _ctrl_addr, _test_addr, _clk_ctrl_addr, \
_sleep_ctrl_addr, _hpm_min_load) \
{ \
.type = PM8XXX_REGULATOR_TYPE_SMPS, \
.ctrl_addr = _ctrl_addr, \
.test_addr = _test_addr, \
.clk_ctrl_addr = _clk_ctrl_addr, \
.sleep_ctrl_addr = _sleep_ctrl_addr, \
.hpm_min_load = PM8XXX_VREG_##_hpm_min_load##_HPM_MIN_LOAD, \
.rdesc.name = _name, \
.rdesc_pc.name = _pc_name, \
.write_count = 0, \
.prev_write_count = -1, \
}
#define FTSMPS(_name, _pwm_ctrl_addr, _fts_cnfg1_addr, _pfm_ctrl_addr, \
_pwr_cnfg_addr, _hpm_min_load) \
{ \
.type = PM8XXX_REGULATOR_TYPE_FTSMPS, \
.ctrl_addr = _pwm_ctrl_addr, \
.test_addr = _fts_cnfg1_addr, \
.pfm_ctrl_addr = _pfm_ctrl_addr, \
.pwr_cnfg_addr = _pwr_cnfg_addr, \
.hpm_min_load = PM8XXX_VREG_##_hpm_min_load##_HPM_MIN_LOAD, \
.rdesc.name = _name, \
.write_count = 0, \
.prev_write_count = -1, \
}
#define VS(_name, _pc_name, _ctrl_addr) \
{ \
.type = PM8XXX_REGULATOR_TYPE_VS, \
.ctrl_addr = _ctrl_addr, \
.rdesc.name = _name, \
.rdesc_pc.name = _pc_name, \
.write_count = 0, \
.prev_write_count = -1, \
}
#define VS300(_name, _ctrl_addr) \
{ \
.type = PM8XXX_REGULATOR_TYPE_VS300, \
.ctrl_addr = _ctrl_addr, \
.rdesc.name = _name, \
.write_count = 0, \
.prev_write_count = -1, \
}
#define NCP(_name, _ctrl_addr) \
{ \
.type = PM8XXX_REGULATOR_TYPE_NCP, \
.ctrl_addr = _ctrl_addr, \
.rdesc.name = _name, \
.write_count = 0, \
.prev_write_count = -1, \
}
#endif