# 通知設計書 33-Battery warning-threshold

## 概要

本ドキュメントは、FreeBSDカーネルのPMU（電源管理ユニット）サブシステムにおけるバッテリー警告閾値通知（Battery warning-threshold）の設計を記述する。Allwinner SoC向けX-Powers AXP803/AXP813/AXP818 PMICドライバ（axp81x.c）が、バッテリー容量が警告レベルの閾値に達した際にdevctl経由でユーザランドへ通知を発行する仕組みを対象とする。

### 本通知の処理概要

本通知は、AXP803/AXP813/AXP818 PMICの燃料ゲージ（Fuel Gauge）機能がバッテリー残量の低下を検出し、設定された警告閾値（warning threshold）に到達した際に発行されるカーネルレベルの通知である。

**業務上の目的・背景**：バッテリー駆動システムにおいて、バッテリー残量が低下した際にユーザに警告を発行し、データ保存やシャットダウン準備の猶予時間を確保することは、データ損失やシステム異常停止を防ぐために不可欠である。PMICはLV1（警告）とLV0（シャットダウン）の2段階の閾値を持ち、本通知はLV1（警告）閾値到達時に発行される。

**通知の送信タイミング**：AXP_IRQSTAT4レジスタにおいてAXP_IRQSTAT4_BATLVL_LO1ビットがセットされた際にハードウェア割り込みが発生し、割り込みハンドラaxp8xx_intr内でdevctl_notifyが呼び出される。

**通知の受信者**：devd(8)デーモンおよびdevctl(4)インターフェースを監視するユーザランドプロセス。

**通知内容の概要**：システム名「PMU」、サブシステム名「Battery」、タイプ「warning-threshold」。追加データはNULL。

**期待されるアクション**：ユーザへのバッテリー低残量警告表示、非重要サービスの停止、データの自動保存、AC電源への接続促進。

## 通知種別

カーネルdevctl通知（devctl_notify経由）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（ハードウェア割り込みハンドラから発行） |
| 優先度 | 高（ハードウェア割り込みレベル） |
| リトライ | 無し |

### 送信先決定ロジック

devctl_notifyによるブロードキャスト。/dev/devctlを監視するすべてのプロセスが受信対象。

## 通知テンプレート

### devctl通知の場合

| 項目 | 内容 |
|-----|------|
| システム名 | PMU |
| サブシステム名 | Battery |
| タイプ | warning-threshold |
| データ | NULL |

### 本文テンプレート

```
!system=PMU subsystem=Battery type=warning-threshold
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| system | 通知のシステム名 | ハードコード "PMU" | Yes |
| subsystem | サブシステム名 | ハードコード "Battery" | Yes |
| type | イベントタイプ | ハードコード "warning-threshold" | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ハードウェア割り込み | AXP_IRQSTAT4_BATLVL_LO1 ビットセット | IRQ4ステータスレジスタ非ゼロ | バッテリー容量がLV1警告閾値に到達 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| IRQ4が有効化されていない場合 | axp8xx_attach関数でAXP_IRQEN4_BATLVL_LO1が有効化されていなければ割り込みは発生しない |
| 燃料ゲージが無効の場合 | AXP_FUEL_GAUGECTL_ENが無効の場合、バッテリー容量の監視が行われない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ハードウェア割り込み発生] --> B[axp8xx_intr 呼び出し]
    B --> C[AXP_IRQSTAT4 レジスタ読み取り]
    C --> D{val が非ゼロ?}
    D -->|Yes| E{AXP_IRQSTAT4_BATLVL_LO1?}
    D -->|No| I[終了]
    E -->|Yes| F["devctl_notify(PMU, Battery, warning-threshold, NULL)"]
    E -->|No| I
    F --> G[IRQ4ステータスACK書き込み]
    G --> I
```

## データベース参照・更新仕様

該当なし（カーネルドライバのため）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| I2Cバス読み取りエラー | AXP_IRQSTAT4レジスタの読み取り失敗 | error != 0 の場合 return で終了 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0 |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし

## セキュリティ考慮事項

/dev/devctlへのアクセスはデフォルトでrootのみ。通知にはバッテリー閾値到達の事実のみが含まれ、具体的な残量値は含まれない。

## 備考

- AXP803/813/818のLV1警告閾値はAXP_BAT_CAP_WARNレジスタのビット4-7で設定（5-20%、1%ステップ）
- LV0（シャットダウン閾値）到達時は別途 "shutdown-threshold" タイプの通知が発行される（AXP_IRQSTAT4_BATLVL_LO0）
- warn_thresとshut_thresの値はaxp8xx_attach関数の1567-1579行目で読み取られる
- AXP209/AXP221（axp209.c）にはこの警告閾値通知は実装されていない

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | axp81x.c | `sys/arm/allwinner/axp81x.c` | AXP_IRQEN4_BATLVL_LO1, AXP_IRQSTAT4_BATLVL_LO1の定数定義（133-134行目, 151-152行目） |
| 1-2 | axp81x.c | `sys/arm/allwinner/axp81x.c` | AXP_BAT_CAP_WARN関連の定数（192-194行目）で閾値設定の仕組みを理解 |
| 1-3 | axp81x.c | `sys/arm/allwinner/axp81x.c` | axp8xx_softc構造体（680-704行目）のwarn_thres, shut_thresフィールド |

**読解のコツ**: AXP_IRQEN4/AXP_IRQSTAT4はペアになっており、ENがイネーブルレジスタ、STATがステータスレジスタ。BATLVL_LO1がwarning、BATLVL_LO0がshutdown。

#### Step 2: 割り込み有効化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | axp81x.c | `sys/arm/allwinner/axp81x.c` | axp8xx_attach関数 1593-1595行目でAXP_IRQEN4にBATLVL_LO0 | BATLVL_LO1を設定 |

**主要処理フロー**:
1. **1567-1579行目**: AXP_BAT_CAP_WARNレジスタから警告閾値とシャットダウン閾値を読み取り
2. **1593-1595行目**: AXP_IRQEN4にBATLVL_LO0とBATLVL_LO1の割り込みを有効化

#### Step 3: 割り込みハンドラを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | axp81x.c | `sys/arm/allwinner/axp81x.c` | axp8xx_intr関数 1123-1136行目のIRQ4処理部分 |

**主要処理フロー**:
- **1123行目**: AXP_IRQSTAT4レジスタの読み取り
- **1130-1131行目**: BATLVL_LO0検出時に "shutdown-threshold" 通知
- **1132-1133行目**: BATLVL_LO1検出時に `devctl_notify("PMU", "Battery", "warning-threshold", NULL)`
- **1135行目**: IRQ4ステータスへのACK書き込み

### プログラム呼び出し階層図

```
ハードウェア割り込み（バッテリー容量低下）
    |
    +-- axp8xx_intr(dev)                              [sys/arm/allwinner/axp81x.c:1068]
            |
            +-- axp8xx_read(AXP_IRQSTAT4)             [1123]
            |
            +-- devctl_notify("PMU","Battery","warning-threshold",NULL) [1133]
            |
            +-- axp8xx_write(AXP_IRQSTAT4, val)       [1135]
```

### データフロー図

```
[入力]                     [処理]                        [出力]

AXP803/813/818          axp8xx_intr()              /dev/devctl
燃料ゲージ -----------> IRQ4ビット判定 -----------> devctl_notify()
(BATLVL_LO1)            devctl_notify呼出          devdデーモン
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| axp81x.c | `sys/arm/allwinner/axp81x.c` | ソース | AXP803/813/818 PMICドライバ本体 |
| subr_bus.c | `sys/kern/subr_bus.c` | ソース | devctl_notify関数の実装 |
| devctl.h | `sys/sys/devctl.h` | ヘッダ | devctl_notifyプロトタイプ |
