cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mach-smartq.c (9912B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// Copyright (C) 2010 Maurus Cuelenaere
      4
      5#include <linux/delay.h>
      6#include <linux/fb.h>
      7#include <linux/gpio.h>
      8#include <linux/gpio/machine.h>
      9#include <linux/init.h>
     10#include <linux/platform_device.h>
     11#include <linux/pwm.h>
     12#include <linux/pwm_backlight.h>
     13#include <linux/serial_core.h>
     14#include <linux/serial_s3c.h>
     15#include <linux/spi/spi_gpio.h>
     16#include <linux/platform_data/s3c-hsotg.h>
     17
     18#include <asm/mach-types.h>
     19#include <asm/mach/map.h>
     20
     21#include "map.h"
     22#include "regs-gpio.h"
     23#include "gpio-samsung.h"
     24
     25#include "cpu.h"
     26#include "devs.h"
     27#include <linux/platform_data/i2c-s3c2410.h>
     28#include "gpio-cfg.h"
     29#include <linux/platform_data/hwmon-s3c.h>
     30#include <linux/platform_data/usb-ohci-s3c2410.h>
     31#include "sdhci.h"
     32#include <linux/platform_data/touchscreen-s3c2410.h>
     33
     34#include <video/platform_lcd.h>
     35
     36#include "s3c64xx.h"
     37#include "mach-smartq.h"
     38#include "regs-modem-s3c64xx.h"
     39
     40#define UCON S3C2410_UCON_DEFAULT
     41#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE)
     42#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
     43
     44static struct s3c2410_uartcfg smartq_uartcfgs[] __initdata = {
     45	[0] = {
     46		.hwport	     = 0,
     47		.flags	     = 0,
     48		.ucon	     = UCON,
     49		.ulcon	     = ULCON,
     50		.ufcon	     = UFCON,
     51	},
     52	[1] = {
     53		.hwport	     = 1,
     54		.flags	     = 0,
     55		.ucon	     = UCON,
     56		.ulcon	     = ULCON,
     57		.ufcon	     = UFCON,
     58	},
     59	[2] = {
     60		.hwport	     = 2,
     61		.flags	     = 0,
     62		.ucon	     = UCON,
     63		.ulcon	     = ULCON,
     64		.ufcon	     = UFCON,
     65	},
     66};
     67
     68static void smartq_usb_host_powercontrol(int port, int to)
     69{
     70	pr_debug("%s(%d, %d)\n", __func__, port, to);
     71
     72	if (port == 0) {
     73		gpio_set_value(S3C64XX_GPL(0), to);
     74		gpio_set_value(S3C64XX_GPL(1), to);
     75	}
     76}
     77
     78static irqreturn_t smartq_usb_host_ocirq(int irq, void *pw)
     79{
     80	struct s3c2410_hcd_info *info = pw;
     81
     82	if (gpio_get_value(S3C64XX_GPL(10)) == 0) {
     83		pr_debug("%s: over-current irq (oc detected)\n", __func__);
     84		s3c2410_usb_report_oc(info, 3);
     85	} else {
     86		pr_debug("%s: over-current irq (oc cleared)\n", __func__);
     87		s3c2410_usb_report_oc(info, 0);
     88	}
     89
     90	return IRQ_HANDLED;
     91}
     92
     93static void smartq_usb_host_enableoc(struct s3c2410_hcd_info *info, int on)
     94{
     95	int ret;
     96
     97	/* This isn't present on a SmartQ 5 board */
     98	if (machine_is_smartq5())
     99		return;
    100
    101	if (on) {
    102		ret = request_irq(gpio_to_irq(S3C64XX_GPL(10)),
    103				  smartq_usb_host_ocirq,
    104				  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
    105				  "USB host overcurrent", info);
    106		if (ret != 0)
    107			pr_err("failed to request usb oc irq: %d\n", ret);
    108	} else {
    109		free_irq(gpio_to_irq(S3C64XX_GPL(10)), info);
    110	}
    111}
    112
    113static struct s3c2410_hcd_info smartq_usb_host_info = {
    114	.port[0]	= {
    115		.flags	= S3C_HCDFLG_USED
    116	},
    117	.port[1]	= {
    118		.flags	= 0
    119	},
    120
    121	.power_control	= smartq_usb_host_powercontrol,
    122	.enable_oc	= smartq_usb_host_enableoc,
    123};
    124
    125static struct gpiod_lookup_table smartq_usb_otg_vbus_gpiod_table = {
    126	.dev_id = "gpio-vbus",
    127	.table = {
    128		GPIO_LOOKUP("GPL", 9, "vbus", GPIO_ACTIVE_LOW),
    129		{ },
    130	},
    131};
    132
    133static struct platform_device smartq_usb_otg_vbus_dev = {
    134	.name			= "gpio-vbus",
    135};
    136
    137static struct pwm_lookup smartq_pwm_lookup[] = {
    138	PWM_LOOKUP("samsung-pwm", 1, "pwm-backlight.0", NULL,
    139		   1000000000 / (1000 * 20), PWM_POLARITY_NORMAL),
    140};
    141
    142static int smartq_bl_init(struct device *dev)
    143{
    144    s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2));
    145
    146    return 0;
    147}
    148
    149static struct platform_pwm_backlight_data smartq_backlight_data = {
    150	.max_brightness	= 1000,
    151	.dft_brightness	= 600,
    152	.init		= smartq_bl_init,
    153};
    154
    155static struct platform_device smartq_backlight_device = {
    156	.name		= "pwm-backlight",
    157	.dev		= {
    158		.parent	= &samsung_device_pwm.dev,
    159		.platform_data = &smartq_backlight_data,
    160	},
    161};
    162
    163static struct s3c2410_ts_mach_info smartq_touchscreen_pdata __initdata = {
    164	.delay			= 65535,
    165	.presc			= 99,
    166	.oversampling_shift	= 4,
    167};
    168
    169static struct s3c_sdhci_platdata smartq_internal_hsmmc_pdata = {
    170	.max_width		= 4,
    171	.cd_type		= S3C_SDHCI_CD_PERMANENT,
    172};
    173
    174static struct s3c_hwmon_pdata smartq_hwmon_pdata __initdata = {
    175	/* Battery voltage (?-4.2V) */
    176	.in[0] = &(struct s3c_hwmon_chcfg) {
    177		.name		= "smartq:battery-voltage",
    178		.mult		= 3300,
    179		.div		= 2048,
    180	},
    181	/* Reference voltage (1.2V) */
    182	.in[1] = &(struct s3c_hwmon_chcfg) {
    183		.name		= "smartq:reference-voltage",
    184		.mult		= 3300,
    185		.div		= 4096,
    186	},
    187};
    188
    189static struct dwc2_hsotg_plat smartq_hsotg_pdata;
    190
    191static int __init smartq_lcd_setup_gpio(void)
    192{
    193	int ret;
    194
    195	ret = gpio_request(S3C64XX_GPM(3), "LCD power");
    196	if (ret < 0)
    197		return ret;
    198
    199	/* turn power off */
    200	gpio_direction_output(S3C64XX_GPM(3), 0);
    201
    202	return 0;
    203}
    204
    205/* GPM0 -> CS */
    206static struct spi_gpio_platform_data smartq_lcd_control = {
    207	.num_chipselect	= 1,
    208};
    209
    210static struct platform_device smartq_lcd_control_device = {
    211	.name			= "spi_gpio",
    212	.id			= 1,
    213	.dev.platform_data	= &smartq_lcd_control,
    214};
    215
    216static struct gpiod_lookup_table smartq_lcd_control_gpiod_table = {
    217	.dev_id         = "spi_gpio",
    218	.table          = {
    219		GPIO_LOOKUP("GPIOM", 1,
    220			    "sck", GPIO_ACTIVE_HIGH),
    221		GPIO_LOOKUP("GPIOM", 2,
    222			    "mosi", GPIO_ACTIVE_HIGH),
    223		GPIO_LOOKUP("GPIOM", 3,
    224			    "miso", GPIO_ACTIVE_HIGH),
    225		GPIO_LOOKUP("GPIOM", 0,
    226			    "cs", GPIO_ACTIVE_HIGH),
    227		{ },
    228	},
    229};
    230
    231static void smartq_lcd_power_set(struct plat_lcd_data *pd, unsigned int power)
    232{
    233	gpio_direction_output(S3C64XX_GPM(3), power);
    234}
    235
    236static struct plat_lcd_data smartq_lcd_power_data = {
    237	.set_power	= smartq_lcd_power_set,
    238};
    239
    240static struct platform_device smartq_lcd_power_device = {
    241	.name			= "platform-lcd",
    242	.dev.parent		= &s3c_device_fb.dev,
    243	.dev.platform_data	= &smartq_lcd_power_data,
    244};
    245
    246static struct i2c_board_info smartq_i2c_devs[] __initdata = {
    247	{ I2C_BOARD_INFO("wm8987", 0x1a), },
    248};
    249
    250static struct platform_device *smartq_devices[] __initdata = {
    251	&s3c_device_hsmmc1,	/* Init iNAND first, ... */
    252	&s3c_device_hsmmc0,	/* ... then the external SD card */
    253	&s3c_device_hsmmc2,
    254	&s3c_device_adc,
    255	&s3c_device_fb,
    256	&s3c_device_hwmon,
    257	&s3c_device_i2c0,
    258	&s3c_device_ohci,
    259	&s3c_device_rtc,
    260	&samsung_device_pwm,
    261	&s3c_device_usb_hsotg,
    262	&s3c64xx_device_iis0,
    263	&smartq_backlight_device,
    264	&smartq_lcd_control_device,
    265	&smartq_lcd_power_device,
    266	&smartq_usb_otg_vbus_dev,
    267};
    268
    269static void __init smartq_lcd_mode_set(void)
    270{
    271	u32 tmp;
    272
    273	/* set the LCD type */
    274	tmp = __raw_readl(S3C64XX_SPCON);
    275	tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
    276	tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
    277	__raw_writel(tmp, S3C64XX_SPCON);
    278
    279	/* remove the LCD bypass */
    280	tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
    281	tmp &= ~MIFPCON_LCD_BYPASS;
    282	__raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
    283}
    284
    285static void smartq_power_off(void)
    286{
    287	gpio_direction_output(S3C64XX_GPK(15), 1);
    288}
    289
    290static int __init smartq_power_off_init(void)
    291{
    292	int ret;
    293
    294	ret = gpio_request(S3C64XX_GPK(15), "Power control");
    295	if (ret < 0) {
    296		pr_err("%s: failed to get GPK15\n", __func__);
    297		return ret;
    298	}
    299
    300	/* leave power on */
    301	gpio_direction_output(S3C64XX_GPK(15), 0);
    302
    303	pm_power_off = smartq_power_off;
    304
    305	return ret;
    306}
    307
    308static int __init smartq_usb_host_init(void)
    309{
    310	int ret;
    311
    312	ret = gpio_request(S3C64XX_GPL(0), "USB power control");
    313	if (ret < 0) {
    314		pr_err("%s: failed to get GPL0\n", __func__);
    315		return ret;
    316	}
    317
    318	ret = gpio_request(S3C64XX_GPL(1), "USB host power control");
    319	if (ret < 0) {
    320		pr_err("%s: failed to get GPL1\n", __func__);
    321		goto err;
    322	}
    323
    324	if (!machine_is_smartq5()) {
    325		/* This isn't present on a SmartQ 5 board */
    326		ret = gpio_request(S3C64XX_GPL(10), "USB host overcurrent");
    327		if (ret < 0) {
    328			pr_err("%s: failed to get GPL10\n", __func__);
    329			goto err2;
    330		}
    331	}
    332
    333	/* turn power off */
    334	gpio_direction_output(S3C64XX_GPL(0), 0);
    335	gpio_direction_output(S3C64XX_GPL(1), 0);
    336	if (!machine_is_smartq5())
    337		gpio_direction_input(S3C64XX_GPL(10));
    338
    339	s3c_device_ohci.dev.platform_data = &smartq_usb_host_info;
    340
    341	return 0;
    342
    343err2:
    344	gpio_free(S3C64XX_GPL(1));
    345err:
    346	gpio_free(S3C64XX_GPL(0));
    347	return ret;
    348}
    349
    350static int __init smartq_wifi_init(void)
    351{
    352	int ret;
    353
    354	ret = gpio_request(S3C64XX_GPK(1), "wifi control");
    355	if (ret < 0) {
    356		pr_err("%s: failed to get GPK1\n", __func__);
    357		return ret;
    358	}
    359
    360	ret = gpio_request(S3C64XX_GPK(2), "wifi reset");
    361	if (ret < 0) {
    362		pr_err("%s: failed to get GPK2\n", __func__);
    363		gpio_free(S3C64XX_GPK(1));
    364		return ret;
    365	}
    366
    367	/* turn power on */
    368	gpio_direction_output(S3C64XX_GPK(1), 1);
    369
    370	/* reset device */
    371	gpio_direction_output(S3C64XX_GPK(2), 0);
    372	mdelay(100);
    373	gpio_set_value(S3C64XX_GPK(2), 1);
    374	gpio_direction_input(S3C64XX_GPK(2));
    375
    376	return 0;
    377}
    378
    379static struct map_desc smartq_iodesc[] __initdata = {};
    380void __init smartq_map_io(void)
    381{
    382	s3c64xx_init_io(smartq_iodesc, ARRAY_SIZE(smartq_iodesc));
    383	s3c64xx_set_xtal_freq(12000000);
    384	s3c64xx_set_xusbxti_freq(12000000);
    385	s3c24xx_init_uarts(smartq_uartcfgs, ARRAY_SIZE(smartq_uartcfgs));
    386	s3c64xx_set_timer_source(S3C64XX_PWM3, S3C64XX_PWM4);
    387
    388	smartq_lcd_mode_set();
    389}
    390
    391static struct gpiod_lookup_table smartq_audio_gpios = {
    392	.dev_id = "smartq-audio",
    393	.table = {
    394		GPIO_LOOKUP("GPL", 12, "headphone detect", 0),
    395		GPIO_LOOKUP("GPK", 12, "amplifiers shutdown", 0),
    396		{ },
    397	},
    398};
    399
    400void __init smartq_machine_init(void)
    401{
    402	s3c_i2c0_set_platdata(NULL);
    403	dwc2_hsotg_set_platdata(&smartq_hsotg_pdata);
    404	s3c_hwmon_set_platdata(&smartq_hwmon_pdata);
    405	s3c_sdhci1_set_platdata(&smartq_internal_hsmmc_pdata);
    406	s3c_sdhci2_set_platdata(&smartq_internal_hsmmc_pdata);
    407	s3c64xx_ts_set_platdata(&smartq_touchscreen_pdata);
    408
    409	i2c_register_board_info(0, smartq_i2c_devs,
    410				ARRAY_SIZE(smartq_i2c_devs));
    411
    412	WARN_ON(smartq_lcd_setup_gpio());
    413	WARN_ON(smartq_power_off_init());
    414	WARN_ON(smartq_usb_host_init());
    415	WARN_ON(smartq_wifi_init());
    416
    417	pwm_add_table(smartq_pwm_lookup, ARRAY_SIZE(smartq_pwm_lookup));
    418	gpiod_add_lookup_table(&smartq_lcd_control_gpiod_table);
    419	gpiod_add_lookup_table(&smartq_usb_otg_vbus_gpiod_table);
    420	platform_add_devices(smartq_devices, ARRAY_SIZE(smartq_devices));
    421
    422	gpiod_add_lookup_table(&smartq_audio_gpios);
    423	platform_device_register_simple("smartq-audio", -1, NULL, 0);
    424}