175238f23SWenyou Yang /*
275238f23SWenyou Yang * Copyright (C) 2015 Atmel Corporation
375238f23SWenyou Yang * Wenyou.Yang <wenyou.yang@atmel.com>
475238f23SWenyou Yang *
575238f23SWenyou Yang * SPDX-License-Identifier: GPL-2.0+
675238f23SWenyou Yang */
775238f23SWenyou Yang
875238f23SWenyou Yang #include <common.h>
975238f23SWenyou Yang #include <atmel_hlcdc.h>
102992dd83SWenyou Yang #include <debug_uart.h>
110daa2e18SWenyou Yang #include <dm.h>
120daa2e18SWenyou Yang #include <i2c.h>
1375238f23SWenyou Yang #include <lcd.h>
1475238f23SWenyou Yang #include <version.h>
1575238f23SWenyou Yang #include <asm/io.h>
1675238f23SWenyou Yang #include <asm/arch/at91_common.h>
1775238f23SWenyou Yang #include <asm/arch/atmel_pio4.h>
1837dadbcaSWenyou Yang #include <asm/arch/atmel_mpddrc.h>
1975238f23SWenyou Yang #include <asm/arch/atmel_sdhci.h>
2075238f23SWenyou Yang #include <asm/arch/clk.h>
2175238f23SWenyou Yang #include <asm/arch/gpio.h>
2275238f23SWenyou Yang #include <asm/arch/sama5d2.h>
2375238f23SWenyou Yang
2475238f23SWenyou Yang DECLARE_GLOBAL_DATA_PTR;
2575238f23SWenyou Yang
board_usb_hw_init(void)2675238f23SWenyou Yang static void board_usb_hw_init(void)
2775238f23SWenyou Yang {
2875238f23SWenyou Yang atmel_pio4_set_pio_output(AT91_PIO_PORTB, 10, 1);
2975238f23SWenyou Yang }
3075238f23SWenyou Yang
3175238f23SWenyou Yang #ifdef CONFIG_LCD
3275238f23SWenyou Yang vidinfo_t panel_info = {
3375238f23SWenyou Yang .vl_col = 480,
3475238f23SWenyou Yang .vl_row = 272,
3575238f23SWenyou Yang .vl_clk = 9000000,
3675238f23SWenyou Yang .vl_bpix = LCD_BPP,
3775238f23SWenyou Yang .vl_tft = 1,
3875238f23SWenyou Yang .vl_hsync_len = 41,
3975238f23SWenyou Yang .vl_left_margin = 2,
4075238f23SWenyou Yang .vl_right_margin = 2,
4175238f23SWenyou Yang .vl_vsync_len = 11,
4275238f23SWenyou Yang .vl_upper_margin = 2,
4375238f23SWenyou Yang .vl_lower_margin = 2,
4475238f23SWenyou Yang .mmio = ATMEL_BASE_LCDC,
4575238f23SWenyou Yang };
4675238f23SWenyou Yang
4775238f23SWenyou Yang /* No power up/down pin for the LCD pannel */
lcd_enable(void)4875238f23SWenyou Yang void lcd_enable(void) { /* Empty! */ }
lcd_disable(void)4975238f23SWenyou Yang void lcd_disable(void) { /* Empty! */ }
5075238f23SWenyou Yang
has_lcdc(void)5175238f23SWenyou Yang unsigned int has_lcdc(void)
5275238f23SWenyou Yang {
5375238f23SWenyou Yang return 1;
5475238f23SWenyou Yang }
5575238f23SWenyou Yang
board_lcd_hw_init(void)5675238f23SWenyou Yang static void board_lcd_hw_init(void)
5775238f23SWenyou Yang {
5875238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 28, 0); /* LCDPWM */
5975238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 29, 0); /* LCDDISP */
6075238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 30, 0); /* LCDVSYNC */
6175238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 31, 0); /* LCDHSYNC */
6275238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTD, 0, 0); /* LCDPCK */
6375238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTD, 1, 0); /* LCDDEN */
6475238f23SWenyou Yang
6575238f23SWenyou Yang /* LCDDAT0 */
6675238f23SWenyou Yang /* LCDDAT1 */
6775238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 10, 0); /* LCDDAT2 */
6875238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 11, 0); /* LCDDAT3 */
6975238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 12, 0); /* LCDDAT4 */
7075238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 13, 0); /* LCDDAT5 */
7175238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 14, 0); /* LCDDAT6 */
7275238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 15, 0); /* LCDDAT7 */
7375238f23SWenyou Yang
7475238f23SWenyou Yang /* LCDDAT8 */
7575238f23SWenyou Yang /* LCDDAT9 */
7675238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 16, 0); /* LCDDAT10 */
7775238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 17, 0); /* LCDDAT11 */
7875238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 18, 0); /* LCDDAT12 */
7975238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 19, 0); /* LCDDAT13 */
8075238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 20, 0); /* LCDDAT14 */
8175238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 21, 0); /* LCDDAT15 */
8275238f23SWenyou Yang
8375238f23SWenyou Yang /* LCDD16 */
8475238f23SWenyou Yang /* LCDD17 */
8575238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 22, 0); /* LCDDAT18 */
8675238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 23, 0); /* LCDDAT19 */
8775238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 24, 0); /* LCDDAT20 */
8875238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 25, 0); /* LCDDAT21 */
8975238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 26, 0); /* LCDDAT22 */
9075238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTC, 27, 0); /* LCDDAT23 */
9175238f23SWenyou Yang
9275238f23SWenyou Yang at91_periph_clk_enable(ATMEL_ID_LCDC);
9375238f23SWenyou Yang }
9475238f23SWenyou Yang
9575238f23SWenyou Yang #ifdef CONFIG_LCD_INFO
lcd_show_board_info(void)9675238f23SWenyou Yang void lcd_show_board_info(void)
9775238f23SWenyou Yang {
9875238f23SWenyou Yang ulong dram_size;
9975238f23SWenyou Yang int i;
10075238f23SWenyou Yang char temp[32];
10175238f23SWenyou Yang
10275238f23SWenyou Yang lcd_printf("%s\n", U_BOOT_VERSION);
10375238f23SWenyou Yang lcd_printf("2015 ATMEL Corp\n");
10475238f23SWenyou Yang lcd_printf("%s CPU at %s MHz\n", get_cpu_name(),
10575238f23SWenyou Yang strmhz(temp, get_cpu_clk_rate()));
10675238f23SWenyou Yang
10775238f23SWenyou Yang dram_size = 0;
10875238f23SWenyou Yang for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
10975238f23SWenyou Yang dram_size += gd->bd->bi_dram[i].size;
11075238f23SWenyou Yang
11175238f23SWenyou Yang lcd_printf("%ld MB SDRAM\n", dram_size >> 20);
11275238f23SWenyou Yang }
11375238f23SWenyou Yang #endif /* CONFIG_LCD_INFO */
11475238f23SWenyou Yang #endif /* CONFIG_LCD */
11575238f23SWenyou Yang
116ed03b1baSWenyou Yang #ifdef CONFIG_DEBUG_UART_BOARD_INIT
board_uart1_hw_init(void)11775238f23SWenyou Yang static void board_uart1_hw_init(void)
11875238f23SWenyou Yang {
11975238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTD, 2, 1); /* URXD1 */
12075238f23SWenyou Yang atmel_pio4_set_a_periph(AT91_PIO_PORTD, 3, 0); /* UTXD1 */
12175238f23SWenyou Yang
12275238f23SWenyou Yang at91_periph_clk_enable(ATMEL_ID_UART1);
12375238f23SWenyou Yang }
12475238f23SWenyou Yang
board_debug_uart_init(void)1252992dd83SWenyou Yang void board_debug_uart_init(void)
12675238f23SWenyou Yang {
12775238f23SWenyou Yang board_uart1_hw_init();
1282992dd83SWenyou Yang }
1292992dd83SWenyou Yang #endif
1302992dd83SWenyou Yang
1312992dd83SWenyou Yang #ifdef CONFIG_BOARD_EARLY_INIT_F
board_early_init_f(void)1322992dd83SWenyou Yang int board_early_init_f(void)
1332992dd83SWenyou Yang {
1342992dd83SWenyou Yang #ifdef CONFIG_DEBUG_UART
1352992dd83SWenyou Yang debug_uart_init();
1362992dd83SWenyou Yang #endif
13775238f23SWenyou Yang
13875238f23SWenyou Yang return 0;
13975238f23SWenyou Yang }
1402992dd83SWenyou Yang #endif
14175238f23SWenyou Yang
board_init(void)14275238f23SWenyou Yang int board_init(void)
14375238f23SWenyou Yang {
14475238f23SWenyou Yang /* address of boot parameters */
14575238f23SWenyou Yang gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
14675238f23SWenyou Yang
14775238f23SWenyou Yang #ifdef CONFIG_LCD
14875238f23SWenyou Yang board_lcd_hw_init();
14975238f23SWenyou Yang #endif
15075238f23SWenyou Yang #ifdef CONFIG_CMD_USB
15175238f23SWenyou Yang board_usb_hw_init();
15275238f23SWenyou Yang #endif
15375238f23SWenyou Yang
15475238f23SWenyou Yang return 0;
15575238f23SWenyou Yang }
15675238f23SWenyou Yang
dram_init(void)15775238f23SWenyou Yang int dram_init(void)
15875238f23SWenyou Yang {
15975238f23SWenyou Yang gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
16075238f23SWenyou Yang CONFIG_SYS_SDRAM_SIZE);
16175238f23SWenyou Yang return 0;
16275238f23SWenyou Yang }
16375238f23SWenyou Yang
1640daa2e18SWenyou Yang #ifdef CONFIG_CMD_I2C
set_ethaddr_from_eeprom(void)1650daa2e18SWenyou Yang static int set_ethaddr_from_eeprom(void)
1660daa2e18SWenyou Yang {
1670daa2e18SWenyou Yang const int ETH_ADDR_LEN = 6;
1680daa2e18SWenyou Yang unsigned char ethaddr[ETH_ADDR_LEN];
1690daa2e18SWenyou Yang const char *ETHADDR_NAME = "ethaddr";
1700daa2e18SWenyou Yang struct udevice *bus, *dev;
1710daa2e18SWenyou Yang
172*00caae6dSSimon Glass if (env_get(ETHADDR_NAME))
1730daa2e18SWenyou Yang return 0;
1740daa2e18SWenyou Yang
1750daa2e18SWenyou Yang if (uclass_get_device_by_seq(UCLASS_I2C, 1, &bus)) {
1760daa2e18SWenyou Yang printf("Cannot find I2C bus 1\n");
1770daa2e18SWenyou Yang return -1;
1780daa2e18SWenyou Yang }
1790daa2e18SWenyou Yang
1800daa2e18SWenyou Yang if (dm_i2c_probe(bus, AT24MAC_ADDR, 0, &dev)) {
1810daa2e18SWenyou Yang printf("Failed to probe I2C chip\n");
1820daa2e18SWenyou Yang return -1;
1830daa2e18SWenyou Yang }
1840daa2e18SWenyou Yang
1850daa2e18SWenyou Yang if (dm_i2c_read(dev, AT24MAC_REG, ethaddr, ETH_ADDR_LEN)) {
1860daa2e18SWenyou Yang printf("Failed to read ethernet address from EEPROM\n");
1870daa2e18SWenyou Yang return -1;
1880daa2e18SWenyou Yang }
1890daa2e18SWenyou Yang
1900daa2e18SWenyou Yang if (!is_valid_ethaddr(ethaddr)) {
1910daa2e18SWenyou Yang printf("The ethernet address read from EEPROM is not valid!\n");
1920daa2e18SWenyou Yang return -1;
1930daa2e18SWenyou Yang }
1940daa2e18SWenyou Yang
195fd1e959eSSimon Glass return eth_env_set_enetaddr(ETHADDR_NAME, ethaddr);
1960daa2e18SWenyou Yang }
1970daa2e18SWenyou Yang #else
set_ethaddr_from_eeprom(void)1980daa2e18SWenyou Yang static int set_ethaddr_from_eeprom(void)
1990daa2e18SWenyou Yang {
2000daa2e18SWenyou Yang return 0;
2010daa2e18SWenyou Yang }
2020daa2e18SWenyou Yang #endif
2030daa2e18SWenyou Yang
2040daa2e18SWenyou Yang #ifdef CONFIG_MISC_INIT_R
misc_init_r(void)2050daa2e18SWenyou Yang int misc_init_r(void)
2060daa2e18SWenyou Yang {
2070daa2e18SWenyou Yang set_ethaddr_from_eeprom();
2080daa2e18SWenyou Yang
2090daa2e18SWenyou Yang return 0;
2100daa2e18SWenyou Yang }
2110daa2e18SWenyou Yang #endif
2120daa2e18SWenyou Yang
21337dadbcaSWenyou Yang /* SPL */
21437dadbcaSWenyou Yang #ifdef CONFIG_SPL_BUILD
spl_board_init(void)21537dadbcaSWenyou Yang void spl_board_init(void)
21637dadbcaSWenyou Yang {
21737dadbcaSWenyou Yang }
21837dadbcaSWenyou Yang
ddrc_conf(struct atmel_mpddrc_config * ddrc)21937dadbcaSWenyou Yang static void ddrc_conf(struct atmel_mpddrc_config *ddrc)
22037dadbcaSWenyou Yang {
22137dadbcaSWenyou Yang ddrc->md = (ATMEL_MPDDRC_MD_DBW_32_BITS | ATMEL_MPDDRC_MD_DDR3_SDRAM);
22237dadbcaSWenyou Yang
22337dadbcaSWenyou Yang ddrc->cr = (ATMEL_MPDDRC_CR_NC_COL_10 |
22437dadbcaSWenyou Yang ATMEL_MPDDRC_CR_NR_ROW_14 |
22537dadbcaSWenyou Yang ATMEL_MPDDRC_CR_CAS_DDR_CAS5 |
22637dadbcaSWenyou Yang ATMEL_MPDDRC_CR_DIC_DS |
22737dadbcaSWenyou Yang ATMEL_MPDDRC_CR_DIS_DLL |
22837dadbcaSWenyou Yang ATMEL_MPDDRC_CR_NB_8BANKS |
22937dadbcaSWenyou Yang ATMEL_MPDDRC_CR_DECOD_INTERLEAVED |
23037dadbcaSWenyou Yang ATMEL_MPDDRC_CR_UNAL_SUPPORTED);
23137dadbcaSWenyou Yang
23237dadbcaSWenyou Yang ddrc->rtr = 0x511;
23337dadbcaSWenyou Yang
23437dadbcaSWenyou Yang ddrc->tpr0 = (6 << ATMEL_MPDDRC_TPR0_TRAS_OFFSET |
23537dadbcaSWenyou Yang 3 << ATMEL_MPDDRC_TPR0_TRCD_OFFSET |
23637dadbcaSWenyou Yang 4 << ATMEL_MPDDRC_TPR0_TWR_OFFSET |
23737dadbcaSWenyou Yang 9 << ATMEL_MPDDRC_TPR0_TRC_OFFSET |
23837dadbcaSWenyou Yang 3 << ATMEL_MPDDRC_TPR0_TRP_OFFSET |
23937dadbcaSWenyou Yang 4 << ATMEL_MPDDRC_TPR0_TRRD_OFFSET |
24037dadbcaSWenyou Yang 4 << ATMEL_MPDDRC_TPR0_TWTR_OFFSET |
24137dadbcaSWenyou Yang 4 << ATMEL_MPDDRC_TPR0_TMRD_OFFSET);
24237dadbcaSWenyou Yang
24337dadbcaSWenyou Yang ddrc->tpr1 = (27 << ATMEL_MPDDRC_TPR1_TRFC_OFFSET |
24437dadbcaSWenyou Yang 29 << ATMEL_MPDDRC_TPR1_TXSNR_OFFSET |
24537dadbcaSWenyou Yang 0 << ATMEL_MPDDRC_TPR1_TXSRD_OFFSET |
24637dadbcaSWenyou Yang 3 << ATMEL_MPDDRC_TPR1_TXP_OFFSET);
24737dadbcaSWenyou Yang
24837dadbcaSWenyou Yang ddrc->tpr2 = (0 << ATMEL_MPDDRC_TPR2_TXARD_OFFSET |
24937dadbcaSWenyou Yang 0 << ATMEL_MPDDRC_TPR2_TXARDS_OFFSET |
25037dadbcaSWenyou Yang 0 << ATMEL_MPDDRC_TPR2_TRPA_OFFSET |
25137dadbcaSWenyou Yang 4 << ATMEL_MPDDRC_TPR2_TRTP_OFFSET |
25237dadbcaSWenyou Yang 7 << ATMEL_MPDDRC_TPR2_TFAW_OFFSET);
25337dadbcaSWenyou Yang }
25437dadbcaSWenyou Yang
mem_init(void)25537dadbcaSWenyou Yang void mem_init(void)
25637dadbcaSWenyou Yang {
25737dadbcaSWenyou Yang struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
25837dadbcaSWenyou Yang struct atmel_mpddr *mpddrc = (struct atmel_mpddr *)ATMEL_BASE_MPDDRC;
25937dadbcaSWenyou Yang struct atmel_mpddrc_config ddrc_config;
26037dadbcaSWenyou Yang u32 reg;
26137dadbcaSWenyou Yang
26237dadbcaSWenyou Yang ddrc_conf(&ddrc_config);
26337dadbcaSWenyou Yang
26437dadbcaSWenyou Yang at91_periph_clk_enable(ATMEL_ID_MPDDRC);
26537dadbcaSWenyou Yang writel(AT91_PMC_DDR, &pmc->scer);
26637dadbcaSWenyou Yang
26737dadbcaSWenyou Yang reg = readl(&mpddrc->io_calibr);
26837dadbcaSWenyou Yang reg &= ~ATMEL_MPDDRC_IO_CALIBR_RDIV;
26937dadbcaSWenyou Yang reg |= ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_55;
27037dadbcaSWenyou Yang reg &= ~ATMEL_MPDDRC_IO_CALIBR_TZQIO;
27137dadbcaSWenyou Yang reg |= ATMEL_MPDDRC_IO_CALIBR_TZQIO_(100);
27237dadbcaSWenyou Yang writel(reg, &mpddrc->io_calibr);
27337dadbcaSWenyou Yang
27437dadbcaSWenyou Yang writel(ATMEL_MPDDRC_RD_DATA_PATH_SHIFT_TWO_CYCLE,
27537dadbcaSWenyou Yang &mpddrc->rd_data_path);
27637dadbcaSWenyou Yang
27737dadbcaSWenyou Yang ddr3_init(ATMEL_BASE_MPDDRC, ATMEL_BASE_DDRCS, &ddrc_config);
27837dadbcaSWenyou Yang
27937dadbcaSWenyou Yang writel(0x3, &mpddrc->cal_mr4);
28037dadbcaSWenyou Yang writel(64, &mpddrc->tim_cal);
28137dadbcaSWenyou Yang }
28237dadbcaSWenyou Yang
at91_pmc_init(void)28337dadbcaSWenyou Yang void at91_pmc_init(void)
28437dadbcaSWenyou Yang {
28537dadbcaSWenyou Yang struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
28637dadbcaSWenyou Yang u32 tmp;
28737dadbcaSWenyou Yang
28837dadbcaSWenyou Yang tmp = AT91_PMC_PLLAR_29 |
28937dadbcaSWenyou Yang AT91_PMC_PLLXR_PLLCOUNT(0x3f) |
29037dadbcaSWenyou Yang AT91_PMC_PLLXR_MUL(82) |
29137dadbcaSWenyou Yang AT91_PMC_PLLXR_DIV(1);
29237dadbcaSWenyou Yang at91_plla_init(tmp);
29337dadbcaSWenyou Yang
29437dadbcaSWenyou Yang writel(0x0 << 8, &pmc->pllicpr);
29537dadbcaSWenyou Yang
29637dadbcaSWenyou Yang tmp = AT91_PMC_MCKR_H32MXDIV |
29737dadbcaSWenyou Yang AT91_PMC_MCKR_PLLADIV_2 |
29837dadbcaSWenyou Yang AT91_PMC_MCKR_MDIV_3 |
29937dadbcaSWenyou Yang AT91_PMC_MCKR_CSS_PLLA;
30037dadbcaSWenyou Yang at91_mck_init(tmp);
30137dadbcaSWenyou Yang }
30237dadbcaSWenyou Yang #endif
303