# 通知設計書 31-Battery connected/disconnected

## 概要

本ドキュメントは、FreeBSDカーネルのPMU（電源管理ユニット）サブシステムにおけるバッテリー接続・切断通知（Battery connected/disconnected）の設計を記述する。Allwinner SoC向けX-Powers AXP209/AXP221 PMICドライバが、バッテリーの物理的な接続および切断を検知した際にdevctl経由でユーザランドへ通知を発行する仕組みを対象とする。

### 本通知の処理概要

本通知は、組み込みLinuxボード等で使用されるAllwinner SoC上のPMIC（Power Management IC）であるAXP209/AXP221が、バッテリーの物理的な接続状態の変化を検知した際に発行されるカーネルレベルの通知である。

**業務上の目的・背景**：組み込みシステムやシングルボードコンピュータにおいて、バッテリーの物理的な接続・切断はシステムの電源安定性に直結する重大なイベントである。バッテリーが予期せず切断された場合、UPS的な電源保護が失われるため、ユーザランドのデーモン（devd等）がこの通知を受け取り、適切な電源管理アクション（データ保存、シャットダウン準備等）を実行する必要がある。

**通知の送信タイミング**：AXP209/AXP221のIRQ2ステータスレジスタにおいて、バッテリー接続ビット（AXP2XX_IRQ2_BATT_CONN）またはバッテリー切断ビット（AXP2XX_IRQ2_BATT_DISCONN）がセットされた際にハードウェア割り込みが発生し、割り込みハンドラ内で通知が発行される。

**通知の受信者**：devd(8)デーモンおよびdevctl(4)インターフェースを監視するユーザランドプロセス全般。devd.confに適切なルールを記述することで任意のアクションを実行可能。

**通知内容の概要**：システム名「PMU」、サブシステム名「Battery」、タイプ「connected」または「disconnected」の3つのフィールドで構成される。追加データ（data引数）はNULLである。

**期待されるアクション**：接続時はバッテリー状態のモニタリング開始、切断時はAC電源のみでの運用への切り替え判断、必要に応じたシャットダウン準備が期待される。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

devctl_notifyはカーネル内のdevctlキューにメッセージを追加し、/dev/devctlをオープンしているすべてのプロセス（通常はdevd(8)）にブロードキャストされる。特定の送信先決定ロジックは存在せず、devctlインターフェースを監視しているすべてのプロセスが受信する。

## 通知テンプレート

### devctl通知の場合

| 項目 | 内容 |
|-----|------|
| システム名 | PMU |
| サブシステム名 | Battery |
| タイプ | connected / disconnected |
| データ | NULL（追加データなし） |

### 本文テンプレート

```
!system=PMU subsystem=Battery type=connected
!system=PMU subsystem=Battery type=disconnected
```

### 添付ファイル

該当なし（カーネルdevctl通知のため）

## テンプレート変数

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

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ハードウェア割り込み | AXP2XX_IRQ2_BATT_CONN ビットセット | IRQ2ステータスレジスタが非ゼロ | バッテリーが物理的に接続された |
| ハードウェア割り込み | AXP2XX_IRQ2_BATT_DISCONN ビットセット | IRQ2ステータスレジスタが非ゼロ | バッテリーが物理的に切断された |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| IRQ2が有効化されていない場合 | axp2xx_start関数でIRQ2のBATT_CONN/BATT_DISCONNが有効化されていなければ割り込みは発生しない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ハードウェア割り込み発生] --> B[axp2xx_intr 呼び出し]
    B --> C[AXP2XX_IRQ2_STATUS レジスタ読み取り]
    C --> D{reg が非ゼロ?}
    D -->|Yes| E{AXP2XX_IRQ2_BATT_CONN?}
    D -->|No| I[終了]
    E -->|Yes| F["devctl_notify(PMU, Battery, connected, NULL)"]
    E -->|No| G{AXP2XX_IRQ2_BATT_DISCONN?}
    G -->|Yes| H["devctl_notify(PMU, Battery, disconnected, NULL)"]
    G -->|No| I
    F --> J[IRQ2ステータスACK書き込み]
    H --> J
    J --> I
```

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

### 参照テーブル一覧

該当なし（カーネルドライバのため、データベースは使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| I2Cバス読み取りエラー | AXP2XX_IRQ2_STATUS レジスタの読み取り失敗 | 暗黙的に無視（regが0のまま処理続行） |
| devctlキュー溢れ | カーネルのdevctlキューが満杯 | devctl_notifyは内部でドロップ、ログなし |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（ハードウェアイベント駆動） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（ハードウェアイベント発生時に即座に通知）

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

/dev/devctl へのアクセスはデフォルトで root のみに制限されている。通知メッセージにはバッテリーの接続状態のみが含まれ、個人情報やセキュリティ上の機密情報は含まれない。

## 備考

- AXP209はAllwinner A10/A13/A20 SoC、AXP221はAllwinner A23/A31/A33 SoC向けのPMICである
- AXP803/AXP813（axp81x.c）でも類似のバッテリー接続通知が存在するが、そちらは "plugged" / "absent" という異なるタイプ名を使用する
- 割り込みハンドラはIRQ2レジスタ内の他のイベント（充電完了、充電中、温度異常等）も同時に処理する

---

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

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

### 推奨読解順序

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

まず、AXP209/AXP221 PMICドライバのソフトウェア構造体と割り込み関連の定数定義を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | axp209reg.h | `sys/arm/allwinner/axp209reg.h` | IRQレジスタアドレスとビットマスク定数（AXP2XX_IRQ2_BATT_CONN, AXP2XX_IRQ2_BATT_DISCONN等） |
| 1-2 | axp209.c | `sys/arm/allwinner/axp209.c` | axp2xx_softc構造体（598-619行目）でドライバの状態管理を把握 |

**読解のコツ**: AXP2XX_IRQ2_xxx はIRQ2ステータス/イネーブルレジスタのビットマスクであり、レジスタアドレスはAXP2XX_IRQ2_STATUSとAXP2XX_IRQ2_ENABLEで定義されている。

#### Step 2: エントリーポイントを理解する

割り込みハンドラの登録とトリガーの仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | axp209.c | `sys/arm/allwinner/axp209.c` | axp2xx_start関数（1198-1279行目）で割り込みイネーブル設定とハンドラ登録を確認 |

**主要処理フロー**:
1. **1235-1243行目**: AXP2XX_IRQ2_ENABLEレジスタにBATT_CONN/BATT_DISCONNビットを書き込み、割り込みを有効化
2. **1274-1276行目**: bus_setup_intrでaxp2xx_intr関数を割り込みハンドラとして登録

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | axp209.c | `sys/arm/allwinner/axp209.c` | axp2xx_intr関数（827-886行目）で割り込み処理全体を確認。特に853-868行目のIRQ2処理部分 |

**主要処理フロー**:
- **853行目**: AXP2XX_IRQ2_STATUSレジスタの読み取り
- **859行目**: AXP2XX_IRQ2_BATT_CONNビット検出時に `devctl_notify("PMU", "Battery", "connected", NULL)` を呼び出し
- **861行目**: AXP2XX_IRQ2_BATT_DISCONNビット検出時に `devctl_notify("PMU", "Battery", "disconnected", NULL)` を呼び出し
- **867行目**: IRQ2ステータスレジスタへのACK書き込み

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

```
ハードウェア割り込み（I2Cバス経由）
    |
    +-- axp2xx_intr(sc)                          [sys/arm/allwinner/axp209.c:827]
            |
            +-- axp2xx_read(AXP2XX_IRQ2_STATUS)  [sys/arm/allwinner/axp209.c:853]
            |
            +-- devctl_notify("PMU","Battery","connected",NULL)  [859]
            |
            +-- devctl_notify("PMU","Battery","disconnected",NULL) [861]
            |
            +-- axp2xx_write(AXP2XX_IRQ2_STATUS, ACK) [867]
```

### データフロー図

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

AXP209/221 IRQ2       axp2xx_intr()              /dev/devctl
ステータスレジスタ -----> レジスタビット判定 --------> devctl_notify()
(BATT_CONN/             devctl_notify呼出          devdデーモン
 BATT_DISCONN)                                    ユーザランドプロセス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| axp209.c | `sys/arm/allwinner/axp209.c` | ソース | AXP209/AXP221 PMICドライバ本体。割り込みハンドラとdevctl_notify発行 |
| axp209reg.h | `sys/arm/allwinner/axp209reg.h` | ヘッダ | AXP209/AXP221レジスタアドレスとビットマスク定義 |
| subr_bus.c | `sys/kern/subr_bus.c` | ソース | devctl_notify関数の実装 |
| devctl.h | `sys/sys/devctl.h` | ヘッダ | devctl_notifyのプロトタイプ宣言 |
| devd.conf | `/etc/devd.conf` | 設定 | devdデーモンのルール設定（ユーザランド側） |
