18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// S3C2442 Machine Support for Openmoko GTA02 / FreeRunner. 48c2ecf20Sopenharmony_ci// 58c2ecf20Sopenharmony_ci// Copyright (C) 2006-2009 by Openmoko, Inc. 68c2ecf20Sopenharmony_ci// Authors: Harald Welte <laforge@openmoko.org> 78c2ecf20Sopenharmony_ci// Andy Green <andy@openmoko.org> 88c2ecf20Sopenharmony_ci// Werner Almesberger <werner@openmoko.org> 98c2ecf20Sopenharmony_ci// All rights reserved. 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/types.h> 138c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 148c2ecf20Sopenharmony_ci#include <linux/list.h> 158c2ecf20Sopenharmony_ci#include <linux/delay.h> 168c2ecf20Sopenharmony_ci#include <linux/timer.h> 178c2ecf20Sopenharmony_ci#include <linux/init.h> 188c2ecf20Sopenharmony_ci#include <linux/gpio/machine.h> 198c2ecf20Sopenharmony_ci#include <linux/gpio.h> 208c2ecf20Sopenharmony_ci#include <linux/gpio_keys.h> 218c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 228c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 238c2ecf20Sopenharmony_ci#include <linux/serial_core.h> 248c2ecf20Sopenharmony_ci#include <linux/serial_s3c.h> 258c2ecf20Sopenharmony_ci#include <linux/input.h> 268c2ecf20Sopenharmony_ci#include <linux/io.h> 278c2ecf20Sopenharmony_ci#include <linux/i2c.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <linux/mmc/host.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include <linux/mfd/pcf50633/adc.h> 328c2ecf20Sopenharmony_ci#include <linux/mfd/pcf50633/backlight.h> 338c2ecf20Sopenharmony_ci#include <linux/mfd/pcf50633/core.h> 348c2ecf20Sopenharmony_ci#include <linux/mfd/pcf50633/gpio.h> 358c2ecf20Sopenharmony_ci#include <linux/mfd/pcf50633/mbc.h> 368c2ecf20Sopenharmony_ci#include <linux/mfd/pcf50633/pmic.h> 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h> 398c2ecf20Sopenharmony_ci#include <linux/mtd/rawnand.h> 408c2ecf20Sopenharmony_ci#include <linux/mtd/nand_ecc.h> 418c2ecf20Sopenharmony_ci#include <linux/mtd/partitions.h> 428c2ecf20Sopenharmony_ci#include <linux/mtd/physmap.h> 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#include <linux/regulator/machine.h> 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include <linux/spi/spi.h> 478c2ecf20Sopenharmony_ci#include <linux/spi/s3c24xx.h> 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#include <asm/irq.h> 508c2ecf20Sopenharmony_ci#include <asm/mach-types.h> 518c2ecf20Sopenharmony_ci#include <asm/mach/arch.h> 528c2ecf20Sopenharmony_ci#include <asm/mach/map.h> 538c2ecf20Sopenharmony_ci#include <asm/mach/irq.h> 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#include <linux/platform_data/i2c-s3c2410.h> 568c2ecf20Sopenharmony_ci#include <linux/platform_data/mtd-nand-s3c2410.h> 578c2ecf20Sopenharmony_ci#include <linux/platform_data/touchscreen-s3c2410.h> 588c2ecf20Sopenharmony_ci#include <linux/platform_data/usb-ohci-s3c2410.h> 598c2ecf20Sopenharmony_ci#include <linux/platform_data/usb-s3c2410_udc.h> 608c2ecf20Sopenharmony_ci#include <linux/platform_data/fb-s3c2410.h> 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#include "regs-gpio.h" 638c2ecf20Sopenharmony_ci#include "regs-irq.h" 648c2ecf20Sopenharmony_ci#include "gpio-samsung.h" 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#include "cpu.h" 678c2ecf20Sopenharmony_ci#include "devs.h" 688c2ecf20Sopenharmony_ci#include "gpio-cfg.h" 698c2ecf20Sopenharmony_ci#include "pm.h" 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci#include "s3c24xx.h" 728c2ecf20Sopenharmony_ci#include "gta02.h" 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic struct pcf50633 *gta02_pcf; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/* 778c2ecf20Sopenharmony_ci * This gets called frequently when we paniced. 788c2ecf20Sopenharmony_ci */ 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic long gta02_panic_blink(int state) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci long delay = 0; 838c2ecf20Sopenharmony_ci char led; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci led = (state) ? 1 : 0; 868c2ecf20Sopenharmony_ci gpio_direction_output(GTA02_GPIO_AUX_LED, led); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci return delay; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic struct map_desc gta02_iodesc[] __initdata = { 938c2ecf20Sopenharmony_ci { 948c2ecf20Sopenharmony_ci .virtual = 0xe0000000, 958c2ecf20Sopenharmony_ci .pfn = __phys_to_pfn(S3C2410_CS3 + 0x01000000), 968c2ecf20Sopenharmony_ci .length = SZ_1M, 978c2ecf20Sopenharmony_ci .type = MT_DEVICE 988c2ecf20Sopenharmony_ci }, 998c2ecf20Sopenharmony_ci}; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#define UCON (S3C2410_UCON_DEFAULT | S3C2443_UCON_RXERR_IRQEN) 1028c2ecf20Sopenharmony_ci#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB) 1038c2ecf20Sopenharmony_ci#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE) 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic struct s3c2410_uartcfg gta02_uartcfgs[] = { 1068c2ecf20Sopenharmony_ci [0] = { 1078c2ecf20Sopenharmony_ci .hwport = 0, 1088c2ecf20Sopenharmony_ci .flags = 0, 1098c2ecf20Sopenharmony_ci .ucon = UCON, 1108c2ecf20Sopenharmony_ci .ulcon = ULCON, 1118c2ecf20Sopenharmony_ci .ufcon = UFCON, 1128c2ecf20Sopenharmony_ci }, 1138c2ecf20Sopenharmony_ci [1] = { 1148c2ecf20Sopenharmony_ci .hwport = 1, 1158c2ecf20Sopenharmony_ci .flags = 0, 1168c2ecf20Sopenharmony_ci .ucon = UCON, 1178c2ecf20Sopenharmony_ci .ulcon = ULCON, 1188c2ecf20Sopenharmony_ci .ufcon = UFCON, 1198c2ecf20Sopenharmony_ci }, 1208c2ecf20Sopenharmony_ci [2] = { 1218c2ecf20Sopenharmony_ci .hwport = 2, 1228c2ecf20Sopenharmony_ci .flags = 0, 1238c2ecf20Sopenharmony_ci .ucon = UCON, 1248c2ecf20Sopenharmony_ci .ulcon = ULCON, 1258c2ecf20Sopenharmony_ci .ufcon = UFCON, 1268c2ecf20Sopenharmony_ci }, 1278c2ecf20Sopenharmony_ci}; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci#ifdef CONFIG_CHARGER_PCF50633 1308c2ecf20Sopenharmony_ci/* 1318c2ecf20Sopenharmony_ci * On GTA02 the 1A charger features a 48K resistor to 0V on the ID pin. 1328c2ecf20Sopenharmony_ci * We use this to recognize that we can pull 1A from the USB socket. 1338c2ecf20Sopenharmony_ci * 1348c2ecf20Sopenharmony_ci * These constants are the measured pcf50633 ADC levels with the 1A 1358c2ecf20Sopenharmony_ci * charger / 48K resistor, and with no pulldown resistor. 1368c2ecf20Sopenharmony_ci */ 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci#define ADC_NOM_CHG_DETECT_1A 6 1398c2ecf20Sopenharmony_ci#define ADC_NOM_CHG_DETECT_USB 43 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci#ifdef CONFIG_PCF50633_ADC 1428c2ecf20Sopenharmony_cistatic void 1438c2ecf20Sopenharmony_cigta02_configure_pmu_for_charger(struct pcf50633 *pcf, void *unused, int res) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci int ma; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci /* Interpret charger type */ 1488c2ecf20Sopenharmony_ci if (res < ((ADC_NOM_CHG_DETECT_USB + ADC_NOM_CHG_DETECT_1A) / 2)) { 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci /* 1518c2ecf20Sopenharmony_ci * Sanity - stop GPO driving out now that we have a 1A charger 1528c2ecf20Sopenharmony_ci * GPO controls USB Host power generation on GTA02 1538c2ecf20Sopenharmony_ci */ 1548c2ecf20Sopenharmony_ci pcf50633_gpio_set(pcf, PCF50633_GPO, 0); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci ma = 1000; 1578c2ecf20Sopenharmony_ci } else 1588c2ecf20Sopenharmony_ci ma = 100; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci pcf50633_mbc_usb_curlim_set(pcf, ma); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci#endif 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic struct delayed_work gta02_charger_work; 1658c2ecf20Sopenharmony_cistatic int gta02_usb_vbus_draw; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic void gta02_charger_worker(struct work_struct *work) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci if (gta02_usb_vbus_draw) { 1708c2ecf20Sopenharmony_ci pcf50633_mbc_usb_curlim_set(gta02_pcf, gta02_usb_vbus_draw); 1718c2ecf20Sopenharmony_ci return; 1728c2ecf20Sopenharmony_ci } 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci#ifdef CONFIG_PCF50633_ADC 1758c2ecf20Sopenharmony_ci pcf50633_adc_async_read(gta02_pcf, 1768c2ecf20Sopenharmony_ci PCF50633_ADCC1_MUX_ADCIN1, 1778c2ecf20Sopenharmony_ci PCF50633_ADCC1_AVERAGE_16, 1788c2ecf20Sopenharmony_ci gta02_configure_pmu_for_charger, 1798c2ecf20Sopenharmony_ci NULL); 1808c2ecf20Sopenharmony_ci#else 1818c2ecf20Sopenharmony_ci /* 1828c2ecf20Sopenharmony_ci * If the PCF50633 ADC is disabled we fallback to a 1838c2ecf20Sopenharmony_ci * 100mA limit for safety. 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ci pcf50633_mbc_usb_curlim_set(gta02_pcf, 100); 1868c2ecf20Sopenharmony_ci#endif 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci#define GTA02_CHARGER_CONFIGURE_TIMEOUT ((3000 * HZ) / 1000) 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic void gta02_pmu_event_callback(struct pcf50633 *pcf, int irq) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci if (irq == PCF50633_IRQ_USBINS) { 1948c2ecf20Sopenharmony_ci schedule_delayed_work(>a02_charger_work, 1958c2ecf20Sopenharmony_ci GTA02_CHARGER_CONFIGURE_TIMEOUT); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci return; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci if (irq == PCF50633_IRQ_USBREM) { 2018c2ecf20Sopenharmony_ci cancel_delayed_work_sync(>a02_charger_work); 2028c2ecf20Sopenharmony_ci gta02_usb_vbus_draw = 0; 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic void gta02_udc_vbus_draw(unsigned int ma) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci if (!gta02_pcf) 2098c2ecf20Sopenharmony_ci return; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci gta02_usb_vbus_draw = ma; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci schedule_delayed_work(>a02_charger_work, 2148c2ecf20Sopenharmony_ci GTA02_CHARGER_CONFIGURE_TIMEOUT); 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci#else /* !CONFIG_CHARGER_PCF50633 */ 2178c2ecf20Sopenharmony_ci#define gta02_pmu_event_callback NULL 2188c2ecf20Sopenharmony_ci#define gta02_udc_vbus_draw NULL 2198c2ecf20Sopenharmony_ci#endif 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic char *gta02_batteries[] = { 2228c2ecf20Sopenharmony_ci "battery", 2238c2ecf20Sopenharmony_ci}; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic struct pcf50633_bl_platform_data gta02_backlight_data = { 2268c2ecf20Sopenharmony_ci .default_brightness = 0x3f, 2278c2ecf20Sopenharmony_ci .default_brightness_limit = 0, 2288c2ecf20Sopenharmony_ci .ramp_time = 5, 2298c2ecf20Sopenharmony_ci}; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_cistatic struct pcf50633_platform_data gta02_pcf_pdata = { 2328c2ecf20Sopenharmony_ci .resumers = { 2338c2ecf20Sopenharmony_ci [0] = PCF50633_INT1_USBINS | 2348c2ecf20Sopenharmony_ci PCF50633_INT1_USBREM | 2358c2ecf20Sopenharmony_ci PCF50633_INT1_ALARM, 2368c2ecf20Sopenharmony_ci [1] = PCF50633_INT2_ONKEYF, 2378c2ecf20Sopenharmony_ci [2] = PCF50633_INT3_ONKEY1S, 2388c2ecf20Sopenharmony_ci [3] = PCF50633_INT4_LOWSYS | 2398c2ecf20Sopenharmony_ci PCF50633_INT4_LOWBAT | 2408c2ecf20Sopenharmony_ci PCF50633_INT4_HIGHTMP, 2418c2ecf20Sopenharmony_ci }, 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci .batteries = gta02_batteries, 2448c2ecf20Sopenharmony_ci .num_batteries = ARRAY_SIZE(gta02_batteries), 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci .charger_reference_current_ma = 1000, 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci .backlight_data = >a02_backlight_data, 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci .reg_init_data = { 2518c2ecf20Sopenharmony_ci [PCF50633_REGULATOR_AUTO] = { 2528c2ecf20Sopenharmony_ci .constraints = { 2538c2ecf20Sopenharmony_ci .min_uV = 3300000, 2548c2ecf20Sopenharmony_ci .max_uV = 3300000, 2558c2ecf20Sopenharmony_ci .valid_modes_mask = REGULATOR_MODE_NORMAL, 2568c2ecf20Sopenharmony_ci .always_on = 1, 2578c2ecf20Sopenharmony_ci .apply_uV = 1, 2588c2ecf20Sopenharmony_ci }, 2598c2ecf20Sopenharmony_ci }, 2608c2ecf20Sopenharmony_ci [PCF50633_REGULATOR_DOWN1] = { 2618c2ecf20Sopenharmony_ci .constraints = { 2628c2ecf20Sopenharmony_ci .min_uV = 1300000, 2638c2ecf20Sopenharmony_ci .max_uV = 1600000, 2648c2ecf20Sopenharmony_ci .valid_modes_mask = REGULATOR_MODE_NORMAL, 2658c2ecf20Sopenharmony_ci .always_on = 1, 2668c2ecf20Sopenharmony_ci .apply_uV = 1, 2678c2ecf20Sopenharmony_ci }, 2688c2ecf20Sopenharmony_ci }, 2698c2ecf20Sopenharmony_ci [PCF50633_REGULATOR_DOWN2] = { 2708c2ecf20Sopenharmony_ci .constraints = { 2718c2ecf20Sopenharmony_ci .min_uV = 1800000, 2728c2ecf20Sopenharmony_ci .max_uV = 1800000, 2738c2ecf20Sopenharmony_ci .valid_modes_mask = REGULATOR_MODE_NORMAL, 2748c2ecf20Sopenharmony_ci .apply_uV = 1, 2758c2ecf20Sopenharmony_ci .always_on = 1, 2768c2ecf20Sopenharmony_ci }, 2778c2ecf20Sopenharmony_ci }, 2788c2ecf20Sopenharmony_ci [PCF50633_REGULATOR_HCLDO] = { 2798c2ecf20Sopenharmony_ci .constraints = { 2808c2ecf20Sopenharmony_ci .min_uV = 2000000, 2818c2ecf20Sopenharmony_ci .max_uV = 3300000, 2828c2ecf20Sopenharmony_ci .valid_modes_mask = REGULATOR_MODE_NORMAL, 2838c2ecf20Sopenharmony_ci .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | 2848c2ecf20Sopenharmony_ci REGULATOR_CHANGE_STATUS, 2858c2ecf20Sopenharmony_ci }, 2868c2ecf20Sopenharmony_ci }, 2878c2ecf20Sopenharmony_ci [PCF50633_REGULATOR_LDO1] = { 2888c2ecf20Sopenharmony_ci .constraints = { 2898c2ecf20Sopenharmony_ci .min_uV = 3300000, 2908c2ecf20Sopenharmony_ci .max_uV = 3300000, 2918c2ecf20Sopenharmony_ci .valid_modes_mask = REGULATOR_MODE_NORMAL, 2928c2ecf20Sopenharmony_ci .valid_ops_mask = REGULATOR_CHANGE_STATUS, 2938c2ecf20Sopenharmony_ci .apply_uV = 1, 2948c2ecf20Sopenharmony_ci }, 2958c2ecf20Sopenharmony_ci }, 2968c2ecf20Sopenharmony_ci [PCF50633_REGULATOR_LDO2] = { 2978c2ecf20Sopenharmony_ci .constraints = { 2988c2ecf20Sopenharmony_ci .min_uV = 3300000, 2998c2ecf20Sopenharmony_ci .max_uV = 3300000, 3008c2ecf20Sopenharmony_ci .valid_modes_mask = REGULATOR_MODE_NORMAL, 3018c2ecf20Sopenharmony_ci .apply_uV = 1, 3028c2ecf20Sopenharmony_ci }, 3038c2ecf20Sopenharmony_ci }, 3048c2ecf20Sopenharmony_ci [PCF50633_REGULATOR_LDO3] = { 3058c2ecf20Sopenharmony_ci .constraints = { 3068c2ecf20Sopenharmony_ci .min_uV = 3000000, 3078c2ecf20Sopenharmony_ci .max_uV = 3000000, 3088c2ecf20Sopenharmony_ci .valid_modes_mask = REGULATOR_MODE_NORMAL, 3098c2ecf20Sopenharmony_ci .apply_uV = 1, 3108c2ecf20Sopenharmony_ci }, 3118c2ecf20Sopenharmony_ci }, 3128c2ecf20Sopenharmony_ci [PCF50633_REGULATOR_LDO4] = { 3138c2ecf20Sopenharmony_ci .constraints = { 3148c2ecf20Sopenharmony_ci .min_uV = 3200000, 3158c2ecf20Sopenharmony_ci .max_uV = 3200000, 3168c2ecf20Sopenharmony_ci .valid_modes_mask = REGULATOR_MODE_NORMAL, 3178c2ecf20Sopenharmony_ci .valid_ops_mask = REGULATOR_CHANGE_STATUS, 3188c2ecf20Sopenharmony_ci .apply_uV = 1, 3198c2ecf20Sopenharmony_ci }, 3208c2ecf20Sopenharmony_ci }, 3218c2ecf20Sopenharmony_ci [PCF50633_REGULATOR_LDO5] = { 3228c2ecf20Sopenharmony_ci .constraints = { 3238c2ecf20Sopenharmony_ci .min_uV = 3000000, 3248c2ecf20Sopenharmony_ci .max_uV = 3000000, 3258c2ecf20Sopenharmony_ci .valid_modes_mask = REGULATOR_MODE_NORMAL, 3268c2ecf20Sopenharmony_ci .valid_ops_mask = REGULATOR_CHANGE_STATUS, 3278c2ecf20Sopenharmony_ci .apply_uV = 1, 3288c2ecf20Sopenharmony_ci }, 3298c2ecf20Sopenharmony_ci }, 3308c2ecf20Sopenharmony_ci [PCF50633_REGULATOR_LDO6] = { 3318c2ecf20Sopenharmony_ci .constraints = { 3328c2ecf20Sopenharmony_ci .min_uV = 3000000, 3338c2ecf20Sopenharmony_ci .max_uV = 3000000, 3348c2ecf20Sopenharmony_ci .valid_modes_mask = REGULATOR_MODE_NORMAL, 3358c2ecf20Sopenharmony_ci }, 3368c2ecf20Sopenharmony_ci }, 3378c2ecf20Sopenharmony_ci [PCF50633_REGULATOR_MEMLDO] = { 3388c2ecf20Sopenharmony_ci .constraints = { 3398c2ecf20Sopenharmony_ci .min_uV = 1800000, 3408c2ecf20Sopenharmony_ci .max_uV = 1800000, 3418c2ecf20Sopenharmony_ci .valid_modes_mask = REGULATOR_MODE_NORMAL, 3428c2ecf20Sopenharmony_ci }, 3438c2ecf20Sopenharmony_ci }, 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci }, 3468c2ecf20Sopenharmony_ci .mbc_event_callback = gta02_pmu_event_callback, 3478c2ecf20Sopenharmony_ci}; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci/* NOR Flash. */ 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci#define GTA02_FLASH_BASE 0x18000000 /* GCS3 */ 3538c2ecf20Sopenharmony_ci#define GTA02_FLASH_SIZE 0x200000 /* 2MBytes */ 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic struct physmap_flash_data gta02_nor_flash_data = { 3568c2ecf20Sopenharmony_ci .width = 2, 3578c2ecf20Sopenharmony_ci}; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic struct resource gta02_nor_flash_resource = 3608c2ecf20Sopenharmony_ci DEFINE_RES_MEM(GTA02_FLASH_BASE, GTA02_FLASH_SIZE); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_cistatic struct platform_device gta02_nor_flash = { 3638c2ecf20Sopenharmony_ci .name = "physmap-flash", 3648c2ecf20Sopenharmony_ci .id = 0, 3658c2ecf20Sopenharmony_ci .dev = { 3668c2ecf20Sopenharmony_ci .platform_data = >a02_nor_flash_data, 3678c2ecf20Sopenharmony_ci }, 3688c2ecf20Sopenharmony_ci .resource = >a02_nor_flash_resource, 3698c2ecf20Sopenharmony_ci .num_resources = 1, 3708c2ecf20Sopenharmony_ci}; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic struct platform_device s3c24xx_pwm_device = { 3748c2ecf20Sopenharmony_ci .name = "s3c24xx_pwm", 3758c2ecf20Sopenharmony_ci .num_resources = 0, 3768c2ecf20Sopenharmony_ci}; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_cistatic struct platform_device gta02_dfbmcs320_device = { 3798c2ecf20Sopenharmony_ci .name = "dfbmcs320", 3808c2ecf20Sopenharmony_ci}; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cistatic struct i2c_board_info gta02_i2c_devs[] __initdata = { 3838c2ecf20Sopenharmony_ci { 3848c2ecf20Sopenharmony_ci I2C_BOARD_INFO("pcf50633", 0x73), 3858c2ecf20Sopenharmony_ci .irq = GTA02_IRQ_PCF50633, 3868c2ecf20Sopenharmony_ci .platform_data = >a02_pcf_pdata, 3878c2ecf20Sopenharmony_ci }, 3888c2ecf20Sopenharmony_ci { 3898c2ecf20Sopenharmony_ci I2C_BOARD_INFO("wm8753", 0x1a), 3908c2ecf20Sopenharmony_ci }, 3918c2ecf20Sopenharmony_ci}; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_cistatic struct s3c2410_nand_set __initdata gta02_nand_sets[] = { 3948c2ecf20Sopenharmony_ci [0] = { 3958c2ecf20Sopenharmony_ci /* 3968c2ecf20Sopenharmony_ci * This name is also hard-coded in the boot loaders, so 3978c2ecf20Sopenharmony_ci * changing it would would require all users to upgrade 3988c2ecf20Sopenharmony_ci * their boot loaders, some of which are stored in a NOR 3998c2ecf20Sopenharmony_ci * that is considered to be immutable. 4008c2ecf20Sopenharmony_ci */ 4018c2ecf20Sopenharmony_ci .name = "neo1973-nand", 4028c2ecf20Sopenharmony_ci .nr_chips = 1, 4038c2ecf20Sopenharmony_ci .flash_bbt = 1, 4048c2ecf20Sopenharmony_ci }, 4058c2ecf20Sopenharmony_ci}; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci/* 4088c2ecf20Sopenharmony_ci * Choose a set of timings derived from S3C@2442B MCP54 4098c2ecf20Sopenharmony_ci * data sheet (K5D2G13ACM-D075 MCP Memory). 4108c2ecf20Sopenharmony_ci */ 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_cistatic struct s3c2410_platform_nand __initdata gta02_nand_info = { 4138c2ecf20Sopenharmony_ci .tacls = 0, 4148c2ecf20Sopenharmony_ci .twrph0 = 25, 4158c2ecf20Sopenharmony_ci .twrph1 = 15, 4168c2ecf20Sopenharmony_ci .nr_sets = ARRAY_SIZE(gta02_nand_sets), 4178c2ecf20Sopenharmony_ci .sets = gta02_nand_sets, 4188c2ecf20Sopenharmony_ci .engine_type = NAND_ECC_ENGINE_TYPE_SOFT, 4198c2ecf20Sopenharmony_ci}; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci/* Get PMU to set USB current limit accordingly. */ 4238c2ecf20Sopenharmony_cistatic struct s3c2410_udc_mach_info gta02_udc_cfg __initdata = { 4248c2ecf20Sopenharmony_ci .vbus_draw = gta02_udc_vbus_draw, 4258c2ecf20Sopenharmony_ci .pullup_pin = GTA02_GPIO_USB_PULLUP, 4268c2ecf20Sopenharmony_ci}; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci/* USB */ 4298c2ecf20Sopenharmony_cistatic struct s3c2410_hcd_info gta02_usb_info __initdata = { 4308c2ecf20Sopenharmony_ci .port[0] = { 4318c2ecf20Sopenharmony_ci .flags = S3C_HCDFLG_USED, 4328c2ecf20Sopenharmony_ci }, 4338c2ecf20Sopenharmony_ci .port[1] = { 4348c2ecf20Sopenharmony_ci .flags = 0, 4358c2ecf20Sopenharmony_ci }, 4368c2ecf20Sopenharmony_ci}; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci/* Touchscreen */ 4398c2ecf20Sopenharmony_cistatic struct s3c2410_ts_mach_info gta02_ts_info = { 4408c2ecf20Sopenharmony_ci .delay = 10000, 4418c2ecf20Sopenharmony_ci .presc = 0xff, /* slow as we can go */ 4428c2ecf20Sopenharmony_ci .oversampling_shift = 2, 4438c2ecf20Sopenharmony_ci}; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci/* Buttons */ 4468c2ecf20Sopenharmony_cistatic struct gpio_keys_button gta02_buttons[] = { 4478c2ecf20Sopenharmony_ci { 4488c2ecf20Sopenharmony_ci .gpio = GTA02_GPIO_AUX_KEY, 4498c2ecf20Sopenharmony_ci .code = KEY_PHONE, 4508c2ecf20Sopenharmony_ci .desc = "Aux", 4518c2ecf20Sopenharmony_ci .type = EV_KEY, 4528c2ecf20Sopenharmony_ci .debounce_interval = 100, 4538c2ecf20Sopenharmony_ci }, 4548c2ecf20Sopenharmony_ci { 4558c2ecf20Sopenharmony_ci .gpio = GTA02_GPIO_HOLD_KEY, 4568c2ecf20Sopenharmony_ci .code = KEY_PAUSE, 4578c2ecf20Sopenharmony_ci .desc = "Hold", 4588c2ecf20Sopenharmony_ci .type = EV_KEY, 4598c2ecf20Sopenharmony_ci .debounce_interval = 100, 4608c2ecf20Sopenharmony_ci }, 4618c2ecf20Sopenharmony_ci}; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cistatic struct gpio_keys_platform_data gta02_buttons_pdata = { 4648c2ecf20Sopenharmony_ci .buttons = gta02_buttons, 4658c2ecf20Sopenharmony_ci .nbuttons = ARRAY_SIZE(gta02_buttons), 4668c2ecf20Sopenharmony_ci}; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_cistatic struct platform_device gta02_buttons_device = { 4698c2ecf20Sopenharmony_ci .name = "gpio-keys", 4708c2ecf20Sopenharmony_ci .id = -1, 4718c2ecf20Sopenharmony_ci .dev = { 4728c2ecf20Sopenharmony_ci .platform_data = >a02_buttons_pdata, 4738c2ecf20Sopenharmony_ci }, 4748c2ecf20Sopenharmony_ci}; 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_cistatic struct gpiod_lookup_table gta02_audio_gpio_table = { 4778c2ecf20Sopenharmony_ci .dev_id = "neo1973-audio", 4788c2ecf20Sopenharmony_ci .table = { 4798c2ecf20Sopenharmony_ci GPIO_LOOKUP("GPIOJ", 2, "amp-shut", GPIO_ACTIVE_HIGH), 4808c2ecf20Sopenharmony_ci GPIO_LOOKUP("GPIOJ", 1, "hp", GPIO_ACTIVE_HIGH), 4818c2ecf20Sopenharmony_ci { }, 4828c2ecf20Sopenharmony_ci }, 4838c2ecf20Sopenharmony_ci}; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic struct platform_device gta02_audio = { 4868c2ecf20Sopenharmony_ci .name = "neo1973-audio", 4878c2ecf20Sopenharmony_ci .id = -1, 4888c2ecf20Sopenharmony_ci}; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_cistatic struct gpiod_lookup_table gta02_mmc_gpio_table = { 4918c2ecf20Sopenharmony_ci .dev_id = "s3c2410-sdi", 4928c2ecf20Sopenharmony_ci .table = { 4938c2ecf20Sopenharmony_ci /* bus pins */ 4948c2ecf20Sopenharmony_ci GPIO_LOOKUP_IDX("GPIOE", 5, "bus", 0, GPIO_ACTIVE_HIGH), 4958c2ecf20Sopenharmony_ci GPIO_LOOKUP_IDX("GPIOE", 6, "bus", 1, GPIO_ACTIVE_HIGH), 4968c2ecf20Sopenharmony_ci GPIO_LOOKUP_IDX("GPIOE", 7, "bus", 2, GPIO_ACTIVE_HIGH), 4978c2ecf20Sopenharmony_ci GPIO_LOOKUP_IDX("GPIOE", 8, "bus", 3, GPIO_ACTIVE_HIGH), 4988c2ecf20Sopenharmony_ci GPIO_LOOKUP_IDX("GPIOE", 9, "bus", 4, GPIO_ACTIVE_HIGH), 4998c2ecf20Sopenharmony_ci GPIO_LOOKUP_IDX("GPIOE", 10, "bus", 5, GPIO_ACTIVE_HIGH), 5008c2ecf20Sopenharmony_ci { }, 5018c2ecf20Sopenharmony_ci }, 5028c2ecf20Sopenharmony_ci}; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cistatic void __init gta02_map_io(void) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc)); 5078c2ecf20Sopenharmony_ci s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs)); 5088c2ecf20Sopenharmony_ci s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4); 5098c2ecf20Sopenharmony_ci} 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci/* These are the guys that don't need to be children of PMU. */ 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_cistatic struct platform_device *gta02_devices[] __initdata = { 5158c2ecf20Sopenharmony_ci &s3c_device_ohci, 5168c2ecf20Sopenharmony_ci &s3c_device_wdt, 5178c2ecf20Sopenharmony_ci &s3c_device_sdi, 5188c2ecf20Sopenharmony_ci &s3c_device_usbgadget, 5198c2ecf20Sopenharmony_ci &s3c_device_nand, 5208c2ecf20Sopenharmony_ci >a02_nor_flash, 5218c2ecf20Sopenharmony_ci &s3c24xx_pwm_device, 5228c2ecf20Sopenharmony_ci &s3c_device_iis, 5238c2ecf20Sopenharmony_ci &s3c_device_i2c0, 5248c2ecf20Sopenharmony_ci >a02_dfbmcs320_device, 5258c2ecf20Sopenharmony_ci >a02_buttons_device, 5268c2ecf20Sopenharmony_ci &s3c_device_adc, 5278c2ecf20Sopenharmony_ci &s3c_device_ts, 5288c2ecf20Sopenharmony_ci >a02_audio, 5298c2ecf20Sopenharmony_ci}; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_cistatic void gta02_poweroff(void) 5328c2ecf20Sopenharmony_ci{ 5338c2ecf20Sopenharmony_ci pcf50633_reg_set_bit_mask(gta02_pcf, PCF50633_REG_OOCSHDWN, 1, 1); 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistatic void __init gta02_machine_init(void) 5378c2ecf20Sopenharmony_ci{ 5388c2ecf20Sopenharmony_ci /* Set the panic callback to turn AUX LED on or off. */ 5398c2ecf20Sopenharmony_ci panic_blink = gta02_panic_blink; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci s3c_pm_init(); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci#ifdef CONFIG_CHARGER_PCF50633 5448c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(>a02_charger_work, gta02_charger_worker); 5458c2ecf20Sopenharmony_ci#endif 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci s3c24xx_udc_set_platdata(>a02_udc_cfg); 5488c2ecf20Sopenharmony_ci s3c24xx_ts_set_platdata(>a02_ts_info); 5498c2ecf20Sopenharmony_ci s3c_ohci_set_platdata(>a02_usb_info); 5508c2ecf20Sopenharmony_ci s3c_nand_set_platdata(>a02_nand_info); 5518c2ecf20Sopenharmony_ci s3c_i2c0_set_platdata(NULL); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs)); 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci /* Configure the I2S pins (GPE0...GPE4) in correct mode */ 5568c2ecf20Sopenharmony_ci s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), 5578c2ecf20Sopenharmony_ci S3C_GPIO_PULL_NONE); 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci gpiod_add_lookup_table(>a02_audio_gpio_table); 5608c2ecf20Sopenharmony_ci gpiod_add_lookup_table(>a02_mmc_gpio_table); 5618c2ecf20Sopenharmony_ci platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices)); 5628c2ecf20Sopenharmony_ci pm_power_off = gta02_poweroff; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci regulator_has_full_constraints(); 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_cistatic void __init gta02_init_time(void) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci s3c2442_init_clocks(12000000); 5708c2ecf20Sopenharmony_ci s3c24xx_timer_init(); 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ciMACHINE_START(NEO1973_GTA02, "GTA02") 5748c2ecf20Sopenharmony_ci /* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */ 5758c2ecf20Sopenharmony_ci .atag_offset = 0x100, 5768c2ecf20Sopenharmony_ci .map_io = gta02_map_io, 5778c2ecf20Sopenharmony_ci .init_irq = s3c2442_init_irq, 5788c2ecf20Sopenharmony_ci .init_machine = gta02_machine_init, 5798c2ecf20Sopenharmony_ci .init_time = gta02_init_time, 5808c2ecf20Sopenharmony_ciMACHINE_END 581