0001
0002
0003
0004
0005 #include <linux/delay.h>
0006 #include <linux/fb.h>
0007 #include <linux/gpio.h>
0008 #include <linux/gpio/machine.h>
0009 #include <linux/init.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/pwm.h>
0012 #include <linux/pwm_backlight.h>
0013 #include <linux/serial_core.h>
0014 #include <linux/serial_s3c.h>
0015 #include <linux/spi/spi_gpio.h>
0016 #include <linux/platform_data/s3c-hsotg.h>
0017
0018 #include <asm/mach-types.h>
0019 #include <asm/mach/map.h>
0020
0021 #include "map.h"
0022 #include "regs-gpio.h"
0023 #include "gpio-samsung.h"
0024
0025 #include "cpu.h"
0026 #include "devs.h"
0027 #include <linux/platform_data/i2c-s3c2410.h>
0028 #include "gpio-cfg.h"
0029 #include <linux/platform_data/hwmon-s3c.h>
0030 #include <linux/platform_data/usb-ohci-s3c2410.h>
0031 #include "sdhci.h"
0032 #include <linux/platform_data/touchscreen-s3c2410.h>
0033
0034 #include <video/platform_lcd.h>
0035
0036 #include "s3c64xx.h"
0037 #include "mach-smartq.h"
0038 #include "regs-modem-s3c64xx.h"
0039
0040 #define UCON S3C2410_UCON_DEFAULT
0041 #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE)
0042 #define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
0043
0044 static struct s3c2410_uartcfg smartq_uartcfgs[] __initdata = {
0045 [0] = {
0046 .hwport = 0,
0047 .flags = 0,
0048 .ucon = UCON,
0049 .ulcon = ULCON,
0050 .ufcon = UFCON,
0051 },
0052 [1] = {
0053 .hwport = 1,
0054 .flags = 0,
0055 .ucon = UCON,
0056 .ulcon = ULCON,
0057 .ufcon = UFCON,
0058 },
0059 [2] = {
0060 .hwport = 2,
0061 .flags = 0,
0062 .ucon = UCON,
0063 .ulcon = ULCON,
0064 .ufcon = UFCON,
0065 },
0066 };
0067
0068 static void smartq_usb_host_powercontrol(int port, int to)
0069 {
0070 pr_debug("%s(%d, %d)\n", __func__, port, to);
0071
0072 if (port == 0) {
0073 gpio_set_value(S3C64XX_GPL(0), to);
0074 gpio_set_value(S3C64XX_GPL(1), to);
0075 }
0076 }
0077
0078 static irqreturn_t smartq_usb_host_ocirq(int irq, void *pw)
0079 {
0080 struct s3c2410_hcd_info *info = pw;
0081
0082 if (gpio_get_value(S3C64XX_GPL(10)) == 0) {
0083 pr_debug("%s: over-current irq (oc detected)\n", __func__);
0084 s3c2410_usb_report_oc(info, 3);
0085 } else {
0086 pr_debug("%s: over-current irq (oc cleared)\n", __func__);
0087 s3c2410_usb_report_oc(info, 0);
0088 }
0089
0090 return IRQ_HANDLED;
0091 }
0092
0093 static void smartq_usb_host_enableoc(struct s3c2410_hcd_info *info, int on)
0094 {
0095 int ret;
0096
0097
0098 if (machine_is_smartq5())
0099 return;
0100
0101 if (on) {
0102 ret = request_irq(gpio_to_irq(S3C64XX_GPL(10)),
0103 smartq_usb_host_ocirq,
0104 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
0105 "USB host overcurrent", info);
0106 if (ret != 0)
0107 pr_err("failed to request usb oc irq: %d\n", ret);
0108 } else {
0109 free_irq(gpio_to_irq(S3C64XX_GPL(10)), info);
0110 }
0111 }
0112
0113 static struct s3c2410_hcd_info smartq_usb_host_info = {
0114 .port[0] = {
0115 .flags = S3C_HCDFLG_USED
0116 },
0117 .port[1] = {
0118 .flags = 0
0119 },
0120
0121 .power_control = smartq_usb_host_powercontrol,
0122 .enable_oc = smartq_usb_host_enableoc,
0123 };
0124
0125 static struct gpiod_lookup_table smartq_usb_otg_vbus_gpiod_table = {
0126 .dev_id = "gpio-vbus",
0127 .table = {
0128 GPIO_LOOKUP("GPL", 9, "vbus", GPIO_ACTIVE_LOW),
0129 { },
0130 },
0131 };
0132
0133 static struct platform_device smartq_usb_otg_vbus_dev = {
0134 .name = "gpio-vbus",
0135 };
0136
0137 static struct pwm_lookup smartq_pwm_lookup[] = {
0138 PWM_LOOKUP("samsung-pwm", 1, "pwm-backlight.0", NULL,
0139 1000000000 / (1000 * 20), PWM_POLARITY_NORMAL),
0140 };
0141
0142 static int smartq_bl_init(struct device *dev)
0143 {
0144 s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2));
0145
0146 return 0;
0147 }
0148
0149 static struct platform_pwm_backlight_data smartq_backlight_data = {
0150 .max_brightness = 1000,
0151 .dft_brightness = 600,
0152 .init = smartq_bl_init,
0153 };
0154
0155 static struct platform_device smartq_backlight_device = {
0156 .name = "pwm-backlight",
0157 .dev = {
0158 .parent = &samsung_device_pwm.dev,
0159 .platform_data = &smartq_backlight_data,
0160 },
0161 };
0162
0163 static struct s3c2410_ts_mach_info smartq_touchscreen_pdata __initdata = {
0164 .delay = 65535,
0165 .presc = 99,
0166 .oversampling_shift = 4,
0167 };
0168
0169 static struct s3c_sdhci_platdata smartq_internal_hsmmc_pdata = {
0170 .max_width = 4,
0171 .cd_type = S3C_SDHCI_CD_PERMANENT,
0172 };
0173
0174 static struct s3c_hwmon_pdata smartq_hwmon_pdata __initdata = {
0175
0176 .in[0] = &(struct s3c_hwmon_chcfg) {
0177 .name = "smartq:battery-voltage",
0178 .mult = 3300,
0179 .div = 2048,
0180 },
0181
0182 .in[1] = &(struct s3c_hwmon_chcfg) {
0183 .name = "smartq:reference-voltage",
0184 .mult = 3300,
0185 .div = 4096,
0186 },
0187 };
0188
0189 static struct dwc2_hsotg_plat smartq_hsotg_pdata;
0190
0191 static int __init smartq_lcd_setup_gpio(void)
0192 {
0193 int ret;
0194
0195 ret = gpio_request(S3C64XX_GPM(3), "LCD power");
0196 if (ret < 0)
0197 return ret;
0198
0199
0200 gpio_direction_output(S3C64XX_GPM(3), 0);
0201
0202 return 0;
0203 }
0204
0205
0206 static struct spi_gpio_platform_data smartq_lcd_control = {
0207 .num_chipselect = 1,
0208 };
0209
0210 static struct platform_device smartq_lcd_control_device = {
0211 .name = "spi_gpio",
0212 .id = 1,
0213 .dev.platform_data = &smartq_lcd_control,
0214 };
0215
0216 static struct gpiod_lookup_table smartq_lcd_control_gpiod_table = {
0217 .dev_id = "spi_gpio",
0218 .table = {
0219 GPIO_LOOKUP("GPIOM", 1,
0220 "sck", GPIO_ACTIVE_HIGH),
0221 GPIO_LOOKUP("GPIOM", 2,
0222 "mosi", GPIO_ACTIVE_HIGH),
0223 GPIO_LOOKUP("GPIOM", 3,
0224 "miso", GPIO_ACTIVE_HIGH),
0225 GPIO_LOOKUP("GPIOM", 0,
0226 "cs", GPIO_ACTIVE_HIGH),
0227 { },
0228 },
0229 };
0230
0231 static void smartq_lcd_power_set(struct plat_lcd_data *pd, unsigned int power)
0232 {
0233 gpio_direction_output(S3C64XX_GPM(3), power);
0234 }
0235
0236 static struct plat_lcd_data smartq_lcd_power_data = {
0237 .set_power = smartq_lcd_power_set,
0238 };
0239
0240 static struct platform_device smartq_lcd_power_device = {
0241 .name = "platform-lcd",
0242 .dev.parent = &s3c_device_fb.dev,
0243 .dev.platform_data = &smartq_lcd_power_data,
0244 };
0245
0246 static struct i2c_board_info smartq_i2c_devs[] __initdata = {
0247 { I2C_BOARD_INFO("wm8987", 0x1a), },
0248 };
0249
0250 static struct platform_device *smartq_devices[] __initdata = {
0251 &s3c_device_hsmmc1,
0252 &s3c_device_hsmmc0,
0253 &s3c_device_hsmmc2,
0254 &s3c_device_adc,
0255 &s3c_device_fb,
0256 &s3c_device_hwmon,
0257 &s3c_device_i2c0,
0258 &s3c_device_ohci,
0259 &s3c_device_rtc,
0260 &samsung_device_pwm,
0261 &s3c_device_usb_hsotg,
0262 &s3c64xx_device_iis0,
0263 &smartq_backlight_device,
0264 &smartq_lcd_control_device,
0265 &smartq_lcd_power_device,
0266 &smartq_usb_otg_vbus_dev,
0267 };
0268
0269 static void __init smartq_lcd_mode_set(void)
0270 {
0271 u32 tmp;
0272
0273
0274 tmp = __raw_readl(S3C64XX_SPCON);
0275 tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
0276 tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
0277 __raw_writel(tmp, S3C64XX_SPCON);
0278
0279
0280 tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
0281 tmp &= ~MIFPCON_LCD_BYPASS;
0282 __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
0283 }
0284
0285 static void smartq_power_off(void)
0286 {
0287 gpio_direction_output(S3C64XX_GPK(15), 1);
0288 }
0289
0290 static int __init smartq_power_off_init(void)
0291 {
0292 int ret;
0293
0294 ret = gpio_request(S3C64XX_GPK(15), "Power control");
0295 if (ret < 0) {
0296 pr_err("%s: failed to get GPK15\n", __func__);
0297 return ret;
0298 }
0299
0300
0301 gpio_direction_output(S3C64XX_GPK(15), 0);
0302
0303 pm_power_off = smartq_power_off;
0304
0305 return ret;
0306 }
0307
0308 static int __init smartq_usb_host_init(void)
0309 {
0310 int ret;
0311
0312 ret = gpio_request(S3C64XX_GPL(0), "USB power control");
0313 if (ret < 0) {
0314 pr_err("%s: failed to get GPL0\n", __func__);
0315 return ret;
0316 }
0317
0318 ret = gpio_request(S3C64XX_GPL(1), "USB host power control");
0319 if (ret < 0) {
0320 pr_err("%s: failed to get GPL1\n", __func__);
0321 goto err;
0322 }
0323
0324 if (!machine_is_smartq5()) {
0325
0326 ret = gpio_request(S3C64XX_GPL(10), "USB host overcurrent");
0327 if (ret < 0) {
0328 pr_err("%s: failed to get GPL10\n", __func__);
0329 goto err2;
0330 }
0331 }
0332
0333
0334 gpio_direction_output(S3C64XX_GPL(0), 0);
0335 gpio_direction_output(S3C64XX_GPL(1), 0);
0336 if (!machine_is_smartq5())
0337 gpio_direction_input(S3C64XX_GPL(10));
0338
0339 s3c_device_ohci.dev.platform_data = &smartq_usb_host_info;
0340
0341 return 0;
0342
0343 err2:
0344 gpio_free(S3C64XX_GPL(1));
0345 err:
0346 gpio_free(S3C64XX_GPL(0));
0347 return ret;
0348 }
0349
0350 static int __init smartq_wifi_init(void)
0351 {
0352 int ret;
0353
0354 ret = gpio_request(S3C64XX_GPK(1), "wifi control");
0355 if (ret < 0) {
0356 pr_err("%s: failed to get GPK1\n", __func__);
0357 return ret;
0358 }
0359
0360 ret = gpio_request(S3C64XX_GPK(2), "wifi reset");
0361 if (ret < 0) {
0362 pr_err("%s: failed to get GPK2\n", __func__);
0363 gpio_free(S3C64XX_GPK(1));
0364 return ret;
0365 }
0366
0367
0368 gpio_direction_output(S3C64XX_GPK(1), 1);
0369
0370
0371 gpio_direction_output(S3C64XX_GPK(2), 0);
0372 mdelay(100);
0373 gpio_set_value(S3C64XX_GPK(2), 1);
0374 gpio_direction_input(S3C64XX_GPK(2));
0375
0376 return 0;
0377 }
0378
0379 static struct map_desc smartq_iodesc[] __initdata = {};
0380 void __init smartq_map_io(void)
0381 {
0382 s3c64xx_init_io(smartq_iodesc, ARRAY_SIZE(smartq_iodesc));
0383 s3c64xx_set_xtal_freq(12000000);
0384 s3c64xx_set_xusbxti_freq(12000000);
0385 s3c24xx_init_uarts(smartq_uartcfgs, ARRAY_SIZE(smartq_uartcfgs));
0386 s3c64xx_set_timer_source(S3C64XX_PWM3, S3C64XX_PWM4);
0387
0388 smartq_lcd_mode_set();
0389 }
0390
0391 static struct gpiod_lookup_table smartq_audio_gpios = {
0392 .dev_id = "smartq-audio",
0393 .table = {
0394 GPIO_LOOKUP("GPL", 12, "headphone detect", 0),
0395 GPIO_LOOKUP("GPK", 12, "amplifiers shutdown", 0),
0396 { },
0397 },
0398 };
0399
0400 void __init smartq_machine_init(void)
0401 {
0402 s3c_i2c0_set_platdata(NULL);
0403 dwc2_hsotg_set_platdata(&smartq_hsotg_pdata);
0404 s3c_hwmon_set_platdata(&smartq_hwmon_pdata);
0405 s3c_sdhci1_set_platdata(&smartq_internal_hsmmc_pdata);
0406 s3c_sdhci2_set_platdata(&smartq_internal_hsmmc_pdata);
0407 s3c64xx_ts_set_platdata(&smartq_touchscreen_pdata);
0408
0409 i2c_register_board_info(0, smartq_i2c_devs,
0410 ARRAY_SIZE(smartq_i2c_devs));
0411
0412 WARN_ON(smartq_lcd_setup_gpio());
0413 WARN_ON(smartq_power_off_init());
0414 WARN_ON(smartq_usb_host_init());
0415 WARN_ON(smartq_wifi_init());
0416
0417 pwm_add_table(smartq_pwm_lookup, ARRAY_SIZE(smartq_pwm_lookup));
0418 gpiod_add_lookup_table(&smartq_lcd_control_gpiod_table);
0419 gpiod_add_lookup_table(&smartq_usb_otg_vbus_gpiod_table);
0420 platform_add_devices(smartq_devices, ARRAY_SIZE(smartq_devices));
0421
0422 gpiod_add_lookup_table(&smartq_audio_gpios);
0423 platform_device_register_simple("smartq-audio", -1, NULL, 0);
0424 }