1 /* 2 * (C) Copyright 2000-2003 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <status_led.h> 10 11 /* 12 * The purpose of this code is to signal the operational status of a 13 * target which usually boots over the network; while running in 14 * U-Boot, a status LED is blinking. As soon as a valid BOOTP reply 15 * message has been received, the LED is turned off. The Linux 16 * kernel, once it is running, will start blinking the LED again, 17 * with another frequency. 18 */ 19 20 /* ------------------------------------------------------------------------- */ 21 22 typedef struct { 23 led_id_t mask; 24 int state; 25 int period; 26 int cnt; 27 } led_dev_t; 28 29 led_dev_t led_dev[] = { 30 { STATUS_LED_BIT, 31 STATUS_LED_STATE, 32 STATUS_LED_PERIOD, 33 0, 34 }, 35 #if defined(STATUS_LED_BIT1) 36 { STATUS_LED_BIT1, 37 STATUS_LED_STATE1, 38 STATUS_LED_PERIOD1, 39 0, 40 }, 41 #endif 42 #if defined(STATUS_LED_BIT2) 43 { STATUS_LED_BIT2, 44 STATUS_LED_STATE2, 45 STATUS_LED_PERIOD2, 46 0, 47 }, 48 #endif 49 #if defined(STATUS_LED_BIT3) 50 { STATUS_LED_BIT3, 51 STATUS_LED_STATE3, 52 STATUS_LED_PERIOD3, 53 0, 54 }, 55 #endif 56 #if defined(STATUS_LED_BIT4) 57 { STATUS_LED_BIT4, 58 STATUS_LED_STATE4, 59 STATUS_LED_PERIOD4, 60 0, 61 }, 62 #endif 63 #if defined(STATUS_LED_BIT5) 64 { STATUS_LED_BIT5, 65 STATUS_LED_STATE5, 66 STATUS_LED_PERIOD5, 67 0, 68 }, 69 #endif 70 }; 71 72 #define MAX_LED_DEV (sizeof(led_dev)/sizeof(led_dev_t)) 73 74 static int status_led_init_done = 0; 75 76 static void status_led_init (void) 77 { 78 led_dev_t *ld; 79 int i; 80 81 for (i = 0, ld = led_dev; i < MAX_LED_DEV; i++, ld++) 82 __led_init (ld->mask, ld->state); 83 status_led_init_done = 1; 84 } 85 86 void status_led_tick (ulong timestamp) 87 { 88 led_dev_t *ld; 89 int i; 90 91 if (!status_led_init_done) 92 status_led_init (); 93 94 for (i = 0, ld = led_dev; i < MAX_LED_DEV; i++, ld++) { 95 96 if (ld->state != STATUS_LED_BLINKING) 97 continue; 98 99 if (++ld->cnt >= ld->period) { 100 __led_toggle (ld->mask); 101 ld->cnt -= ld->period; 102 } 103 104 } 105 } 106 107 void status_led_set (int led, int state) 108 { 109 led_dev_t *ld; 110 111 if (led < 0 || led >= MAX_LED_DEV) 112 return; 113 114 if (!status_led_init_done) 115 status_led_init (); 116 117 ld = &led_dev[led]; 118 119 ld->state = state; 120 if (state == STATUS_LED_BLINKING) { 121 ld->cnt = 0; /* always start with full period */ 122 state = STATUS_LED_ON; /* always start with LED _ON_ */ 123 } 124 __led_set (ld->mask, state); 125 } 126