[U-Boot] [RFC] POWER framework v3 - wish list
Przemyslaw Marczak
p.marczak at samsung.com
Fri May 9 12:25:53 CEST 2014
Hello,
Some time ago I had a pleasure to work on some kind of a simple
charger manager for u-boot. For checking battery charge level, cable
state, and some more info I made a common calls which were implemented
in board files, so actually it didn't base directly on PMIC framework.
This allowed making charger abstraction but it was a second power
related framework next to the PMIC.
From my side I would like to introduce its next version according to
the doc/README.power-framework documents "TO DO" list and some more...
In this RFC any comments about next version of power management
framework are welcome.
What new PMIC framework should provide?
How to extend it?
What can be fixed?
So, what should be done (in my opinion):
1. Framework architecture:
I think that current PMIC hierarchy is not so clean as it could be.
It is just based on Trats board architecture. I would like to add
there some more abstraction to make it common and simply to use.
The main problem is that current PMIC framework is based on names of
devices.
So to check some specific device options I need to know the name of such
device.
Examples of useful options:
- battery state,
- battery level
- charger state,
- charger type,
- battery charge,
and some else...
On Trats2 which I mostly use, not every option refers to a single PMIC
device. Now this problem refers only to few Samsung boards - no more
supports battery charger at present - but this maybe change...
Looking at pmic header we can find some specific ops:
[struct structure_name: fields (ops)]
- struct power_fg: fg_battery_check; fg_battery_update;
- struct power_chrg: chrg_type; chrg_bat_present; chrg_state;
- struct power_battery: struct bat; battery_init; battery_charge;
To simplify this - in my opinion those all operations could be stored in
a single structure,
because actually it refers to one abstract device - CHARGER.
Battery should not be treated as a device because it is only passive
element and actually in a simple version it has no logical interface
besides power contacts - so actually charger is responsible for
maintaining battery condition and checking its state.
Next architectural change which I'm thinking of about is to add some
abstraction of real IC features.
Nowadays boards come with highly integrated power management ICs which
provide various subsystems like:
- ldo / buck
- battery charger
- micro USB interface controller
- gpio / keys
- rtc
- led flash driver
- motor driver
- system temperature control
- and more, and more...(e.g. device power off feature)
And this all is often controlled by more then one device/interface.
Example in trats2: there are two power ICs registered as many devices,
some of them share the same interface and bus.
This is shown on diagram below:
(taken from: doc/README.power-framework)
-----------------
--------| BAT |------------
| | | |
| ----------------- |
| | |
\|/ \|/ \|/
----------- ----------------- ---------
|FG | |MUIC | |CHRG |
| | | | | |
----------- ----------------- ---------
MAX77693 MAX77693 MAX77693
addr: 0x6C addr: 0x4A addr: 0xCC
There is also another ic: MAX77686 - which acts as:
- LDO/BUCK regulator, pwr key event (i2c addr: 0x12)
- rtc (i2c addr: 0x0C)
So this is the main POWER device - but framework doesn't provide any
common ops for it besides standard register's read/write.
I think that this architecture could look as shown on the diagram below.
-------------------------
| COMMON POWER FRAMEWORK |
| with supported ops: |
| - A |
| - B |
| - C |
| - and N - others |
-------------------------
| | | | | |
(N-number of registered power devices)
| | . . . |
| | |
------------- ------------- ----
| POWER DEV | | POWER DEV | |
| name "AAA" | | name "BBB" | |
| dev id 0 | | dev id 1 | . . . |
|-------------| |-------------| | . . .
| ops type A | | ops type B | |
| iface I2C1 | | iface SPI1 | |
|-------------| ------------- |
| ops type B | |
| iface I2C2 | .
|-------------| .
| ops type C | .
| iface XXXX |
-------------
So the main change is to add multiple ops on a multiple interfaces.
And those changes actually resolve PMIC IC instances problem.
Please look at some piece of code below.
(some part of include/power/pmic.h):
enum { PMIC_I2C, PMIC_SPI, PMIC_NONE};
enum { I2C_PMIC, I2C_NUM, };
enum { PMIC_READ, PMIC_WRITE, };
enum { PMIC_SENSOR_BYTE_ORDER_LITTLE, PMIC_SENSOR_BYTE_ORDER_BIG, };
struct p_i2c { no changes };
struct p_spi { no changes };
(new framework):
enum {
POWER_OPS_REGISTER_RW,
POWER_OPS_REGULATOR,
POWER_OPS_CHARGER,
POWER_OPS_MUIC,
POWER_OPS_KEY_POWER,
POWER_OPS_RTC,
POWER_OPS_MOTOR,
POWER_OPS_LED_FLASH,
POWER_OPS_TEMP_CONTROL,
};
struct power_ops_register_rw {
int (*register_read) (int reg, int *val);
int (*register_write) (int reg, int *val);
};
struct power_ops_regulator {
int (*ldo_set_value) (int regulator, int val, int mode, ...);
int (*ldo_get_value) (int regulator, int *val, int mode, ...);
int (*buck_set_value) (int buck, int val, int mode, ...);
int (*buck_get_value) (int buck, int *val, int mode, ...);
};
struct power_ops_charger {
int (*chrg_present) (void);
int (*chrg_type) (void);
int (*bat_present) (void);
int (*battery_state) (struct battery *bat);
int (*battery_charge) (struct battery *bat);
};
struct power_ops_muic {
int (*cable_attached) (void);
int (*cable_accesory_type) (void);
};
struct power_ops_key_power {
int (*key_state) (int *state);
};
struct power_ops_rtc {
int (*sec) (int set_get, int *val);
int (*min) (int set_get, int *val);
int (*hour) (int set_get, int *val);
int (*day) (int set_get, int *val);
int (*month) (int set_get, int *val);
int (*year) (int set_get, int *val);
};
struct power_ops_motor {
int (*configure) (void);
int (*enable) (int time, int gain);
};
struct power_ops_led_flash {
int (*configure) (void);
int (*enable) (void);
int (*disable) (void);
};
struct power_ops_temp_control {
int (*configure) (void);
int (*get_temp) (int *val);
};
struct power_dev_interface {
int id; /* One device can use few interfaces */
int type; /* enum { PMIC_I2C, PMIC_SPI, ...}; */
int bus;
int sensor_byte_order;
int number_of_regs;
union hw {
struct p_i2c i2c;
struct p_spi spi;
} hw;
};
struct power_dev_ops {
/* type: enum { POWER_DEV_REGULATOR, ... } */
int type;
/* id: for multiple ops of one type */
int id;
/* corresponding interface */
struct power_dev_interface *io;
/* Pointer to proper type ops structure */
void *ops;
/* Recognized by sequential OPS */
struct list_head list;
};
struct power_dev {
int id;
const char *name;
/* device operations list */
struct power_dev_ops *ops;
/* device instances list */
struct list_head list;
};
Such organization of structures allows to:
- initialize few instances of one driver,
- initialize only supported operations,
- provide driver's operations on a few interfaces,
- initialize driver with the same ops on a different interfaces,
Specified ops types allow implementation of optional framework command line
tool especially we can search devices by: name, ops type, interface -
every with optional multiple instance.
e.g. command use
# power list ops
# power list devices
# power list interfaces
the rest of commands could be used as in current pmic framework.
Of course this is just a proposition - It's not implemented yet.
The next change is the integration with device tree which is obligatory
here and device model could be added in the future.
Drivers ops and interfaces could be initialized into linker lists.
Device parameters like an interface, bus and instances could be
parsed from dtb at runtime.
So this gives some abstraction to power related devices.
On a top of those changes I will add a simple charger manager.
Before I start writing code I would like to receive some feedback,
about this idea.
Thank you,
--
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com
More information about the U-Boot
mailing list