board-cpuimx51sd.c 9.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
/*
 *
 * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
 *
 * based on board-mx51_babbage.c which is
 * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
 *
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/i2c/tsc2007.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/fsl_devices.h>
#include <linux/i2c-gpio.h>
#include <linux/spi/spi.h>
#include <linux/can/platform/mcp251x.h>

#include <mach/eukrea-baseboards.h>
#include <mach/common.h>
#include <mach/hardware.h>
#include <mach/iomux-mx51.h>
#include <mach/mxc_ehci.h>

#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>

#include "devices-imx51.h"
#include "devices.h"

A
Arnaud Patard (Rtp) 已提交
46 47 48 49 50 51 52 53 54 55 56 57 58
#define USBH1_RST		IMX_GPIO_NR(2, 28)
#define ETH_RST			IMX_GPIO_NR(2, 31)
#define TSC2007_IRQGPIO		IMX_GPIO_NR(3, 12)
#define CAN_IRQGPIO		IMX_GPIO_NR(1, 1)
#define CAN_RST			IMX_GPIO_NR(4, 15)
#define CAN_NCS			IMX_GPIO_NR(4, 24)
#define CAN_RXOBF		IMX_GPIO_NR(1, 4)
#define CAN_RX1BF		IMX_GPIO_NR(1, 6)
#define CAN_TXORTS		IMX_GPIO_NR(1, 7)
#define CAN_TX1RTS		IMX_GPIO_NR(1, 8)
#define CAN_TX2RTS		IMX_GPIO_NR(1, 9)
#define I2C_SCL			IMX_GPIO_NR(4, 16)
#define I2C_SDA			IMX_GPIO_NR(4, 17)
59 60 61 62 63 64 65 66 67

/* USB_CTRL_1 */
#define MX51_USB_CTRL_1_OFFSET		0x10
#define MX51_USB_CTRL_UH1_EXT_CLK_EN	(1 << 25)

#define	MX51_USB_PLLDIV_12_MHZ		0x00
#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
#define	MX51_USB_PLL_DIV_24_MHZ		0x02

68
static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
	/* UART1 */
	MX51_PAD_UART1_RXD__UART1_RXD,
	MX51_PAD_UART1_TXD__UART1_TXD,
	MX51_PAD_UART1_RTS__UART1_RTS,
	MX51_PAD_UART1_CTS__UART1_CTS,

	/* USB HOST1 */
	MX51_PAD_USBH1_CLK__USBH1_CLK,
	MX51_PAD_USBH1_DIR__USBH1_DIR,
	MX51_PAD_USBH1_NXT__USBH1_NXT,
	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
	MX51_PAD_USBH1_STP__USBH1_STP,
S
Sascha Hauer 已提交
88
	MX51_PAD_EIM_CS3__GPIO2_28,		/* PHY nRESET */
89 90

	/* FEC */
S
Sascha Hauer 已提交
91
	MX51_PAD_EIM_DTACK__GPIO2_31,		/* PHY nRESET */
92 93

	/* HSI2C */
S
Sascha Hauer 已提交
94 95
	MX51_PAD_I2C1_CLK__GPIO4_16,
	MX51_PAD_I2C1_DAT__GPIO4_17,
96 97 98 99 100

	/* CAN */
	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
S
Sascha Hauer 已提交
101 102 103 104 105 106 107 108
	MX51_PAD_CSPI1_SS0__GPIO4_24,		/* nCS */
	MX51_PAD_CSI2_PIXCLK__GPIO4_15,		/* nReset */
	MX51_PAD_GPIO1_1__GPIO1_1,		/* IRQ */
	MX51_PAD_GPIO1_4__GPIO1_4,		/* Control signals */
	MX51_PAD_GPIO1_6__GPIO1_6,
	MX51_PAD_GPIO1_7__GPIO1_7,
	MX51_PAD_GPIO1_8__GPIO1_8,
	MX51_PAD_GPIO1_9__GPIO1_9,
109 110

	/* Touchscreen */
S
Sascha Hauer 已提交
111 112 113 114
	/* IRQ */
	_MX51_PAD_CSI1_D8__GPIO3_12 | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
};

static const struct imxuart_platform_data uart_pdata __initconst = {
	.flags = IMXUART_HAVE_RTSCTS,
};

static int ts_get_pendown_state(void)
{
	return gpio_get_value(TSC2007_IRQGPIO) ? 0 : 1;
}

static struct tsc2007_platform_data tsc2007_info = {
	.model			= 2007,
	.x_plate_ohms		= 180,
	.get_pendown_state	= ts_get_pendown_state,
};

static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
	{
		I2C_BOARD_INFO("pcf8563", 0x51),
	}, {
		I2C_BOARD_INFO("tsc2007", 0x49),
		.type		= "tsc2007",
		.platform_data	= &tsc2007_info,
		.irq		= gpio_to_irq(TSC2007_IRQGPIO),
	},
};

static const struct mxc_nand_platform_data
		eukrea_cpuimx51sd_nand_board_info __initconst = {
	.width		= 1,
	.hw_ecc		= 1,
	.flash_bbt	= 1,
};

/* This function is board specific as the bit mask for the plldiv will also
be different for other Freescale SoCs, thus a common bitmask is not
possible and cannot get place in /plat-mxc/ehci.c.*/
static int initialize_otg_port(struct platform_device *pdev)
{
	u32 v;
	void __iomem *usb_base;
	void __iomem *usbother_base;

	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
160 161
	if (!usb_base)
		return -ENOMEM;
162 163 164 165 166 167 168 169
	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;

	/* Set the PHY clock to 19.2MHz */
	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
	v |= MX51_USB_PLL_DIV_19_2_MHZ;
	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
	iounmap(usb_base);
170 171 172 173

	mdelay(10);

	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
174 175 176 177 178 179 180 181 182
}

static int initialize_usbh1_port(struct platform_device *pdev)
{
	u32 v;
	void __iomem *usb_base;
	void __iomem *usbother_base;

	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
183 184
	if (!usb_base)
		return -ENOMEM;
185 186 187 188 189 190 191
	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;

	/* The clock for the USBH1 ULPI port will come from the PHY. */
	v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
			usbother_base + MX51_USB_CTRL_1_OFFSET);
	iounmap(usb_base);
192 193 194 195 196

	mdelay(10);

	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
			MXC_EHCI_ITC_NO_THRESHOLD);
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
}

static struct mxc_usbh_platform_data dr_utmi_config = {
	.init		= initialize_otg_port,
	.portsc	= MXC_EHCI_UTMI_16BIT,
};

static struct fsl_usb2_platform_data usb_pdata = {
	.operating_mode	= FSL_USB2_DR_DEVICE,
	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
};

static struct mxc_usbh_platform_data usbh1_config = {
	.init		= initialize_usbh1_port,
	.portsc	= MXC_EHCI_MODE_ULPI,
};

static int otg_mode_host;

static int __init eukrea_cpuimx51sd_otg_mode(char *options)
{
	if (!strcmp(options, "host"))
		otg_mode_host = 1;
	else if (!strcmp(options, "device"))
		otg_mode_host = 0;
	else
		pr_info("otg_mode neither \"host\" nor \"device\". "
			"Defaulting to device\n");
	return 0;
}
__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode);

static struct i2c_gpio_platform_data pdata = {
	.sda_pin		= I2C_SDA,
	.sda_is_open_drain	= 0,
	.scl_pin		= I2C_SCL,
	.scl_is_open_drain	= 0,
	.udelay			= 2,
};

static struct platform_device hsi2c_gpio_device = {
	.name			= "i2c-gpio",
	.id			= 0,
	.dev.platform_data	= &pdata,
};

static struct mcp251x_platform_data mcp251x_info = {
	.oscillator_frequency = 24E6,
};

static struct spi_board_info cpuimx51sd_spi_device[] = {
	{
		.modalias        = "mcp2515",
		.max_speed_hz    = 6500000,
		.bus_num         = 0,
		.mode		= SPI_MODE_0,
		.chip_select     = 0,
		.platform_data   = &mcp251x_info,
A
Arnaud Patard (Rtp) 已提交
255
		.irq             = gpio_to_irq(CAN_IRQGPIO)
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
	},
};

static int cpuimx51sd_spi1_cs[] = {
	CAN_NCS,
};

static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = {
	.chipselect	= cpuimx51sd_spi1_cs,
	.num_chipselect	= ARRAY_SIZE(cpuimx51sd_spi1_cs),
};

static struct platform_device *platform_devices[] __initdata = {
	&hsi2c_gpio_device,
};

static void __init eukrea_cpuimx51sd_init(void)
{
	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
					ARRAY_SIZE(eukrea_cpuimx51sd_pads));

	imx51_add_imx_uart(0, &uart_pdata);
	imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);

	gpio_request(ETH_RST, "eth_rst");
	gpio_set_value(ETH_RST, 1);
	imx51_add_fec(NULL);

	gpio_request(CAN_IRQGPIO, "can_irq");
	gpio_direction_input(CAN_IRQGPIO);
	gpio_free(CAN_IRQGPIO);
	gpio_request(CAN_NCS, "can_ncs");
	gpio_direction_output(CAN_NCS, 1);
	gpio_free(CAN_NCS);
	gpio_request(CAN_RST, "can_rst");
	gpio_direction_output(CAN_RST, 0);
	msleep(20);
	gpio_set_value(CAN_RST, 1);
	imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata);
	spi_register_board_info(cpuimx51sd_spi_device,
				ARRAY_SIZE(cpuimx51sd_spi_device));

	gpio_request(TSC2007_IRQGPIO, "tsc2007_irq");
	gpio_direction_input(TSC2007_IRQGPIO);
	gpio_free(TSC2007_IRQGPIO);

	i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices,
			ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices));
	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));

	if (otg_mode_host)
		mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
	else {
		initialize_otg_port(NULL);
		mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
	}

	gpio_request(USBH1_RST, "usb_rst");
	gpio_direction_output(USBH1_RST, 0);
	msleep(20);
	gpio_set_value(USBH1_RST, 1);
	mxc_register_device(&mxc_usbh1_device, &usbh1_config);

#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
	eukrea_mbimxsd51_baseboard_init();
#endif
}

static void __init eukrea_cpuimx51sd_timer_init(void)
{
	mx51_clocks_init(32768, 24000000, 22579200, 0);
}

static struct sys_timer mxc_timer = {
	.init	= eukrea_cpuimx51sd_timer_init,
};

MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
	/* Maintainer: Eric Bénard <eric@eukrea.com> */
335
	.boot_params = MX51_PHYS_OFFSET + 0x100,
336
	.map_io = mx51_map_io,
337
	.init_early = imx51_init_early,
338 339
	.init_irq = mx51_init_irq,
	.timer = &mxc_timer,
340
	.init_machine = eukrea_cpuimx51sd_init,
341
MACHINE_END