Résolution des anomalies des LED PHY Ethernet sur la plateforme AM335x lors des redémarrages logiciels

Contexte et Symptômes

Lors de l'exécution d'une commande de redémarrage logiciel sur un système embarqué basé sur le processeur AM335x, des comportements anormaux sont observés au niveau des indicateurs LED du port Ethernet (contrôlé par une puce PHY telle que le LAN8710). Lorsque le câble réseau est connecté, le redémarrage éteint correctement la LED "LINK", mais la LED "ACTIVE" reste allumée. Après le redémarrage, la LED "LINK" se rallume nomralement, tandis que la LED "ACTIVE" s'éteint (bien qu'elle clignote correctement lors des transferts de données). Si le câble est déconnecté, la LED "LINK" s'éteint et la LED "ACTIVE" s'allume. De plus, lors de redémarrages successifs avec le câble connecté, l'état de la LED "ACTIVE" au repos alterne de manière imprévisible entre allumé et éteint.

Analyse de la Cause Racine

L'investigation matérielle révèle que la puce PHY n'est pas correctement réinitialisée. La broche nRST du LAN8710 nécessite un maintien à l'état bas d'au moins 100 µs pour garantir un reset fiable. Or, le signal nRESETIN_OUT généré par l'AM335x ne produit qu'une impulsion basse d'environ 700 ns. Même après avoir traversé un tampon à collecteur ouvert (comme le SN74LVC1G07DBV), la durée du signal bas n'atteint que 1 µs, ce qui est largement insuffisant. Ce défaut de temporisation empêche la PHY de compléter sa séquence de réinitialisation.

Atténuation Logiciel via le Registre PRCM

Le manuel de référence technique (TRM) de l'AM335x indique qu'il est possible d'étendre la durée de l'impulsion de réinitialisation globale (Global Warm Reset) en modifiant le registre PRM_RSTTIME. Plus précisément, le champ RSTTIME1 permet d'ajuster ce temporisateur.

Une validation initiale peut être effectuée dans l'environnement U-Boot en écrasant la valeur du registre PRM_RSTTIME (adresse 0x44E00F04) :

U-Boot# md.l 0x44E00F04 1
44e00f04: 00001fff
U-Boot# mw.l 0x44E00F04 0x0000FFFF
U-Boot# md.l 0x44E00F04 1
44e00f04: 0000ffff
U-Boot# reset

Bien que cette configuration étende l'impulsion à environ 12 µs (ce qui reste en dessous des 100 µs théoriques), elle s'avère suffisante pour rétablir le comportement correct des LED.

Cependant, appliquer cette modification directement dans le noyau Linux échoue. L'analyse du flux de redémarrage montre que la fonction de réinitialisation déclenche par défaut une réinitialisation à froid (RST_GLOBAL_COLD_SW). Ce type de reset restaure tous les registres PRCM à leurs valeurs par défaut, annulant ainsi notre configuration de PRM_RSTTIME.

La solution logicière consiste à forcer une réinitialisation à chaud (RST_GLOBAL_WARM_SW), qui préserve la configuration de notre registre de temporisation.

Refonte du Code Noyau

Voici une version restructurée de la fonction de réenitialisation dans le fichier arch/arm/mach-omap2/prcm.c, intégrant la correction pour les architectures AM33xx :

/* Pointeur de fonction pour le gestionnaire de réinitialisation spécifique à l'architecture */
void (*arch_reset_handler)(char mode, const char *boot_cmd) = omap_prcm_execute_reset;

static void omap_prcm_execute_reset(char reset_mode, const char *boot_cmd)
{
    int16_t module_offset = 0;

    if (cpu_is_omap24xx()) {
        omap2xxx_clk_prepare_for_reboot();
        module_offset = WKUP_MOD;
    } 
    else if (cpu_is_am33xx()) {
        module_offset = AM33XX_PRM_DEVICE_MOD;

        /* 
         * Étendre la durée de l'impulsion de reset en maximisant le champ RSTTIME1.
         * Cela garantit que la PHY reçoit un signal bas suffisamment long.
         */
        omap2_prm_set_mod_reg_bits(0xFF, module_offset, AM33XX_PRM_RSTTIME_OFFSET);

        /* 
         * Déclencher une réinitialisation à chaud au lieu d'une réinitialisation à froid.
         * Une réinitialisation à chaud préserve la configuration de PRM_RSTTIME,
         * tandis qu'une réinitialisation à froid la réinitialiserait aux valeurs par défaut.
         */
        omap2_prm_set_mod_reg_bits(OMAP4430_RST_GLOBAL_WARM_SW_MASK, 
                                   module_offset, 
                                   AM33XX_PRM_RSTCTRL_OFFSET);
    } 
    else if (cpu_is_omap34xx()) {
        module_offset = OMAP3430_GR_MOD;
        omap3_ctrl_write_boot_mode((boot_cmd ? (uint8_t)*boot_cmd : 0));
    } 
    else if (cpu_is_omap44xx()) {
        omap4_prminst_global_warm_sw_reset();
    } 
    else {
        WARN_ON(1);
    }
}

Solutions Matérielles et Alternatives à Long Terme

Bien que la modification logicielle du registre PRCM résolve le problème, elle reste une solution de contournement. Pour une intégration robuste, les approches suivantes sont recommandées :

  • Utiliser une broche GPIO standard pour piloter directement la broche de reset de la PHY, en s'assurant que le GPIO est maintenu à l'état bas lors de la séquence de reboot.
  • Connecter la broche nRST de la PHY directement à la tension d'alimentation (pull-up), en omettant volontairement le reset matériel lors des redémarrages logiciels.
  • Revoir la conception du schéma matériel pour ajouter un circuit de temporisation (ex: circuit RC ou générateur de reset dédié) garantissant un pulse de reset conforme aux spécifications de la PHY.

Étiquettes: am335x linux-kernel ethernet-phy u-boot embedded-linux

Publié le 26 juin à 20h21