1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2010 4 * ISEE 2007 SL, <www.iseebcn.com> 5 */ 6#include <common.h> 7#include <env.h> 8#include <init.h> 9#include <malloc.h> 10#include <net.h> 11#include <status_led.h> 12#include <dm.h> 13#include <ns16550.h> 14#include <twl4030.h> 15#include <netdev.h> 16#include <spl.h> 17#include <asm/gpio.h> 18#include <asm/io.h> 19#include <asm/arch/mem.h> 20#include <asm/arch/mmc_host_def.h> 21#include <asm/arch/mux.h> 22#include <asm/arch/sys_proto.h> 23#include <linux/delay.h> 24#include <linux/mtd/mtd.h> 25#include <linux/mtd/rawnand.h> 26#include <linux/mtd/onenand.h> 27#include <jffs2/load_kernel.h> 28#include <mtd_node.h> 29#include <fdt_support.h> 30#include "igep00x0.h" 31 32static const struct ns16550_plat igep_serial = { 33 .base = OMAP34XX_UART3, 34 .reg_shift = 2, 35 .clock = V_NS16550_CLK, 36 .fcr = UART_FCR_DEFVAL, 37}; 38 39U_BOOT_DRVINFO(igep_uart) = { 40 "ns16550_serial", 41 &igep_serial 42}; 43 44/* 45 * Routine: get_board_revision 46 * Description: GPIO_28 and GPIO_129 are used to read board and revision from 47 * IGEP00x0 boards. First of all, it is necessary to reset USB transceiver from 48 * IGEP0030 in order to read GPIO_IGEP00X0_BOARD_DETECTION correctly, because 49 * this functionality is shared by USB HOST. 50 * Once USB reset is applied, U-Boot configures these pins as input pullup to 51 * detect board and revision: 52 * IGEP0020-RF = 0b00 53 * IGEP0020-RC = 0b01 54 * IGEP0030-RG = 0b10 55 * IGEP0030-RE = 0b11 56 */ 57static int get_board_revision(void) 58{ 59 int revision; 60 61 gpio_request(IGEP0030_USB_TRANSCEIVER_RESET, 62 "igep0030_usb_transceiver_reset"); 63 gpio_direction_output(IGEP0030_USB_TRANSCEIVER_RESET, 0); 64 65 gpio_request(GPIO_IGEP00X0_BOARD_DETECTION, "igep00x0_board_detection"); 66 gpio_direction_input(GPIO_IGEP00X0_BOARD_DETECTION); 67 revision = 2 * gpio_get_value(GPIO_IGEP00X0_BOARD_DETECTION); 68 gpio_free(GPIO_IGEP00X0_BOARD_DETECTION); 69 70 gpio_request(GPIO_IGEP00X0_REVISION_DETECTION, 71 "igep00x0_revision_detection"); 72 gpio_direction_input(GPIO_IGEP00X0_REVISION_DETECTION); 73 revision = revision + gpio_get_value(GPIO_IGEP00X0_REVISION_DETECTION); 74 gpio_free(GPIO_IGEP00X0_REVISION_DETECTION); 75 76 gpio_free(IGEP0030_USB_TRANSCEIVER_RESET); 77 78 return revision; 79} 80 81int onenand_board_init(struct mtd_info *mtd) 82{ 83 if (gpmc_cs0_flash == MTD_DEV_TYPE_ONENAND) { 84 struct onenand_chip *this = mtd->priv; 85 this->base = (void *)CFG_SYS_ONENAND_BASE; 86 return 0; 87 } 88 return 1; 89} 90 91#ifdef CONFIG_OF_BOARD_SETUP 92static int ft_enable_by_compatible(void *blob, char *compat, int enable) 93{ 94 int off = fdt_node_offset_by_compatible(blob, -1, compat); 95 if (off < 0) 96 return off; 97 98 if (enable) 99 fdt_status_okay(blob, off); 100 else 101 fdt_status_disabled(blob, off); 102 103 return 0; 104} 105 106int ft_board_setup(void *blob, struct bd_info *bd) 107{ 108#ifdef CONFIG_FDT_FIXUP_PARTITIONS 109 static const struct node_info nodes[] = { 110 { "ti,omap2-nand", MTD_DEV_TYPE_NAND, }, 111 { "ti,omap2-onenand", MTD_DEV_TYPE_ONENAND, }, 112 }; 113 114 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes)); 115#endif 116 ft_enable_by_compatible(blob, "ti,omap2-nand", 117 gpmc_cs0_flash == MTD_DEV_TYPE_NAND); 118 ft_enable_by_compatible(blob, "ti,omap2-onenand", 119 gpmc_cs0_flash == MTD_DEV_TYPE_ONENAND); 120 121 return 0; 122} 123#endif 124 125void set_led(void) 126{ 127 switch (get_board_revision()) { 128 case 0: 129 case 1: 130 gpio_request(IGEP0020_GPIO_LED, "igep0020_gpio_led"); 131 gpio_direction_output(IGEP0020_GPIO_LED, 1); 132 break; 133 case 2: 134 case 3: 135 gpio_request(IGEP0030_GPIO_LED, "igep0030_gpio_led"); 136 gpio_direction_output(IGEP0030_GPIO_LED, 0); 137 break; 138 default: 139 /* Should not happen... */ 140 break; 141 } 142} 143 144void set_boardname(void) 145{ 146 char rev[5] = { 'F','C','G','E', }; 147 int i = get_board_revision(); 148 149 rev[i+1] = 0; 150 env_set("board_rev", rev + i); 151 env_set("board_name", i < 2 ? "igep0020" : "igep0030"); 152} 153 154/* 155 * Routine: misc_init_r 156 * Description: Configure board specific parts 157 */ 158int misc_init_r(void) 159{ 160 t2_t *t2_base = (t2_t *)T2_BASE; 161 u32 pbias_lite; 162 163 twl4030_power_init(); 164 165 /* set VSIM to 1.8V */ 166 twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VSIM_DEDICATED, 167 TWL4030_PM_RECEIVER_VSIM_VSEL_18, 168 TWL4030_PM_RECEIVER_VSIM_DEV_GRP, 169 TWL4030_PM_RECEIVER_DEV_GRP_P1); 170 171 /* set up dual-voltage GPIOs to 1.8V */ 172 pbias_lite = readl(&t2_base->pbias_lite); 173 pbias_lite &= ~PBIASLITEVMODE1; 174 pbias_lite |= PBIASLITEPWRDNZ1; 175 writel(pbias_lite, &t2_base->pbias_lite); 176 if (get_cpu_family() == CPU_OMAP36XX) 177 writel(readl(OMAP34XX_CTRL_WKUP_CTRL) | 178 OMAP34XX_CTRL_WKUP_CTRL_GPIO_IO_PWRDNZ, 179 OMAP34XX_CTRL_WKUP_CTRL); 180 181 omap_die_id_display(); 182 183 set_led(); 184 185 set_boardname(); 186 187 return 0; 188} 189 190void board_mtdparts_default(const char **mtdids, const char **mtdparts) 191{ 192 struct mtd_info *mtd = get_mtd_device(NULL, 0); 193 if (mtd) { 194 static char ids[24]; 195 static char parts[48]; 196 const char *linux_name = "omap2-nand"; 197 if (strncmp(mtd->name, "onenand0", 8) == 0) 198 linux_name = "omap2-onenand"; 199 snprintf(ids, sizeof(ids), "%s=%s", mtd->name, linux_name); 200 snprintf(parts, sizeof(parts), "mtdparts=%s:%dk(SPL),-(UBI)", 201 linux_name, 4 * mtd->erasesize >> 10); 202 *mtdids = ids; 203 *mtdparts = parts; 204 } 205} 206