From mboxrd@z Thu Jan 1 00:00:00 1970 From: mcuelenaere@gmail.com (Maurus Cuelenaere) Date: Mon, 8 Mar 2010 19:39:06 +0100 Subject: [PATCH 7/7] ARM: S3C6410: Add basic support for SmartQ machines Message-ID: To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org This adds new machine definitions for the SmartQ 5 and 7 Signed-off-by: Maurus Cuelenaere --- arch/arm/mach-s3c64xx/Kconfig | 29 +++ arch/arm/mach-s3c64xx/Makefile | 3 + arch/arm/mach-s3c64xx/mach-smartq.c | 325 ++++++++++++++++++++++++++++++++++ arch/arm/mach-s3c64xx/mach-smartq5.c | 204 +++++++++++++++++++++ arch/arm/mach-s3c64xx/mach-smartq7.c | 220 +++++++++++++++++++++++ 5 files changed, 781 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-s3c64xx/mach-smartq.c create mode 100644 arch/arm/mach-s3c64xx/mach-smartq5.c create mode 100644 arch/arm/mach-s3c64xx/mach-smartq7.c diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig index 959df38..a747728 100644 --- a/arch/arm/mach-s3c64xx/Kconfig +++ b/arch/arm/mach-s3c64xx/Kconfig @@ -178,3 +178,32 @@ config MACH_HMT select HAVE_PWM help Machine support for the Airgoo HMT + +config MACH_SMARTQ + bool + select CPU_S3C6410 + select S3C_ADC + select S3C_DEV_HSMMC + select S3C_DEV_HSMMC1 + select S3C_DEV_HSMMC2 + select S3C_DEV_FB + select S3C_DEV_USB_HSOTG + select S3C_DEV_USB_HOST + select S3C64XX_DEV_TS + select S3C64XX_SETUP_SDHCI + select S3C64XX_SETUP_FB_24BPP + select HAVE_PWM + help + Shared machine support for SmartQ 5/7 + +config MACH_SMARTQ5 + bool "SmartQ 5" + select MACH_SMARTQ + help + Machine support for the SmartQ 5 + +config MACH_SMARTQ7 + bool "SmartQ 7" + select MACH_SMARTQ + help + Machine support for the SmartQ 7 diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile index d1d341a..6844796 100644 --- a/arch/arm/mach-s3c64xx/Makefile +++ b/arch/arm/mach-s3c64xx/Makefile @@ -52,6 +52,9 @@ obj-$(CONFIG_MACH_SMDK6400) += mach-smdk6400.o obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o obj-$(CONFIG_MACH_NCP) += mach-ncp.o obj-$(CONFIG_MACH_HMT) += mach-hmt.o +obj-$(CONFIG_MACH_SMARTQ) += mach-smartq.o +obj-$(CONFIG_MACH_SMARTQ5) += mach-smartq5.o +obj-$(CONFIG_MACH_SMARTQ7) += mach-smartq7.o # device support diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c new file mode 100644 index 0000000..2e97a12 --- /dev/null +++ b/arch/arm/mach-s3c64xx/mach-smartq.c @@ -0,0 +1,325 @@ +/* + * linux/arch/arm/mach-s3c64xx/mach-smartq.c + * + * Copyright (C) 2010 Maurus Cuelenaere + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define UCON S3C2410_UCON_DEFAULT +#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE) +#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE) + +static struct s3c2410_uartcfg smartq_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + }, + [2] = { + .hwport = 2, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + }, +}; + +static void smartq_usb_host_powercontrol(int port, int to) +{ + pr_debug("smartq_usb_host_powercontrol(%d,%d)\n", port, to); + + if (port == 0) { + gpio_set_value(S3C64XX_GPL(0), to); + gpio_set_value(S3C64XX_GPL(1), to); + } +} + +static irqreturn_t smartq_usb_host_ocirq(int irq, void *pw) +{ + struct s3c2410_hcd_info *info = pw; + + if (gpio_get_value(S3C64XX_GPL(10)) == 0) { + pr_debug("smartq_usb_host: over-current irq (oc detected)\n"); + s3c2410_usb_report_oc(info, 3); + } else { + pr_debug("smartq_usb_host: over-current irq (oc cleared)\n"); + s3c2410_usb_report_oc(info, 0); + } + + return IRQ_HANDLED; +} + +static void smartq_usb_host_enableoc(struct s3c2410_hcd_info *info, int on) +{ + int ret; + + /* This isn't present on a SmartQ 5 board */ + if (machine_is_smartq5()) + return; + + if (on) { + ret = request_irq(gpio_to_irq(S3C64XX_GPL(10)), + smartq_usb_host_ocirq, IRQF_DISABLED | + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "USB host overcurrent", info); + if (ret != 0) + pr_err("failed to request usb oc irq: %d\n", ret); + } else { + free_irq(gpio_to_irq(S3C64XX_GPL(10)), info); + } +} + +static struct s3c2410_hcd_info smartq_usb_host_info = { + .port[0] = { + .flags = S3C_HCDFLG_USED + }, + .port[1] = { + .flags = 0 + }, + + .power_control = smartq_usb_host_powercontrol, + .enable_oc = smartq_usb_host_enableoc, +}; + +static int __init smartq_usb_host_init(void) +{ + int ret; + + ret = gpio_request(S3C64XX_GPL(0), "USB power control"); + if (ret < 0) { + pr_err("%s: failed to get GPL0\n", __func__); + return ret; + } + + ret = gpio_request(S3C64XX_GPL(1), "USB host power control"); + if (ret < 0) { + pr_err("%s: failed to get GPL1\n", __func__); + goto err; + } + + if (!machine_is_smartq5()) { + /* This isn't present on a SmartQ 5 board */ + ret = gpio_request(S3C64XX_GPL(10), "USB host overcurrent"); + if (ret < 0) { + pr_err("%s: failed to get GPL10\n", __func__); + goto err2; + } + } + + /* turn power off */ + gpio_direction_output(S3C64XX_GPL(0), 0); + gpio_direction_output(S3C64XX_GPL(1), 0); + if (!machine_is_smartq5()) + gpio_direction_input(S3C64XX_GPL(10)); + + s3c_device_ohci.dev.platform_data = &smartq_usb_host_info; + + return 0; + +err2: + gpio_free(S3C64XX_GPL(1)); +err: + gpio_free(S3C64XX_GPL(0)); + return ret; +} + +static int __init smartq_power_off_init(void) +{ + int ret; + + ret = gpio_request(S3C64XX_GPK(15), "Power control"); + if (ret < 0) { + pr_err("%s: failed to get GPK15\n", __func__); + return ret; + } + + /* leave power on */ + gpio_direction_output(S3C64XX_GPK(15), 0); + + return ret; +} + +static struct gpio_vbus_mach_info smartq_usb_otg_vbus_pdata = { + .gpio_vbus = S3C64XX_GPL(9), + .gpio_pullup = -1, + .gpio_vbus_inverted = true, +}; + +static struct platform_device smartq_usb_otg_vbus_dev = { + .name = "gpio-vbus", + .dev.platform_data = &smartq_usb_otg_vbus_pdata, +}; + +static struct s3c_hsotg_plat smartq_usb_otg_pdata = { + .clk_sel = S3C_HSOTG_CLKFREQ_12MHZ, +}; + +static void __init smartq_usb_otg_init(void) +{ + s3c_device_usb_hsotg.dev.platform_data = &smartq_usb_otg_pdata; +} + +static int __init smartq_wifi_init(void) +{ + int ret; + + ret = gpio_request(S3C64XX_GPK(1), "wifi control"); + if (ret < 0) { + pr_err("%s: failed to get GPK1\n", __func__); + return ret; + } + + ret = gpio_request(S3C64XX_GPK(2), "wifi reset"); + if (ret < 0) { + pr_err("%s: failed to get GPK2\n", __func__); + gpio_free(S3C64XX_GPK(1)); + return ret; + } + + /* turn power on */ + gpio_direction_output(S3C64XX_GPK(1), 1); + + /* reset device */ + gpio_direction_output(S3C64XX_GPK(2), 0); + mdelay(100); + gpio_set_value(S3C64XX_GPK(2), 1); + gpio_direction_input(S3C64XX_GPK(2)); + + return 0; +} + +static int __init smartq_bl_init(struct device *dev) +{ + s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2)); + + return 0; +} + +static struct platform_pwm_backlight_data smartq_backlight_data = { + .pwm_id = 1, + .max_brightness = 1000, + .dft_brightness = 600, + .pwm_period_ns = 1000000000 / (1000 * 20), + .init = smartq_bl_init, +}; + +static struct platform_device smartq_backlight_device = { + .name = "pwm-backlight", + .dev = { + .parent = &s3c_device_timer[1].dev, + .platform_data = &smartq_backlight_data, + }, +}; + +static struct s3c2410_ts_mach_info smartq_touchscreen_pdata __initdata = { + .delay = 65535, + .presc = 99, + .oversampling_shift = 4, +}; + +static struct s3c_sdhci_platdata smartq_internal_hsmmc_pdata = { + .max_width = 4, + .broken_card_detection = true, +}; + +static struct platform_device *smartq_devices[] __initdata = { + &s3c_device_hsmmc1, /* Init iNAND first, ... */ + &s3c_device_hsmmc0, /* ... then the external SD card */ + &s3c_device_hsmmc2, + &s3c_device_adc, + &s3c_device_fb, + &s3c_device_i2c0, + &s3c_device_ohci, + &s3c_device_rtc, + &s3c_device_timer[1], + &s3c_device_ts, + &s3c_device_usb_hsotg, + &smartq_backlight_device, + &smartq_usb_otg_vbus_dev, +}; + +static void __init smartq_lcd_mode_set(void) +{ + u32 tmp; + + /* set the LCD type */ + tmp = __raw_readl(S3C64XX_SPCON); + tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK; + tmp |= S3C64XX_SPCON_LCD_SEL_RGB; + __raw_writel(tmp, S3C64XX_SPCON); + + /* remove the LCD bypass */ + tmp = __raw_readl(S3C64XX_MODEM_MIFPCON); + tmp &= ~MIFPCON_LCD_BYPASS; + __raw_writel(tmp, S3C64XX_MODEM_MIFPCON); +} + +static void smartq_power_off(void) +{ + gpio_direction_output(S3C64XX_GPK(15), 1); +} + +static struct map_desc smartq_iodesc[] __initdata = {}; +void __init smartq_map_io(void) +{ + s3c64xx_init_io(smartq_iodesc, ARRAY_SIZE(smartq_iodesc)); + s3c24xx_init_clocks(12000000); + s3c24xx_init_uarts(smartq_uartcfgs, ARRAY_SIZE(smartq_uartcfgs)); + + smartq_lcd_mode_set(); +} + +void __init smartq_machine_init(void) +{ + s3c_i2c0_set_platdata(NULL); + s3c_sdhci1_set_platdata(&smartq_internal_hsmmc_pdata); + s3c_sdhci2_set_platdata(&smartq_internal_hsmmc_pdata); + s3c24xx_ts_set_platdata(&smartq_touchscreen_pdata); + + smartq_power_off_init(); + smartq_usb_host_init(); + smartq_usb_otg_init(); + smartq_wifi_init(); + + platform_add_devices(smartq_devices, ARRAY_SIZE(smartq_devices)); + pm_power_off = smartq_power_off; +} diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c new file mode 100644 index 0000000..67a98da --- /dev/null +++ b/arch/arm/mach-s3c64xx/mach-smartq5.c @@ -0,0 +1,204 @@ +/* + * linux/arch/arm/mach-s3c64xx/mach-smartq5.c + * + * Copyright (C) 2010 Maurus Cuelenaere + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include