This document introduces a developer guide for PMIC and regulator support in U-Boot. It covers subsystem architecture, Kconfig options, Device Tree integration, SPL considerations, and debugging methods, using TPS65219 + BeaglePlay as an example.
Signed-off-by: Bhimeswararao Matsa <bhimeswararao.ma...@gmail.com> --- doc/README.pmic | 345 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 doc/README.pmic diff --git a/doc/README.pmic b/doc/README.pmic new file mode 100644 index 00000000000..f7c7ef629b9 --- /dev/null +++ b/doc/README.pmic @@ -0,0 +1,345 @@ +# U‑Boot PMIC & Regulator Mini‑Guide (README.pmic) + +> A concise, practical guide to understanding and extending PMIC + regulator support in U‑Boot. Target audience: BSP/Board bring‑up engineers. + +--- + +## 0) TL;DR + +* **Code paths:** `drivers/power/pmic/` (PMIC bus + register access) and `drivers/power/regulator/` (voltage rails). +* **Device Tree:** Describe PMIC node (I²C/SPI), child regulator nodes with `regulator-` properties. +* **Kconfig:** Enable the PMIC driver (e.g., `CONFIG_PMIC_TPS65219`) and the regulator framework (`CONFIG_DM_REGULATOR*`). +* **SPL vs U‑Boot proper:** Decide where rails must be on (e.g., for DDR/IP). Mirror minimal regulator config in SPL (size‑conscious). +* **Debug:** Use `i2c dev`, `i2c md`, regulator debug prints, and `log level`. + +--- + +## 1) Architecture Overview + +### 1.1 Subsystems + +* **PMIC layer (`drivers/power/pmic/`)** + + * Abstracts low‑level register operations on a given chip (read/write, init, IRQ masks, sequencing registers, etc.). + * Typically binds to an **I²C** or **SPI** bus via a devicetree node. +* **Regulator layer (`drivers/power/regulator/`)** + + * Presents each rail (BUCK/SMPS, LDO, switch) as a `regulator` device. + * Methods: `enable/disable`, `set_value/get_value` (µV), `set_current` (µA), `get_status`. +* **Consumers** + + * Other drivers (MMC, USB, PHY, PCIe, camera, etc.) request rails via phandles or use fixed supplies. + +### 1.2 Typical Call Flow + +U‑Boot start → dm_init → ofnode parse PMIC → PMIC probe → create regulator children +→ Early/SPL: board code sets essential rails (DDR, core) → Later: drivers request rails as needed + +--- + +## 2) Kconfig & Build + +Enable core frameworks: + +CONFIG_DM=y +CONFIG_DM_I2C=y # or DM_SPI for SPI PMICs +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_UCLASS=y +CONFIG_SPL_DM=y # if using SPL with DM +CONFIG_SPL_DM_REGULATOR=y + +Enable a specific PMIC (example, TI TPS65219): + +CONFIG_PMIC_TPS65219=y +CONFIG_DM_REGULATOR_TPS65219=y # if split, or enable generic DM_REGULATOR helpers + +Optional helpers: + +CONFIG_CMD_I2C=y +CONFIG_CMD_REGULATOR=y # if available on your tree +CONFIG_LOG=y +CONFIG_LOGLEVEL=6 # verbose logs + +--- + +## 3) Device Tree Basics + +### 3.1 PMIC Node (I²C example) + +&i2c0 { + status = "okay"; + pmic: tps65219@24 { + compatible = "ti,tps65219"; + reg = <0x24>; // I²C address + /* Optional: IRQ, GPIOs, power‑on config */ + interrupt-parent = <&gpio1>; + interrupts = <12 IRQ_TYPE_LEVEL_LOW>; + + /* Child regulators */ + buck1: buck1 { + regulator-name = "vdd_core"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + }; + + buck2: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1000000>; + regulator-boot-on; + }; + + ldo1: ldo1 { + regulator-name = "vdda_pll"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-allow-bypass; + }; + }; +}; + +### 3.2 Consumers referencing regulators + +&mmc1 { + vmmc-supply = <&buck2>; // card supply + vqmmc-supply = <&ldo1>; // IO voltage +}; + +&usbss0 { + vbus-supply = <&buck1>; +}; + +**Notes** + +* Use chip‑specific child node names if the driver expects them (some drivers match by `regulator-name` or by order/index). +* `regulator-boot-on` ensures the framework enables the rail during init if safe. +* For **fixed rails** not controlled by PMIC, use `regulator-fixed` nodes under `fixedregulator@…` in DTS. + +--- + +## 4) Adding/Porting a PMIC Driver + +### 4.1 Skeleton (PMIC layer) + +// drivers/power/pmic/pmic_foo.c +#include <dm.h> +#include <power/pmic.h> +#include <i2c.h> + +struct foo_priv { struct udevice *dev; /* cached addr, etc. */ }; + +static int foo_read(struct udevice *dev, uint reg, u8 *val) +{ return dm_i2c_read(dev, reg, val, 1); } + +static int foo_write(struct udevice *dev, uint reg, const u8 *val) +{ return dm_i2c_write(dev, reg, *val, 1); } + +static int foo_probe(struct udevice *dev) +{ + // Optionally: unlock, set default pages, mask IRQs, sanity checks + return 0; +} + +static const struct udevice_id foo_ids[] = { + { .compatible = "vendor,foo1234" }, + { } +}; + +U_BOOT_DRIVER(pmic_foo) = { + .name = "pmic_foo", + .id = UCLASS_PMIC, + .of_match = foo_ids, + .probe = foo_probe, +}; +``` + +### 4.2 Per‑regulator ops (Regulator layer) + +// drivers/power/regulator/foo_reg.c +#include <dm.h> +#include <power/regulator.h> + +static int foo_reg_enable(struct udevice *dev, bool enable) +{ /* read reg; set/clear enable bit; write back */ return 0; } + +static int foo_reg_set_value(struct udevice *dev, int uV) +{ /* map uV → selector → register field */ return 0; } + +static const struct dm_regulator_ops foo_reg_ops = { + .enable = foo_reg_enable, + .set_value = foo_reg_set_value, + .get_value = dm_regulator_common_get_value, // or custom +}; + +U_BOOT_DRIVER(foo_buck) = { + .name = "foo_buck", + .id = UCLASS_REGULATOR, + .ops = &foo_reg_ops, + .of_match = foo_buck_ids, +}; + +### 4.3 Kconfig/Makefile + +config PMIC_FOO + bool "PMIC Foo1234 support" + depends on DM_I2C && DM_REGULATOR + +obj-$(CONFIG_PMIC_FOO) += pmic_foo.o +obj-$(CONFIG_PMIC_FOO) += foo_reg.o + +--- + +## 5) SPL Considerations + +* **Goal:** Bring up only the rails required for DDR init, boot storage (eMMC/SD), and console. +* Enable minimal configs: `CONFIG_SPL_DM_REGULATOR`, `CONFIG_SPL_I2C`, `CONFIG_SPL_OF_CONTROL`. +* **Shrink tips:** + + * Avoid complex features (interrupts/OTPs) in SPL unless mandatory. + * Hard‑code essential voltage selectors if DT parsing in SPL is too heavy; keep U‑Boot proper fully DT‑driven. +* **Mirroring:** Ensure voltages set in SPL match what Linux expects later (handoff harmony). + +--- + +## 6) Runtime Control & Sequencing + +* **Power‑on sequence:** Many PMICs have programmable sequences (buck → ldo delays). U‑Boot typically leaves factory OTP; use minimal tweaks only if required by board. +* **Regulator constraints:** Honour `min/max µV`, `always‑on`, `boot‑on`. Error if request violates limits. +* **DVFS:** If CPU frequency scaling at early boot is needed, expose a CPU rail regulator and provide OPP‑safe transitions. + +--- + +## 7) Debugging Playbook + +1. **Confirm bus & probe** + +```sh +=> i2c bus # list buses +=> i2c dev 0 # select bus +=> i2c probe # scan addresses; ensure PMIC addr shows up +``` + +2. **Peek registers** + +```sh +=> i2c md 0x24 0x00 0x10 # dump first 16 regs (TPS65219 example) +``` + +3. **Regulator ops (if command present)** + +```sh +=> regulator list +=> regulator dev <n> +=> regulator read +=> regulator set value 1000000 +=> regulator enable +``` + +4. **Logs** + +```sh +=> setenv loglevel 7; saveenv +``` + +5. **Scope & DMM**: Verify rails physically (bring up issues often are voltage/seq mismatches). + +**Common Pitfalls** + +* PMIC **variant mismatch**: OTP differs (missing rail in DTS → peripherals fail; e.g., USB not detected). +* Wrong **I²C address** or bus number in DTS. +* Missing `regulator-boot-on` for rails needed before their consumers probe. +* Using `regulator-always-on` on rails that must be toggled for reset/PM suspend (stuck devices). +* Not mirroring SPL/U‑Boot‑proper settings → surprise voltage switch later. + +--- + +## 8) Example: TI TPS65219 + BeaglePlay‑like Board + +### 8.1 DTS (excerpt) + +&i2c2 { + status = "okay"; + pmic: tps65219@24 { + compatible = "ti,tps65219"; + reg = <0x24>; + + buck1: buck1 { /* VDD_CORE */ + regulator-name = "vdd_core"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1100000>; + regulator-boot-on; + regulator-always-on; + }; + buck2: buck2 { /* VDD_DDR */ + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1000000>; + regulator-boot-on; + }; + ldo1: ldo1 { /* VDDA_PLL */ + regulator-name = "vdda_pll"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + }; +}; + +&dwc3_0 { vbus-supply = <&buck1>; }; +&mmc0 { vmmc-supply = <&buck2>; vqmmc-supply = <&ldo1>; }; +``` + +### 8.2 Board code (optional guardrails) + +int board_init(void) +{ + struct udevice *reg; + if (!uclass_get_device_by_name(UCLASS_REGULATOR, "vdd_ddr", ®)) + regulator_set_value(reg, 950000); + return 0; +} + +--- + +## 9) Checklists + +### 9.1 New Board Bring‑up + +* [ ] PMIC bus verified (I²C/SPI, pull‑ups, address, reset line) +* [ ] DTS PMIC node + child regulators authored +* [ ] Rails mapped to consumers (MMC/USB/PHY/PCIe/CSI/eth) +* [ ] SPL minimal rails configured +* [ ] Boot to shell; validate `regulator list` +* [ ] Measure voltages; confirm within tolerance under load +* [ ] Exercise suspend/resume (if used) and warm reset + +### 9.2 New PMIC Driver + +* [ ] Read/write helpers done +* [ ] ID/OTP/version readout +* [ ] Regulator enumerate + ops (enable, set/get µV) +* [ ] DT bindings documented (yaml in Linux style if upstreaming) +* [ ] Kconfig/Makefile wired +* [ ] Tested on real hardware; provide scope captures for critical rails + +--- + +## 10) Upstreaming Tips + +* Mirror **Linux bindings** (names, properties) to ease review. +* Keep **per‑rail tables** (selector↔µV) static‑const; avoid magic numbers. +* Add **`dev_dbg()` breadcrumbs** for probe, set\_value, enable. +* Provide `MAINTAINERS` entry and `doc/` note pointing here. + +--- + +## 11) References & Useful Pointers + +* `drivers/power/pmic/` and `drivers/power/regulator/` examples in U‑Boot tree (TPS, RK8xx, MAX77xxx, PMIC for NXP, etc.) +* Linux kernel `Documentation/devicetree/bindings/regulator/*` for property patterns. +* Datasheet/OTP app notes for your PMIC (voltage tables, sequencing, reset behavior). + +--- + + -- 2.43.0