blob: d9e2dda437c0c42fb2f237913b3bd6e95cb458ca [file] [log] [blame]
Luotao Fu33731692009-08-06 11:19:39 +02001/*
2 * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
3 * Copyright (C) 2009 Sascha Hauer (kernel@pengutronix.de)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 */
19
20#include <linux/platform_device.h>
21#include <linux/io.h>
22#include <linux/i2c.h>
23#include <linux/i2c/at24.h>
24#include <linux/dma-mapping.h>
25#include <linux/spi/spi.h>
26#include <linux/spi/eeprom.h>
27#include <linux/irq.h>
Sascha Hauerc8a68852010-02-08 16:42:28 +010028#include <linux/delay.h>
Luotao Fu33731692009-08-06 11:19:39 +020029#include <linux/gpio.h>
Sascha Hauereee7c492010-02-03 17:13:29 +010030#include <linux/usb/otg.h>
31#include <linux/usb/ulpi.h>
Luotao Fu33731692009-08-06 11:19:39 +020032
33#include <asm/mach/arch.h>
34#include <asm/mach-types.h>
35#include <mach/common.h>
36#include <mach/hardware.h>
Uwe Kleine-Könige835d882010-02-16 11:07:49 +010037#include <mach/iomux-mx27.h>
Luotao Fu33731692009-08-06 11:19:39 +020038#include <asm/mach/time.h>
Sascha Hauerc8a68852010-02-08 16:42:28 +010039#include <mach/audmux.h>
Luotao Fu33731692009-08-06 11:19:39 +020040#include <mach/mxc_nand.h>
41#include <mach/irqs.h>
Sascha Hauereee7c492010-02-03 17:13:29 +010042#include <mach/ulpi.h>
Luotao Fu33731692009-08-06 11:19:39 +020043
Uwe Kleine-König0e7a29a2010-06-16 07:35:31 +020044#include "devices-imx27.h"
Luotao Fu33731692009-08-06 11:19:39 +020045#include "devices.h"
46
Sascha Hauereee7c492010-02-03 17:13:29 +010047#define OTG_PHY_CS_GPIO (GPIO_PORTB + 23)
48#define USBH2_PHY_CS_GPIO (GPIO_PORTB + 24)
Luotao Fub725aba2010-06-18 09:23:19 +020049#define SPI1_SS0 (GPIO_PORTD + 28)
50#define SPI1_SS1 (GPIO_PORTD + 27)
51#define SD2_CD (GPIO_PORTC + 29)
Sascha Hauereee7c492010-02-03 17:13:29 +010052
Uwe Kleine-König6c80ee52010-09-28 21:53:31 +020053static const int pca100_pins[] __initconst = {
Luotao Fu33731692009-08-06 11:19:39 +020054 /* UART1 */
55 PE12_PF_UART1_TXD,
56 PE13_PF_UART1_RXD,
57 PE14_PF_UART1_CTS,
58 PE15_PF_UART1_RTS,
59 /* SDHC */
60 PB4_PF_SD2_D0,
61 PB5_PF_SD2_D1,
62 PB6_PF_SD2_D2,
63 PB7_PF_SD2_D3,
64 PB8_PF_SD2_CMD,
65 PB9_PF_SD2_CLK,
Luotao Fub725aba2010-06-18 09:23:19 +020066 SD2_CD | GPIO_GPIO | GPIO_IN,
Luotao Fu33731692009-08-06 11:19:39 +020067 /* FEC */
68 PD0_AIN_FEC_TXD0,
69 PD1_AIN_FEC_TXD1,
70 PD2_AIN_FEC_TXD2,
71 PD3_AIN_FEC_TXD3,
72 PD4_AOUT_FEC_RX_ER,
73 PD5_AOUT_FEC_RXD1,
74 PD6_AOUT_FEC_RXD2,
75 PD7_AOUT_FEC_RXD3,
76 PD8_AF_FEC_MDIO,
77 PD9_AIN_FEC_MDC,
78 PD10_AOUT_FEC_CRS,
79 PD11_AOUT_FEC_TX_CLK,
80 PD12_AOUT_FEC_RXD0,
81 PD13_AOUT_FEC_RX_DV,
82 PD14_AOUT_FEC_RX_CLK,
83 PD15_AOUT_FEC_COL,
84 PD16_AIN_FEC_TX_ER,
85 PF23_AIN_FEC_TX_EN,
86 /* SSI1 */
87 PC20_PF_SSI1_FS,
88 PC21_PF_SSI1_RXD,
89 PC22_PF_SSI1_TXD,
90 PC23_PF_SSI1_CLK,
91 /* onboard I2C */
92 PC5_PF_I2C2_SDA,
93 PC6_PF_I2C2_SCL,
94 /* external I2C */
95 PD17_PF_I2C_DATA,
96 PD18_PF_I2C_CLK,
97 /* SPI1 */
98 PD25_PF_CSPI1_RDY,
99 PD29_PF_CSPI1_SCLK,
100 PD30_PF_CSPI1_MISO,
101 PD31_PF_CSPI1_MOSI,
Sascha Hauereee7c492010-02-03 17:13:29 +0100102 /* OTG */
103 OTG_PHY_CS_GPIO | GPIO_GPIO | GPIO_OUT,
104 PC7_PF_USBOTG_DATA5,
105 PC8_PF_USBOTG_DATA6,
106 PC9_PF_USBOTG_DATA0,
107 PC10_PF_USBOTG_DATA2,
108 PC11_PF_USBOTG_DATA1,
109 PC12_PF_USBOTG_DATA4,
110 PC13_PF_USBOTG_DATA3,
111 PE0_PF_USBOTG_NXT,
112 PE1_PF_USBOTG_STP,
113 PE2_PF_USBOTG_DIR,
114 PE24_PF_USBOTG_CLK,
115 PE25_PF_USBOTG_DATA7,
116 /* USBH2 */
117 USBH2_PHY_CS_GPIO | GPIO_GPIO | GPIO_OUT,
118 PA0_PF_USBH2_CLK,
119 PA1_PF_USBH2_DIR,
120 PA2_PF_USBH2_DATA7,
121 PA3_PF_USBH2_NXT,
122 PA4_PF_USBH2_STP,
123 PD19_AF_USBH2_DATA4,
124 PD20_AF_USBH2_DATA3,
125 PD21_AF_USBH2_DATA6,
126 PD22_AF_USBH2_DATA0,
127 PD23_AF_USBH2_DATA2,
128 PD24_AF_USBH2_DATA1,
129 PD26_AF_USBH2_DATA5,
Luotao Fu42216fc2010-06-18 09:23:18 +0200130 /* display */
131 PA5_PF_LSCLK,
132 PA6_PF_LD0,
133 PA7_PF_LD1,
134 PA8_PF_LD2,
135 PA9_PF_LD3,
136 PA10_PF_LD4,
137 PA11_PF_LD5,
138 PA12_PF_LD6,
139 PA13_PF_LD7,
140 PA14_PF_LD8,
141 PA15_PF_LD9,
142 PA16_PF_LD10,
143 PA17_PF_LD11,
144 PA18_PF_LD12,
145 PA19_PF_LD13,
146 PA20_PF_LD14,
147 PA21_PF_LD15,
148 PA22_PF_LD16,
149 PA23_PF_LD17,
150 PA26_PF_PS,
151 PA28_PF_HSYNC,
152 PA29_PF_VSYNC,
153 PA31_PF_OE_ACD,
Luotao Fub725aba2010-06-18 09:23:19 +0200154 /* free GPIO */
155 GPIO_PORTC | 31 | GPIO_GPIO | GPIO_IN, /* GPIO0_IRQ */
156 GPIO_PORTC | 25 | GPIO_GPIO | GPIO_IN, /* GPIO1_IRQ */
157 GPIO_PORTE | 5 | GPIO_GPIO | GPIO_IN, /* GPIO2_IRQ */
Luotao Fu33731692009-08-06 11:19:39 +0200158};
159
Uwe Kleine-Königd5dac4a2010-06-23 09:36:01 +0200160static const struct imxuart_platform_data uart_pdata __initconst = {
Luotao Fu33731692009-08-06 11:19:39 +0200161 .flags = IMXUART_HAVE_RTSCTS,
162};
163
Uwe Kleine-König0e7a29a2010-06-16 07:35:31 +0200164static const struct mxc_nand_platform_data
165pca100_nand_board_info __initconst = {
Luotao Fu33731692009-08-06 11:19:39 +0200166 .width = 1,
167 .hw_ecc = 1,
168};
169
Uwe Kleine-Königc6987152010-06-16 17:25:40 +0200170static const struct imxi2c_platform_data pca100_i2c1_data __initconst = {
Luotao Fu33731692009-08-06 11:19:39 +0200171 .bitrate = 100000,
172};
173
174static struct at24_platform_data board_eeprom = {
175 .byte_len = 4096,
176 .page_size = 32,
177 .flags = AT24_FLAG_ADDR16,
178};
179
180static struct i2c_board_info pca100_i2c_devices[] = {
181 {
182 I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
183 .platform_data = &board_eeprom,
184 }, {
Uwe Kleine-Königbd9e3102010-09-28 22:04:01 +0200185 I2C_BOARD_INFO("pcf8563", 0x51),
Luotao Fu33731692009-08-06 11:19:39 +0200186 }, {
187 I2C_BOARD_INFO("lm75", 0x4a),
Luotao Fu33731692009-08-06 11:19:39 +0200188 }
189};
190
191#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
192static struct spi_eeprom at25320 = {
193 .name = "at25320an",
194 .byte_len = 4096,
195 .page_size = 32,
196 .flags = EE_ADDR2,
197};
198
199static struct spi_board_info pca100_spi_board_info[] __initdata = {
200 {
201 .modalias = "at25",
202 .max_speed_hz = 30000,
203 .bus_num = 0,
204 .chip_select = 1,
205 .platform_data = &at25320,
206 },
207};
208
Luotao Fub725aba2010-06-18 09:23:19 +0200209static int pca100_spi_cs[] = {SPI1_SS0, SPI1_SS1};
Luotao Fu33731692009-08-06 11:19:39 +0200210
Uwe Kleine-König7536cf92010-06-22 09:00:22 +0200211static const struct spi_imx_master pca100_spi0_data __initconst = {
Luotao Fu33731692009-08-06 11:19:39 +0200212 .chipselect = pca100_spi_cs,
213 .num_chipselect = ARRAY_SIZE(pca100_spi_cs),
214};
215#endif
216
Sascha Hauerc8a68852010-02-08 16:42:28 +0100217static void pca100_ac97_warm_reset(struct snd_ac97 *ac97)
218{
219 mxc_gpio_mode(GPIO_PORTC | 20 | GPIO_GPIO | GPIO_OUT);
220 gpio_set_value(GPIO_PORTC + 20, 1);
221 udelay(2);
222 gpio_set_value(GPIO_PORTC + 20, 0);
223 mxc_gpio_mode(PC20_PF_SSI1_FS);
224 msleep(2);
225}
226
227static void pca100_ac97_cold_reset(struct snd_ac97 *ac97)
228{
229 mxc_gpio_mode(GPIO_PORTC | 20 | GPIO_GPIO | GPIO_OUT); /* FS */
230 gpio_set_value(GPIO_PORTC + 20, 0);
231 mxc_gpio_mode(GPIO_PORTC | 22 | GPIO_GPIO | GPIO_OUT); /* TX */
232 gpio_set_value(GPIO_PORTC + 22, 0);
233 mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_OUT); /* reset */
234 gpio_set_value(GPIO_PORTC + 28, 0);
235 udelay(10);
236 gpio_set_value(GPIO_PORTC + 28, 1);
237 mxc_gpio_mode(PC20_PF_SSI1_FS);
238 mxc_gpio_mode(PC22_PF_SSI1_TXD);
239 msleep(2);
240}
241
Uwe Kleine-König4697bb92010-08-25 17:37:45 +0200242static const struct imx_ssi_platform_data pca100_ssi_pdata __initconst = {
Sascha Hauerc8a68852010-02-08 16:42:28 +0100243 .ac97_reset = pca100_ac97_cold_reset,
244 .ac97_warm_reset = pca100_ac97_warm_reset,
245 .flags = IMX_SSI_USE_AC97,
246};
247
Luotao Fu33731692009-08-06 11:19:39 +0200248static int pca100_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
249 void *data)
250{
251 int ret;
252
253 ret = request_irq(IRQ_GPIOC(29), detect_irq,
254 IRQF_DISABLED | IRQF_TRIGGER_FALLING,
255 "imx-mmc-detect", data);
256 if (ret)
257 printk(KERN_ERR
258 "pca100: Failed to reuest irq for sd/mmc detection\n");
259
260 return ret;
261}
262
263static void pca100_sdhc2_exit(struct device *dev, void *data)
264{
265 free_irq(IRQ_GPIOC(29), data);
266}
267
Uwe Kleine-König9d3d9452010-11-05 17:26:09 +0100268static const struct imxmmc_platform_data sdhc_pdata __initconst = {
Luotao Fu33731692009-08-06 11:19:39 +0200269 .init = pca100_sdhc2_init,
270 .exit = pca100_sdhc2_exit,
271};
272
Wolfram Sangc18e8fa2010-05-21 06:52:06 +0200273#if defined(CONFIG_USB_ULPI)
Sascha Hauereee7c492010-02-03 17:13:29 +0100274static int otg_phy_init(struct platform_device *pdev)
275{
276 gpio_set_value(OTG_PHY_CS_GPIO, 0);
277 return 0;
278}
279
Uwe Kleine-König2eb42d52010-11-05 18:52:09 +0100280static struct mxc_usbh_platform_data otg_pdata __initdata = {
Sascha Hauereee7c492010-02-03 17:13:29 +0100281 .init = otg_phy_init,
282 .portsc = MXC_EHCI_MODE_ULPI,
283 .flags = MXC_EHCI_INTERFACE_DIFF_UNI,
284};
285
286static int usbh2_phy_init(struct platform_device *pdev)
287{
288 gpio_set_value(USBH2_PHY_CS_GPIO, 0);
289 return 0;
290}
291
Uwe Kleine-König2eb42d52010-11-05 18:52:09 +0100292static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
Sascha Hauereee7c492010-02-03 17:13:29 +0100293 .init = usbh2_phy_init,
294 .portsc = MXC_EHCI_MODE_ULPI,
295 .flags = MXC_EHCI_INTERFACE_DIFF_UNI,
296};
Wolfram Sangc18e8fa2010-05-21 06:52:06 +0200297#endif
Sascha Hauereee7c492010-02-03 17:13:29 +0100298
Uwe Kleine-Königbd455ed2010-11-09 17:52:14 +0100299static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
Sascha Hauereee7c492010-02-03 17:13:29 +0100300 .operating_mode = FSL_USB2_DR_DEVICE,
301 .phy_mode = FSL_USB2_PHY_ULPI,
302};
303
304static int otg_mode_host;
305
306static int __init pca100_otg_mode(char *options)
307{
308 if (!strcmp(options, "host"))
309 otg_mode_host = 1;
310 else if (!strcmp(options, "device"))
311 otg_mode_host = 0;
312 else
313 pr_info("otg_mode neither \"host\" nor \"device\". "
314 "Defaulting to device\n");
315 return 0;
316}
317__setup("otg_mode=", pca100_otg_mode);
318
Luotao Fu42216fc2010-06-18 09:23:18 +0200319/* framebuffer info */
320static struct imx_fb_videomode pca100_fb_modes[] = {
321 {
322 .mode = {
323 .name = "EMERGING-ETV570G0DHU",
324 .refresh = 60,
325 .xres = 640,
326 .yres = 480,
327 .pixclock = 39722, /* in ps (25.175 MHz) */
328 .hsync_len = 30,
329 .left_margin = 114,
330 .right_margin = 16,
331 .vsync_len = 3,
332 .upper_margin = 32,
333 .lower_margin = 0,
334 },
335 /*
336 * TFT
337 * Pixel pol active high
338 * HSYNC active low
339 * VSYNC active low
340 * use HSYNC for ACD count
341 * line clock disable while idle
342 * always enable line clock even if no data
343 */
344 .pcr = 0xf0c08080,
345 .bpp = 16,
346 },
347};
348
Uwe Kleine-Königad851bf2010-11-04 17:07:48 +0100349static const struct imx_fb_platform_data pca100_fb_data __initconst = {
Luotao Fu42216fc2010-06-18 09:23:18 +0200350 .mode = pca100_fb_modes,
351 .num_modes = ARRAY_SIZE(pca100_fb_modes),
352
353 .pwmr = 0x00A903FF,
354 .lscr1 = 0x00120300,
355 .dmacr = 0x00020010,
356};
357
Luotao Fu33731692009-08-06 11:19:39 +0200358static void __init pca100_init(void)
359{
360 int ret;
361
Sascha Hauerc8a68852010-02-08 16:42:28 +0100362 /* SSI unit */
363 mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
364 MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */
365 MXC_AUDMUX_V1_PCR_TFCSEL(3) |
366 MXC_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */
367 MXC_AUDMUX_V1_PCR_RXDSEL(3));
368 mxc_audmux_v1_configure_port(3,
369 MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */
370 MXC_AUDMUX_V1_PCR_TFCSEL(0) |
371 MXC_AUDMUX_V1_PCR_TFSDIR |
372 MXC_AUDMUX_V1_PCR_RXDSEL(0));
373
Luotao Fu33731692009-08-06 11:19:39 +0200374 ret = mxc_gpio_setup_multiple_pins(pca100_pins,
375 ARRAY_SIZE(pca100_pins), "PCA100");
376 if (ret)
377 printk(KERN_ERR "pca100: Failed to setup pins (%d)\n", ret);
378
Uwe Kleine-König4697bb92010-08-25 17:37:45 +0200379 imx27_add_imx_ssi(0, &pca100_ssi_pdata);
Sascha Hauerc8a68852010-02-08 16:42:28 +0100380
Uwe Kleine-Königd5dac4a2010-06-23 09:36:01 +0200381 imx27_add_imx_uart0(&uart_pdata);
Luotao Fu33731692009-08-06 11:19:39 +0200382
Uwe Kleine-König9d3d9452010-11-05 17:26:09 +0100383 imx27_add_mxc_mmc(1, &sdhc_pdata);
Luotao Fu33731692009-08-06 11:19:39 +0200384
Uwe Kleine-König0e7a29a2010-06-16 07:35:31 +0200385 imx27_add_mxc_nand(&pca100_nand_board_info);
Luotao Fu33731692009-08-06 11:19:39 +0200386
387 /* only the i2c master 1 is used on this CPU card */
388 i2c_register_board_info(1, pca100_i2c_devices,
389 ARRAY_SIZE(pca100_i2c_devices));
390
Uwe Kleine-König77a406d2010-08-25 12:19:50 +0200391 imx27_add_imx_i2c(1, &pca100_i2c1_data);
Luotao Fu33731692009-08-06 11:19:39 +0200392
Luotao Fu33731692009-08-06 11:19:39 +0200393#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
Luotao Fub725aba2010-06-18 09:23:19 +0200394 mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_IN);
395 mxc_gpio_mode(GPIO_PORTD | 27 | GPIO_GPIO | GPIO_IN);
Luotao Fu33731692009-08-06 11:19:39 +0200396 spi_register_board_info(pca100_spi_board_info,
397 ARRAY_SIZE(pca100_spi_board_info));
Uwe Kleine-König4df772d2010-08-10 21:18:57 +0100398 imx27_add_spi_imx0(&pca100_spi0_data);
Luotao Fu33731692009-08-06 11:19:39 +0200399#endif
400
Sascha Hauereee7c492010-02-03 17:13:29 +0100401 gpio_request(OTG_PHY_CS_GPIO, "usb-otg-cs");
402 gpio_direction_output(OTG_PHY_CS_GPIO, 1);
403 gpio_request(USBH2_PHY_CS_GPIO, "usb-host2-cs");
404 gpio_direction_output(USBH2_PHY_CS_GPIO, 1);
405
406#if defined(CONFIG_USB_ULPI)
407 if (otg_mode_host) {
408 otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
Uwe Kleine-König70ddd472010-08-13 14:06:50 +0200409 ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
Sascha Hauereee7c492010-02-03 17:13:29 +0100410
Uwe Kleine-König2eb42d52010-11-05 18:52:09 +0100411 imx27_add_mxc_ehci_otg(&otg_pdata);
Sascha Hauereee7c492010-02-03 17:13:29 +0100412 }
413
414 usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
Uwe Kleine-König70ddd472010-08-13 14:06:50 +0200415 ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
Sascha Hauereee7c492010-02-03 17:13:29 +0100416
Uwe Kleine-König2eb42d52010-11-05 18:52:09 +0100417 imx27_add_mxc_ehci_hs(2, &usbh2_pdata);
Sascha Hauereee7c492010-02-03 17:13:29 +0100418#endif
419 if (!otg_mode_host) {
420 gpio_set_value(OTG_PHY_CS_GPIO, 0);
Uwe Kleine-Königbd455ed2010-11-09 17:52:14 +0100421 imx27_add_fsl_usb2_udc(&otg_device_pdata);
Sascha Hauereee7c492010-02-03 17:13:29 +0100422 }
423
Uwe Kleine-Königad851bf2010-11-04 17:07:48 +0100424 imx27_add_imx_fb(&pca100_fb_data);
Luotao Fu42216fc2010-06-18 09:23:18 +0200425
Uwe Kleine-König6bd96f32010-10-06 12:00:18 +0200426 imx27_add_fec(NULL);
Uwe Kleine-Könige0a19612010-11-04 10:09:10 +0100427 imx27_add_imx2_wdt(NULL);
Uwe Kleine-Königae71a562010-10-29 10:56:07 +0200428 imx27_add_mxc_w1(NULL);
Luotao Fu33731692009-08-06 11:19:39 +0200429}
430
431static void __init pca100_timer_init(void)
432{
433 mx27_clocks_init(26000000);
434}
435
436static struct sys_timer pca100_timer = {
437 .init = pca100_timer_init,
438};
439
440MACHINE_START(PCA100, "phyCARD-i.MX27")
Uwe Kleine-König34101232010-01-29 17:36:05 +0100441 .boot_params = MX27_PHYS_OFFSET + 0x100,
Luotao Fu33731692009-08-06 11:19:39 +0200442 .map_io = mx27_map_io,
Sascha Hauerf6f1bc62009-11-12 11:30:08 +0100443 .init_irq = mx27_init_irq,
Luotao Fu33731692009-08-06 11:19:39 +0200444 .init_machine = pca100_init,
445 .timer = &pca100_timer,
446MACHINE_END
447