1*ffe2052dSSimon Glass /* 2*ffe2052dSSimon Glass * Copyright (c) 2017 Google, Inc 3*ffe2052dSSimon Glass * Written by Simon Glass <sjg@chromium.org> 4*ffe2052dSSimon Glass * 5*ffe2052dSSimon Glass * SPDX-License-Identifier: GPL-2.0+ 6*ffe2052dSSimon Glass */ 7*ffe2052dSSimon Glass 8*ffe2052dSSimon Glass #include <common.h> 9*ffe2052dSSimon Glass #include <command.h> 10*ffe2052dSSimon Glass #include <dm.h> 11*ffe2052dSSimon Glass #include <led.h> 12*ffe2052dSSimon Glass #include <dm/uclass-internal.h> 13*ffe2052dSSimon Glass 14*ffe2052dSSimon Glass #define LED_TOGGLE LEDST_COUNT 15*ffe2052dSSimon Glass 16*ffe2052dSSimon Glass static const char *const state_label[] = { 17*ffe2052dSSimon Glass [LEDST_OFF] = "off", 18*ffe2052dSSimon Glass [LEDST_ON] = "on", 19*ffe2052dSSimon Glass [LEDST_TOGGLE] = "toggle", 20*ffe2052dSSimon Glass #ifdef CONFIG_LED_BLINK 21*ffe2052dSSimon Glass [LEDST_BLINK] = "blink", 22*ffe2052dSSimon Glass #endif 23*ffe2052dSSimon Glass }; 24*ffe2052dSSimon Glass 25*ffe2052dSSimon Glass enum led_state_t get_led_cmd(char *var) 26*ffe2052dSSimon Glass { 27*ffe2052dSSimon Glass int i; 28*ffe2052dSSimon Glass 29*ffe2052dSSimon Glass for (i = 0; i < LEDST_COUNT; i++) { 30*ffe2052dSSimon Glass if (!strncmp(var, state_label[i], strlen(var))) 31*ffe2052dSSimon Glass return i; 32*ffe2052dSSimon Glass } 33*ffe2052dSSimon Glass 34*ffe2052dSSimon Glass return -1; 35*ffe2052dSSimon Glass } 36*ffe2052dSSimon Glass 37*ffe2052dSSimon Glass static int show_led_state(struct udevice *dev) 38*ffe2052dSSimon Glass { 39*ffe2052dSSimon Glass int ret; 40*ffe2052dSSimon Glass 41*ffe2052dSSimon Glass ret = led_get_state(dev); 42*ffe2052dSSimon Glass if (ret >= LEDST_COUNT) 43*ffe2052dSSimon Glass ret = -EINVAL; 44*ffe2052dSSimon Glass if (ret >= 0) 45*ffe2052dSSimon Glass printf("%s\n", state_label[ret]); 46*ffe2052dSSimon Glass 47*ffe2052dSSimon Glass return ret; 48*ffe2052dSSimon Glass } 49*ffe2052dSSimon Glass 50*ffe2052dSSimon Glass static int list_leds(void) 51*ffe2052dSSimon Glass { 52*ffe2052dSSimon Glass struct udevice *dev; 53*ffe2052dSSimon Glass int ret; 54*ffe2052dSSimon Glass 55*ffe2052dSSimon Glass for (uclass_find_first_device(UCLASS_LED, &dev); 56*ffe2052dSSimon Glass dev; 57*ffe2052dSSimon Glass uclass_find_next_device(&dev)) { 58*ffe2052dSSimon Glass struct led_uc_plat *plat = dev_get_uclass_platdata(dev); 59*ffe2052dSSimon Glass 60*ffe2052dSSimon Glass if (!plat->label) 61*ffe2052dSSimon Glass continue; 62*ffe2052dSSimon Glass printf("%-15s ", plat->label); 63*ffe2052dSSimon Glass if (device_active(dev)) { 64*ffe2052dSSimon Glass ret = show_led_state(dev); 65*ffe2052dSSimon Glass if (ret < 0) 66*ffe2052dSSimon Glass printf("Error %d\n", ret); 67*ffe2052dSSimon Glass } else { 68*ffe2052dSSimon Glass printf("<inactive>\n"); 69*ffe2052dSSimon Glass } 70*ffe2052dSSimon Glass } 71*ffe2052dSSimon Glass 72*ffe2052dSSimon Glass return 0; 73*ffe2052dSSimon Glass } 74*ffe2052dSSimon Glass 75*ffe2052dSSimon Glass int do_led(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 76*ffe2052dSSimon Glass { 77*ffe2052dSSimon Glass enum led_state_t cmd; 78*ffe2052dSSimon Glass const char *led_label; 79*ffe2052dSSimon Glass struct udevice *dev; 80*ffe2052dSSimon Glass #ifdef CONFIG_LED_BLINK 81*ffe2052dSSimon Glass int freq_ms = 0; 82*ffe2052dSSimon Glass #endif 83*ffe2052dSSimon Glass int ret; 84*ffe2052dSSimon Glass 85*ffe2052dSSimon Glass /* Validate arguments */ 86*ffe2052dSSimon Glass if (argc < 2) 87*ffe2052dSSimon Glass return CMD_RET_USAGE; 88*ffe2052dSSimon Glass led_label = argv[1]; 89*ffe2052dSSimon Glass if (*led_label == 'l') 90*ffe2052dSSimon Glass return list_leds(); 91*ffe2052dSSimon Glass 92*ffe2052dSSimon Glass cmd = argc > 2 ? get_led_cmd(argv[2]) : LEDST_COUNT; 93*ffe2052dSSimon Glass if (cmd < 0) 94*ffe2052dSSimon Glass return CMD_RET_USAGE; 95*ffe2052dSSimon Glass #ifdef CONFIG_LED_BLINK 96*ffe2052dSSimon Glass if (cmd == LEDST_BLINK) { 97*ffe2052dSSimon Glass if (argc < 4) 98*ffe2052dSSimon Glass return CMD_RET_USAGE; 99*ffe2052dSSimon Glass freq_ms = simple_strtoul(argv[3], NULL, 10); 100*ffe2052dSSimon Glass } 101*ffe2052dSSimon Glass #endif 102*ffe2052dSSimon Glass ret = led_get_by_label(led_label, &dev); 103*ffe2052dSSimon Glass if (ret) { 104*ffe2052dSSimon Glass printf("LED '%s' not found (err=%d)\n", led_label, ret); 105*ffe2052dSSimon Glass return CMD_RET_FAILURE; 106*ffe2052dSSimon Glass } 107*ffe2052dSSimon Glass switch (cmd) { 108*ffe2052dSSimon Glass case LEDST_OFF: 109*ffe2052dSSimon Glass case LEDST_ON: 110*ffe2052dSSimon Glass case LEDST_TOGGLE: 111*ffe2052dSSimon Glass ret = led_set_state(dev, cmd); 112*ffe2052dSSimon Glass break; 113*ffe2052dSSimon Glass #ifdef CONFIG_LED_BLINK 114*ffe2052dSSimon Glass case LEDST_BLINK: 115*ffe2052dSSimon Glass ret = led_set_period(dev, freq_ms); 116*ffe2052dSSimon Glass if (!ret) 117*ffe2052dSSimon Glass ret = led_set_state(dev, LEDST_BLINK); 118*ffe2052dSSimon Glass break; 119*ffe2052dSSimon Glass #endif 120*ffe2052dSSimon Glass case LEDST_COUNT: 121*ffe2052dSSimon Glass printf("LED '%s': ", led_label); 122*ffe2052dSSimon Glass ret = show_led_state(dev); 123*ffe2052dSSimon Glass break; 124*ffe2052dSSimon Glass } 125*ffe2052dSSimon Glass if (ret < 0) { 126*ffe2052dSSimon Glass printf("LED '%s' operation failed (err=%d)\n", led_label, ret); 127*ffe2052dSSimon Glass return CMD_RET_FAILURE; 128*ffe2052dSSimon Glass } 129*ffe2052dSSimon Glass 130*ffe2052dSSimon Glass return 0; 131*ffe2052dSSimon Glass } 132*ffe2052dSSimon Glass 133*ffe2052dSSimon Glass #ifdef CONFIG_LED_BLINK 134*ffe2052dSSimon Glass #define BLINK "|blink [blink-freq in ms]" 135*ffe2052dSSimon Glass #else 136*ffe2052dSSimon Glass #define BLINK "" 137*ffe2052dSSimon Glass #endif 138*ffe2052dSSimon Glass 139*ffe2052dSSimon Glass U_BOOT_CMD( 140*ffe2052dSSimon Glass led, 4, 1, do_led, 141*ffe2052dSSimon Glass "manage LEDs", 142*ffe2052dSSimon Glass "<led_label> on|off|toggle" BLINK "\tChange LED state\n" 143*ffe2052dSSimon Glass "led [<led_label>\tGet LED state\n" 144*ffe2052dSSimon Glass "led list\t\tshow a list of LEDs" 145*ffe2052dSSimon Glass ); 146