186887f8eSPeter Barada /* 286887f8eSPeter Barada * (C) Copyright 2011 386887f8eSPeter Barada * Logic Product Development <www.logicpd.com> 486887f8eSPeter Barada * 586887f8eSPeter Barada * Author : 686887f8eSPeter Barada * Peter Barada <peter.barada@logicpd.com> 786887f8eSPeter Barada * 886887f8eSPeter Barada * Derived from Beagle Board and 3430 SDP code by 986887f8eSPeter Barada * Richard Woodruff <r-woodruff2@ti.com> 1086887f8eSPeter Barada * Syed Mohammed Khasim <khasim@ti.com> 1186887f8eSPeter Barada * 121a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 1386887f8eSPeter Barada */ 1486887f8eSPeter Barada #include <common.h> 157b77b1f6SAdam Ford #include <dm.h> 167b77b1f6SAdam Ford #include <ns16550.h> 1786887f8eSPeter Barada #include <netdev.h> 1886887f8eSPeter Barada #include <flash.h> 1986887f8eSPeter Barada #include <nand.h> 2086887f8eSPeter Barada #include <i2c.h> 2186887f8eSPeter Barada #include <twl4030.h> 2286887f8eSPeter Barada #include <asm/io.h> 2386887f8eSPeter Barada #include <asm/arch/mmc_host_def.h> 2486887f8eSPeter Barada #include <asm/arch/mux.h> 2586887f8eSPeter Barada #include <asm/arch/mem.h> 2686887f8eSPeter Barada #include <asm/arch/sys_proto.h> 2786887f8eSPeter Barada #include <asm/gpio.h> 2886887f8eSPeter Barada #include <asm/mach-types.h> 296ae3900aSMasahiro Yamada #include <linux/mtd/rawnand.h> 30588e41d2SAdam Ford #include <asm/omap_musb.h> 311221ce45SMasahiro Yamada #include <linux/errno.h> 32588e41d2SAdam Ford #include <linux/usb/ch9.h> 33588e41d2SAdam Ford #include <linux/usb/gadget.h> 34588e41d2SAdam Ford #include <linux/usb/musb.h> 3586887f8eSPeter Barada #include "omap3logic.h" 3674cd48e1SAdam Ford #ifdef CONFIG_USB_EHCI_HCD 3774cd48e1SAdam Ford #include <usb.h> 3874cd48e1SAdam Ford #include <asm/ehci-omap.h> 3974cd48e1SAdam Ford #endif 4086887f8eSPeter Barada 4186887f8eSPeter Barada DECLARE_GLOBAL_DATA_PTR; 4286887f8eSPeter Barada 4315fde737SAdam Ford /* This is only needed until SPL gets OF support */ 4415fde737SAdam Ford #ifdef CONFIG_SPL_BUILD 457b77b1f6SAdam Ford static const struct ns16550_platdata omap3logic_serial = { 462f6ed3b8SAdam Ford .base = OMAP34XX_UART1, 472f6ed3b8SAdam Ford .reg_shift = 2, 4817fa0326SHeiko Schocher .clock = V_NS16550_CLK, 4917fa0326SHeiko Schocher .fcr = UART_FCR_DEFVAL, 507b77b1f6SAdam Ford }; 517b77b1f6SAdam Ford 527b77b1f6SAdam Ford U_BOOT_DEVICE(omap3logic_uart) = { 53c7b9686dSThomas Chou "ns16550_serial", 547b77b1f6SAdam Ford &omap3logic_serial 557b77b1f6SAdam Ford }; 5615fde737SAdam Ford #endif 577b77b1f6SAdam Ford 5815fde737SAdam Ford /* 5915fde737SAdam Ford * two dimensional array of strucures containining board name and Linux 6015fde737SAdam Ford * machine IDs; row it selected based on CPU column is slected based 6115fde737SAdam Ford * on hsusb0_data5 pin having a pulldown resistor 6215fde737SAdam Ford */ 6386887f8eSPeter Barada static struct board_id { 6486887f8eSPeter Barada char *name; 6586887f8eSPeter Barada int machine_id; 66c63d270dSTom Rini char *fdtfile; 6786887f8eSPeter Barada } boards[2][2] = { 6886887f8eSPeter Barada { 6986887f8eSPeter Barada { 7086887f8eSPeter Barada .name = "OMAP35xx SOM LV", 7186887f8eSPeter Barada .machine_id = MACH_TYPE_OMAP3530_LV_SOM, 72c63d270dSTom Rini .fdtfile = "logicpd-som-lv-35xx-devkit.dtb", 7386887f8eSPeter Barada }, 7486887f8eSPeter Barada { 7586887f8eSPeter Barada .name = "OMAP35xx Torpedo", 7686887f8eSPeter Barada .machine_id = MACH_TYPE_OMAP3_TORPEDO, 77c63d270dSTom Rini .fdtfile = "logicpd-torpedo-35xx-devkit.dtb", 7886887f8eSPeter Barada }, 7986887f8eSPeter Barada }, 8086887f8eSPeter Barada { 8186887f8eSPeter Barada { 8286887f8eSPeter Barada .name = "DM37xx SOM LV", 83c63d270dSTom Rini .fdtfile = "logicpd-som-lv-37xx-devkit.dtb", 8486887f8eSPeter Barada }, 8586887f8eSPeter Barada { 8686887f8eSPeter Barada .name = "DM37xx Torpedo", 87c63d270dSTom Rini .fdtfile = "logicpd-torpedo-37xx-devkit.dtb", 8886887f8eSPeter Barada }, 8986887f8eSPeter Barada }, 9086887f8eSPeter Barada }; 9186887f8eSPeter Barada 9249c7303fSAdam Ford #ifdef CONFIG_SPL_OS_BOOT 9349c7303fSAdam Ford int spl_start_uboot(void) 9449c7303fSAdam Ford { 9549c7303fSAdam Ford /* break into full u-boot on 'c' */ 9649c7303fSAdam Ford return serial_tstc() && serial_getc() == 'c'; 9749c7303fSAdam Ford } 9849c7303fSAdam Ford #endif 9949c7303fSAdam Ford 10049c7303fSAdam Ford #if defined(CONFIG_SPL_BUILD) 10149c7303fSAdam Ford /* 10249c7303fSAdam Ford * Routine: get_board_mem_timings 10349c7303fSAdam Ford * Description: If we use SPL then there is no x-loader nor config header 10449c7303fSAdam Ford * so we have to setup the DDR timings ourself on the first bank. This 10549c7303fSAdam Ford * provides the timing values back to the function that configures 10649c7303fSAdam Ford * the memory. 10749c7303fSAdam Ford */ 10849c7303fSAdam Ford void get_board_mem_timings(struct board_sdrc_timings *timings) 10949c7303fSAdam Ford { 11049c7303fSAdam Ford timings->mr = MICRON_V_MR_165; 11149c7303fSAdam Ford /* 256MB DDR */ 11249c7303fSAdam Ford timings->mcfg = MICRON_V_MCFG_200(256 << 20); 11349c7303fSAdam Ford timings->ctrla = MICRON_V_ACTIMA_200; 11449c7303fSAdam Ford timings->ctrlb = MICRON_V_ACTIMB_200; 11549c7303fSAdam Ford timings->rfr_ctrl = SDP_3430_SDRC_RFR_CTRL_200MHz; 11649c7303fSAdam Ford } 117*6032c029SAdam Ford 118*6032c029SAdam Ford #define GPMC_NAND_COMMAND_0 (OMAP34XX_GPMC_BASE + 0x7c) 119*6032c029SAdam Ford #define GPMC_NAND_DATA_0 (OMAP34XX_GPMC_BASE + 0x84) 120*6032c029SAdam Ford #define GPMC_NAND_ADDRESS_0 (OMAP34XX_GPMC_BASE + 0x80) 121*6032c029SAdam Ford 122*6032c029SAdam Ford void spl_board_prepare_for_linux(void) 123*6032c029SAdam Ford { 124*6032c029SAdam Ford /* The Micron NAND starts locked which 125*6032c029SAdam Ford * prohibits mounting the NAND as RW 126*6032c029SAdam Ford * The following commands are what unlocks 127*6032c029SAdam Ford * the NAND to become RW Falcon Mode does not 128*6032c029SAdam Ford * have as many smarts as U-Boot, but Logic PD 129*6032c029SAdam Ford * only makes NAND with 512MB so these hard coded 130*6032c029SAdam Ford * values should work for all current models 131*6032c029SAdam Ford */ 132*6032c029SAdam Ford 133*6032c029SAdam Ford writeb(0x70, GPMC_NAND_COMMAND_0); 134*6032c029SAdam Ford writeb(-1, GPMC_NAND_DATA_0); 135*6032c029SAdam Ford writeb(0x7a, GPMC_NAND_COMMAND_0); 136*6032c029SAdam Ford writeb(0x00, GPMC_NAND_ADDRESS_0); 137*6032c029SAdam Ford writeb(0x00, GPMC_NAND_ADDRESS_0); 138*6032c029SAdam Ford writeb(0x00, GPMC_NAND_ADDRESS_0); 139*6032c029SAdam Ford writeb(-1, GPMC_NAND_COMMAND_0); 140*6032c029SAdam Ford 141*6032c029SAdam Ford /* Begin address 0 */ 142*6032c029SAdam Ford writeb(NAND_CMD_UNLOCK1, 0x6e00007c); 143*6032c029SAdam Ford writeb(0x00, GPMC_NAND_ADDRESS_0); 144*6032c029SAdam Ford writeb(0x00, GPMC_NAND_ADDRESS_0); 145*6032c029SAdam Ford writeb(0x00, GPMC_NAND_ADDRESS_0); 146*6032c029SAdam Ford writeb(-1, GPMC_NAND_DATA_0); 147*6032c029SAdam Ford 148*6032c029SAdam Ford /* Ending address at the end of Flash */ 149*6032c029SAdam Ford writeb(NAND_CMD_UNLOCK2, GPMC_NAND_COMMAND_0); 150*6032c029SAdam Ford writeb(0xc0, GPMC_NAND_ADDRESS_0); 151*6032c029SAdam Ford writeb(0xff, GPMC_NAND_ADDRESS_0); 152*6032c029SAdam Ford writeb(0x03, GPMC_NAND_ADDRESS_0); 153*6032c029SAdam Ford writeb(-1, GPMC_NAND_DATA_0); 154*6032c029SAdam Ford writeb(0x79, GPMC_NAND_COMMAND_0); 155*6032c029SAdam Ford writeb(-1, GPMC_NAND_DATA_0); 156*6032c029SAdam Ford writeb(-1, GPMC_NAND_DATA_0); 157*6032c029SAdam Ford } 15849c7303fSAdam Ford #endif 15949c7303fSAdam Ford 160588e41d2SAdam Ford #ifdef CONFIG_USB_MUSB_OMAP2PLUS 161588e41d2SAdam Ford static struct musb_hdrc_config musb_config = { 162588e41d2SAdam Ford .multipoint = 1, 163588e41d2SAdam Ford .dyn_fifo = 1, 164588e41d2SAdam Ford .num_eps = 16, 165588e41d2SAdam Ford .ram_bits = 12, 166588e41d2SAdam Ford }; 167588e41d2SAdam Ford 168588e41d2SAdam Ford static struct omap_musb_board_data musb_board_data = { 169588e41d2SAdam Ford .interface_type = MUSB_INTERFACE_ULPI, 170588e41d2SAdam Ford }; 171588e41d2SAdam Ford 172588e41d2SAdam Ford static struct musb_hdrc_platform_data musb_plat = { 173588e41d2SAdam Ford #if defined(CONFIG_USB_MUSB_HOST) 174588e41d2SAdam Ford .mode = MUSB_HOST, 175588e41d2SAdam Ford #elif defined(CONFIG_USB_MUSB_GADGET) 176588e41d2SAdam Ford .mode = MUSB_PERIPHERAL, 177588e41d2SAdam Ford #else 178588e41d2SAdam Ford #error "Please define either CONFIG_USB_MUSB_HOST or CONFIG_USB_MUSB_GADGET" 179588e41d2SAdam Ford #endif 180588e41d2SAdam Ford .config = &musb_config, 181588e41d2SAdam Ford .power = 100, 182588e41d2SAdam Ford .platform_ops = &omap2430_ops, 183588e41d2SAdam Ford .board_data = &musb_board_data, 184588e41d2SAdam Ford }; 185588e41d2SAdam Ford #endif 186588e41d2SAdam Ford 18774cd48e1SAdam Ford #if defined(CONFIG_USB_EHCI_HCD) && !defined(CONFIG_SPL_BUILD) 18874cd48e1SAdam Ford /* Call usb_stop() before starting the kernel */ 18974cd48e1SAdam Ford void show_boot_progress(int val) 19074cd48e1SAdam Ford { 19174cd48e1SAdam Ford if (val == BOOTSTAGE_ID_RUN_OS) 19274cd48e1SAdam Ford usb_stop(); 19374cd48e1SAdam Ford } 19474cd48e1SAdam Ford 19574cd48e1SAdam Ford static struct omap_usbhs_board_data usbhs_bdata = { 19674cd48e1SAdam Ford .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, 19774cd48e1SAdam Ford .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY, 19874cd48e1SAdam Ford .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED 19974cd48e1SAdam Ford }; 20074cd48e1SAdam Ford 20174cd48e1SAdam Ford int ehci_hcd_init(int index, enum usb_init_type init, 20274cd48e1SAdam Ford struct ehci_hccr **hccr, struct ehci_hcor **hcor) 20374cd48e1SAdam Ford { 20474cd48e1SAdam Ford return omap_ehci_hcd_init(index, &usbhs_bdata, hccr, hcor); 20574cd48e1SAdam Ford } 20674cd48e1SAdam Ford 20774cd48e1SAdam Ford int ehci_hcd_stop(int index) 20874cd48e1SAdam Ford { 20974cd48e1SAdam Ford return omap_ehci_hcd_stop(); 21074cd48e1SAdam Ford } 21174cd48e1SAdam Ford 21274cd48e1SAdam Ford #endif /* CONFIG_USB_EHCI_HCD */ 21374cd48e1SAdam Ford 214588e41d2SAdam Ford 21549c7303fSAdam Ford /* 21649c7303fSAdam Ford * Routine: misc_init_r 21749c7303fSAdam Ford * Description: Configure board specific parts 21849c7303fSAdam Ford */ 21949c7303fSAdam Ford int misc_init_r(void) 22049c7303fSAdam Ford { 22149c7303fSAdam Ford twl4030_power_init(); 22249c7303fSAdam Ford omap_die_id_display(); 22349c7303fSAdam Ford 224588e41d2SAdam Ford #ifdef CONFIG_USB_MUSB_OMAP2PLUS 225588e41d2SAdam Ford musb_register(&musb_plat, &musb_board_data, (void *)MUSB_BASE); 226588e41d2SAdam Ford #endif 227588e41d2SAdam Ford 22849c7303fSAdam Ford return 0; 22949c7303fSAdam Ford } 23049c7303fSAdam Ford 23186887f8eSPeter Barada /* 23286887f8eSPeter Barada * BOARD_ID_GPIO - GPIO of pin with optional pulldown resistor on SOM LV 23386887f8eSPeter Barada */ 23486887f8eSPeter Barada #define BOARD_ID_GPIO 189 /* hsusb0_data5 pin */ 23586887f8eSPeter Barada 23686887f8eSPeter Barada /* 23786887f8eSPeter Barada * Routine: board_init 23886887f8eSPeter Barada * Description: Early hardware init. 23986887f8eSPeter Barada */ 24086887f8eSPeter Barada int board_init(void) 24186887f8eSPeter Barada { 24286887f8eSPeter Barada gpmc_init(); /* in SRAM or SDRAM, finish GPMC */ 24386887f8eSPeter Barada 24486887f8eSPeter Barada /* boot param addr */ 24586887f8eSPeter Barada gd->bd->bi_boot_params = (OMAP34XX_SDRC_CS0 + 0x100); 24686887f8eSPeter Barada 247c63d270dSTom Rini return 0; 248c63d270dSTom Rini } 249c63d270dSTom Rini 250c63d270dSTom Rini #ifdef CONFIG_BOARD_LATE_INIT 251157af4f8SAdam Ford 252157af4f8SAdam Ford static void unlock_nand(void) 253157af4f8SAdam Ford { 254157af4f8SAdam Ford int dev = nand_curr_device; 255157af4f8SAdam Ford struct mtd_info *mtd; 256157af4f8SAdam Ford 257157af4f8SAdam Ford mtd = get_nand_dev_by_index(dev); 258157af4f8SAdam Ford nand_unlock(mtd, 0, mtd->size, 0); 259157af4f8SAdam Ford } 260157af4f8SAdam Ford 261c63d270dSTom Rini int board_late_init(void) 262c63d270dSTom Rini { 263c63d270dSTom Rini struct board_id *board; 264c63d270dSTom Rini unsigned int val; 265c63d270dSTom Rini 26686887f8eSPeter Barada /* 26786887f8eSPeter Barada * To identify between a SOM LV and Torpedo module, 26886887f8eSPeter Barada * a pulldown resistor is on hsusb0_data5 for the SOM LV module. 26986887f8eSPeter Barada * Drive the pin (and let it soak), then read it back. 27086887f8eSPeter Barada * If the pin is still high its a Torpedo. If low its a SOM LV 27186887f8eSPeter Barada */ 27286887f8eSPeter Barada 27386887f8eSPeter Barada /* Mux hsusb0_data5 as a GPIO */ 27486887f8eSPeter Barada MUX_VAL(CP(HSUSB0_DATA5), (IEN | PTD | DIS | M4)); 27586887f8eSPeter Barada 27686887f8eSPeter Barada if (gpio_request(BOARD_ID_GPIO, "husb0_data5.gpio_189") == 0) { 27786887f8eSPeter Barada 27886887f8eSPeter Barada /* 27986887f8eSPeter Barada * Drive BOARD_ID_GPIO - the pulldown resistor on the SOM LV 28086887f8eSPeter Barada * will drain the voltage. 28186887f8eSPeter Barada */ 28286887f8eSPeter Barada gpio_direction_output(BOARD_ID_GPIO, 0); 28386887f8eSPeter Barada gpio_set_value(BOARD_ID_GPIO, 1); 28486887f8eSPeter Barada 28586887f8eSPeter Barada /* Let it soak for a bit */ 28686887f8eSPeter Barada sdelay(0x100); 28786887f8eSPeter Barada 28886887f8eSPeter Barada /* 28986887f8eSPeter Barada * Read state of BOARD_ID_GPIO as an input and if its set. 29086887f8eSPeter Barada * If so the board is a Torpedo 29186887f8eSPeter Barada */ 29286887f8eSPeter Barada gpio_direction_input(BOARD_ID_GPIO); 29386887f8eSPeter Barada val = gpio_get_value(BOARD_ID_GPIO); 29486887f8eSPeter Barada gpio_free(BOARD_ID_GPIO); 29586887f8eSPeter Barada 29686887f8eSPeter Barada board = &boards[!!(get_cpu_family() == CPU_OMAP36XX)][!!val]; 29786887f8eSPeter Barada printf("Board: %s\n", board->name); 29886887f8eSPeter Barada 29986887f8eSPeter Barada /* Set the machine_id passed to Linux */ 300c63d270dSTom Rini if (board->machine_id) 30186887f8eSPeter Barada gd->bd->bi_arch_number = board->machine_id; 302c63d270dSTom Rini 303c63d270dSTom Rini /* If the user has not set fdtimage, set the default */ 30400caae6dSSimon Glass if (!env_get("fdtimage")) 305382bee57SSimon Glass env_set("fdtimage", board->fdtfile); 30686887f8eSPeter Barada } 30786887f8eSPeter Barada 30886887f8eSPeter Barada /* restore hsusb0_data5 pin as hsusb0_data5 */ 30986887f8eSPeter Barada MUX_VAL(CP(HSUSB0_DATA5), (IEN | PTD | DIS | M0)); 310157af4f8SAdam Ford 311157af4f8SAdam Ford #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK 312157af4f8SAdam Ford unlock_nand(); 313157af4f8SAdam Ford #endif 31426ef7a27SAdam Ford return 0; 31526ef7a27SAdam Ford } 31626ef7a27SAdam Ford #endif 31726ef7a27SAdam Ford 3184aa2ba3aSMasahiro Yamada #if defined(CONFIG_MMC) 31986887f8eSPeter Barada int board_mmc_init(bd_t *bis) 32086887f8eSPeter Barada { 321e3913f56SNikita Kiryanov return omap_mmc_init(0, 0, 0, -1, -1); 32286887f8eSPeter Barada } 32386887f8eSPeter Barada #endif 32486887f8eSPeter Barada 3254aa2ba3aSMasahiro Yamada #if defined(CONFIG_MMC) 326aac5450eSPaul Kocialkowski void board_mmc_power_init(void) 327aac5450eSPaul Kocialkowski { 328aac5450eSPaul Kocialkowski twl4030_power_mmc_init(0); 329aac5450eSPaul Kocialkowski } 330aac5450eSPaul Kocialkowski #endif 331aac5450eSPaul Kocialkowski 33286887f8eSPeter Barada #ifdef CONFIG_SMC911X 33386887f8eSPeter Barada /* GPMC CS1 settings for Logic SOM LV/Torpedo LAN92xx Ethernet chip */ 33486887f8eSPeter Barada static const u32 gpmc_lan92xx_config[] = { 33586887f8eSPeter Barada NET_LAN92XX_GPMC_CONFIG1, 33686887f8eSPeter Barada NET_LAN92XX_GPMC_CONFIG2, 33786887f8eSPeter Barada NET_LAN92XX_GPMC_CONFIG3, 33886887f8eSPeter Barada NET_LAN92XX_GPMC_CONFIG4, 33986887f8eSPeter Barada NET_LAN92XX_GPMC_CONFIG5, 34086887f8eSPeter Barada NET_LAN92XX_GPMC_CONFIG6, 34186887f8eSPeter Barada }; 34286887f8eSPeter Barada 34386887f8eSPeter Barada int board_eth_init(bd_t *bis) 34486887f8eSPeter Barada { 34586887f8eSPeter Barada enable_gpmc_cs_config(gpmc_lan92xx_config, &gpmc_cfg->cs[1], 34686887f8eSPeter Barada CONFIG_SMC911X_BASE, GPMC_SIZE_16M); 34786887f8eSPeter Barada 34886887f8eSPeter Barada return smc911x_initialize(0, CONFIG_SMC911X_BASE); 34986887f8eSPeter Barada } 35086887f8eSPeter Barada #endif 35186887f8eSPeter Barada 35286887f8eSPeter Barada 353