2 * linux/arch/arm/mach-s3c2410/mach-gta01.c
4 * S3C2410 Machine Support for the FIC Neo1973 GTA01
6 * Copyright (C) 2006-2007 by Openmoko, Inc.
7 * Author: Harald Welte <laforge@openmoko.org>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 #include <linux/kernel.h>
28 #include <linux/types.h>
29 #include <linux/interrupt.h>
30 #include <linux/list.h>
31 #include <linux/timer.h>
32 #include <linux/init.h>
33 #include <linux/workqueue.h>
34 #include <linux/platform_device.h>
35 #include <linux/serial_core.h>
36 #include <asm/arch/ts.h>
37 #include <linux/spi/spi.h>
38 #include <linux/spi/spi_bitbang.h>
39 #include <linux/mmc/mmc.h>
40 #include <linux/mmc/host.h>
42 #include <linux/mtd/mtd.h>
43 #include <linux/mtd/nand.h>
44 #include <linux/mtd/nand_ecc.h>
45 #include <linux/mtd/partitions.h>
47 #include <linux/mmc/host.h>
49 #include <linux/pcf50606.h>
51 #include <asm/mach/arch.h>
52 #include <asm/mach/map.h>
53 #include <asm/mach/irq.h>
55 #include <asm/hardware.h>
58 #include <asm/mach-types.h>
60 #include <asm/arch/regs-gpio.h>
61 #include <asm/arch/fb.h>
62 #include <asm/arch/mci.h>
63 #include <asm/arch/spi.h>
64 #include <asm/arch/spi-gpio.h>
65 #include <asm/arch/usb-control.h>
67 #include <asm/arch/gta01.h>
69 #include <asm/plat-s3c/regs-serial.h>
70 #include <asm/plat-s3c/nand.h>
71 #include <asm/plat-s3c24xx/devs.h>
72 #include <asm/plat-s3c24xx/cpu.h>
73 #include <asm/plat-s3c24xx/pm.h>
74 #include <asm/plat-s3c24xx/udc.h>
75 #include <asm/plat-s3c24xx/neo1973.h>
76 #include <linux/jbt6k74.h>
78 static struct map_desc gta01_iodesc
[] __initdata
= {
80 .virtual = 0xe0000000,
81 .pfn
= __phys_to_pfn(S3C2410_CS3
+0x01000000),
87 #define UCON S3C2410_UCON_DEFAULT
88 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
89 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
90 /* UFCON for the gta01 sets the FIFO trigger level at 4, not 8 */
91 #define UFCON_GTA01_PORT0 S3C2410_UFCON_FIFOMODE
93 static struct s3c2410_uartcfg gta01_uartcfgs
[] = {
99 .ufcon
= UFCON_GTA01_PORT0
,
110 /* PMU driver info */
112 static int pmu_callback(struct device
*dev
, unsigned int feature
,
113 enum pmu_event event
)
116 case PCF50606_FEAT_ACD
:
119 pcf50606_charge_fast(pcf50606_global
, 1);
122 pcf50606_charge_fast(pcf50606_global
, 0);
135 static struct pcf50606_platform_data gta01_pcf_pdata
= {
136 .used_features
= PCF50606_FEAT_EXTON
|
141 PCF50606_FEAT_CHGCUR
|
142 PCF50606_FEAT_BATVOLT
|
143 PCF50606_FEAT_BATTEMP
,
144 .onkey_seconds_required
= 3,
147 .r_fix_batt_par
= 10000,
148 .r_sense_milli
= 220,
150 [PCF50606_REGULATOR_D1REG
] = {
157 [PCF50606_REGULATOR_D2REG
] = {
164 [PCF50606_REGULATOR_D3REG
] = {
166 .flags
= PMU_VRAIL_F_SUSPEND_ON
,
172 [PCF50606_REGULATOR_DCD
] = {
179 [PCF50606_REGULATOR_DCDE
] = {
181 .flags
= PMU_VRAIL_F_SUSPEND_ON
,
187 [PCF50606_REGULATOR_DCUD
] = {
189 .flags
= PMU_VRAIL_F_SUSPEND_ON
,
195 [PCF50606_REGULATOR_IOREG
] = {
202 [PCF50606_REGULATOR_LPREG
] = {
212 static void cfg_pmu_vrail(struct pmu_voltage_rail
*vrail
, char *name
,
213 unsigned int flags
, unsigned int init
,
217 vrail
->flags
= flags
;
218 vrail
->voltage
.init
= init
;
219 vrail
->voltage
.max
= max
;
222 static void mangle_pmu_pdata_by_system_rev(void)
224 switch (system_rev
) {
225 case GTA01Bv4_SYSTEM_REV
:
226 gta01_pcf_pdata
.used_features
|= PCF50606_FEAT_ACD
;
228 case GTA01Bv3_SYSTEM_REV
:
229 case GTA01Bv2_SYSTEM_REV
:
230 gta01_pcf_pdata
.rails
[PCF50606_REGULATOR_D3REG
]
232 gta01_pcf_pdata
.rails
[PCF50606_REGULATOR_D3REG
]
233 .flags
&= ~PMU_VRAIL_F_SUSPEND_ON
;
234 gta01_pcf_pdata
.rails
[PCF50606_REGULATOR_D3REG
]
235 .flags
= PMU_VRAIL_F_UNUSED
;
237 case GTA01v4_SYSTEM_REV
:
238 cfg_pmu_vrail(>a01_pcf_pdata
.rails
[PCF50606_REGULATOR_DCUD
],
239 "core_1v8", PMU_VRAIL_F_SUSPEND_ON
, 1800, 1800);
240 cfg_pmu_vrail(>a01_pcf_pdata
.rails
[PCF50606_REGULATOR_D1REG
],
241 "vrf_3v", 0, 3000, 3000);
242 cfg_pmu_vrail(>a01_pcf_pdata
.rails
[PCF50606_REGULATOR_D3REG
],
243 "vtcxo_2v8", 0, 2800, 2800);
244 cfg_pmu_vrail(>a01_pcf_pdata
.rails
[PCF50606_REGULATOR_DCD
],
245 "gl_3v5", 0, 3500, 3500);
247 case GTA01v3_SYSTEM_REV
:
248 cfg_pmu_vrail(>a01_pcf_pdata
.rails
[PCF50606_REGULATOR_D1REG
],
249 "vrf_3v", 0, 3000, 3000);
250 cfg_pmu_vrail(>a01_pcf_pdata
.rails
[PCF50606_REGULATOR_D2REG
],
251 "sd_3v3", 0, 3300, 3300);
252 cfg_pmu_vrail(>a01_pcf_pdata
.rails
[PCF50606_REGULATOR_D3REG
],
253 "codec_3v3", 0, 3300, 3300);
254 cfg_pmu_vrail(>a01_pcf_pdata
.rails
[PCF50606_REGULATOR_DCD
],
255 "gpsio_3v3", 0, 3300, 3300);
256 cfg_pmu_vrail(>a01_pcf_pdata
.rails
[PCF50606_REGULATOR_DCUD
],
257 "core_1v8", PMU_VRAIL_F_SUSPEND_ON
, 1800, 1800);
258 cfg_pmu_vrail(>a01_pcf_pdata
.rails
[PCF50606_REGULATOR_IOREG
],
259 "vtcxo_2v8", 0, 2800, 2800);
264 static struct resource gta01_pmu_resources
[] = {
266 .flags
= IORESOURCE_IRQ
,
267 .start
= GTA01_IRQ_PCF50606
,
268 .end
= GTA01_IRQ_PCF50606
,
272 struct platform_device gta01_pmu_dev
= {
274 .num_resources
= ARRAY_SIZE(gta01_pmu_resources
),
275 .resource
= gta01_pmu_resources
,
277 .platform_data
= >a01_pcf_pdata
,
281 /* LCD driver info */
283 /* Configuration for 480x640 toppoly TD028TTEC1.
284 * Do not mark this as __initdata or it will break! */
285 static struct s3c2410fb_display gta01_displays
[] = {
287 .type
= S3C2410_LCDCON1_TFT
,
294 .pixclock
= 40000, /* HCLK/4 */
301 .lcdcon5
= S3C2410_LCDCON5_FRM565
|
302 S3C2410_LCDCON5_INVVCLK
|
303 S3C2410_LCDCON5_INVVLINE
|
304 S3C2410_LCDCON5_INVVFRAME
|
305 S3C2410_LCDCON5_PWREN
|
306 S3C2410_LCDCON5_HWSWP
,
309 .type
= S3C2410_LCDCON1_TFT
,
316 .pixclock
= 40000, /* HCLK/4 */
323 .lcdcon5
= S3C2410_LCDCON5_FRM565
|
324 S3C2410_LCDCON5_INVVCLK
|
325 S3C2410_LCDCON5_INVVLINE
|
326 S3C2410_LCDCON5_INVVFRAME
|
327 S3C2410_LCDCON5_PWREN
|
328 S3C2410_LCDCON5_HWSWP
,
331 .type
= S3C2410_LCDCON1_TFT
,
338 .pixclock
= 40000, /* HCLK/4 */
345 .lcdcon5
= S3C2410_LCDCON5_FRM565
|
346 S3C2410_LCDCON5_INVVCLK
|
347 S3C2410_LCDCON5_INVVLINE
|
348 S3C2410_LCDCON5_INVVFRAME
|
349 S3C2410_LCDCON5_PWREN
|
350 S3C2410_LCDCON5_HWSWP
,
354 static struct s3c2410fb_mach_info gta01_lcd_cfg __initdata
= {
355 .displays
= gta01_displays
,
356 .num_displays
= ARRAY_SIZE(gta01_displays
),
357 .default_display
= 0,
359 .lpcsel
= ((0xCE6) & ~7) | 1<<4,
362 static struct platform_device
*gta01_devices
[] __initdata
= {
369 &s3c_device_usbgadget
,
374 static struct s3c2410_nand_set gta01_nand_sets
[] = {
376 .name
= "neo1973-nand",
378 .flags
= S3C2410_NAND_BBT
,
382 static struct s3c2410_platform_nand gta01_nand_info
= {
386 .nr_sets
= ARRAY_SIZE(gta01_nand_sets
),
387 .sets
= gta01_nand_sets
,
390 static void gta01_mmc_set_power(unsigned char power_mode
, unsigned short vdd
)
393 int mv
= 1700; /* 1.7V for MMC_VDD_165_195 */
395 printk(KERN_DEBUG
"mmc_set_power(power_mode=%u, vdd=%u)\n",
398 switch (system_rev
) {
399 case GTA01v3_SYSTEM_REV
:
400 switch (power_mode
) {
402 pcf50606_onoff_set(pcf50606_global
,
403 PCF50606_REGULATOR_D2REG
, 0);
406 /* translate MMC_VDD_* VDD bit to mv */
407 for (bit
= 8; bit
!= 24; bit
++)
408 if (vdd
== (1 << bit
))
409 mv
+= 100 * (bit
- 4);
410 pcf50606_voltage_set(pcf50606_global
,
411 PCF50606_REGULATOR_D2REG
, mv
);
412 pcf50606_onoff_set(pcf50606_global
,
413 PCF50606_REGULATOR_D2REG
, 1);
417 case GTA01v4_SYSTEM_REV
:
418 case GTA01Bv2_SYSTEM_REV
:
419 case GTA01Bv3_SYSTEM_REV
:
420 case GTA01Bv4_SYSTEM_REV
:
421 switch (power_mode
) {
423 neo1973_gpb_setpin(GTA01_GPIO_SDMMC_ON
, 1);
426 neo1973_gpb_setpin(GTA01_GPIO_SDMMC_ON
, 0);
433 static struct s3c24xx_mci_pdata gta01_mmc_cfg
= {
434 .gpio_detect
= GTA01_GPIO_nSD_DETECT
,
435 .set_power
= >a01_mmc_set_power
,
436 .ocr_avail
= MMC_VDD_165_195
|MMC_VDD_20_21
|
437 MMC_VDD_21_22
|MMC_VDD_22_23
|MMC_VDD_23_24
|
438 MMC_VDD_24_25
|MMC_VDD_25_26
|MMC_VDD_26_27
|
439 MMC_VDD_27_28
|MMC_VDD_28_29
|MMC_VDD_29_30
|
440 MMC_VDD_30_31
|MMC_VDD_31_32
|MMC_VDD_32_33
,
443 static void gta01_udc_command(enum s3c2410_udc_cmd_e cmd
)
445 printk(KERN_DEBUG
"%s(%d)\n", __func__
, cmd
);
448 case S3C2410_UDC_P_ENABLE
:
449 neo1973_gpb_setpin(GTA01_GPIO_USB_PULLUP
, 1);
451 case S3C2410_UDC_P_DISABLE
:
452 neo1973_gpb_setpin(GTA01_GPIO_USB_PULLUP
, 0);
459 /* use a work queue, since I2C API inherently schedules
460 * and we get called in hardirq context from UDC driver */
463 struct work_struct work
;
466 static struct vbus_draw gta01_udc_vbus_drawer
;
468 static void __gta01_udc_vbus_draw(struct work_struct
*work
)
470 /* this is a fix to work around boot-time ordering problems if the
471 * s3c2410_udc is initialized before the pcf50606 driver has defined
473 if (!pcf50606_global
)
476 if (gta01_udc_vbus_drawer
.ma
>= 500) {
477 /* enable fast charge */
478 printk(KERN_DEBUG
"udc: enabling fast charge\n");
479 pcf50606_charge_fast(pcf50606_global
, 1);
481 /* disable fast charge */
482 printk(KERN_DEBUG
"udc: disabling fast charge\n");
483 pcf50606_charge_fast(pcf50606_global
, 0);
487 static void gta01_udc_vbus_draw(unsigned int ma
)
489 gta01_udc_vbus_drawer
.ma
= ma
;
490 schedule_work(>a01_udc_vbus_drawer
.work
);
493 static struct s3c2410_udc_mach_info gta01_udc_cfg
= {
494 .vbus_draw
= gta01_udc_vbus_draw
,
497 static struct s3c2410_ts_mach_info gta01_ts_cfg
= {
499 .presc
= 50000000 / 1000000, /* 50 MHz PCLK / 1MHz */
500 /* simple averaging, 2^n samples */
501 .oversampling_shift
= 5,
502 /* averaging filter length, 2^n */
503 .excursion_filter_len_bits
= 5,
504 /* flagged for beauty contest on next sample if differs from
505 * average more than this
507 .reject_threshold_vs_avg
= 2,
512 static void gta01_jbt6k74_reset(int devidx
, int level
)
514 /* empty place holder; gta01 does not yet use this */
515 printk(KERN_DEBUG
"gta01_jbt6k74_reset\n");
518 static void gta01_jbt6k74_resuming(int devidx
)
520 gta01bl_deferred_resume();
523 const struct jbt6k74_platform_data gta01_jbt6k74_pdata
= {
524 .reset
= gta01_jbt6k74_reset
,
525 .resuming
= gta01_jbt6k74_resuming
,
528 static struct spi_board_info gta01_spi_board_info
[] = {
530 .modalias
= "jbt6k74",
531 .platform_data
= >a01_jbt6k74_pdata
,
532 /* controller_data */
534 .max_speed_hz
= 10 * 1000 * 1000,
540 static void spi_gpio_cs(struct s3c2410_spigpio_info
*spi
, int csidx
, int cs
)
543 case BITBANG_CS_ACTIVE
:
544 s3c2410_gpio_setpin(S3C2410_GPG3
, 0);
546 case BITBANG_CS_INACTIVE
:
547 s3c2410_gpio_setpin(S3C2410_GPG3
, 1);
552 static struct s3c2410_spigpio_info spi_gpio_cfg
= {
553 .pin_clk
= S3C2410_GPG7
,
554 .pin_mosi
= S3C2410_GPG6
,
555 .pin_miso
= S3C2410_GPG5
,
556 .board_size
= ARRAY_SIZE(gta01_spi_board_info
),
557 .board_info
= gta01_spi_board_info
,
558 .chip_select
= &spi_gpio_cs
,
559 .num_chipselect
= 2, /*** Should be 1 or 2 for gta01? ***/
562 static struct resource s3c_spi_lcm_resource
[] = {
564 .start
= S3C2410_GPG3
,
568 .start
= S3C2410_GPG5
,
572 .start
= S3C2410_GPG6
,
576 .start
= S3C2410_GPG7
,
581 struct platform_device s3c_device_spi_lcm
= {
582 .name
= "spi_s3c24xx_gpio",
584 .num_resources
= ARRAY_SIZE(s3c_spi_lcm_resource
),
585 .resource
= s3c_spi_lcm_resource
,
587 .platform_data
= &spi_gpio_cfg
,
591 static struct gta01bl_machinfo backlight_machinfo
= {
592 .default_intensity
= 1,
595 .defer_resume_backlight
= 1,
598 static struct resource gta01_bl_resources
[] = {
600 .start
= GTA01_GPIO_BACKLIGHT
,
601 .end
= GTA01_GPIO_BACKLIGHT
,
605 struct platform_device gta01_bl_dev
= {
607 .num_resources
= ARRAY_SIZE(gta01_bl_resources
),
608 .resource
= gta01_bl_resources
,
610 .platform_data
= &backlight_machinfo
,
614 static struct resource gta01_led_resources
[] = {
616 .start
= GTA01_GPIO_VIBRATOR_ON
,
617 .end
= GTA01_GPIO_VIBRATOR_ON
,
621 struct platform_device gta01_led_dev
= {
622 .name
= "neo1973-vibrator",
623 .num_resources
= ARRAY_SIZE(gta01_led_resources
),
624 .resource
= gta01_led_resources
,
627 static struct resource gta01_button_resources
[] = {
629 .start
= GTA01_GPIO_AUX_KEY
,
630 .end
= GTA01_GPIO_AUX_KEY
,
633 .start
= GTA01_GPIO_HOLD_KEY
,
634 .end
= GTA01_GPIO_HOLD_KEY
,
637 .start
= GTA01_GPIO_JACK_INSERT
,
638 .end
= GTA01_GPIO_JACK_INSERT
,
642 struct platform_device gta01_button_dev
= {
643 .name
= "neo1973-button",
644 .num_resources
= ARRAY_SIZE(gta01_button_resources
),
645 .resource
= gta01_button_resources
,
648 static struct platform_device gta01_pm_gsm_dev
= {
649 .name
= "neo1973-pm-gsm",
653 static struct s3c2410_hcd_info gta01_usb_info
= {
655 .flags
= S3C_HCDFLG_USED
,
662 static void __init
gta01_map_io(void)
664 s3c24xx_init_io(gta01_iodesc
, ARRAY_SIZE(gta01_iodesc
));
665 s3c24xx_init_clocks(12*1000*1000);
666 s3c24xx_init_uarts(gta01_uartcfgs
, ARRAY_SIZE(gta01_uartcfgs
));
669 extern int gta_gsm_interrupts
;
671 static irqreturn_t
gta01_modem_irq(int irq
, void *param
)
673 printk(KERN_DEBUG
"GSM wakeup interrupt (IRQ %d)\n", irq
);
674 gta_gsm_interrupts
++;
678 static void __init
gta01_machine_init(void)
682 if (system_rev
== GTA01v4_SYSTEM_REV
||
683 system_rev
== GTA01Bv2_SYSTEM_REV
||
684 system_rev
== GTA01Bv3_SYSTEM_REV
||
685 system_rev
== GTA01Bv4_SYSTEM_REV
) {
686 gta01_udc_cfg
.udc_command
= gta01_udc_command
;
687 gta01_mmc_cfg
.ocr_avail
= MMC_VDD_32_33
;
690 s3c_device_usb
.dev
.platform_data
= >a01_usb_info
;
691 s3c_device_nand
.dev
.platform_data
= >a01_nand_info
;
692 s3c_device_sdi
.dev
.platform_data
= >a01_mmc_cfg
;
694 s3c24xx_fb_set_platdata(>a01_lcd_cfg
);
696 INIT_WORK(>a01_udc_vbus_drawer
.work
, __gta01_udc_vbus_draw
);
697 s3c24xx_udc_set_platdata(>a01_udc_cfg
);
698 set_s3c2410ts_info(>a01_ts_cfg
);
700 /* Set LCD_RESET / XRES to high */
701 s3c2410_gpio_cfgpin(S3C2410_GPC6
, S3C2410_GPIO_OUTPUT
);
702 s3c2410_gpio_setpin(S3C2410_GPC6
, 1);
704 /* SPI chip select is gpio output */
705 s3c2410_gpio_cfgpin(S3C2410_GPG3
, S3C2410_GPIO_OUTPUT
);
706 s3c2410_gpio_setpin(S3C2410_GPG3
, 1);
707 platform_device_register(&s3c_device_spi_lcm
);
709 platform_device_register(>a01_bl_dev
);
710 platform_device_register(>a01_button_dev
);
711 platform_device_register(>a01_pm_gsm_dev
);
713 switch (system_rev
) {
714 case GTA01v3_SYSTEM_REV
:
715 case GTA01v4_SYSTEM_REV
:
716 /* just use the default (GTA01_IRQ_PCF50606) */
718 case GTA01Bv2_SYSTEM_REV
:
719 case GTA01Bv3_SYSTEM_REV
:
720 /* just use the default (GTA01_IRQ_PCF50606) */
721 gta01_led_resources
[0].start
=
722 gta01_led_resources
[0].end
= GTA01Bv2_GPIO_VIBRATOR_ON
;
724 case GTA01Bv4_SYSTEM_REV
:
725 gta01_pmu_resources
[0].start
=
726 gta01_pmu_resources
[0].end
= GTA01Bv4_IRQ_PCF50606
;
727 gta01_led_resources
[0].start
=
728 gta01_led_resources
[0].end
= GTA01Bv4_GPIO_VIBRATOR_ON
;
731 mangle_pmu_pdata_by_system_rev();
732 platform_device_register(>a01_pmu_dev
);
733 platform_device_register(>a01_led_dev
);
735 platform_add_devices(gta01_devices
, ARRAY_SIZE(gta01_devices
));
739 set_irq_type(GTA01_IRQ_MODEM
, IRQT_RISING
);
740 rc
= request_irq(GTA01_IRQ_MODEM
, gta01_modem_irq
, IRQF_DISABLED
,
742 enable_irq_wake(GTA01_IRQ_MODEM
);
743 printk(KERN_DEBUG
"Enabled GSM wakeup IRQ %d (rc=%d)\n",
744 GTA01_IRQ_MODEM
, rc
);
747 MACHINE_START(NEO1973_GTA01
, "GTA01")
748 .phys_io
= S3C2410_PA_UART
,
749 .io_pg_offst
= (((u32
)S3C24XX_VA_UART
) >> 18) & 0xfffc,
750 .boot_params
= S3C2410_SDRAM_PA
+ 0x100,
751 .map_io
= gta01_map_io
,
752 .init_irq
= s3c24xx_init_irq
,
753 .init_machine
= gta01_machine_init
,
754 .timer
= &s3c24xx_timer
,