1 /* 2 * Bluewater Systems Snapper 9260/9G20 modules 3 * 4 * (C) Copyright 2011 Bluewater Systems 5 * Author: Andre Renaud <andre@bluewatersys.com> 6 * Author: Ryan Mallon <ryan@bluewatersys.com> 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11 #include <common.h> 12 #include <atmel_lcd.h> 13 #include <atmel_lcdc.h> 14 #include <atmel_mci.h> 15 #include <dm.h> 16 #include <lcd.h> 17 #include <net.h> 18 #ifndef CONFIG_DM_ETH 19 #include <netdev.h> 20 #endif 21 #include <spi.h> 22 #include <asm/gpio.h> 23 #include <asm/io.h> 24 #include <asm/arch/at91sam9g45_matrix.h> 25 #include <asm/arch/at91sam9_smc.h> 26 #include <asm/arch/at91_common.h> 27 #include <asm/arch/at91_emac.h> 28 #include <asm/arch/at91_rstc.h> 29 #include <asm/arch/at91_rtc.h> 30 #include <asm/arch/at91_sck.h> 31 #include <asm/arch/atmel_serial.h> 32 #include <asm/arch/clk.h> 33 #include <asm/arch/gpio.h> 34 #include <dm/uclass-internal.h> 35 36 #ifdef CONFIG_GURNARD_SPLASH 37 #include "splash_logo.h" 38 #endif 39 40 DECLARE_GLOBAL_DATA_PTR; 41 42 /* IO Expander pins */ 43 #define IO_EXP_ETH_RESET (0 << 1) 44 #define IO_EXP_ETH_POWER (1 << 1) 45 46 #ifdef CONFIG_MACB 47 static void gurnard_macb_hw_init(void) 48 { 49 struct at91_port *pioa = (struct at91_port *)ATMEL_BASE_PIOA; 50 51 at91_periph_clk_enable(ATMEL_ID_EMAC); 52 53 /* 54 * Enable pull-up on: 55 * RXDV (PA12) => MODE0 - PHY also has pull-up 56 * ERX0 (PA13) => MODE1 - PHY also has pull-up 57 * ERX1 (PA15) => MODE2 - PHY also has pull-up 58 */ 59 writel(pin_to_mask(AT91_PIN_PA15) | 60 pin_to_mask(AT91_PIN_PA12) | 61 pin_to_mask(AT91_PIN_PA13), 62 &pioa->puer); 63 64 at91_phy_reset(); 65 66 at91_macb_hw_init(); 67 } 68 #endif 69 70 #ifdef CONFIG_CMD_NAND 71 static int gurnard_nand_hw_init(void) 72 { 73 struct at91_matrix *matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX; 74 struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC; 75 ulong flags; 76 int ret; 77 78 /* Enable CS3 as NAND/SmartMedia */ 79 setbits_le32(&matrix->ebicsa, AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA); 80 81 /* Configure SMC CS3 for NAND/SmartMedia */ 82 writel(AT91_SMC_SETUP_NWE(2) | AT91_SMC_SETUP_NCS_WR(0) | 83 AT91_SMC_SETUP_NRD(2) | AT91_SMC_SETUP_NCS_RD(0), 84 &smc->cs[3].setup); 85 writel(AT91_SMC_PULSE_NWE(4) | AT91_SMC_PULSE_NCS_WR(4) | 86 AT91_SMC_PULSE_NRD(4) | AT91_SMC_PULSE_NCS_RD(4), 87 &smc->cs[3].pulse); 88 writel(AT91_SMC_CYCLE_NWE(7) | AT91_SMC_CYCLE_NRD(7), 89 &smc->cs[3].cycle); 90 #ifdef CONFIG_SYS_NAND_DBW_16 91 flags = AT91_SMC_MODE_DBW_16; 92 #else 93 flags = AT91_SMC_MODE_DBW_8; 94 #endif 95 writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE | 96 AT91_SMC_MODE_EXNW_DISABLE | 97 flags | 98 AT91_SMC_MODE_TDF_CYCLE(3), 99 &smc->cs[3].mode); 100 101 ret = gpio_request(CONFIG_SYS_NAND_READY_PIN, "nand_rdy"); 102 if (ret) 103 return ret; 104 gpio_direction_input(CONFIG_SYS_NAND_READY_PIN); 105 106 /* Enable NandFlash */ 107 ret = gpio_request(CONFIG_SYS_NAND_ENABLE_PIN, "nand_ce"); 108 if (ret) 109 return ret; 110 gpio_direction_output(CONFIG_SYS_NAND_ENABLE_PIN, 1); 111 112 return 0; 113 } 114 #endif 115 116 #ifdef CONFIG_GURNARD_SPLASH 117 static void lcd_splash(int width, int height) 118 { 119 u16 colour; 120 int x, y; 121 u16 *base_addr = (u16 *)gd->video_bottom; 122 123 memset(base_addr, 0xff, width * height * 2); 124 /* 125 * Blit the logo to the center of the screen 126 */ 127 for (y = 0; y < BMP_LOGO_HEIGHT; y++) { 128 for (x = 0; x < BMP_LOGO_WIDTH; x++) { 129 int posx, posy; 130 colour = bmp_logo_palette[bmp_logo_bitmap[ 131 y * BMP_LOGO_WIDTH + x]]; 132 posx = x + (width - BMP_LOGO_WIDTH) / 2; 133 posy = y; 134 base_addr[posy * width + posx] = colour; 135 } 136 } 137 } 138 #endif 139 140 #ifdef CONFIG_DM_VIDEO 141 static void at91sam9g45_lcd_hw_init(void) 142 { 143 at91_set_A_periph(AT91_PIN_PE0, 0); /* LCDDPWR */ 144 at91_set_A_periph(AT91_PIN_PE2, 0); /* LCDCC */ 145 at91_set_A_periph(AT91_PIN_PE3, 0); /* LCDVSYNC */ 146 at91_set_A_periph(AT91_PIN_PE4, 0); /* LCDHSYNC */ 147 at91_set_A_periph(AT91_PIN_PE5, 0); /* LCDDOTCK */ 148 149 at91_set_A_periph(AT91_PIN_PE7, 0); /* LCDD0 */ 150 at91_set_A_periph(AT91_PIN_PE8, 0); /* LCDD1 */ 151 at91_set_A_periph(AT91_PIN_PE9, 0); /* LCDD2 */ 152 at91_set_A_periph(AT91_PIN_PE10, 0); /* LCDD3 */ 153 at91_set_A_periph(AT91_PIN_PE11, 0); /* LCDD4 */ 154 at91_set_A_periph(AT91_PIN_PE12, 0); /* LCDD5 */ 155 at91_set_A_periph(AT91_PIN_PE13, 0); /* LCDD6 */ 156 at91_set_A_periph(AT91_PIN_PE14, 0); /* LCDD7 */ 157 at91_set_A_periph(AT91_PIN_PE15, 0); /* LCDD8 */ 158 at91_set_A_periph(AT91_PIN_PE16, 0); /* LCDD9 */ 159 at91_set_A_periph(AT91_PIN_PE17, 0); /* LCDD10 */ 160 at91_set_A_periph(AT91_PIN_PE18, 0); /* LCDD11 */ 161 at91_set_A_periph(AT91_PIN_PE19, 0); /* LCDD12 */ 162 at91_set_B_periph(AT91_PIN_PE20, 0); /* LCDD13 */ 163 at91_set_A_periph(AT91_PIN_PE21, 0); /* LCDD14 */ 164 at91_set_A_periph(AT91_PIN_PE22, 0); /* LCDD15 */ 165 at91_set_A_periph(AT91_PIN_PE23, 0); /* LCDD16 */ 166 at91_set_A_periph(AT91_PIN_PE24, 0); /* LCDD17 */ 167 at91_set_A_periph(AT91_PIN_PE25, 0); /* LCDD18 */ 168 at91_set_A_periph(AT91_PIN_PE26, 0); /* LCDD19 */ 169 at91_set_A_periph(AT91_PIN_PE27, 0); /* LCDD20 */ 170 at91_set_B_periph(AT91_PIN_PE28, 0); /* LCDD21 */ 171 at91_set_A_periph(AT91_PIN_PE29, 0); /* LCDD22 */ 172 at91_set_A_periph(AT91_PIN_PE30, 0); /* LCDD23 */ 173 174 at91_periph_clk_enable(ATMEL_ID_LCDC); 175 } 176 #endif 177 178 #ifdef CONFIG_GURNARD_FPGA 179 /** 180 * Initialise the memory bus settings so that we can talk to the 181 * memory mapped FPGA 182 */ 183 static int fpga_hw_init(void) 184 { 185 struct at91_matrix *matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX; 186 struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC; 187 int i; 188 189 setbits_le32(&matrix->ebicsa, AT91_MATRIX_EBI_CS1A_SDRAMC); 190 191 at91_set_a_periph(2, 4, 0); /* EBIA21 */ 192 at91_set_a_periph(2, 5, 0); /* EBIA22 */ 193 at91_set_a_periph(2, 6, 0); /* EBIA23 */ 194 at91_set_a_periph(2, 7, 0); /* EBIA24 */ 195 at91_set_a_periph(2, 12, 0); /* EBIA25 */ 196 for (i = 15; i <= 31; i++) /* EBINWAIT & EBID16 - 31 */ 197 at91_set_a_periph(2, i, 0); 198 199 /* configure SMC cs0 for FPGA access timing */ 200 writel(AT91_SMC_SETUP_NWE(1) | AT91_SMC_SETUP_NCS_WR(2) | 201 AT91_SMC_SETUP_NRD(0) | AT91_SMC_SETUP_NCS_RD(2), 202 &smc->cs[0].setup); 203 writel(AT91_SMC_PULSE_NWE(5) | AT91_SMC_PULSE_NCS_WR(4) | 204 AT91_SMC_PULSE_NRD(6) | AT91_SMC_PULSE_NCS_RD(4), 205 &smc->cs[0].pulse); 206 writel(AT91_SMC_CYCLE_NWE(6) | AT91_SMC_CYCLE_NRD(6), 207 &smc->cs[0].cycle); 208 writel(AT91_SMC_MODE_BAT | 209 AT91_SMC_MODE_EXNW_DISABLE | 210 AT91_SMC_MODE_DBW_32 | 211 AT91_SMC_MODE_TDF | 212 AT91_SMC_MODE_TDF_CYCLE(2), 213 &smc->cs[0].mode); 214 215 /* Do a write to within EBI_CS1 to enable the SDCK */ 216 writel(0, ATMEL_BASE_CS1); 217 218 return 0; 219 } 220 #endif 221 222 #ifdef CONFIG_CMD_USB 223 224 #define USB0_ENABLE_PIN AT91_PIN_PB22 225 #define USB1_ENABLE_PIN AT91_PIN_PB23 226 227 void gurnard_usb_init(void) 228 { 229 at91_set_gpio_output(USB0_ENABLE_PIN, 1); 230 at91_set_gpio_value(USB0_ENABLE_PIN, 0); 231 at91_set_gpio_output(USB1_ENABLE_PIN, 1); 232 at91_set_gpio_value(USB1_ENABLE_PIN, 0); 233 } 234 #endif 235 236 #ifdef CONFIG_GENERIC_ATMEL_MCI 237 int cpu_mmc_init(bd_t *bis) 238 { 239 return atmel_mci_init((void *)ATMEL_BASE_MCI0); 240 } 241 #endif 242 243 static void gurnard_enable_console(int enable) 244 { 245 at91_set_gpio_output(AT91_PIN_PB14, 1); 246 at91_set_gpio_value(AT91_PIN_PB14, enable ? 0 : 1); 247 } 248 249 void at91sam9g45_slowclock_init(void) 250 { 251 /* 252 * On AT91SAM9G45 revC CPUs, the slow clock can be based on an 253 * internal impreciseRC oscillator or an external 32kHz oscillator. 254 * Switch to the latter. 255 */ 256 unsigned i, tmp; 257 ulong *reg = (ulong *)ATMEL_BASE_SCKCR; 258 259 tmp = readl(reg); 260 if ((tmp & AT91SAM9G45_SCKCR_OSCSEL) == AT91SAM9G45_SCKCR_OSCSEL_RC) { 261 timer_init(); 262 tmp |= AT91SAM9G45_SCKCR_OSC32EN; 263 writel(tmp, reg); 264 for (i = 0; i < 1200; i++) 265 udelay(1000); 266 tmp |= AT91SAM9G45_SCKCR_OSCSEL_32; 267 writel(tmp, reg); 268 udelay(200); 269 tmp &= ~AT91SAM9G45_SCKCR_RCEN; 270 writel(tmp, reg); 271 } 272 } 273 274 int board_early_init_f(void) 275 { 276 at91_seriald_hw_init(); 277 gurnard_enable_console(1); 278 279 return 0; 280 } 281 282 int board_init(void) 283 { 284 const char *rev_str; 285 #ifdef CONFIG_CMD_NAND 286 int ret; 287 #endif 288 289 at91_periph_clk_enable(ATMEL_ID_PIOA); 290 at91_periph_clk_enable(ATMEL_ID_PIOB); 291 at91_periph_clk_enable(ATMEL_ID_PIOC); 292 at91_periph_clk_enable(ATMEL_ID_PIODE); 293 294 at91sam9g45_slowclock_init(); 295 296 /* 297 * Clear the RTC IDR to disable all IRQs. Avoid issues when Linux 298 * boots with spurious IRQs. 299 */ 300 writel(0xffffffff, AT91_RTC_IDR); 301 302 /* Make sure that the reset signal is attached properly */ 303 setbits_le32(AT91_ASM_RSTC_MR, AT91_RSTC_KEY | AT91_RSTC_MR_URSTEN); 304 305 gd->bd->bi_arch_number = MACH_TYPE_SNAPPER_9260; 306 307 /* Address of boot parameters */ 308 gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; 309 310 #ifdef CONFIG_CMD_NAND 311 ret = gurnard_nand_hw_init(); 312 if (ret) 313 return ret; 314 #endif 315 #ifdef CONFIG_ATMEL_SPI 316 at91_spi0_hw_init(1 << 4); 317 #endif 318 319 #ifdef CONFIG_MACB 320 gurnard_macb_hw_init(); 321 #endif 322 323 #ifdef CONFIG_GURNARD_FPGA 324 fpga_hw_init(); 325 #endif 326 327 #ifdef CONFIG_CMD_USB 328 gurnard_usb_init(); 329 #endif 330 331 #ifdef CONFIG_CMD_MMC 332 at91_set_A_periph(AT91_PIN_PA12, 0); 333 at91_set_gpio_output(AT91_PIN_PA8, 1); 334 at91_set_gpio_value(AT91_PIN_PA8, 0); 335 at91_mci_hw_init(); 336 #endif 337 338 #ifdef CONFIG_DM_VIDEO 339 at91sam9g45_lcd_hw_init(); 340 at91_set_A_periph(AT91_PIN_PE6, 1); /* power up */ 341 342 /* Select the second timing index for board rev 2 */ 343 rev_str = getenv("board_rev"); 344 if (rev_str && !strncmp(rev_str, "2", 1)) { 345 struct udevice *dev; 346 347 uclass_find_first_device(UCLASS_VIDEO, &dev); 348 if (dev) { 349 struct atmel_lcd_platdata *plat = dev_get_platdata(dev); 350 351 plat->timing_index = 1; 352 } 353 } 354 #endif 355 356 return 0; 357 } 358 359 int board_late_init(void) 360 { 361 u_int8_t env_enetaddr[8]; 362 char *env_str; 363 char *end; 364 int i; 365 366 /* 367 * Set MAC address so we do not need to init Ethernet before Linux 368 * boot 369 */ 370 env_str = getenv("ethaddr"); 371 if (env_str) { 372 struct at91_emac *emac = (struct at91_emac *)ATMEL_BASE_EMAC; 373 /* Parse MAC address */ 374 for (i = 0; i < 6; i++) { 375 env_enetaddr[i] = env_str ? 376 simple_strtoul(env_str, &end, 16) : 0; 377 if (env_str) 378 env_str = (*end) ? end+1 : end; 379 } 380 381 /* Set hardware address */ 382 writel(env_enetaddr[0] | env_enetaddr[1] << 8 | 383 env_enetaddr[2] << 16 | env_enetaddr[3] << 24, 384 &emac->sa2l); 385 writel((env_enetaddr[4] | env_enetaddr[5] << 8), &emac->sa2h); 386 387 printf("MAC: %s\n", getenv("ethaddr")); 388 } else { 389 /* Not set in environment */ 390 printf("MAC: not set\n"); 391 } 392 #ifdef CONFIG_GURNARD_SPLASH 393 lcd_splash(480, 272); 394 #endif 395 396 return 0; 397 } 398 399 #ifndef CONFIG_DM_ETH 400 int board_eth_init(bd_t *bis) 401 { 402 return macb_eth_initialize(0, (void *)ATMEL_BASE_EMAC, 0); 403 } 404 #endif 405 406 int dram_init(void) 407 { 408 gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, 409 CONFIG_SYS_SDRAM_SIZE); 410 return 0; 411 } 412 413 void reset_phy(void) 414 { 415 } 416 417 /* SPI chip select control - only used for FPGA programming */ 418 #ifdef CONFIG_ATMEL_SPI 419 420 int spi_cs_is_valid(unsigned int bus, unsigned int cs) 421 { 422 return bus == 0 && cs == 0; 423 } 424 425 void spi_cs_activate(struct spi_slave *slave) 426 { 427 /* We don't use chipselects for FPGA programming */ 428 } 429 430 void spi_cs_deactivate(struct spi_slave *slave) 431 { 432 /* We don't use chipselects for FPGA programming */ 433 } 434 #endif /* CONFIG_ATMEL_SPI */ 435 436 static struct atmel_serial_platdata at91sam9260_serial_plat = { 437 .base_addr = ATMEL_BASE_DBGU, 438 }; 439 440 U_BOOT_DEVICE(at91sam9260_serial) = { 441 .name = "serial_atmel", 442 .platdata = &at91sam9260_serial_plat, 443 }; 444