1 /* 2 * Copyright (c) 2012 Michael Walle 3 * Michael Walle <michael@walle.cc> 4 * 5 * Based on sheevaplug/sheevaplug.c by 6 * Marvell Semiconductor <www.marvell.com> 7 * 8 * See file CREDITS for list of people who contributed to this 9 * project. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 24 * MA 02110-1301 USA 25 */ 26 27 #include <common.h> 28 #include <net.h> 29 #include <malloc.h> 30 #include <netdev.h> 31 #include <miiphy.h> 32 #include <asm/arch/kirkwood.h> 33 #include <asm/arch/cpu.h> 34 #include <asm/arch/mpp.h> 35 #include <asm/arch/gpio.h> 36 #include <spi_flash.h> 37 38 #include "lsxl.h" 39 40 /* 41 * Rescue mode 42 * 43 * Selected by holding the push button for 3 seconds, while powering on 44 * the device. 45 * 46 * These linkstations don't have a (populated) serial port. There is no 47 * way to access an (unmodified) board other than using the netconsole. If 48 * you want to recover from a bad environment setting or an empty environment, 49 * you can do this only with a working network connection. Therefore, a random 50 * ethernet address is generated if none is set and a DHCP request is sent. 51 * After a successful DHCP response is received, the network settings are 52 * configured and the ncip is unset. Therefore, all netconsole packets are 53 * broadcasted. 54 * Additionally, the bootsource is set to 'rescue'. 55 */ 56 57 #ifndef CONFIG_ENV_OVERWRITE 58 # error "You need to set CONFIG_ENV_OVERWRITE" 59 #endif 60 61 DECLARE_GLOBAL_DATA_PTR; 62 63 int board_early_init_f(void) 64 { 65 /* 66 * default gpio configuration 67 * There are maximum 64 gpios controlled through 2 sets of registers 68 * the below configuration configures mainly initial LED status 69 */ 70 kw_config_gpio(LSXL_OE_VAL_LOW, 71 LSXL_OE_VAL_HIGH, 72 LSXL_OE_LOW, LSXL_OE_HIGH); 73 74 /* 75 * Multi-Purpose Pins Functionality configuration 76 * These strappings are taken from the original vendor uboot port. 77 */ 78 static const u32 kwmpp_config[] = { 79 MPP0_SPI_SCn, 80 MPP1_SPI_MOSI, 81 MPP2_SPI_SCK, 82 MPP3_SPI_MISO, 83 MPP4_UART0_RXD, 84 MPP5_UART0_TXD, 85 MPP6_SYSRST_OUTn, 86 MPP7_GPO, 87 MPP8_GPIO, 88 MPP9_GPIO, 89 MPP10_GPO, /* HDD power */ 90 MPP11_GPIO, /* USB Vbus enable */ 91 MPP12_SD_CLK, 92 MPP13_SD_CMD, 93 MPP14_SD_D0, 94 MPP15_SD_D1, 95 MPP16_SD_D2, 96 MPP17_SD_D3, 97 MPP18_GPO, /* fan speed high */ 98 MPP19_GPO, /* fan speed low */ 99 MPP20_GE1_0, 100 MPP21_GE1_1, 101 MPP22_GE1_2, 102 MPP23_GE1_3, 103 MPP24_GE1_4, 104 MPP25_GE1_5, 105 MPP26_GE1_6, 106 MPP27_GE1_7, 107 MPP28_GPIO, 108 MPP29_GPIO, 109 MPP30_GE1_10, 110 MPP31_GE1_11, 111 MPP32_GE1_12, 112 MPP33_GE1_13, 113 MPP34_GPIO, 114 MPP35_GPIO, 115 MPP36_GPIO, /* function LED */ 116 MPP37_GPIO, /* alarm LED */ 117 MPP38_GPIO, /* info LED */ 118 MPP39_GPIO, /* power LED */ 119 MPP40_GPIO, /* fan alarm */ 120 MPP41_GPIO, /* funtion button */ 121 MPP42_GPIO, /* power switch */ 122 MPP43_GPIO, /* power auto switch */ 123 MPP44_GPIO, 124 MPP45_GPIO, 125 MPP46_GPIO, 126 MPP47_GPIO, 127 MPP48_GPIO, /* function red LED */ 128 MPP49_GPIO, 129 0 130 }; 131 132 kirkwood_mpp_conf(kwmpp_config, NULL); 133 134 return 0; 135 } 136 137 #define LED_OFF 0 138 #define LED_ALARM_ON 1 139 #define LED_ALARM_BLINKING 2 140 #define LED_POWER_ON 3 141 #define LED_POWER_BLINKING 4 142 #define LED_INFO_ON 5 143 #define LED_INFO_BLINKING 6 144 145 static void __set_led(int blink_alarm, int blink_info, int blink_power, 146 int value_alarm, int value_info, int value_power) 147 { 148 kw_gpio_set_blink(GPIO_ALARM_LED, blink_alarm); 149 kw_gpio_set_blink(GPIO_INFO_LED, blink_info); 150 kw_gpio_set_blink(GPIO_POWER_LED, blink_power); 151 kw_gpio_set_value(GPIO_ALARM_LED, value_alarm); 152 kw_gpio_set_value(GPIO_INFO_LED, value_info); 153 kw_gpio_set_value(GPIO_POWER_LED, value_power); 154 } 155 156 static void set_led(int state) 157 { 158 switch (state) { 159 case LED_OFF: 160 __set_led(0, 0, 0, 1, 1, 1); 161 break; 162 case LED_ALARM_ON: 163 __set_led(0, 0, 0, 0, 1, 1); 164 break; 165 case LED_ALARM_BLINKING: 166 __set_led(1, 0, 0, 1, 1, 1); 167 break; 168 case LED_INFO_ON: 169 __set_led(0, 0, 0, 1, 0, 1); 170 break; 171 case LED_INFO_BLINKING: 172 __set_led(0, 1, 0, 1, 1, 1); 173 break; 174 case LED_POWER_ON: 175 __set_led(0, 0, 0, 1, 1, 0); 176 break; 177 case LED_POWER_BLINKING: 178 __set_led(0, 0, 1, 1, 1, 1); 179 break; 180 } 181 } 182 183 int board_init(void) 184 { 185 /* address of boot parameters */ 186 gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100; 187 188 set_led(LED_POWER_BLINKING); 189 190 return 0; 191 } 192 193 #ifdef CONFIG_MISC_INIT_R 194 static void check_power_switch(void) 195 { 196 if (kw_gpio_get_value(GPIO_POWER_SWITCH)) { 197 /* turn off fan, HDD and USB power */ 198 kw_gpio_set_value(GPIO_HDD_POWER, 0); 199 kw_gpio_set_value(GPIO_USB_VBUS, 0); 200 kw_gpio_set_value(GPIO_FAN_HIGH, 1); 201 kw_gpio_set_value(GPIO_FAN_LOW, 1); 202 set_led(LED_OFF); 203 204 /* loop until released */ 205 while (kw_gpio_get_value(GPIO_POWER_SWITCH)) 206 ; 207 208 /* turn power on again */ 209 kw_gpio_set_value(GPIO_HDD_POWER, 1); 210 kw_gpio_set_value(GPIO_USB_VBUS, 1); 211 kw_gpio_set_value(GPIO_FAN_HIGH, 0); 212 kw_gpio_set_value(GPIO_FAN_LOW, 0); 213 set_led(LED_POWER_BLINKING); 214 } 215 } 216 217 void check_enetaddr(void) 218 { 219 uchar enetaddr[6]; 220 221 if (!eth_getenv_enetaddr("ethaddr", enetaddr)) { 222 /* signal unset/invalid ethaddr to user */ 223 set_led(LED_INFO_BLINKING); 224 } 225 } 226 227 static void erase_environment(void) 228 { 229 struct spi_flash *flash; 230 231 printf("Erasing environment..\n"); 232 flash = spi_flash_probe(0, 0, 1000000, SPI_MODE_3); 233 if (!flash) { 234 printf("Erasing flash failed\n"); 235 return; 236 } 237 238 spi_flash_erase(flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE); 239 spi_flash_free(flash); 240 do_reset(NULL, 0, 0, NULL); 241 } 242 243 static void rescue_mode(void) 244 { 245 uchar enetaddr[6]; 246 247 printf("Entering rescue mode..\n"); 248 #ifdef CONFIG_RANDOM_MACADDR 249 if (!eth_getenv_enetaddr("ethaddr", enetaddr)) { 250 eth_random_enetaddr(enetaddr); 251 if (eth_setenv_enetaddr("ethaddr", enetaddr)) { 252 printf("Failed to set ethernet address\n"); 253 set_led(LED_ALARM_BLINKING); 254 return; 255 } 256 } 257 #endif 258 setenv("bootsource", "rescue"); 259 } 260 261 static void check_push_button(void) 262 { 263 int i = 0; 264 265 while (!kw_gpio_get_value(GPIO_FUNC_BUTTON)) { 266 udelay(100000); 267 i++; 268 269 if (i == 10) 270 set_led(LED_INFO_ON); 271 272 if (i >= 100) { 273 set_led(LED_INFO_BLINKING); 274 break; 275 } 276 } 277 278 if (i >= 100) 279 erase_environment(); 280 else if (i >= 10) 281 rescue_mode(); 282 } 283 284 int misc_init_r(void) 285 { 286 check_power_switch(); 287 check_enetaddr(); 288 check_push_button(); 289 290 return 0; 291 } 292 #endif 293 294 #ifdef CONFIG_SHOW_BOOT_PROGRESS 295 void show_boot_progress(int progress) 296 { 297 if (progress > 0) 298 return; 299 300 /* this is not an error, eg. bootp with autoload=no will trigger this */ 301 if (progress == -BOOTSTAGE_ID_NET_LOADED) 302 return; 303 304 set_led(LED_ALARM_BLINKING); 305 } 306 #endif 307