| |
| /* * Copyright (c) 2012 - 2013 The Linux Foundation. All rights reserved.* */ |
| |
| #include <common.h> |
| #include <linux/mtd/ipq_nand.h> |
| #include <asm/arch-ipq806x/gpio.h> |
| #include <asm/global_data.h> |
| #include <asm/io.h> |
| #include <asm/arch-ipq806x/clock.h> |
| #include <asm/arch-ipq806x/ebi2.h> |
| #include <asm/arch-ipq806x/smem.h> |
| #include <asm/errno.h> |
| #include "ipq806x_board_param.h" |
| #include "ipq806x_cdp.h" |
| #include <asm/arch-ipq806x/nss/msm_ipq806x_gmac.h> |
| #include <asm/arch-ipq806x/timer.h> |
| #include <nand.h> |
| #include <phy.h> |
| |
| DECLARE_GLOBAL_DATA_PTR; |
| |
| |
| /* Watchdog bite time set to default reset value */ |
| #define RESET_WDT_BITE_TIME 0x31F3 |
| |
| /* Watchdog bark time value is ketp larger than the watchdog timeout |
| * of 0x31F3, effectively disabling the watchdog bark interrupt |
| */ |
| #define RESET_WDT_BARK_TIME (5 * RESET_WDT_BITE_TIME) |
| |
| /* |
| * If SMEM is not found, we provide a value, that will prevent the |
| * environment from being written to random location in the flash. |
| * |
| * NAND: In the case of NAND, we do this by setting ENV_RANGE to |
| * zero. If ENV_RANGE < ENV_SIZE, then environment is not written. |
| * |
| * SPI Flash: In the case of SPI Flash, we do this by setting the |
| * flash_index to -1. |
| */ |
| |
| loff_t board_env_offset; |
| loff_t board_env_range; |
| extern int nand_env_device; |
| |
| board_ipq806x_params_t *gboard_param; |
| extern int ipq_gmac_eth_initialize(const char *ethaddr); |
| uchar ipq_def_enetaddr[6] = {0x00, 0x03, 0x7F, 0xBA, 0xDB, 0xAD}; |
| |
| /******************************************************* |
| Function description: Board specific initialization. |
| I/P : None |
| O/P : integer, 0 - no error. |
| |
| ********************************************************/ |
| static board_ipq806x_params_t *get_board_param(unsigned int machid) |
| { |
| unsigned int index = 0; |
| |
| for (index = 0; index < NUM_IPQ806X_BOARDS; index++) { |
| if (machid == board_params[index].machid) |
| return &board_params[index]; |
| } |
| BUG_ON(index == NUM_IPQ806X_BOARDS); |
| printf("cdp: Invalid machine id 0x%x\n", machid); |
| for (;;); |
| } |
| |
| int board_init() |
| { |
| int ret; |
| uint32_t start_blocks; |
| uint32_t size_blocks; |
| loff_t board_env_size; |
| ipq_smem_flash_info_t *sfi = &ipq_smem_flash_info; |
| |
| /* |
| * after relocation gboard_param is reset to NULL |
| * initialize again |
| */ |
| gd->bd->bi_boot_params = IPQ_BOOT_PARAMS_ADDR; |
| gd->bd->bi_arch_number = smem_get_board_machtype(); |
| gboard_param = get_board_param(gd->bd->bi_arch_number); |
| |
| /* |
| * Should be inited, before env_relocate() is called, |
| * since env. offset is obtained from SMEM. |
| */ |
| ret = smem_ptable_init(); |
| if (ret < 0) { |
| printf("cdp: SMEM init failed\n"); |
| return ret; |
| } |
| |
| ret = smem_get_boot_flash(&sfi->flash_type, |
| &sfi->flash_index, |
| &sfi->flash_chip_select, |
| &sfi->flash_block_size); |
| if (ret < 0) { |
| printf("cdp: get boot flash failed\n"); |
| return ret; |
| } |
| |
| if (sfi->flash_type == SMEM_BOOT_NAND_FLASH) { |
| nand_env_device = CONFIG_IPQ_NAND_NAND_INFO_IDX; |
| } else if (sfi->flash_type == SMEM_BOOT_SPI_FLASH) { |
| nand_env_device = CONFIG_IPQ_SPI_NAND_INFO_IDX; |
| } else { |
| printf("BUG: unsupported flash type : %d\n", sfi->flash_type); |
| BUG(); |
| } |
| |
| ret = smem_getpart("0:APPSBLENV", &start_blocks, &size_blocks); |
| if (ret < 0) { |
| printf("cdp: get environment part failed\n"); |
| return ret; |
| } |
| |
| board_env_offset = ((loff_t) sfi->flash_block_size) * start_blocks; |
| board_env_size = ((loff_t) sfi->flash_block_size) * size_blocks; |
| board_env_range = CONFIG_ENV_SIZE; |
| BUG_ON(board_env_size < CONFIG_ENV_SIZE); |
| |
| return 0; |
| } |
| |
| void enable_caches(void) |
| { |
| icache_enable(); |
| /* When dcache is enabled it causes the tftp timeout CR is raised CR.No: 513868. |
| * disabing dcache now to make tftp to work */ |
| #if (CONFIG_IPQ_CACHE_ENABLE == 1) |
| dcache_enable(); |
| #endif |
| } |
| |
| |
| /******************************************************* |
| Function description: DRAM initialization. |
| I/P : None |
| O/P : integer, 0 - no error. |
| |
| ********************************************************/ |
| |
| int dram_init(void) |
| { |
| struct smem_ram_ptable rtable; |
| int i; |
| int mx = ARRAY_SIZE(rtable.parts); |
| |
| if (smem_ram_ptable_init(&rtable) > 0) { |
| gd->ram_size = 0; |
| for (i = 0; i < mx; i++) { |
| if (rtable.parts[i].category == RAM_PARTITION_SDRAM |
| && rtable.parts[i].type == RAM_PARTITION_SYS_MEMORY) { |
| gd->ram_size += rtable.parts[i].size; |
| } |
| } |
| gboard_param->ddr_size = gd->ram_size; |
| } else { |
| gd->ram_size = gboard_param->ddr_size; |
| } |
| return 0; |
| } |
| |
| /******************************************************* |
| Function description: initi Dram Bank size |
| I/P : None |
| O/P : integer, 0 - no error. |
| |
| ********************************************************/ |
| |
| |
| void dram_init_banksize(void) |
| { |
| gd->bd->bi_dram[0].start = IPQ_KERNEL_START_ADDR; |
| gd->bd->bi_dram[0].size = gboard_param->ddr_size - GENERATED_IPQ_RESERVE_SIZE; |
| |
| } |
| |
| /********************************************************** |
| Function description: Display board information on console. |
| I/P : None |
| O/P : integer, 0 - no error. |
| |
| **********************************************************/ |
| |
| #ifdef CONFIG_DISPLAY_BOARDINFO |
| int checkboard(void) |
| { |
| printf("Board: %s\n", sysinfo.board_string); |
| return 0; |
| } |
| #endif /* CONFIG_DISPLAY_BOARDINFO */ |
| |
| void reset_cpu(ulong addr) |
| { |
| printf("\nResetting with watch dog!\n"); |
| |
| writel(0, APCS_WDT0_EN); |
| writel(1, APCS_WDT0_RST); |
| writel(RESET_WDT_BARK_TIME, APCS_WDT0_BARK_TIME); |
| writel(RESET_WDT_BITE_TIME, APCS_WDT0_BITE_TIME); |
| writel(1, APCS_WDT0_EN); |
| writel(1, APCS_WDT0_CPU0_WDOG_EXPIRED_ENABLE); |
| |
| for(;;); |
| } |
| |
| static void configure_nand_gpio(void) |
| { |
| /* EBI2 CS, CLE, ALE, WE, OE */ |
| gpio_tlmm_config(34, 1, 0, GPIO_NO_PULL, GPIO_10MA, GPIO_DISABLE); |
| gpio_tlmm_config(35, 1, 0, GPIO_NO_PULL, GPIO_10MA, GPIO_DISABLE); |
| gpio_tlmm_config(36, 1, 0, GPIO_NO_PULL, GPIO_10MA, GPIO_DISABLE); |
| gpio_tlmm_config(37, 1, 0, GPIO_NO_PULL, GPIO_10MA, GPIO_DISABLE); |
| gpio_tlmm_config(38, 1, 0, GPIO_NO_PULL, GPIO_10MA, GPIO_DISABLE); |
| |
| /* EBI2 BUSY */ |
| gpio_tlmm_config(39, 1, 0, GPIO_PULL_UP, GPIO_10MA, GPIO_DISABLE); |
| |
| /* EBI2 D7 - D0 */ |
| gpio_tlmm_config(40, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); |
| gpio_tlmm_config(41, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); |
| gpio_tlmm_config(42, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); |
| gpio_tlmm_config(43, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); |
| gpio_tlmm_config(44, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); |
| gpio_tlmm_config(45, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); |
| gpio_tlmm_config(46, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); |
| gpio_tlmm_config(47, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); |
| } |
| |
| void board_nand_init(void) |
| { |
| struct ebi2cr_regs *ebi2_regs; |
| extern int ipq_spi_init(void); |
| |
| if (gboard_param->flashdesc != NOR_MMC) { |
| |
| ebi2_regs = (struct ebi2cr_regs *) EBI2CR_BASE; |
| |
| nand_clock_config(); |
| configure_nand_gpio(); |
| |
| /* NAND Flash is connected to CS0 */ |
| clrsetbits_le32(&ebi2_regs->chip_select_cfg0, CS0_CFG_MASK, |
| CS0_CFG_SERIAL_FLASH_DEVICE); |
| |
| ipq_nand_init(IPQ_NAND_LAYOUT_LINUX); |
| } |
| |
| ipq_spi_init(); |
| } |
| |
| void ipq_get_part_details(void) |
| { |
| int ret, i; |
| uint32_t start; /* block number */ |
| uint32_t size; /* no. of blocks */ |
| |
| ipq_smem_flash_info_t *smem = &ipq_smem_flash_info; |
| |
| struct { char *name; ipq_part_entry_t *part; } entries[] = { |
| { "0:HLOS", &smem->hlos }, |
| { "0:NSS0", &smem->nss[0] }, |
| { "0:NSS1", &smem->nss[1] }, |
| }; |
| |
| for (i = 0; i < ARRAY_SIZE(entries); i++) { |
| ret = smem_getpart(entries[i].name, &start, &size); |
| if (ret < 0) { |
| ipq_part_entry_t *part = entries[i].part; |
| printf("cdp: get part failed for %s\n", entries[i].name); |
| part->offset = 0xBAD0FF5E; |
| part->size = 0xBAD0FF5E; |
| } |
| ipq_set_part_entry(smem, entries[i].part, start, size); |
| } |
| |
| return; |
| } |
| |
| /* |
| * Get the kernel partition details from SMEM and populate the, |
| * environment with sufficient information for the boot command to |
| * load and execute the kernel. |
| */ |
| int board_late_init(void) |
| { |
| unsigned int machid; |
| |
| ipq_get_part_details(); |
| |
| /* get machine type from SMEM and set in env */ |
| machid = gd->bd->bi_arch_number; |
| if (machid != 0) { |
| setenv_addr("machid", (void *)machid); |
| gd->bd->bi_arch_number = machid; |
| } |
| |
| return 0; |
| } |
| |
| /* |
| * This function is called in the very beginning. |
| * Retreive the machtype info from SMEM and map the board specific |
| * parameters. Shared memory region at Dram address 0x40400000 |
| * contains the machine id/ board type data polulated by SBL. |
| */ |
| int board_early_init_f(void) |
| { |
| gboard_param = get_board_param(smem_get_board_machtype()); |
| |
| return 0; |
| } |
| |
| /* |
| * Gets the ethernet address from the ART partition table and return the value |
| */ |
| int get_eth_mac_address(uchar *enetaddr, uint no_of_macs) |
| { |
| s32 ret; |
| u32 start_blocks; |
| u32 size_blocks; |
| u32 length = (6 * no_of_macs); |
| u32 flash_type; |
| loff_t art_offset; |
| |
| if (ipq_smem_flash_info.flash_type == SMEM_BOOT_SPI_FLASH) |
| flash_type = CONFIG_IPQ_SPI_NAND_INFO_IDX; |
| else if (ipq_smem_flash_info.flash_type == SMEM_BOOT_NAND_FLASH) |
| flash_type = CONFIG_IPQ_NAND_NAND_INFO_IDX; |
| else { |
| printf("Unknown flash type\n"); |
| return -EINVAL; |
| } |
| |
| ret = smem_getpart("0:ART", &start_blocks, &size_blocks); |
| if (ret < 0) { |
| printf("No ART partition found\n"); |
| return ret; |
| } |
| |
| /* |
| * ART partition 0th position (6 * 4) 24 bytes will contain the |
| * 4 MAC Address. First 0-5 bytes for GMAC0, Second 6-11 bytes |
| * for GMAC1, 12-17 bytes for GMAC2 and 18-23 bytes for GMAC3 |
| */ |
| art_offset = ((loff_t) ipq_smem_flash_info.flash_block_size * start_blocks); |
| |
| ret = nand_read(&nand_info[flash_type], art_offset, &length, enetaddr); |
| if (ret < 0) |
| printf("ART partition read failed..\n"); |
| return ret; |
| } |
| |
| void ipq_configure_gpio(gpio_func_data_t *gpio, uint count) |
| { |
| int i; |
| |
| for (i = 0; i < count; i++) { |
| gpio_tlmm_config(gpio->gpio, gpio->func, gpio->dir, |
| gpio->pull, gpio->drvstr, gpio->enable); |
| gpio++; |
| } |
| } |
| |
| int board_eth_init(bd_t *bis) |
| { |
| int status; |
| |
| ipq_gmac_common_init(gboard_param->gmac_cfg); |
| |
| ipq_configure_gpio(gboard_param->gmac_gpio, |
| gboard_param->gmac_gpio_count); |
| |
| status = ipq_gmac_init(gboard_param->gmac_cfg); |
| return status; |
| } |