MasterOfGizmo hat geschrieben:Was war denn an dem Ausschalten knifflig? Der rtc zieht gegen den Pullup in der Selbsthaltung das Enable-Signal gegen Masse. Damit gehen die 5v aus.
Jein. Ja, die CPU (ich nehme an das meintest Du, "rtc" macht in dem Zusammenhang keinen Sinn) zieht bei Aktivierung des Abschalt-Pins die Leitung gegen den Pullup auf Masse.
Aber: Zum einen hängt die Leitung hängt gar nicht direkt am Enable-Signal, sondern nur über eine Diode (bzw. genauer: Über die eine Hälfte eines BAT54C) - d.h. die Leitung kann Enable direkt nur auf 1 ziehen, nicht auf 0. OK, dafür gibts hinter der Diode einen passenden Pull-Down Widerstand. Nur (und das ist der Knackpunkt): Die 5V gehen halt
nicht aus,
obwohl die CPU beim Shutdown natürlich wie üblich den Abschalt-Pin auf 1 legt.
Die Fehlermeldung, die Raphael bekommen hat, ist die direkte Folge davon. Beim Poweroff macht der Linux-Kernel das hier (nur der relevante Ausschnitt):
Code: Alles auswählen
mutex_lock(&reboot_mutex);
switch (cmd) {
... irrelevanter Kram ...
case LINUX_REBOOT_CMD_POWER_OFF:
kernel_power_off();
do_exit(0);
break;
.... und so weiter ...
Normalerweise geht irgendwo in kernel_power_off() der Strom aus (und damit ist dann Schicht im Schacht). Wenn nicht, dann läuft der Kernel weiter, d.h. kernel_power_off() kommt zurück und do_exit(0) wird ausgeführt. Das wiederum prüft, ob der aktuelle Thread noch irgendwelche Locks hält - und Bingo, reboot_mutex ist noch gesperrt. Kabumm. Kernel Panic.
Der Grund dafür, dass der Strom nicht ausgeht, ist die
zweite Leitung, die zum Enable-Pin führt (ebenfalls über eine Diode, genauer gesagt über die andere Hälfte des oben erwähnten BAT54C). Und die hängt ziemlich direkt an INT1 vom tps65910 (da gibts noch einen Pullup gegen VRTC, aber den kann man hier ignorieren).
So weit, so gut - das ist halt ein Schutz davor, den Saft abzudrehen so lange noch Interrupts anhängig sind.
Allerdings: Laut Datenblatt vom TPS65910 ist INT1 "active low". Mit anderen Worten: Das zieht Enable auf 1, wenn gerade
kein Interrupt anliegt - also quasi immer. Logische Folge: Abschalten per Software sollte eigentlich so gut wie
nie funktionieren. Tut es aber prima, zumindest wenn man nicht an der RTC herumschraubt....
Da dran hab ich eine ganze Weile dran rumgeknapst. Bis ich irgendwann das Datenblatt vom tps65910 nicht nur quer- sondern durchgelesen habe und darüber gestolpert bin, dass man die Polarität von INT1 umschalten kann. Kurzer Blick ins Devcontrol-Register (Debugfs sei dank geht das ganz simpel) und siehe da: Im TXT ist INT1 auf "active high" konfiguriert

Damit macht die Schaltung dann auch wieder Sinn: Solange am tps65910 ein unquittierter Interrupt anliegt, bleibt auch der Strom an.
Und damit war dann auch endlich klar was das Problem ist: Beim Aufwachen per RTC-Alarm signalisiert der tps65910 das brav per Interrupt, d.h. er setzt INT1 auf 1 und schreibt die passenden Flags in die entsprechenden Register. Linux läuft da noch nicht, kriegt das daher auch nicht mit, und quittiert den Interrupt dementsprechend nie. Also bleibt INT1 immer auf 1, und beim nächsten (und allen folgenden, zumindest solange der selbst tps65910 nicht durch herausnehmen der Knopfzelle neu gestartet wird) Shutdowns knallt es dann halt.
Und ja, der Treiber für den tps65910 (bzw. der für dessen RTC-Funktion) setzt natürlich bei der Initialisierung alle anstehenden Interrupt-Flags zurück. Nur muss man das halt ausgerechnet für den RTC-Alarm an
zwei Stellen tun und nicht nur an einer.
Und genau das macht dann mein Patch...
MasterOfGizmo hat geschrieben:Jetzt muss der ftc-user noch Zugriff auf den rtc bekommen (wenn er's nicht eh schon hat)
Nein, hat er nicht - dafür reicht aber ein passendes chmod/chown auf /sys/class/rtc/rtc1/wakealarm aus.