00 Linux regulator framework mimarisi
Linux regulator framework, güç kaynağı donanımını (PMIC, LDO, buck converter) ve bu kaynakları kullanan tüketicileri (SoC, DDR, peripheral) soyutlayan kernel alt sistemidir.
┌──────────────────────────────────────────────────────┐
│ Consumer (tüketen driver) │
│ regulator_get() → regulator_enable() → set_v() │
├──────────────────────────────────────────────────────┤
│ Regulator Core │
│ regulator_dev + regulator_desc + ops │
├──────────────────────────────────────────────────────┤
│ Regulator Driver (Provider) │
│ AXP20x / TPS65217 / BD71837 / fixed-regulator │
├──────────────────────────────────────────────────────┤
│ Hardware (I2C/SPI PMIC, Discrete) │
└──────────────────────────────────────────────────────┘
Temel veri yapıları
PMIC mimarisi örneği
Battery / VIN
│
├── DCDC1 (Buck 3.3V) ─── VCC_3V3_SYS
│ │ ├── DDR (LDO1 1.35V)
│ │ └── USB PHY
│
├── DCDC2 (Buck, variable) ─── VDD_CPU (cpufreq kontrollü)
│
├── DCDC3 (Buck, variable) ─── VDD_GPU
│
├── LDO1 (1.8V) ─── VCCIO_SD
├── LDO2 (3.0V) ─── VCCIO_WIFI
└── LDO3 (1.8V) ─── VCC_SENSOR
01 DT regulator binding
PMIC regulator'ları Device Tree'de iki katmanda tanımlanır: PMIC'in kendisi (I2C/SPI client) ve PMIC içindeki her regulator bloğu.
&i2c0 {
axp209: pmic@34 {
compatible = "x-powers,axp209";
reg = <0x34>;
interrupts = <0 62 4>;
interrupt-controller;
#interrupt-cells = <1>;
regulators {
/* DC-DC1 — VCC 3.3V, her zaman açık */
reg_dcdc1: dcdc1 {
regulator-name = "vcc-3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on; /* system rail, kapatılmaz */
};
/* DC-DC2 — VDD CPU, değiştirilebilir */
reg_dcdc2: dcdc2 {
regulator-name = "vdd-cpu";
regulator-min-microvolt = <700000>; /* 0.7V */
regulator-max-microvolt = <1300000>; /* 1.3V */
regulator-always-on;
/* cpufreq driver bu regulator'ı kullanır */
};
/* LDO3 — USB PHY 3.3V */
reg_ldo3: ldo3 {
regulator-name = "vcc-usb";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on; /* önyükleme sırasında aç */
};
/* LDO4 — sensör 2.8V (isteğe bağlı açık/kapalı) */
reg_ldo4: ldo4 {
regulator-name = "vcc-sensor";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
/* regulator-always-on YOK: consumer açıp kapayabilir */
};
};
};
};
Önemli DT özellikleri
02 Consumer API — get, enable, set_voltage
Consumer driver'ları regulator'lara standart bir API ile erişir. Bu API, donanım farklılıklarını soyutlar.
#include <linux/regulator/consumer.h>
struct mydev_priv {
struct device *dev;
struct regulator *vdd; /* güç kaynağı */
struct regulator *vio; /* I/O voltajı */
};
static int mydev_probe(struct platform_device *pdev)
{
struct mydev_priv *priv;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
/* Regulator'ı al — DT'de "vdd-supply" property'si ile eşleşir */
priv->vdd = devm_regulator_get(&pdev->dev, "vdd");
if (IS_ERR(priv->vdd)) {
dev_err(&pdev->dev, "vdd regulator alınamadı\n");
return PTR_ERR(priv->vdd);
}
priv->vio = devm_regulator_get_optional(&pdev->dev, "vio");
/* get_optional: regulator yoksa hata değil, NULL döner */
/* Voltaj ayarla */
int ret = regulator_set_voltage(priv->vdd, 1800000, 1800000);
/* min_uV ve max_uV eşit = sabit voltaj iste */
if (ret) {
dev_err(&pdev->dev, "voltaj ayarlanamadı\n");
return ret;
}
/* Regulator'ı aç */
ret = regulator_enable(priv->vdd);
if (ret) {
dev_err(&pdev->dev, "regulator açılamadı\n");
return ret;
}
/* Açılma süresi — bazı regulator'lar stabil olmak için zaman ister */
usleep_range(1000, 2000); /* 1-2ms */
/* ... donanım başlatma ... */
return 0;
}
static void mydev_remove(struct platform_device *pdev)
{
struct mydev_priv *priv = platform_get_drvdata(pdev);
regulator_disable(priv->vdd);
/* devm_regulator_get ile alındıysa regulator_put otomatik */
}
Ek API fonksiyonları
static const char * const supply_names[] = {
"vdd", "vio", "vana"
};
struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
/* İsimleri ata */
for (int i = 0; i < ARRAY_SIZE(supply_names); i++)
supplies[i].supply = supply_names[i];
/* Tümünü al */
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supplies), supplies);
/* Tümünü aç */
ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
/* Tümünü kapat */
regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
03 Regulator türleri — LDO, buck, boost, fixed
Her regulator tipi farklı elektriksel özelliklere sahiptir. Doğru tip seçimi hem verimlilik hem de düzenleme kalitesi için önemlidir.
compatible = "regulator-fixed".