linux/arch/arm/mach-s3c2440/mach-gta02.c
<<
>>
Prefs
   1/*
   2 * linux/arch/arm/mach-s3c2442/mach-gta02.c
   3 *
   4 * S3C2442 Machine Support for Openmoko GTA02 / FreeRunner.
   5 *
   6 * Copyright (C) 2006-2009 by Openmoko, Inc.
   7 * Authors: Harald Welte <laforge@openmoko.org>
   8 *          Andy Green <andy@openmoko.org>
   9 *          Werner Almesberger <werner@openmoko.org>
  10 * All rights reserved.
  11 *
  12 * This program is free software; you can redistribute it and/or
  13 * modify it under the terms of the GNU General Public License as
  14 * published by the Free Software Foundation; either version 2 of
  15 * the License, or (at your option) any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 *
  22 * You should have received a copy of the GNU General Public License
  23 * along with this program; if not, write to the Free Software
  24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  25 * MA 02111-1307 USA
  26 *
  27 */
  28
  29#include <linux/kernel.h>
  30#include <linux/types.h>
  31#include <linux/interrupt.h>
  32#include <linux/list.h>
  33#include <linux/delay.h>
  34#include <linux/timer.h>
  35#include <linux/init.h>
  36#include <linux/gpio.h>
  37#include <linux/workqueue.h>
  38#include <linux/platform_device.h>
  39#include <linux/serial_core.h>
  40#include <linux/spi/spi.h>
  41
  42#include <linux/mmc/host.h>
  43
  44#include <linux/mtd/mtd.h>
  45#include <linux/mtd/nand.h>
  46#include <linux/mtd/nand_ecc.h>
  47#include <linux/mtd/partitions.h>
  48#include <linux/mtd/physmap.h>
  49#include <linux/io.h>
  50
  51#include <linux/i2c.h>
  52#include <linux/regulator/machine.h>
  53
  54#include <linux/mfd/pcf50633/core.h>
  55#include <linux/mfd/pcf50633/mbc.h>
  56#include <linux/mfd/pcf50633/adc.h>
  57#include <linux/mfd/pcf50633/gpio.h>
  58#include <linux/mfd/pcf50633/pmic.h>
  59#include <linux/mfd/pcf50633/backlight.h>
  60
  61#include <linux/input.h>
  62#include <linux/gpio_keys.h>
  63
  64#include <asm/mach/arch.h>
  65#include <asm/mach/map.h>
  66#include <asm/mach/irq.h>
  67
  68#include <asm/irq.h>
  69#include <asm/mach-types.h>
  70
  71#include <mach/regs-irq.h>
  72#include <mach/regs-gpio.h>
  73#include <mach/regs-gpioj.h>
  74#include <mach/fb.h>
  75
  76#include <mach/spi.h>
  77#include <mach/spi-gpio.h>
  78#include <plat/usb-control.h>
  79#include <mach/regs-mem.h>
  80#include <mach/hardware.h>
  81
  82#include <mach/gta02.h>
  83
  84#include <plat/regs-serial.h>
  85#include <plat/nand.h>
  86#include <plat/devs.h>
  87#include <plat/cpu.h>
  88#include <plat/pm.h>
  89#include <plat/udc.h>
  90#include <plat/gpio-cfg.h>
  91#include <plat/iic.h>
  92#include <plat/ts.h>
  93
  94
  95static struct pcf50633 *gta02_pcf;
  96
  97/*
  98 * This gets called frequently when we paniced.
  99 */
 100
 101static long gta02_panic_blink(int state)
 102{
 103        long delay = 0;
 104        char led;
 105
 106        led = (state) ? 1 : 0;
 107        gpio_direction_output(GTA02_GPIO_AUX_LED, led);
 108
 109        return delay;
 110}
 111
 112
 113static struct map_desc gta02_iodesc[] __initdata = {
 114        {
 115                .virtual        = 0xe0000000,
 116                .pfn            = __phys_to_pfn(S3C2410_CS3 + 0x01000000),
 117                .length         = SZ_1M,
 118                .type           = MT_DEVICE
 119        },
 120};
 121
 122#define UCON (S3C2410_UCON_DEFAULT | S3C2443_UCON_RXERR_IRQEN)
 123#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
 124#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
 125
 126static struct s3c2410_uartcfg gta02_uartcfgs[] = {
 127        [0] = {
 128                .hwport         = 0,
 129                .flags          = 0,
 130                .ucon           = UCON,
 131                .ulcon          = ULCON,
 132                .ufcon          = UFCON,
 133        },
 134        [1] = {
 135                .hwport         = 1,
 136                .flags          = 0,
 137                .ucon           = UCON,
 138                .ulcon          = ULCON,
 139                .ufcon          = UFCON,
 140        },
 141        [2] = {
 142                .hwport         = 2,
 143                .flags          = 0,
 144                .ucon           = UCON,
 145                .ulcon          = ULCON,
 146                .ufcon          = UFCON,
 147        },
 148};
 149
 150#ifdef CONFIG_CHARGER_PCF50633
 151/*
 152 * On GTA02 the 1A charger features a 48K resistor to 0V on the ID pin.
 153 * We use this to recognize that we can pull 1A from the USB socket.
 154 *
 155 * These constants are the measured pcf50633 ADC levels with the 1A
 156 * charger / 48K resistor, and with no pulldown resistor.
 157 */
 158
 159#define ADC_NOM_CHG_DETECT_1A 6
 160#define ADC_NOM_CHG_DETECT_USB 43
 161
 162static void
 163gta02_configure_pmu_for_charger(struct pcf50633 *pcf, void *unused, int res)
 164{
 165        int  ma;
 166
 167        /* Interpret charger type */
 168        if (res < ((ADC_NOM_CHG_DETECT_USB + ADC_NOM_CHG_DETECT_1A) / 2)) {
 169
 170                /*
 171                 * Sanity - stop GPO driving out now that we have a 1A charger
 172                 * GPO controls USB Host power generation on GTA02
 173                 */
 174                pcf50633_gpio_set(pcf, PCF50633_GPO, 0);
 175
 176                ma = 1000;
 177        } else
 178                ma = 100;
 179
 180        pcf50633_mbc_usb_curlim_set(pcf, ma);
 181}
 182
 183static struct delayed_work gta02_charger_work;
 184static int gta02_usb_vbus_draw;
 185
 186static void gta02_charger_worker(struct work_struct *work)
 187{
 188        if (gta02_usb_vbus_draw) {
 189                pcf50633_mbc_usb_curlim_set(gta02_pcf, gta02_usb_vbus_draw);
 190                return;
 191        }
 192
 193#ifdef CONFIG_PCF50633_ADC
 194        pcf50633_adc_async_read(gta02_pcf,
 195                                PCF50633_ADCC1_MUX_ADCIN1,
 196                                PCF50633_ADCC1_AVERAGE_16,
 197                                gta02_configure_pmu_for_charger,
 198                                NULL);
 199#else
 200        /*
 201         * If the PCF50633 ADC is disabled we fallback to a
 202         * 100mA limit for safety.
 203         */
 204        pcf50633_mbc_usb_curlim_set(pcf, 100);
 205#endif
 206}
 207
 208#define GTA02_CHARGER_CONFIGURE_TIMEOUT ((3000 * HZ) / 1000)
 209
 210static void gta02_pmu_event_callback(struct pcf50633 *pcf, int irq)
 211{
 212        if (irq == PCF50633_IRQ_USBINS) {
 213                schedule_delayed_work(&gta02_charger_work,
 214                                      GTA02_CHARGER_CONFIGURE_TIMEOUT);
 215
 216                return;
 217        }
 218
 219        if (irq == PCF50633_IRQ_USBREM) {
 220                cancel_delayed_work_sync(&gta02_charger_work);
 221                gta02_usb_vbus_draw = 0;
 222        }
 223}
 224
 225static void gta02_udc_vbus_draw(unsigned int ma)
 226{
 227        if (!gta02_pcf)
 228                return;
 229
 230        gta02_usb_vbus_draw = ma;
 231
 232        schedule_delayed_work(&gta02_charger_work,
 233                              GTA02_CHARGER_CONFIGURE_TIMEOUT);
 234}
 235#else /* !CONFIG_CHARGER_PCF50633 */
 236#define gta02_pmu_event_callback        NULL
 237#define gta02_udc_vbus_draw             NULL
 238#endif
 239
 240/*
 241 * This is called when pc50633 is probed, unfortunately quite late in the
 242 * day since it is an I2C bus device. Here we can belatedly define some
 243 * platform devices with the advantage that we can mark the pcf50633 as the
 244 * parent. This makes them get suspended and resumed with their parent
 245 * the pcf50633 still around.
 246 */
 247
 248static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf);
 249
 250
 251static char *gta02_batteries[] = {
 252        "battery",
 253};
 254
 255static struct pcf50633_bl_platform_data gta02_backlight_data = {
 256        .default_brightness = 0x3f,
 257        .default_brightness_limit = 0,
 258        .ramp_time = 5,
 259};
 260
 261struct pcf50633_platform_data gta02_pcf_pdata = {
 262        .resumers = {
 263                [0] =   PCF50633_INT1_USBINS |
 264                        PCF50633_INT1_USBREM |
 265                        PCF50633_INT1_ALARM,
 266                [1] =   PCF50633_INT2_ONKEYF,
 267                [2] =   PCF50633_INT3_ONKEY1S,
 268                [3] =   PCF50633_INT4_LOWSYS |
 269                        PCF50633_INT4_LOWBAT |
 270                        PCF50633_INT4_HIGHTMP,
 271        },
 272
 273        .batteries = gta02_batteries,
 274        .num_batteries = ARRAY_SIZE(gta02_batteries),
 275
 276        .charger_reference_current_ma = 1000,
 277
 278        .backlight_data = &gta02_backlight_data,
 279
 280        .reg_init_data = {
 281                [PCF50633_REGULATOR_AUTO] = {
 282                        .constraints = {
 283                                .min_uV = 3300000,
 284                                .max_uV = 3300000,
 285                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
 286                                .always_on = 1,
 287                                .apply_uV = 1,
 288                        },
 289                },
 290                [PCF50633_REGULATOR_DOWN1] = {
 291                        .constraints = {
 292                                .min_uV = 1300000,
 293                                .max_uV = 1600000,
 294                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
 295                                .always_on = 1,
 296                                .apply_uV = 1,
 297                        },
 298                },
 299                [PCF50633_REGULATOR_DOWN2] = {
 300                        .constraints = {
 301                                .min_uV = 1800000,
 302                                .max_uV = 1800000,
 303                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
 304                                .apply_uV = 1,
 305                                .always_on = 1,
 306                        },
 307                },
 308                [PCF50633_REGULATOR_HCLDO] = {
 309                        .constraints = {
 310                                .min_uV = 2000000,
 311                                .max_uV = 3300000,
 312                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
 313                                .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
 314                                                REGULATOR_CHANGE_STATUS,
 315                        },
 316                },
 317                [PCF50633_REGULATOR_LDO1] = {
 318                        .constraints = {
 319                                .min_uV = 3300000,
 320                                .max_uV = 3300000,
 321                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
 322                                .valid_ops_mask = REGULATOR_CHANGE_STATUS,
 323                                .apply_uV = 1,
 324                        },
 325                },
 326                [PCF50633_REGULATOR_LDO2] = {
 327                        .constraints = {
 328                                .min_uV = 3300000,
 329                                .max_uV = 3300000,
 330                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
 331                                .apply_uV = 1,
 332                        },
 333                },
 334                [PCF50633_REGULATOR_LDO3] = {
 335                        .constraints = {
 336                                .min_uV = 3000000,
 337                                .max_uV = 3000000,
 338                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
 339                                .apply_uV = 1,
 340                        },
 341                },
 342                [PCF50633_REGULATOR_LDO4] = {
 343                        .constraints = {
 344                                .min_uV = 3200000,
 345                                .max_uV = 3200000,
 346                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
 347                                .valid_ops_mask = REGULATOR_CHANGE_STATUS,
 348                                .apply_uV = 1,
 349                        },
 350                },
 351                [PCF50633_REGULATOR_LDO5] = {
 352                        .constraints = {
 353                                .min_uV = 3000000,
 354                                .max_uV = 3000000,
 355                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
 356                                .valid_ops_mask = REGULATOR_CHANGE_STATUS,
 357                                .apply_uV = 1,
 358                        },
 359                },
 360                [PCF50633_REGULATOR_LDO6] = {
 361                        .constraints = {
 362                                .min_uV = 3000000,
 363                                .max_uV = 3000000,
 364                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
 365                        },
 366                },
 367                [PCF50633_REGULATOR_MEMLDO] = {
 368                        .constraints = {
 369                                .min_uV = 1800000,
 370                                .max_uV = 1800000,
 371                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
 372                        },
 373                },
 374
 375        },
 376        .probe_done = gta02_pmu_attach_child_devices,
 377        .mbc_event_callback = gta02_pmu_event_callback,
 378};
 379
 380
 381/* NOR Flash. */
 382
 383#define GTA02_FLASH_BASE        0x18000000 /* GCS3 */
 384#define GTA02_FLASH_SIZE        0x200000 /* 2MBytes */
 385
 386static struct physmap_flash_data gta02_nor_flash_data = {
 387        .width          = 2,
 388};
 389
 390static struct resource gta02_nor_flash_resource = {
 391        .start          = GTA02_FLASH_BASE,
 392        .end            = GTA02_FLASH_BASE + GTA02_FLASH_SIZE - 1,
 393        .flags          = IORESOURCE_MEM,
 394};
 395
 396static struct platform_device gta02_nor_flash = {
 397        .name           = "physmap-flash",
 398        .id             = 0,
 399        .dev            = {
 400                .platform_data  = &gta02_nor_flash_data,
 401        },
 402        .resource       = &gta02_nor_flash_resource,
 403        .num_resources  = 1,
 404};
 405
 406
 407struct platform_device s3c24xx_pwm_device = {
 408        .name           = "s3c24xx_pwm",
 409        .num_resources  = 0,
 410};
 411
 412static struct platform_device gta02_dfbmcs320_device = {
 413        .name = "dfbmcs320",
 414};
 415
 416static struct i2c_board_info gta02_i2c_devs[] __initdata = {
 417        {
 418                I2C_BOARD_INFO("pcf50633", 0x73),
 419                .irq = GTA02_IRQ_PCF50633,
 420                .platform_data = &gta02_pcf_pdata,
 421        },
 422        {
 423                I2C_BOARD_INFO("wm8753", 0x1a),
 424        },
 425};
 426
 427static struct s3c2410_nand_set __initdata gta02_nand_sets[] = {
 428        [0] = {
 429                /*
 430                 * This name is also hard-coded in the boot loaders, so
 431                 * changing it would would require all users to upgrade
 432                 * their boot loaders, some of which are stored in a NOR
 433                 * that is considered to be immutable.
 434                 */
 435                .name           = "neo1973-nand",
 436                .nr_chips       = 1,
 437                .flash_bbt      = 1,
 438        },
 439};
 440
 441/*
 442 * Choose a set of timings derived from S3C@2442B MCP54
 443 * data sheet (K5D2G13ACM-D075 MCP Memory).
 444 */
 445
 446static struct s3c2410_platform_nand __initdata gta02_nand_info = {
 447        .tacls          = 0,
 448        .twrph0         = 25,
 449        .twrph1         = 15,
 450        .nr_sets        = ARRAY_SIZE(gta02_nand_sets),
 451        .sets           = gta02_nand_sets,
 452};
 453
 454
 455/* Get PMU to set USB current limit accordingly. */
 456static struct s3c2410_udc_mach_info gta02_udc_cfg __initdata = {
 457        .vbus_draw      = gta02_udc_vbus_draw,
 458        .pullup_pin = GTA02_GPIO_USB_PULLUP,
 459};
 460
 461/* USB */
 462static struct s3c2410_hcd_info gta02_usb_info __initdata = {
 463        .port[0]        = {
 464                .flags  = S3C_HCDFLG_USED,
 465        },
 466        .port[1]        = {
 467                .flags  = 0,
 468        },
 469};
 470
 471/* Touchscreen */
 472static struct s3c2410_ts_mach_info gta02_ts_info = {
 473        .delay                  = 10000,
 474        .presc                  = 0xff, /* slow as we can go */
 475        .oversampling_shift     = 2,
 476};
 477
 478/* Buttons */
 479static struct gpio_keys_button gta02_buttons[] = {
 480        {
 481                .gpio = GTA02_GPIO_AUX_KEY,
 482                .code = KEY_PHONE,
 483                .desc = "Aux",
 484                .type = EV_KEY,
 485                .debounce_interval = 100,
 486        },
 487        {
 488                .gpio = GTA02_GPIO_HOLD_KEY,
 489                .code = KEY_PAUSE,
 490                .desc = "Hold",
 491                .type = EV_KEY,
 492                .debounce_interval = 100,
 493        },
 494};
 495
 496static struct gpio_keys_platform_data gta02_buttons_pdata = {
 497        .buttons = gta02_buttons,
 498        .nbuttons = ARRAY_SIZE(gta02_buttons),
 499};
 500
 501static struct platform_device gta02_buttons_device = {
 502        .name = "gpio-keys",
 503        .id = -1,
 504        .dev = {
 505                .platform_data = &gta02_buttons_pdata,
 506        },
 507};
 508
 509static void __init gta02_map_io(void)
 510{
 511        s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc));
 512        s3c24xx_init_clocks(12000000);
 513        s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs));
 514}
 515
 516
 517/* These are the guys that don't need to be children of PMU. */
 518
 519static struct platform_device *gta02_devices[] __initdata = {
 520        &s3c_device_ohci,
 521        &s3c_device_wdt,
 522        &s3c_device_sdi,
 523        &s3c_device_usbgadget,
 524        &s3c_device_nand,
 525        &gta02_nor_flash,
 526        &s3c24xx_pwm_device,
 527        &s3c_device_iis,
 528        &samsung_asoc_dma,
 529        &s3c_device_i2c0,
 530        &gta02_dfbmcs320_device,
 531        &gta02_buttons_device,
 532        &s3c_device_adc,
 533        &s3c_device_ts,
 534};
 535
 536/* These guys DO need to be children of PMU. */
 537
 538static struct platform_device *gta02_devices_pmu_children[] = {
 539};
 540
 541
 542/*
 543 * This is called when pc50633 is probed, quite late in the day since it is an
 544 * I2C bus device.  Here we can define platform devices with the advantage that
 545 * we can mark the pcf50633 as the parent.  This makes them get suspended and
 546 * resumed with their parent the pcf50633 still around.  All devices whose
 547 * operation depends on something from pcf50633 must have this relationship
 548 * made explicit like this, or suspend and resume will become an unreliable
 549 * hellworld.
 550 */
 551
 552static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf)
 553{
 554        int n;
 555
 556        /* Grab a copy of the now probed PMU pointer. */
 557        gta02_pcf = pcf;
 558
 559        for (n = 0; n < ARRAY_SIZE(gta02_devices_pmu_children); n++)
 560                gta02_devices_pmu_children[n]->dev.parent = pcf->dev;
 561
 562        platform_add_devices(gta02_devices_pmu_children,
 563                             ARRAY_SIZE(gta02_devices_pmu_children));
 564}
 565
 566static void gta02_poweroff(void)
 567{
 568        pcf50633_reg_set_bit_mask(gta02_pcf, PCF50633_REG_OOCSHDWN, 1, 1);
 569}
 570
 571static void __init gta02_machine_init(void)
 572{
 573        /* Set the panic callback to turn AUX LED on or off. */
 574        panic_blink = gta02_panic_blink;
 575
 576        s3c_pm_init();
 577
 578#ifdef CONFIG_CHARGER_PCF50633
 579        INIT_DELAYED_WORK(&gta02_charger_work, gta02_charger_worker);
 580#endif
 581
 582        s3c24xx_udc_set_platdata(&gta02_udc_cfg);
 583        s3c24xx_ts_set_platdata(&gta02_ts_info);
 584        s3c_ohci_set_platdata(&gta02_usb_info);
 585        s3c_nand_set_platdata(&gta02_nand_info);
 586        s3c_i2c0_set_platdata(NULL);
 587
 588        i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs));
 589
 590        platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
 591        pm_power_off = gta02_poweroff;
 592
 593        regulator_has_full_constraints();
 594}
 595
 596
 597MACHINE_START(NEO1973_GTA02, "GTA02")
 598        /* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
 599        .boot_params    = S3C2410_SDRAM_PA + 0x100,
 600        .map_io         = gta02_map_io,
 601        .init_irq       = s3c24xx_init_irq,
 602        .init_machine   = gta02_machine_init,
 603        .timer          = &s3c24xx_timer,
 604MACHINE_END
 605