Aubrey Li | 26bf7de | 2007-03-19 01:24:52 +0800 | [diff] [blame] | 1 | /* |
| 2 | * U-boot - cmd_bf537led.c |
| 3 | * |
| 4 | * Copyright (C) 2006 Aaron Gage, Ocean Optics Inc. |
| 5 | * |
| 6 | * See file CREDITS for list of people who contributed to this |
| 7 | * project. |
| 8 | * |
| 9 | * This program is free software; you can redistribute it and/or |
| 10 | * modify it under the terms of the GNU General Public License as |
| 11 | * published by the Free Software Foundation; either version 2 of |
| 12 | * the License, or (at your option) any later version. |
| 13 | * |
| 14 | * This program is distributed in the hope that it will be useful, |
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 17 | * GNU General Public License for more details. |
| 18 | * |
| 19 | * You should have received a copy of the GNU General Public License |
| 20 | * along with this program; if not, write to the Free Software |
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
| 22 | * MA 02111-1307 USA |
| 23 | */ |
| 24 | #include <common.h> |
| 25 | #include <config.h> |
| 26 | #include <command.h> |
| 27 | #include <asm/blackfin.h> |
| 28 | #include <asm-blackfin/string.h> |
| 29 | #ifdef CONFIG_BF537_STAMP_LEDCMD |
| 30 | |
| 31 | /* Define the command usage in a reusable way */ |
| 32 | #define USAGE_LONG \ |
| 33 | "led <number> <action>\n" \ |
| 34 | " <number> - Index (0-5) of LED to change, or \"all\"\n" \ |
| 35 | " <action> - Must be one of:\n" \ |
Wolfgang Denk | a89c33d | 2009-05-24 17:06:54 +0200 | [diff] [blame] | 36 | " on off toggle" |
Aubrey Li | 26bf7de | 2007-03-19 01:24:52 +0800 | [diff] [blame] | 37 | |
| 38 | /* Number of LEDs supported by the board */ |
| 39 | #define NUMBER_LEDS 6 |
| 40 | /* The BF537 stamp has 6 LEDs. This mask indicates that all should be lit. */ |
| 41 | #define LED_ALL_MASK 0x003F |
| 42 | |
| 43 | void show_cmd_usage(void); |
| 44 | void set_led_state(int index, int state); |
| 45 | void configure_GPIO_to_output(int index); |
| 46 | |
| 47 | /* Map of LEDs according to their GPIO ports. This can be rearranged or |
| 48 | * otherwise changed to account for different GPIO configurations. |
| 49 | */ |
| 50 | int led_ports[] = { PF6, PF7, PF8, PF9, PF10, PF11 }; |
| 51 | |
| 52 | #define ACTION_TOGGLE -1 |
| 53 | #define ACTION_OFF 0 |
| 54 | #define ACTION_ON 1 |
| 55 | |
| 56 | #define LED_STATE_OFF 0 |
| 57 | #define LED_STATE_ON 1 |
| 58 | |
| 59 | /* This is a trivial atoi implementation since we don't have one available */ |
| 60 | int atoi(char *string) |
| 61 | { |
| 62 | int length; |
| 63 | int retval = 0; |
| 64 | int i; |
| 65 | int sign = 1; |
| 66 | |
| 67 | length = strlen(string); |
| 68 | for (i = 0; i < length; i++) { |
| 69 | if (0 == i && string[0] == '-') { |
| 70 | sign = -1; |
| 71 | continue; |
| 72 | } |
| 73 | if (string[i] > '9' || string[i] < '0') { |
| 74 | break; |
| 75 | } |
| 76 | retval *= 10; |
| 77 | retval += string[i] - '0'; |
| 78 | } |
| 79 | retval *= sign; |
| 80 | return retval; |
| 81 | } |
| 82 | |
| 83 | int do_bf537led(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) |
| 84 | { |
| 85 | int led_mask = 0; |
| 86 | int led_current_state = 0; |
| 87 | int action = ACTION_OFF; |
| 88 | int temp; |
| 89 | |
| 90 | if (3 != argc) { |
| 91 | /* Not enough arguments, so just show usage information */ |
| 92 | show_cmd_usage(); |
| 93 | return 1; |
| 94 | } |
| 95 | |
| 96 | if (strcmp(argv[1], "all") == 0) { |
| 97 | led_mask = LED_ALL_MASK; |
| 98 | } else { |
| 99 | temp = atoi(argv[1]); |
| 100 | if (temp < 0 || temp >= NUMBER_LEDS) { |
| 101 | printf("Invalid LED number [%s]\n", argv[1]); |
| 102 | show_cmd_usage(); |
| 103 | return 2; |
| 104 | } |
| 105 | led_mask |= (1 << temp); |
| 106 | } |
| 107 | |
| 108 | if (strcmp(argv[2], "off") == 0) { |
| 109 | action = ACTION_OFF; |
| 110 | } else if (strcmp(argv[2], "on") == 0) { |
| 111 | action = ACTION_ON; |
| 112 | } else if (strcmp(argv[2], "toggle") == 0) { |
| 113 | action = ACTION_TOGGLE; |
| 114 | } else { |
| 115 | printf("Invalid action [%s]\n", argv[2]); |
| 116 | show_cmd_usage(); |
| 117 | return 3; |
| 118 | } |
| 119 | |
| 120 | for (temp = 0; temp < NUMBER_LEDS; temp++) { |
| 121 | if ((led_mask & (1 << temp)) > 0) { |
| 122 | /* |
| 123 | * It is possible that the user has wired one of PF6-PF11 to |
| 124 | * something other than an LED, so this will only change a pin |
| 125 | * to output if the user has indicated a state change. This may |
| 126 | * happen a lot, but this way is safer than just setting all pins |
| 127 | * to output. |
| 128 | */ |
| 129 | configure_GPIO_to_output(temp); |
| 130 | |
| 131 | led_current_state = |
| 132 | ((*pPORTFIO & led_ports[temp]) > |
| 133 | 0) ? LED_STATE_ON : LED_STATE_OFF; |
| 134 | /* |
| 135 | printf("LED state for index %d (%x) is %d\n", temp, led_ports[temp], |
| 136 | led_current_state); |
| 137 | printf("*pPORTFIO is %x\n", *pPORTFIO); |
| 138 | */ |
| 139 | if (ACTION_ON == action |
| 140 | || (ACTION_TOGGLE == action |
| 141 | && 0 == led_current_state)) { |
| 142 | printf("Turning LED %d on\n", temp); |
| 143 | set_led_state(temp, LED_STATE_ON); |
| 144 | } else { |
| 145 | printf("Turning LED %d off\n", temp); |
| 146 | set_led_state(temp, LED_STATE_OFF); |
| 147 | } |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | return 0; |
| 152 | } |
| 153 | |
| 154 | /* |
| 155 | * The GPIO pins that go to the LEDs on the BF537 stamp must be configured |
| 156 | * as output. This function simply configures them that way. This could |
| 157 | * be done to all of the GPIO lines at once, but if a user is using a |
| 158 | * custom board, this will try to be nice and only change the GPIO lines |
| 159 | * that the user specifically names. |
| 160 | */ |
| 161 | void configure_GPIO_to_output(int index) |
| 162 | { |
| 163 | int port; |
| 164 | |
| 165 | port = led_ports[index]; |
| 166 | |
| 167 | /* Clear the Port F Function Enable Register */ |
| 168 | *pPORTF_FER &= ~port; |
| 169 | /* Set the Port F I/O direction register */ |
| 170 | *pPORTFIO_DIR |= port; |
| 171 | /* Clear the Port F I/O Input Enable Register */ |
| 172 | *pPORTFIO_INEN &= ~port; |
| 173 | } |
| 174 | |
| 175 | /* Enforce the given state on the GPIO line for the indicated LED */ |
| 176 | void set_led_state(int index, int state) |
| 177 | { |
| 178 | int port; |
| 179 | |
| 180 | port = led_ports[index]; |
| 181 | |
| 182 | if (LED_STATE_OFF == state) { |
| 183 | /* Clear the bit to turn off the LED */ |
| 184 | *pPORTFIO &= ~port; |
| 185 | } else { |
| 186 | /* Set the bit to turn on the LED */ |
| 187 | *pPORTFIO |= port; |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | /* Display usage information */ |
| 192 | void show_cmd_usage() |
| 193 | { |
Wolfgang Denk | a89c33d | 2009-05-24 17:06:54 +0200 | [diff] [blame] | 194 | printf("Usage:\n%s\n", USAGE_LONG); |
Aubrey Li | 26bf7de | 2007-03-19 01:24:52 +0800 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | /* Register information for u-boot to find this command */ |
| 198 | U_BOOT_CMD(led, 3, 1, do_bf537led, |
Peter Tyser | 2fb2604 | 2009-01-27 18:03:12 -0600 | [diff] [blame] | 199 | "Control BF537 stamp LEDs", USAGE_LONG); |
Aubrey Li | 26bf7de | 2007-03-19 01:24:52 +0800 | [diff] [blame] | 200 | |
| 201 | #endif |