9
0
Fork 0
barebox/arch/arm/boards/freescale-mx28-evk/mx28-evk.c

303 lines
8.0 KiB
C

/*
* Copyright (C) 2010 Juergen Beisert, Pengutronix <kernel@pengutronix.de>
* Copyright (C) 2011 Marc Kleine-Budde, Pengutronix <mkl@pengutronix.de>
* Copyright (C) 2011 Wolfram Sang, Pengutronix <w.sang@pengutronix.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <common.h>
#include <environment.h>
#include <errno.h>
#include <fec.h>
#include <gpio.h>
#include <init.h>
#include <mci.h>
#include <io.h>
#include <net.h>
#include <mach/clock.h>
#include <mach/imx-regs.h>
#include <mach/iomux-imx28.h>
#include <mach/mci.h>
#include <mach/fb.h>
#include <mach/ocotp.h>
#include <spi/spi.h>
#include <asm/armlinux.h>
#include <asm/mmu.h>
#include <generated/mach-types.h>
#define MX28EVK_FEC_PHY_RESET_GPIO 141
/* setup the CPU card internal signals */
static const uint32_t mx28evk_pads[] = {
/* duart */
PWM0_DUART_RX | VE_3_3V,
PWM1_DUART_TX | VE_3_3V,
/* fec0 */
ENET_CLK | VE_3_3V | BITKEEPER(0),
ENET0_MDC | VE_3_3V | PULLUP(1),
ENET0_MDIO | VE_3_3V | PULLUP(1),
ENET0_TXD0 | VE_3_3V | PULLUP(1),
ENET0_TXD1 | VE_3_3V | PULLUP(1),
ENET0_TX_EN | VE_3_3V | PULLUP(1),
ENET0_TX_CLK | VE_3_3V | BITKEEPER(0),
ENET0_RXD0 | VE_3_3V | PULLUP(1),
ENET0_RXD1 | VE_3_3V | PULLUP(1),
ENET0_RX_EN | VE_3_3V | PULLUP(1),
/* send a "good morning" to the ext. phy 0 = reset */
ENET0_RX_CLK_GPIO | VE_3_3V | PULLUP(0) | GPIO_OUT | GPIO_VALUE(0),
/* phy power control 1 = on */
SSP1_D3_GPIO | VE_3_3V | PULLUP(0) | GPIO_OUT | GPIO_VALUE(0),
/* mmc0 */
SSP0_D0 | VE_3_3V | PULLUP(1),
SSP0_D1 | VE_3_3V | PULLUP(1),
SSP0_D2 | VE_3_3V | PULLUP(1),
SSP0_D3 | VE_3_3V | PULLUP(1),
SSP0_D4 | VE_3_3V | PULLUP(1),
SSP0_D5 | VE_3_3V | PULLUP(1),
SSP0_D6 | VE_3_3V | PULLUP(1),
SSP0_D7 | VE_3_3V | PULLUP(1),
SSP0_CMD | VE_3_3V | PULLUP(1),
SSP0_CD | VE_3_3V | PULLUP(1),
SSP0_SCK | VE_3_3V | BITKEEPER(0),
/* MCI slot power control 1 = off */
PWM3_GPIO | VE_3_3V | GPIO_OUT | GPIO_VALUE(0),
/* MCI write protect 1 = not protected */
SSP1_SCK_GPIO | VE_3_3V | GPIO_IN,
/* lcd */
LCD_WR_RWN_LCD_HSYNC | VE_3_3V | STRENGTH(S8MA),
LCD_RD_E_LCD_VSYNC | VE_3_3V | STRENGTH(S8MA),
LCD_CS_LCD_ENABLE | VE_3_3V | STRENGTH(S8MA),
LCD_RS_LCD_DOTCLK | VE_3_3V | STRENGTH(S8MA),
LCD_D0 | VE_3_3V | STRENGTH(S8MA),
LCD_D1 | VE_3_3V | STRENGTH(S8MA),
LCD_D2 | VE_3_3V | STRENGTH(S8MA),
LCD_D3 | VE_3_3V | STRENGTH(S8MA),
LCD_D4 | VE_3_3V | STRENGTH(S8MA),
LCD_D5 | VE_3_3V | STRENGTH(S8MA),
LCD_D6 | VE_3_3V | STRENGTH(S8MA),
LCD_D7 | VE_3_3V | STRENGTH(S8MA),
LCD_D8 | VE_3_3V | STRENGTH(S8MA),
LCD_D9 | VE_3_3V | STRENGTH(S8MA),
LCD_D10 | VE_3_3V | STRENGTH(S8MA),
LCD_D11 | VE_3_3V | STRENGTH(S8MA),
LCD_D12 | VE_3_3V | STRENGTH(S8MA),
LCD_D13 | VE_3_3V | STRENGTH(S8MA),
LCD_D14 | VE_3_3V | STRENGTH(S8MA),
LCD_D15 | VE_3_3V | STRENGTH(S8MA),
LCD_D16 | VE_3_3V | STRENGTH(S8MA),
LCD_D17 | VE_3_3V | STRENGTH(S8MA),
LCD_D18 | VE_3_3V | STRENGTH(S8MA),
LCD_D19 | VE_3_3V | STRENGTH(S8MA),
LCD_D20 | VE_3_3V | STRENGTH(S8MA),
LCD_D21 | VE_3_3V | STRENGTH(S8MA),
LCD_D22 | VE_3_3V | STRENGTH(S8MA),
LCD_D23 | VE_3_3V | STRENGTH(S8MA),
LCD_RESET_GPIO | VE_3_3V | GPIO_OUT | GPIO_VALUE(0),
/* backlight */
PWM2_GPIO | VE_3_3V | STRENGTH(S4MA) | SE | VE,
/* GPMI-NAND (blocks mmc1 for now) */
GPMI_D0 | VE_3_3V,
GPMI_D1 | VE_3_3V,
GPMI_D2 | VE_3_3V,
GPMI_D3 | VE_3_3V,
GPMI_D4 | VE_3_3V,
GPMI_D5 | VE_3_3V,
GPMI_D6 | VE_3_3V,
GPMI_D7 | VE_3_3V,
GPMI_READY0 | VE_3_3V, /* external PU */
GPMI_CE0N | VE_3_3V, /* external PU */
GPMI_RDN | VE_3_3V,
GPMI_WRN | VE_3_3V,
GPMI_ALE | VE_3_3V,
GPMI_CLE | VE_3_3V,
GPMI_RESETN, /* act as WP, external PU */
/* SSP */
SSP2_D0 | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* MISO DO */
SSP2_D3 | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* SS0 !CS */
SSP2_CMD | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* MOSI DIO */
SSP2_SCK | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* CLK */
};
static struct mxs_mci_platform_data mci_pdata = {
.caps = MMC_MODE_8BIT,
.voltages = MMC_VDD_32_33 | MMC_VDD_33_34, /* fixed to 3.3 V */
.f_min = 400 * 1000,
.f_max = 25000000,
};
/* fec */
static void mx28_evk_get_ethaddr(void)
{
u8 mac_ocotp[3], mac[6];
int ret;
ret = mxs_ocotp_read(mac_ocotp, 3, 0);
if (ret != 3) {
pr_err("Reading MAC from OCOTP failed!\n");
return;
}
mac[0] = 0x00;
mac[1] = 0x04;
mac[2] = 0x9f;
mac[3] = mac_ocotp[2];
mac[4] = mac_ocotp[1];
mac[5] = mac_ocotp[0];
eth_register_ethaddr(0, mac);
}
static void __init mx28_evk_fec_reset(void)
{
mdelay(1);
gpio_set_value(MX28EVK_FEC_PHY_RESET_GPIO, 1);
}
/* PhyAD[0..2]=0, RMIISEL=1 */
static struct fec_platform_data fec_info = {
.xcv_type = PHY_INTERFACE_MODE_RMII,
.phy_addr = 0,
};
/* LCD */
static struct fb_videomode mx28_evk_vmodes[] = {
{
.name = "43WVF1G-0",
.refresh = 60,
.xres = 800,
.yres = 480,
.pixclock = 29851 /* (33,5 MHz) */,
.left_margin = 89,
.hsync_len = 10,
.right_margin = 164,
.upper_margin = 23,
.vsync_len = 10,
.lower_margin = 10,
.sync = FB_SYNC_DE_HIGH_ACT | FB_SYNC_CLK_INVERT,
.vmode = FB_VMODE_NONINTERLACED,
.flag = 0,
}
};
#define MAX_FB_SIZE SZ_2M
#define GPIO_LCD_RESET 126 /* Reset */
#define GPIO_BACKLIGHT 114 /* Backlight active */
static void mx28_evk_fb_enable(int enable)
{
gpio_direction_output(GPIO_LCD_RESET, enable);
/* Give the display a chance to sync before we enable
* the backlight to avoid flickering
*/
if (enable)
mdelay(200);
gpio_direction_output(GPIO_BACKLIGHT, enable);
}
static struct imx_fb_platformdata mx28_evk_fb_pdata = {
.mode_list = mx28_evk_vmodes,
.mode_cnt = ARRAY_SIZE(mx28_evk_vmodes),
.dotclk_delay = 0, /* no adaption required */
.ld_intf_width = STMLCDIF_24BIT, /* full 24 bit */
.bits_per_pixel = 32,
.fixed_screen = NULL,
.enable = mx28_evk_fb_enable,
};
static int mx28_evk_mem_init(void)
{
arm_add_mem_device("ram0", IMX_MEMORY_BASE, 128 * 1024 * 1024);
return 0;
}
mem_initcall(mx28_evk_mem_init);
static const struct spi_board_info mx28evk_spi_board_info[] = {
{
.name = "m25p80",
/*
* we leave this with the lower frequency
* as the ssp unit otherwise locks up
*/
.max_speed_hz = 32000000,
.bus_num = 2,
.chip_select = 0,
}
};
static int mx28_evk_devices_init(void)
{
int i;
/* initizalize muxing */
for (i = 0; i < ARRAY_SIZE(mx28evk_pads); i++)
imx_gpio_mode(mx28evk_pads[i]);
/* enable IOCLK0 to run at the PLL frequency */
imx_set_ioclk(0, 480000000);
imx_set_ioclk(1, 320000000);
/* run the SSP unit clock at 100 MHz */
imx_set_sspclk(0, 100000000, 1);
/* run the SSP unit 2 clock at 160Mhz */
imx_set_sspclk(2, 160000000, 1);
armlinux_set_bootparams((void *)IMX_MEMORY_BASE + 0x100);
armlinux_set_architecture(MACH_TYPE_MX28EVK);
add_generic_device("mxs_mci", 0, NULL, IMX_SSP0_BASE, 0x2000,
IORESOURCE_MEM, &mci_pdata);
add_generic_device("stmfb", 0, NULL, IMX_FB_BASE, 0x2000,
IORESOURCE_MEM, &mx28_evk_fb_pdata);
add_generic_device("ocotp", 0, NULL, IMX_OCOTP_BASE, 0x2000,
IORESOURCE_MEM, NULL);
mx28_evk_get_ethaddr(); /* must be after registering ocotp */
imx_enable_enetclk();
mx28_evk_fec_reset();
add_generic_device("imx28-fec", 0, NULL, IMX_FEC0_BASE, 0x4000,
IORESOURCE_MEM, &fec_info);
add_generic_device("mxs_nand", 0, NULL, MXS_GPMI_BASE, 0x2000,
IORESOURCE_MEM, NULL);
spi_register_board_info(mx28evk_spi_board_info,
ARRAY_SIZE(mx28evk_spi_board_info));
add_generic_device("mxs_spi", 2, NULL, IMX_SSP2_BASE, 0x2000,
IORESOURCE_MEM, NULL);
return 0;
}
device_initcall(mx28_evk_devices_init);
static int mx28_evk_console_init(void)
{
add_generic_device("stm_serial", 0, NULL, IMX_DBGUART_BASE, 0x2000,
IORESOURCE_MEM, NULL);
return 0;
}
console_initcall(mx28_evk_console_init);