code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2009 Simtec Electronics
//	http://armlinux.simtec.co.uk/
//	Ben Dooks <ben@simtec.co.uk>
//
// Simtec Osiris Dynamic Voltage Scaling support.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/cpufreq.h>
#include <linux/gpio.h>

#include <linux/mfd/tps65010.h>

#include <linux/soc/samsung/s3c-cpu-freq.h>
#include "gpio-samsung.h"

#define OSIRIS_GPIO_DVS	S3C2410_GPB(5)

static bool dvs_en;

static void osiris_dvs_tps_setdvs(bool on)
{
	unsigned vregs1 = 0, vdcdc2 = 0;

	if (!on) {
		vdcdc2 = TPS_VCORE_DISCH | TPS_LP_COREOFF;
		vregs1 = TPS_LDO1_OFF;	/* turn off in low-power mode */
	}

	dvs_en = on;
	vdcdc2 |= TPS_VCORE_1_3V | TPS_VCORE_LP_1_0V;
	vregs1 |= TPS_LDO2_ENABLE | TPS_LDO1_ENABLE;

	tps65010_config_vregs1(vregs1);
	tps65010_config_vdcdc2(vdcdc2);
}

static bool is_dvs(struct s3c_freq *f)
{
	/* at the moment, we assume ARMCLK = HCLK => DVS */
	return f->armclk == f->hclk;
}

/* keep track of current state */
static bool cur_dvs = false;

static int osiris_dvs_notify(struct notifier_block *nb,
			      unsigned long val, void *data)
{
	struct cpufreq_freqs *cf = data;
	struct s3c_cpufreq_freqs *freqs = to_s3c_cpufreq(cf);
	bool old_dvs = is_dvs(&freqs->old);
	bool new_dvs = is_dvs(&freqs->new);
	int ret = 0;

	if (!dvs_en)
		return 0;

	printk(KERN_DEBUG "%s: old %ld,%ld new %ld,%ld\n", __func__,
	       freqs->old.armclk, freqs->old.hclk,
	       freqs->new.armclk, freqs->new.hclk);

	switch (val) {
	case CPUFREQ_PRECHANGE:
		if ((old_dvs && !new_dvs) ||
		    (cur_dvs && !new_dvs)) {
			pr_debug("%s: exiting dvs\n", __func__);
			cur_dvs = false;
			gpio_set_value(OSIRIS_GPIO_DVS, 1);
		}
		break;
	case CPUFREQ_POSTCHANGE:
		if ((!old_dvs && new_dvs) ||
		    (!cur_dvs && new_dvs)) {
			pr_debug("entering dvs\n");
			cur_dvs = true;
			gpio_set_value(OSIRIS_GPIO_DVS, 0);
		}
		break;
	}

	return ret;
}

static struct notifier_block osiris_dvs_nb = {
	.notifier_call	= osiris_dvs_notify,
};

static int osiris_dvs_probe(struct platform_device *pdev)
{
	int ret;

	dev_info(&pdev->dev, "initialising\n");

	ret = gpio_request(OSIRIS_GPIO_DVS, "osiris-dvs");
	if (ret) {
		dev_err(&pdev->dev, "cannot claim gpio\n");
		goto err_nogpio;
	}

	/* start with dvs disabled */
	gpio_direction_output(OSIRIS_GPIO_DVS, 1);

	ret = cpufreq_register_notifier(&osiris_dvs_nb,
					CPUFREQ_TRANSITION_NOTIFIER);
	if (ret) {
		dev_err(&pdev->dev, "failed to register with cpufreq\n");
		goto err_nofreq;
	}

	osiris_dvs_tps_setdvs(true);

	return 0;

err_nofreq:
	gpio_free(OSIRIS_GPIO_DVS);

err_nogpio:
	return ret;
}

static int osiris_dvs_remove(struct platform_device *pdev)
{
	dev_info(&pdev->dev, "exiting\n");

	/* disable any current dvs */
	gpio_set_value(OSIRIS_GPIO_DVS, 1);
	osiris_dvs_tps_setdvs(false);

	cpufreq_unregister_notifier(&osiris_dvs_nb,
				    CPUFREQ_TRANSITION_NOTIFIER);

	gpio_free(OSIRIS_GPIO_DVS);

	return 0;
}

/* the CONFIG_PM block is so small, it isn't worth actually compiling it
 * out if the configuration isn't set. */

static int osiris_dvs_suspend(struct device *dev)
{
	gpio_set_value(OSIRIS_GPIO_DVS, 1);
	osiris_dvs_tps_setdvs(false);
	cur_dvs = false;

	return 0;
}

static int osiris_dvs_resume(struct device *dev)
{
	osiris_dvs_tps_setdvs(true);
	return 0;
}

static const struct dev_pm_ops osiris_dvs_pm = {
	.suspend	= osiris_dvs_suspend,
	.resume		= osiris_dvs_resume,
};

static struct platform_driver osiris_dvs_driver = {
	.probe		= osiris_dvs_probe,
	.remove		= osiris_dvs_remove,
	.driver		= {
		.name	= "osiris-dvs",
		.pm	= &osiris_dvs_pm,
	},
};

module_platform_driver(osiris_dvs_driver);

MODULE_DESCRIPTION("Simtec OSIRIS DVS support");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:osiris-dvs");


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2005-2008 Simtec Electronics
//	http://armlinux.simtec.co.uk/
//	Ben Dooks <ben@simtec.co.uk>

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/syscore_ops.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/platform_device.h>

#include <linux/mfd/tps65010.h>

#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <asm/irq.h>

#include <linux/platform_data/mtd-nand-s3c2410.h>
#include <linux/platform_data/i2c-s3c2410.h>

#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand-ecc-sw-hamming.h>
#include <linux/mtd/partitions.h>

#include "cpu.h"
#include <linux/soc/samsung/s3c-cpu-freq.h>
#include "devs.h"
#include "gpio-cfg.h"

#include "regs-gpio.h"
#include "gpio-samsung.h"

#include "s3c24xx.h"
#include "osiris.h"
#include "regs-mem-s3c24xx.h"

/* onboard perihperal map */

static struct map_desc osiris_iodesc[] __initdata = {
  /* ISA IO areas (may be over-written later) */

  {
	  .virtual	= (u32)S3C24XX_VA_ISA_BYTE,
	  .pfn		= __phys_to_pfn(S3C2410_CS5),
	  .length	= SZ_16M,
	  .type		= MT_DEVICE,
  },

  /* CPLD control registers */

  {
	  .virtual	= (u32)OSIRIS_VA_CTRL0,
	  .pfn		= __phys_to_pfn(OSIRIS_PA_CTRL0),
	  .length	= SZ_16K,
	  .type		= MT_DEVICE,
  }, {
	  .virtual	= (u32)OSIRIS_VA_CTRL1,
	  .pfn		= __phys_to_pfn(OSIRIS_PA_CTRL1),
	  .length	= SZ_16K,
	  .type		= MT_DEVICE,
  }, {
	  .virtual	= (u32)OSIRIS_VA_CTRL2,
	  .pfn		= __phys_to_pfn(OSIRIS_PA_CTRL2),
	  .length	= SZ_16K,
	  .type		= MT_DEVICE,
  }, {
	  .virtual	= (u32)OSIRIS_VA_IDREG,
	  .pfn		= __phys_to_pfn(OSIRIS_PA_IDREG),
	  .length	= SZ_16K,
	  .type		= MT_DEVICE,
  },
};

#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE

static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
	[0] = {
		.hwport	     = 0,
		.flags	     = 0,
		.ucon	     = UCON,
		.ulcon	     = ULCON,
		.ufcon	     = UFCON,
		.clk_sel	= S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
	},
	[1] = {
		.hwport	     = 1,
		.flags	     = 0,
		.ucon	     = UCON,
		.ulcon	     = ULCON,
		.ufcon	     = UFCON,
		.clk_sel	= S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
	},
	[2] = {
		.hwport	     = 2,
		.flags	     = 0,
		.ucon	     = UCON,
		.ulcon	     = ULCON,
		.ufcon	     = UFCON,
		.clk_sel	= S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
	}
};

/* NAND Flash on Osiris board */

static int external_map[]   = { 2 };
static int chip0_map[]      = { 0 };
static int chip1_map[]      = { 1 };

static struct mtd_partition __initdata osiris_default_nand_part[] = {
	[0] = {
		.name	= "Boot Agent",
		.size	= SZ_16K,
		.offset	= 0,
	},
	[1] = {
		.name	= "/boot",
		.size	= SZ_4M - SZ_16K,
		.offset	= SZ_16K,
	},
	[2] = {
		.name	= "user1",
		.offset	= SZ_4M,
		.size	= SZ_32M - SZ_4M,
	},
	[3] = {
		.name	= "user2",
		.offset	= SZ_32M,
		.size	= MTDPART_SIZ_FULL,
	}
};

static struct mtd_partition __initdata osiris_default_nand_part_large[] = {
	[0] = {
		.name	= "Boot Agent",
		.size	= SZ_128K,
		.offset	= 0,
	},
	[1] = {
		.name	= "/boot",
		.size	= SZ_4M - SZ_128K,
		.offset	= SZ_128K,
	},
	[2] = {
		.name	= "user1",
		.offset	= SZ_4M,
		.size	= SZ_32M - SZ_4M,
	},
	[3] = {
		.name	= "user2",
		.offset	= SZ_32M,
		.size	= MTDPART_SIZ_FULL,
	}
};

/* the Osiris has 3 selectable slots for nand-flash, the two
 * on-board chip areas, as well as the external slot.
 *
 * Note, there is no current hot-plug support for the External
 * socket.
*/

static struct s3c2410_nand_set __initdata osiris_nand_sets[] = {
	[1] = {
		.name		= "External",
		.nr_chips	= 1,
		.nr_map		= external_map,
		.options	= NAND_SCAN_SILENT_NODEV,
		.nr_partitions	= ARRAY_SIZE(osiris_default_nand_part),
		.partitions	= osiris_default_nand_part,
	},
	[0] = {
		.name		= "chip0",
		.nr_chips	= 1,
		.nr_map		= chip0_map,
		.nr_partitions	= ARRAY_SIZE(osiris_default_nand_part),
		.partitions	= osiris_default_nand_part,
	},
	[2] = {
		.name		= "chip1",
		.nr_chips	= 1,
		.nr_map		= chip1_map,
		.options	= NAND_SCAN_SILENT_NODEV,
		.nr_partitions	= ARRAY_SIZE(osiris_default_nand_part),
		.partitions	= osiris_default_nand_part,
	},
};

static void osiris_nand_select(struct s3c2410_nand_set *set, int slot)
{
	unsigned int tmp;

	slot = set->nr_map[slot] & 3;

	pr_debug("osiris_nand: selecting slot %d (set %p,%p)\n",
		 slot, set, set->nr_map);

	tmp = __raw_readb(OSIRIS_VA_CTRL0);
	tmp &= ~OSIRIS_CTRL0_NANDSEL;
	tmp |= slot;

	pr_debug("osiris_nand: ctrl0 now %02x\n", tmp);

	__raw_writeb(tmp, OSIRIS_VA_CTRL0);
}

static struct s3c2410_platform_nand __initdata osiris_nand_info = {
	.tacls		= 25,
	.twrph0		= 60,
	.twrph1		= 60,
	.nr_sets	= ARRAY_SIZE(osiris_nand_sets),
	.sets		= osiris_nand_sets,
	.select_chip	= osiris_nand_select,
	.engine_type	= NAND_ECC_ENGINE_TYPE_SOFT,
};

/* PCMCIA control and configuration */

static struct resource osiris_pcmcia_resource[] = {
	[0] = DEFINE_RES_MEM(0x0f000000, SZ_1M),
	[1] = DEFINE_RES_MEM(0x0c000000, SZ_1M),
};

static struct platform_device osiris_pcmcia = {
	.name		= "osiris-pcmcia",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(osiris_pcmcia_resource),
	.resource	= osiris_pcmcia_resource,
};

/* Osiris power management device */

#ifdef CONFIG_PM
static unsigned char pm_osiris_ctrl0;

static int osiris_pm_suspend(void)
{
	unsigned int tmp;

	pm_osiris_ctrl0 = __raw_readb(OSIRIS_VA_CTRL0);
	tmp = pm_osiris_ctrl0 & ~OSIRIS_CTRL0_NANDSEL;

	/* ensure correct NAND slot is selected on resume */
	if ((pm_osiris_ctrl0 & OSIRIS_CTRL0_BOOT_INT) == 0)
	        tmp |= 2;

	__raw_writeb(tmp, OSIRIS_VA_CTRL0);

	/* ensure that an nRESET is not generated on resume. */
	gpio_request_one(S3C2410_GPA(21), GPIOF_OUT_INIT_HIGH, NULL);
	gpio_free(S3C2410_GPA(21));

	return 0;
}

static void osiris_pm_resume(void)
{
	if (pm_osiris_ctrl0 & OSIRIS_CTRL0_FIX8)
		__raw_writeb(OSIRIS_CTRL1_FIX8, OSIRIS_VA_CTRL1);

	__raw_writeb(pm_osiris_ctrl0, OSIRIS_VA_CTRL0);

	s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
}

#else
#define osiris_pm_suspend NULL
#define osiris_pm_resume NULL
#endif

static struct syscore_ops osiris_pm_syscore_ops = {
	.suspend	= osiris_pm_suspend,
	.resume		= osiris_pm_resume,
};

/* Link for DVS driver to TPS65011 */

static void osiris_tps_release(struct device *dev)
{
	/* static device, do not need to release anything */
}

static struct platform_device osiris_tps_device = {
	.name	= "osiris-dvs",
	.id	= -1,
	.dev.release = osiris_tps_release,
};

static int osiris_tps_setup(struct i2c_client *client, void *context)
{
	osiris_tps_device.dev.parent = &client->dev;
	return platform_device_register(&osiris_tps_device);
}

static int osiris_tps_remove(struct i2c_client *client, void *context)
{
	platform_device_unregister(&osiris_tps_device);
	return 0;
}

static struct tps65010_board osiris_tps_board = {
	.base		= -1,	/* GPIO can go anywhere at the moment */
	.setup		= osiris_tps_setup,
	.teardown	= osiris_tps_remove,
};

/* I2C devices fitted. */

static struct i2c_board_info osiris_i2c_devs[] __initdata = {
	{
		I2C_BOARD_INFO("tps65011", 0x48),
		.irq	= IRQ_EINT20,
		.platform_data = &osiris_tps_board,
	},
};

/* Standard Osiris devices */

static struct platform_device *osiris_devices[] __initdata = {
	&s3c2410_device_dclk,
	&s3c_device_i2c0,
	&s3c_device_wdt,
	&s3c_device_nand,
	&osiris_pcmcia,
};

static struct s3c_cpufreq_board __initdata osiris_cpufreq = {
	.refresh	= 7800, /* refresh period is 7.8usec */
	.auto_io	= 1,
	.need_io	= 1,
};

static void __init osiris_map_io(void)
{
	unsigned long flags;

	s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc));
	s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);

	/* check for the newer revision boards with large page nand */

	if ((__raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK) >= 4) {
		printk(KERN_INFO "OSIRIS-B detected (revision %d)\n",
		       __raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK);
		osiris_nand_sets[0].partitions = osiris_default_nand_part_large;
		osiris_nand_sets[0].nr_partitions = ARRAY_SIZE(osiris_default_nand_part_large);
	} else {
		/* write-protect line to the NAND */
		gpio_request_one(S3C2410_GPA(0), GPIOF_OUT_INIT_HIGH, NULL);
		gpio_free(S3C2410_GPA(0));
	}

	/* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */

	local_irq_save(flags);
	__raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON);
	local_irq_restore(flags);
}

static void __init osiris_init_time(void)
{
	s3c2440_init_clocks(12000000);
	s3c24xx_timer_init();
}

static void __init osiris_init(void)
{
	register_syscore_ops(&osiris_pm_syscore_ops);

	s3c_i2c0_set_platdata(NULL);
	s3c_nand_set_platdata(&osiris_nand_info);

	s3c_cpufreq_setboard(&osiris_cpufreq);

	i2c_register_board_info(0, osiris_i2c_devs,
				ARRAY_SIZE(osiris_i2c_devs));

	platform_add_devices(osiris_devices, ARRAY_SIZE(osiris_devices));
};

MACHINE_START(OSIRIS, "Simtec-OSIRIS")
	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2440,
	.map_io		= osiris_map_io,
	.init_irq	= s3c2440_init_irq,
	.init_machine	= osiris_init,
	.init_time	= osiris_init_time,
MACHINE_END

repo_name: angery/linux


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2004 Nex Vision
//   Guillaume GOURAT <guillaume.gourat@nexvision.fr>

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/platform_device.h>
#include <linux/io.h>

#include <linux/platform_data/i2c-s3c2410.h>

#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include "gpio-samsung.h"
#include "gpio-cfg.h"

#include "cpu.h"
#include "devs.h"

#include "s3c24xx.h"
#include "otom.h"

static struct map_desc otom11_iodesc[] __initdata = {
  /* Device area */
	{ (u32)OTOM_VA_CS8900A_BASE, OTOM_PA_CS8900A_BASE, SZ_16M, MT_DEVICE },
};

#define UCON S3C2410_UCON_DEFAULT
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE

static struct s3c2410_uartcfg otom11_uartcfgs[] __initdata = {
	[0] = {
		.hwport	     = 0,
		.flags	     = 0,
		.ucon	     = UCON,
		.ulcon	     = ULCON,
		.ufcon	     = UFCON,
	},
	[1] = {
		.hwport	     = 1,
		.flags	     = 0,
		.ucon	     = UCON,
		.ulcon	     = ULCON,
		.ufcon	     = UFCON,
	},
	/* port 2 is not actually used */
	[2] = {
		.hwport	     = 2,
		.flags	     = 0,
		.ucon	     = UCON,
		.ulcon	     = ULCON,
		.ufcon	     = UFCON,
	}
};

/* NOR Flash on NexVision OTOM board */

static struct resource otom_nor_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_CS0, SZ_4M),
};

static struct platform_device otom_device_nor = {
	.name		= "mtd-flash",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(otom_nor_resource),
	.resource	= otom_nor_resource,
};

/* Standard OTOM devices */

static struct platform_device *otom11_devices[] __initdata = {
	&s3c_device_ohci,
	&s3c_device_lcd,
	&s3c_device_wdt,
	&s3c_device_i2c0,
	&s3c_device_iis,
 	&s3c_device_rtc,
	&otom_device_nor,
};

static void __init otom11_map_io(void)
{
	s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc));
	s3c24xx_init_uarts(otom11_uartcfgs, ARRAY_SIZE(otom11_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
}

static void __init otom11_init_time(void)
{
	s3c2410_init_clocks(12000000);
	s3c24xx_timer_init();
}

static void __init otom11_init(void)
{
	s3c_i2c0_set_platdata(NULL);

	/* Configure the I2S pins (GPE0...GPE4) in correct mode */
	s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
			      S3C_GPIO_PULL_NONE);
	platform_add_devices(otom11_devices, ARRAY_SIZE(otom11_devices));
}

MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
	/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2410,
	.map_io		= otom11_map_io,
	.init_machine	= otom11_init,
	.init_irq	= s3c2410_init_irq,
	.init_time	= otom11_init_time,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0+
//
// Copyright (C) 2006 by OpenMoko, Inc.
// Author: Harald Welte <laforge@openmoko.org>
// All rights reserved.

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_gpio.h>
#include <linux/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand-ecc-sw-hamming.h>
#include <linux/mtd/partitions.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include <asm/irq.h>
#include <asm/mach-types.h>

#include <linux/platform_data/leds-s3c24xx.h>
#include <linux/platform_data/fb-s3c2410.h>
#include <linux/platform_data/mtd-nand-s3c2410.h>
#include <linux/platform_data/usb-s3c2410_udc.h>
#include <linux/platform_data/i2c-s3c2410.h>
#include "gpio-samsung.h"

#include "gpio-cfg.h"
#include "devs.h"
#include "cpu.h"
#include "pm.h"

#include "s3c24xx.h"
#include "common-smdk-s3c24xx.h"

static struct map_desc qt2410_iodesc[] __initdata = {
	{ 0xe0000000, __phys_to_pfn(S3C2410_CS3+0x01000000), SZ_1M, MT_DEVICE }
};

#define UCON S3C2410_UCON_DEFAULT
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE

static struct s3c2410_uartcfg smdk2410_uartcfgs[] = {
	[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,
	}
};

/* LCD driver info */

static struct s3c2410fb_display qt2410_lcd_cfg[] __initdata = {
	{
		/* Configuration for 640x480 SHARP LQ080V3DG01 */
		.lcdcon5 = S3C2410_LCDCON5_FRM565 |
			   S3C2410_LCDCON5_INVVLINE |
			   S3C2410_LCDCON5_INVVFRAME |
			   S3C2410_LCDCON5_PWREN |
			   S3C2410_LCDCON5_HWSWP,

		.type		= S3C2410_LCDCON1_TFT,
		.width		= 640,
		.height		= 480,

		.pixclock	= 40000, /* HCLK/4 */
		.xres		= 640,
		.yres		= 480,
		.bpp		= 16,
		.left_margin	= 44,
		.right_margin	= 116,
		.hsync_len	= 96,
		.upper_margin	= 19,
		.lower_margin	= 11,
		.vsync_len	= 15,
	},
	{
		/* Configuration for 480x640 toppoly TD028TTEC1 */
		.lcdcon5 = S3C2410_LCDCON5_FRM565 |
			   S3C2410_LCDCON5_INVVLINE |
			   S3C2410_LCDCON5_INVVFRAME |
			   S3C2410_LCDCON5_PWREN |
			   S3C2410_LCDCON5_HWSWP,

		.type		= S3C2410_LCDCON1_TFT,
		.width		= 480,
		.height		= 640,
		.pixclock	= 40000, /* HCLK/4 */
		.xres		= 480,
		.yres		= 640,
		.bpp		= 16,
		.left_margin	= 8,
		.right_margin	= 24,
		.hsync_len	= 8,
		.upper_margin	= 2,
		.lower_margin	= 4,
		.vsync_len	= 2,
	},
	{
		/* Config for 240x320 LCD */
		.lcdcon5 = S3C2410_LCDCON5_FRM565 |
			   S3C2410_LCDCON5_INVVLINE |
			   S3C2410_LCDCON5_INVVFRAME |
			   S3C2410_LCDCON5_PWREN |
			   S3C2410_LCDCON5_HWSWP,

		.type		= S3C2410_LCDCON1_TFT,
		.width		= 240,
		.height		= 320,
		.pixclock	= 100000, /* HCLK/10 */
		.xres		= 240,
		.yres		= 320,
		.bpp		= 16,
		.left_margin	= 13,
		.right_margin	= 8,
		.hsync_len	= 4,
		.upper_margin	= 2,
		.lower_margin	= 7,
		.vsync_len	= 4,
	},
};

static struct s3c2410fb_mach_info qt2410_fb_info __initdata = {
	.displays 	= qt2410_lcd_cfg,
	.num_displays 	= ARRAY_SIZE(qt2410_lcd_cfg),
	.default_display = 0,

	.lpcsel		= ((0xCE6) & ~7) | 1<<4,
};

/* CS8900 */

static struct resource qt2410_cs89x0_resources[] = {
	[0] = DEFINE_RES_MEM(0x19000000, 17),
	[1] = DEFINE_RES_IRQ(IRQ_EINT9),
};

static struct platform_device qt2410_cs89x0 = {
	.name		= "cirrus-cs89x0",
	.num_resources	= ARRAY_SIZE(qt2410_cs89x0_resources),
	.resource	= qt2410_cs89x0_resources,
};

/* LED */

static struct gpiod_lookup_table qt2410_led_gpio_table = {
	.dev_id = "s3c24xx_led.0",
	.table = {
		GPIO_LOOKUP("GPB", 0, NULL, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN),
		{ },
	},
};

static struct s3c24xx_led_platdata qt2410_pdata_led = {
	.name		= "led",
	.def_trigger	= "timer",
};

static struct platform_device qt2410_led = {
	.name		= "s3c24xx_led",
	.id		= 0,
	.dev		= {
		.platform_data = &qt2410_pdata_led,
	},
};

/* SPI */

static struct spi_gpio_platform_data spi_gpio_cfg = {
	.num_chipselect	= 1,
};

static struct platform_device qt2410_spi = {
	.name		= "spi_gpio",
	.id		= 1,
	.dev.platform_data = &spi_gpio_cfg,
};

static struct gpiod_lookup_table qt2410_spi_gpiod_table = {
	.dev_id         = "spi_gpio",
	.table          = {
		GPIO_LOOKUP("GPIOG", 7,
			    "sck", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("GPIOG", 6,
			    "mosi", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("GPIOG", 5,
			    "miso", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("GPIOB", 5,
			    "cs", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct gpiod_lookup_table qt2410_mmc_gpiod_table = {
	.dev_id = "s3c2410-sdi",
	.table = {
		/* bus pins */
		GPIO_LOOKUP_IDX("GPIOE",  5, "bus", 0, GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP_IDX("GPIOE",  6, "bus", 1, GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP_IDX("GPIOE",  7, "bus", 2, GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP_IDX("GPIOE",  8, "bus", 3, GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP_IDX("GPIOE",  9, "bus", 4, GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP_IDX("GPIOE", 10, "bus", 5, GPIO_ACTIVE_HIGH),
		{ },
	},
};

/* Board devices */

static struct platform_device *qt2410_devices[] __initdata = {
	&s3c_device_ohci,
	&s3c_device_lcd,
	&s3c_device_wdt,
	&s3c_device_i2c0,
	&s3c_device_iis,
	&s3c_device_sdi,
	&s3c_device_usbgadget,
	&qt2410_spi,
	&qt2410_cs89x0,
	&qt2410_led,
};

static struct mtd_partition __initdata qt2410_nand_part[] = {
	[0] = {
		.name	= "U-Boot",
		.size	= 0x30000,
		.offset	= 0,
	},
	[1] = {
		.name	= "U-Boot environment",
		.offset = 0x30000,
		.size	= 0x4000,
	},
	[2] = {
		.name	= "kernel",
		.offset = 0x34000,
		.size	= SZ_2M,
	},
	[3] = {
		.name	= "initrd",
		.offset	= 0x234000,
		.size	= SZ_4M,
	},
	[4] = {
		.name	= "jffs2",
		.offset = 0x634000,
		.size	= 0x39cc000,
	},
};

static struct s3c2410_nand_set __initdata qt2410_nand_sets[] = {
	[0] = {
		.name		= "NAND",
		.nr_chips	= 1,
		.nr_partitions	= ARRAY_SIZE(qt2410_nand_part),
		.partitions	= qt2410_nand_part,
	},
};

/* choose a set of timings which should suit most 512Mbit
 * chips and beyond.
 */

static struct s3c2410_platform_nand __initdata qt2410_nand_info = {
	.tacls		= 20,
	.twrph0		= 60,
	.twrph1		= 20,
	.nr_sets	= ARRAY_SIZE(qt2410_nand_sets),
	.sets		= qt2410_nand_sets,
	.engine_type	= NAND_ECC_ENGINE_TYPE_SOFT,
};

/* UDC */

static struct s3c2410_udc_mach_info qt2410_udc_cfg = {
};

static char tft_type = 's';

static int __init qt2410_tft_setup(char *str)
{
	tft_type = str[0];
	return 1;
}

__setup("tft=", qt2410_tft_setup);

static void __init qt2410_map_io(void)
{
	s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
	s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
}

static void __init qt2410_init_time(void)
{
	s3c2410_init_clocks(12000000);
	s3c24xx_timer_init();
}

static void __init qt2410_machine_init(void)
{
	s3c_nand_set_platdata(&qt2410_nand_info);

	switch (tft_type) {
	case 'p': /* production */
		qt2410_fb_info.default_display = 1;
		break;
	case 'b': /* big */
		qt2410_fb_info.default_display = 0;
		break;
	case 's': /* small */
	default:
		qt2410_fb_info.default_display = 2;
		break;
	}
	s3c24xx_fb_set_platdata(&qt2410_fb_info);

	/* set initial state of the LED GPIO */
	WARN_ON(gpio_request_one(S3C2410_GPB(0), GPIOF_OUT_INIT_HIGH, NULL));
	gpio_free(S3C2410_GPB(0));

	s3c24xx_udc_set_platdata(&qt2410_udc_cfg);
	s3c_i2c0_set_platdata(NULL);

	/* Configure the I2S pins (GPE0...GPE4) in correct mode */
	s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
			      S3C_GPIO_PULL_NONE);
	gpiod_add_lookup_table(&qt2410_spi_gpiod_table);
	s3c_gpio_setpull(S3C2410_GPB(0), S3C_GPIO_PULL_NONE);
	gpiod_add_lookup_table(&qt2410_led_gpio_table);
	gpiod_add_lookup_table(&qt2410_mmc_gpiod_table);
	platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices));
	s3c_pm_init();
}

MACHINE_START(QT2410, "QT2410")
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2410,
	.map_io		= qt2410_map_io,
	.init_irq	= s3c2410_init_irq,
	.init_machine	= qt2410_machine_init,
	.init_time	= qt2410_init_time,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2010 Darius Augulis <augulis.darius@gmail.com>
// Copyright 2008 Openmoko, Inc.
// Copyright 2008 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//	http://armlinux.simtec.co.uk/

#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/dm9000.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/types.h>

#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>

#include "map.h"
#include "regs-gpio.h"
#include "gpio-samsung.h"
#include "irqs.h"

#include <linux/soc/samsung/s3c-adc.h>
#include "cpu.h"
#include "devs.h"
#include "fb.h"
#include <linux/platform_data/mtd-nand-s3c2410.h>
#include <linux/platform_data/touchscreen-s3c2410.h>

#include <video/platform_lcd.h>
#include <video/samsung_fimd.h>

#include "s3c64xx.h"
#include "regs-modem-s3c64xx.h"
#include "regs-srom-s3c64xx.h"

#define UCON S3C2410_UCON_DEFAULT
#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)

static struct s3c2410_uartcfg real6410_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,
	},
	[3] = {
		.hwport	= 3,
		.flags	= 0,
		.ucon	= UCON,
		.ulcon	= ULCON,
		.ufcon	= UFCON,
	},
};

/* DM9000AEP 10/100 ethernet controller */

static struct resource real6410_dm9k_resource[] = {
	[0] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN1, 2),
	[1] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN1 + 4, 2),
	[2] = DEFINE_RES_NAMED(S3C_EINT(7), 1, NULL, IORESOURCE_IRQ \
					| IORESOURCE_IRQ_HIGHLEVEL),
};

static struct dm9000_plat_data real6410_dm9k_pdata = {
	.flags		= (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
};

static struct platform_device real6410_device_eth = {
	.name		= "dm9000",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(real6410_dm9k_resource),
	.resource	= real6410_dm9k_resource,
	.dev		= {
		.platform_data	= &real6410_dm9k_pdata,
	},
};

static struct s3c_fb_pd_win real6410_lcd_type0_fb_win = {
	.max_bpp	= 32,
	.default_bpp	= 16,
	.xres		= 480,
	.yres		= 272,
};

static struct fb_videomode real6410_lcd_type0_timing = {
	/* 4.3" 480x272 */
	.left_margin	= 3,
	.right_margin	= 2,
	.upper_margin	= 1,
	.lower_margin	= 1,
	.hsync_len	= 40,
	.vsync_len	= 1,
};

static struct s3c_fb_pd_win real6410_lcd_type1_fb_win = {
	.max_bpp	= 32,
	.default_bpp	= 16,
	.xres		= 800,
	.yres		= 480,
};

static struct fb_videomode real6410_lcd_type1_timing = {
	/* 7.0" 800x480 */
	.left_margin	= 8,
	.right_margin	= 13,
	.upper_margin	= 7,
	.lower_margin	= 5,
	.hsync_len	= 3,
	.vsync_len	= 1,
	.xres		= 800,
	.yres		= 480,
};

static struct s3c_fb_platdata real6410_lcd_pdata[] __initdata = {
	{
		.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
		.vtiming	= &real6410_lcd_type0_timing,
		.win[0]		= &real6410_lcd_type0_fb_win,
		.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
		.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
	}, {
		.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
		.vtiming	= &real6410_lcd_type1_timing,
		.win[0]		= &real6410_lcd_type1_fb_win,
		.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
		.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
	},
	{ },
};

static struct mtd_partition real6410_nand_part[] = {
	[0] = {
		.name	= "uboot",
		.size	= SZ_1M,
		.offset	= 0,
	},
	[1] = {
		.name	= "kernel",
		.size	= SZ_2M,
		.offset	= SZ_1M,
	},
	[2] = {
		.name	= "rootfs",
		.size	= MTDPART_SIZ_FULL,
		.offset	= SZ_1M + SZ_2M,
	},
};

static struct s3c2410_nand_set real6410_nand_sets[] = {
	[0] = {
		.name		= "nand",
		.nr_chips	= 1,
		.nr_partitions	= ARRAY_SIZE(real6410_nand_part),
		.partitions	= real6410_nand_part,
	},
};

static struct s3c2410_platform_nand real6410_nand_info = {
	.tacls		= 25,
	.twrph0		= 55,
	.twrph1		= 40,
	.nr_sets	= ARRAY_SIZE(real6410_nand_sets),
	.sets		= real6410_nand_sets,
	.engine_type	= NAND_ECC_ENGINE_TYPE_SOFT,
};

static struct platform_device *real6410_devices[] __initdata = {
	&real6410_device_eth,
	&s3c_device_hsmmc0,
	&s3c_device_hsmmc1,
	&s3c_device_fb,
	&s3c_device_nand,
	&s3c_device_adc,
	&s3c_device_ohci,
};

static void __init real6410_map_io(void)
{
	u32 tmp;

	s3c64xx_init_io(NULL, 0);
	s3c24xx_init_clocks(12000000);
	s3c24xx_init_uarts(real6410_uartcfgs, ARRAY_SIZE(real6410_uartcfgs));
	s3c64xx_set_timer_source(S3C64XX_PWM3, S3C64XX_PWM4);

	/* 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);
}

/*
 * real6410_features string
 *
 * 0-9 LCD configuration
 *
 */
static char real6410_features_str[12] __initdata = "0";

static int __init real6410_features_setup(char *str)
{
	if (str)
		strlcpy(real6410_features_str, str,
			sizeof(real6410_features_str));
	return 1;
}

__setup("real6410=", real6410_features_setup);

#define FEATURE_SCREEN (1 << 0)

struct real6410_features_t {
	int done;
	int lcd_index;
};

static void real6410_parse_features(
		struct real6410_features_t *features,
		const char *features_str)
{
	const char *fp = features_str;

	features->done = 0;
	features->lcd_index = 0;

	while (*fp) {
		char f = *fp++;

		switch (f) {
		case '0'...'9':	/* tft screen */
			if (features->done & FEATURE_SCREEN) {
				printk(KERN_INFO "REAL6410: '%c' ignored, "
					"screen type already set\n", f);
			} else {
				int li = f - '0';
				if (li >= ARRAY_SIZE(real6410_lcd_pdata))
					printk(KERN_INFO "REAL6410: '%c' out "
						"of range LCD mode\n", f);
				else {
					features->lcd_index = li;
				}
			}
			features->done |= FEATURE_SCREEN;
			break;
		}
	}
}

static void __init real6410_machine_init(void)
{
	u32 cs1;
	struct real6410_features_t features = { 0 };

	printk(KERN_INFO "REAL6410: Option string real6410=%s\n",
			real6410_features_str);

	/* Parse the feature string */
	real6410_parse_features(&features, real6410_features_str);

	printk(KERN_INFO "REAL6410: selected LCD display is %dx%d\n",
		real6410_lcd_pdata[features.lcd_index].win[0]->xres,
		real6410_lcd_pdata[features.lcd_index].win[0]->yres);

	s3c_fb_set_platdata(&real6410_lcd_pdata[features.lcd_index]);
	s3c_nand_set_platdata(&real6410_nand_info);
	s3c64xx_ts_set_platdata(NULL);

	/* configure nCS1 width to 16 bits */

	cs1 = __raw_readl(S3C64XX_SROM_BW) &
		~(S3C64XX_SROM_BW__CS_MASK << S3C64XX_SROM_BW__NCS1__SHIFT);
	cs1 |= ((1 << S3C64XX_SROM_BW__DATAWIDTH__SHIFT) |
		(1 << S3C64XX_SROM_BW__WAITENABLE__SHIFT) |
		(1 << S3C64XX_SROM_BW__BYTEENABLE__SHIFT)) <<
			S3C64XX_SROM_BW__NCS1__SHIFT;
	__raw_writel(cs1, S3C64XX_SROM_BW);

	/* set timing for nCS1 suitable for ethernet chip */

	__raw_writel((0 << S3C64XX_SROM_BCX__PMC__SHIFT) |
		(6 << S3C64XX_SROM_BCX__TACP__SHIFT) |
		(4 << S3C64XX_SROM_BCX__TCAH__SHIFT) |
		(1 << S3C64XX_SROM_BCX__TCOH__SHIFT) |
		(13 << S3C64XX_SROM_BCX__TACC__SHIFT) |
		(4 << S3C64XX_SROM_BCX__TCOS__SHIFT) |
		(0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1);

	gpio_request(S3C64XX_GPF(15), "LCD power");

	platform_add_devices(real6410_devices, ARRAY_SIZE(real6410_devices));
}

MACHINE_START(REAL6410, "REAL6410")
	/* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
	.atag_offset	= 0x100,
	.nr_irqs	= S3C64XX_NR_IRQS,
	.init_irq	= s3c6410_init_irq,
	.map_io		= real6410_map_io,
	.init_machine	= real6410_machine_init,
	.init_time	= s3c64xx_timer_init,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2006-2009 Victor Chukhantsev, Denis Grigoriev,
// Copyright (c) 2007-2010 Vasily Khoruzhick
//
// based on smdk2440 written by Ben Dooks

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/memblock.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/device.h>
#include <linux/pda_power.h>
#include <linux/pwm_backlight.h>
#include <linux/pwm.h>
#include <linux/s3c_adc_battery.h>
#include <linux/leds.h>
#include <linux/i2c.h>

#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>

#include <linux/mmc/host.h>

#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>

#include <linux/platform_data/i2c-s3c2410.h>
#include <linux/platform_data/mmc-s3cmci.h>
#include <linux/platform_data/mtd-nand-s3c2410.h>
#include <linux/platform_data/touchscreen-s3c2410.h>
#include <linux/platform_data/usb-s3c2410_udc.h>
#include <linux/platform_data/fb-s3c2410.h>

#include <sound/uda1380.h>

#include "hardware-s3c24xx.h"
#include "regs-gpio.h"
#include "gpio-samsung.h"

#include "cpu.h"
#include "devs.h"
#include "pm.h"
#include "gpio-cfg.h"

#include "s3c24xx.h"
#include "h1940.h"

#define LCD_PWM_PERIOD 192960
#define LCD_PWM_DUTY 127353

static struct map_desc rx1950_iodesc[] __initdata = {
};

static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = {
	[0] = {
	       .hwport = 0,
	       .flags = 0,
	       .ucon = 0x3c5,
	       .ulcon = 0x03,
	       .ufcon = 0x51,
		.clk_sel = S3C2410_UCON_CLKSEL3,
	},
	[1] = {
	       .hwport = 1,
	       .flags = 0,
	       .ucon = 0x3c5,
	       .ulcon = 0x03,
	       .ufcon = 0x51,
		.clk_sel = S3C2410_UCON_CLKSEL3,
	},
	/* IR port */
	[2] = {
	       .hwport = 2,
	       .flags = 0,
	       .ucon = 0x3c5,
	       .ulcon = 0x43,
	       .ufcon = 0xf1,
		.clk_sel = S3C2410_UCON_CLKSEL3,
	},
};

static struct s3c2410fb_display rx1950_display = {
	.type = S3C2410_LCDCON1_TFT,
	.width = 240,
	.height = 320,
	.xres = 240,
	.yres = 320,
	.bpp = 16,

	.pixclock = 260000,
	.left_margin = 10,
	.right_margin = 20,
	.hsync_len = 10,
	.upper_margin = 2,
	.lower_margin = 2,
	.vsync_len = 2,

	.lcdcon5 = S3C2410_LCDCON5_FRM565 |
			   S3C2410_LCDCON5_INVVCLK |
			   S3C2410_LCDCON5_INVVLINE |
			   S3C2410_LCDCON5_INVVFRAME |
			   S3C2410_LCDCON5_HWSWP |
			   (0x02 << 13) |
			   (0x02 << 15),

};

static int power_supply_init(struct device *dev)
{
	return gpio_request(S3C2410_GPF(2), "cable plugged");
}

static int rx1950_is_ac_online(void)
{
	return !gpio_get_value(S3C2410_GPF(2));
}

static void power_supply_exit(struct device *dev)
{
	gpio_free(S3C2410_GPF(2));
}

static char *rx1950_supplicants[] = {
	"main-battery"
};

static struct pda_power_pdata power_supply_info = {
	.init			= power_supply_init,
	.is_ac_online		= rx1950_is_ac_online,
	.exit			= power_supply_exit,
	.supplied_to		= rx1950_supplicants,
	.num_supplicants	= ARRAY_SIZE(rx1950_supplicants),
};

static struct resource power_supply_resources[] = {
	[0] = DEFINE_RES_NAMED(IRQ_EINT2, 1, "ac", IORESOURCE_IRQ \
			| IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE),
};

static struct platform_device power_supply = {
	.name			= "pda-power",
	.id			= -1,
	.dev			= {
					.platform_data =
						&power_supply_info,
	},
	.resource		= power_supply_resources,
	.num_resources		= ARRAY_SIZE(power_supply_resources),
};

static const struct s3c_adc_bat_thresh bat_lut_noac[] = {
	{ .volt = 4100, .cur = 156, .level = 100},
	{ .volt = 4050, .cur = 156, .level = 95},
	{ .volt = 4025, .cur = 141, .level = 90},
	{ .volt = 3995, .cur = 144, .level = 85},
	{ .volt = 3957, .cur = 162, .level = 80},
	{ .volt = 3931, .cur = 147, .level = 75},
	{ .volt = 3902, .cur = 147, .level = 70},
	{ .volt = 3863, .cur = 153, .level = 65},
	{ .volt = 3838, .cur = 150, .level = 60},
	{ .volt = 3800, .cur = 153, .level = 55},
	{ .volt = 3765, .cur = 153, .level = 50},
	{ .volt = 3748, .cur = 172, .level = 45},
	{ .volt = 3740, .cur = 153, .level = 40},
	{ .volt = 3714, .cur = 175, .level = 35},
	{ .volt = 3710, .cur = 156, .level = 30},
	{ .volt = 3963, .cur = 156, .level = 25},
	{ .volt = 3672, .cur = 178, .level = 20},
	{ .volt = 3651, .cur = 178, .level = 15},
	{ .volt = 3629, .cur = 178, .level = 10},
	{ .volt = 3612, .cur = 162, .level = 5},
	{ .volt = 3605, .cur = 162, .level = 0},
};

static const struct s3c_adc_bat_thresh bat_lut_acin[] = {
	{ .volt = 4200, .cur = 0, .level = 100},
	{ .volt = 4190, .cur = 0, .level = 99},
	{ .volt = 4178, .cur = 0, .level = 95},
	{ .volt = 4110, .cur = 0, .level = 70},
	{ .volt = 4076, .cur = 0, .level = 65},
	{ .volt = 4046, .cur = 0, .level = 60},
	{ .volt = 4021, .cur = 0, .level = 55},
	{ .volt = 3999, .cur = 0, .level = 50},
	{ .volt = 3982, .cur = 0, .level = 45},
	{ .volt = 3965, .cur = 0, .level = 40},
	{ .volt = 3957, .cur = 0, .level = 35},
	{ .volt = 3948, .cur = 0, .level = 30},
	{ .volt = 3936, .cur = 0, .level = 25},
	{ .volt = 3927, .cur = 0, .level = 20},
	{ .volt = 3906, .cur = 0, .level = 15},
	{ .volt = 3880, .cur = 0, .level = 10},
	{ .volt = 3829, .cur = 0, .level = 5},
	{ .volt = 3820, .cur = 0, .level = 0},
};

static struct gpiod_lookup_table rx1950_bat_gpio_table = {
	.dev_id = "s3c-adc-battery",
	.table = {
		/* Charge status S3C2410_GPF(3) */
		GPIO_LOOKUP("GPIOF", 3, "charge-status", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static int rx1950_bat_init(void)
{
	int ret;

	ret = gpio_request(S3C2410_GPJ(2), "rx1950-charger-enable-1");
	if (ret)
		goto err_gpio1;
	ret = gpio_request(S3C2410_GPJ(3), "rx1950-charger-enable-2");
	if (ret)
		goto err_gpio2;

	return 0;

err_gpio2:
	gpio_free(S3C2410_GPJ(2));
err_gpio1:
	return ret;
}

static void rx1950_bat_exit(void)
{
	gpio_free(S3C2410_GPJ(2));
	gpio_free(S3C2410_GPJ(3));
}

static void rx1950_enable_charger(void)
{
	gpio_direction_output(S3C2410_GPJ(2), 1);
	gpio_direction_output(S3C2410_GPJ(3), 1);
}

static void rx1950_disable_charger(void)
{
	gpio_direction_output(S3C2410_GPJ(2), 0);
	gpio_direction_output(S3C2410_GPJ(3), 0);
}

static DEFINE_SPINLOCK(rx1950_blink_spin);

static int rx1950_led_blink_set(struct gpio_desc *desc, int state,
	unsigned long *delay_on, unsigned long *delay_off)
{
	int gpio = desc_to_gpio(desc);
	int blink_gpio, check_gpio;

	switch (gpio) {
	case S3C2410_GPA(6):
		blink_gpio = S3C2410_GPA(4);
		check_gpio = S3C2410_GPA(3);
		break;
	case S3C2410_GPA(7):
		blink_gpio = S3C2410_GPA(3);
		check_gpio = S3C2410_GPA(4);
		break;
	default:
		return -EINVAL;
	}

	if (delay_on && delay_off && !*delay_on && !*delay_off)
		*delay_on = *delay_off = 500;

	spin_lock(&rx1950_blink_spin);

	switch (state) {
	case GPIO_LED_NO_BLINK_LOW:
	case GPIO_LED_NO_BLINK_HIGH:
		if (!gpio_get_value(check_gpio))
			gpio_set_value(S3C2410_GPJ(6), 0);
		gpio_set_value(blink_gpio, 0);
		gpio_set_value(gpio, state);
		break;
	case GPIO_LED_BLINK:
		gpio_set_value(gpio, 0);
		gpio_set_value(S3C2410_GPJ(6), 1);
		gpio_set_value(blink_gpio, 1);
		break;
	}

	spin_unlock(&rx1950_blink_spin);

	return 0;
}

static struct gpio_led rx1950_leds_desc[] = {
	{
		.name			= "Green",
		.default_trigger	= "main-battery-full",
		.gpio			= S3C2410_GPA(6),
		.retain_state_suspended	= 1,
	},
	{
		.name			= "Red",
		.default_trigger
			= "main-battery-charging-blink-full-solid",
		.gpio			= S3C2410_GPA(7),
		.retain_state_suspended	= 1,
	},
	{
		.name			= "Blue",
		.default_trigger	= "rx1950-acx-mem",
		.gpio			= S3C2410_GPA(11),
		.retain_state_suspended	= 1,
	},
};

static struct gpio_led_platform_data rx1950_leds_pdata = {
	.num_leds	= ARRAY_SIZE(rx1950_leds_desc),
	.leds		= rx1950_leds_desc,
	.gpio_blink_set	= rx1950_led_blink_set,
};

static struct platform_device rx1950_leds = {
	.name	= "leds-gpio",
	.id		= -1,
	.dev	= {
				.platform_data = &rx1950_leds_pdata,
	},
};

static struct s3c_adc_bat_pdata rx1950_bat_cfg = {
	.init = rx1950_bat_init,
	.exit = rx1950_bat_exit,
	.enable_charger = rx1950_enable_charger,
	.disable_charger = rx1950_disable_charger,
	.lut_noac = bat_lut_noac,
	.lut_noac_cnt = ARRAY_SIZE(bat_lut_noac),
	.lut_acin = bat_lut_acin,
	.lut_acin_cnt = ARRAY_SIZE(bat_lut_acin),
	.volt_channel = 0,
	.current_channel = 1,
	.volt_mult = 4235,
	.current_mult = 2900,
	.internal_impedance = 200,
};

static struct platform_device rx1950_battery = {
	.name             = "s3c-adc-battery",
	.id               = -1,
	.dev = {
		.parent = &s3c_device_adc.dev,
		.platform_data = &rx1950_bat_cfg,
	},
};

static struct s3c2410fb_mach_info rx1950_lcd_cfg = {
	.displays = &rx1950_display,
	.num_displays = 1,
	.default_display = 0,

	.lpcsel = 0x02,
	.gpccon = 0xaa9556a9,
	.gpccon_mask = 0xffc003fc,
	.gpccon_reg = S3C2410_GPCCON,
	.gpcup = 0x0000ffff,
	.gpcup_mask = 0xffffffff,
	.gpcup_reg = S3C2410_GPCUP,

	.gpdcon = 0xaa90aaa1,
	.gpdcon_mask = 0xffc0fff0,
	.gpdcon_reg = S3C2410_GPDCON,
	.gpdup = 0x0000fcfd,
	.gpdup_mask = 0xffffffff,
	.gpdup_reg = S3C2410_GPDUP,
};

static struct pwm_lookup rx1950_pwm_lookup[] = {
	PWM_LOOKUP("samsung-pwm", 0, "pwm-backlight.0", NULL, 48000,
		   PWM_POLARITY_NORMAL),
	PWM_LOOKUP("samsung-pwm", 1, "pwm-backlight.0", "RX1950 LCD", LCD_PWM_PERIOD,
		   PWM_POLARITY_NORMAL),
};

static struct pwm_device *lcd_pwm;
static struct pwm_state lcd_pwm_state;

static void rx1950_lcd_power(int enable)
{
	int i;
	static int enabled;
	if (enabled == enable)
		return;
	if (!enable) {

		/* GPC11-GPC15->OUTPUT */
		for (i = 11; i < 16; i++)
			gpio_direction_output(S3C2410_GPC(i), 1);

		/* Wait a bit here... */
		mdelay(100);

		/* GPD2-GPD7->OUTPUT */
		/* GPD11-GPD15->OUTPUT */
		/* GPD2-GPD7->1, GPD11-GPD15->1 */
		for (i = 2; i < 8; i++)
			gpio_direction_output(S3C2410_GPD(i), 1);
		for (i = 11; i < 16; i++)
			gpio_direction_output(S3C2410_GPD(i), 1);

		/* Wait a bit here...*/
		mdelay(100);

		/* GPB0->OUTPUT, GPB0->0 */
		gpio_direction_output(S3C2410_GPB(0), 0);

		/* GPC1-GPC4->OUTPUT, GPC1-4->0 */
		for (i = 1; i < 5; i++)
			gpio_direction_output(S3C2410_GPC(i), 0);

		/* GPC15-GPC11->0 */
		for (i = 11; i < 16; i++)
			gpio_direction_output(S3C2410_GPC(i), 0);

		/* GPD15-GPD11->0, GPD2->GPD7->0 */
		for (i = 11; i < 16; i++)
			gpio_direction_output(S3C2410_GPD(i), 0);

		for (i = 2; i < 8; i++)
			gpio_direction_output(S3C2410_GPD(i), 0);

		/* GPC6->0, GPC7->0, GPC5->0 */
		gpio_direction_output(S3C2410_GPC(6), 0);
		gpio_direction_output(S3C2410_GPC(7), 0);
		gpio_direction_output(S3C2410_GPC(5), 0);

		/* GPB1->OUTPUT, GPB1->0 */
		gpio_direction_output(S3C2410_GPB(1), 0);

		lcd_pwm_state.enabled = false;
		pwm_apply_state(lcd_pwm, &lcd_pwm_state);

		/* GPC0->0, GPC10->0 */
		gpio_direction_output(S3C2410_GPC(0), 0);
		gpio_direction_output(S3C2410_GPC(10), 0);
	} else {
		lcd_pwm_state.enabled = true;
		pwm_apply_state(lcd_pwm, &lcd_pwm_state);

		gpio_direction_output(S3C2410_GPC(0), 1);
		gpio_direction_output(S3C2410_GPC(5), 1);

		s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPB1_TOUT1);
		gpio_direction_output(S3C2410_GPC(7), 1);

		for (i = 1; i < 5; i++)
			s3c_gpio_cfgpin(S3C2410_GPC(i), S3C_GPIO_SFN(2));

		for (i = 11; i < 16; i++)
			s3c_gpio_cfgpin(S3C2410_GPC(i), S3C_GPIO_SFN(2));

		for (i = 2; i < 8; i++)
			s3c_gpio_cfgpin(S3C2410_GPD(i), S3C_GPIO_SFN(2));

		for (i = 11; i < 16; i++)
			s3c_gpio_cfgpin(S3C2410_GPD(i), S3C_GPIO_SFN(2));

		gpio_direction_output(S3C2410_GPC(10), 1);
		gpio_direction_output(S3C2410_GPC(6), 1);
	}
	enabled = enable;
}

static void rx1950_bl_power(int enable)
{
	static int enabled;
	if (enabled == enable)
		return;
	if (!enable) {
			gpio_direction_output(S3C2410_GPB(0), 0);
	} else {
			/* LED driver need a "push" to power on */
			gpio_direction_output(S3C2410_GPB(0), 1);
			/* Warm up backlight for one period of PWM.
			 * Without this trick its almost impossible to
			 * enable backlight with low brightness value
			 */
			ndelay(48000);
			s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);
	}
	enabled = enable;
}

static int rx1950_backlight_init(struct device *dev)
{
	WARN_ON(gpio_request(S3C2410_GPB(0), "Backlight"));
	lcd_pwm = pwm_get(dev, "RX1950 LCD");
	if (IS_ERR(lcd_pwm)) {
		dev_err(dev, "Unable to request PWM for LCD power!\n");
		return PTR_ERR(lcd_pwm);
	}

	/*
	 * Call pwm_init_state to initialize .polarity and .period. The other
	 * values are fixed in this driver.
	 */
	pwm_init_state(lcd_pwm, &lcd_pwm_state);

	lcd_pwm_state.duty_cycle = LCD_PWM_DUTY;

	rx1950_lcd_power(1);
	rx1950_bl_power(1);

	return 0;
}

static void rx1950_backlight_exit(struct device *dev)
{
	rx1950_bl_power(0);
	rx1950_lcd_power(0);

	pwm_put(lcd_pwm);
	gpio_free(S3C2410_GPB(0));
}

static int rx1950_backlight_notify(struct device *dev, int brightness)
{
	if (!brightness) {
		rx1950_bl_power(0);
		rx1950_lcd_power(0);
	} else {
		rx1950_lcd_power(1);
		rx1950_bl_power(1);
	}
	return brightness;
}

static struct platform_pwm_backlight_data rx1950_backlight_data = {
	.max_brightness = 24,
	.dft_brightness = 4,
	.init = rx1950_backlight_init,
	.notify = rx1950_backlight_notify,
	.exit = rx1950_backlight_exit,
};

static struct platform_device rx1950_backlight = {
	.name = "pwm-backlight",
	.dev = {
		.parent = &samsung_device_pwm.dev,
		.platform_data = &rx1950_backlight_data,
	},
};

static void rx1950_set_mmc_power(unsigned char power_mode, unsigned short vdd)
{
	s3c24xx_mci_def_set_power(power_mode, vdd);

	switch (power_mode) {
	case MMC_POWER_OFF:
		gpio_direction_output(S3C2410_GPJ(1), 0);
		break;
	case MMC_POWER_UP:
	case MMC_POWER_ON:
		gpio_direction_output(S3C2410_GPJ(1), 1);
		break;
	default:
		break;
	}
}

static struct s3c24xx_mci_pdata rx1950_mmc_cfg __initdata = {
	.set_power = rx1950_set_mmc_power,
	.ocr_avail = MMC_VDD_32_33,
};

static struct gpiod_lookup_table rx1950_mmc_gpio_table = {
	.dev_id = "s3c2410-sdi",
	.table = {
		/* Card detect S3C2410_GPF(5) */
		GPIO_LOOKUP("GPIOF", 5, "cd", GPIO_ACTIVE_LOW),
		/* Write protect S3C2410_GPH(8) */
		GPIO_LOOKUP("GPIOH", 8, "wp", GPIO_ACTIVE_LOW),
		/* bus pins */
		GPIO_LOOKUP_IDX("GPIOE",  5, "bus", 0, GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP_IDX("GPIOE",  6, "bus", 1, GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP_IDX("GPIOE",  7, "bus", 2, GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP_IDX("GPIOE",  8, "bus", 3, GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP_IDX("GPIOE",  9, "bus", 4, GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP_IDX("GPIOE", 10, "bus", 5, GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct mtd_partition rx1950_nand_part[] = {
	[0] = {
			.name = "Boot0",
			.offset = 0,
			.size = 0x4000,
			.mask_flags = MTD_WRITEABLE,
	},
	[1] = {
			.name = "Boot1",
			.offset = MTDPART_OFS_APPEND,
			.size = 0x40000,
			.mask_flags = MTD_WRITEABLE,
	},
	[2] = {
			.name = "Kernel",
			.offset = MTDPART_OFS_APPEND,
			.size = 0x300000,
			.mask_flags = 0,
	},
	[3] = {
			.name = "Filesystem",
			.offset = MTDPART_OFS_APPEND,
			.size = MTDPART_SIZ_FULL,
			.mask_flags = 0,
	},
};

static struct s3c2410_nand_set rx1950_nand_sets[] = {
	[0] = {
			.name = "Internal",
			.nr_chips = 1,
			.nr_partitions = ARRAY_SIZE(rx1950_nand_part),
			.partitions = rx1950_nand_part,
	},
};

static struct s3c2410_platform_nand rx1950_nand_info = {
	.tacls = 25,
	.twrph0 = 50,
	.twrph1 = 15,
	.nr_sets = ARRAY_SIZE(rx1950_nand_sets),
	.sets = rx1950_nand_sets,
	.engine_type = NAND_ECC_ENGINE_TYPE_SOFT,
};

static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = {
};

static struct gpiod_lookup_table rx1950_udc_gpio_table = {
	.dev_id = "s3c2410-usbgadget",
	.table = {
		GPIO_LOOKUP("GPIOG", 5, "vbus", GPIO_ACTIVE_LOW),
		GPIO_LOOKUP("GPIOJ", 5, "pullup", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct s3c2410_ts_mach_info rx1950_ts_cfg __initdata = {
	.delay = 10000,
	.presc = 49,
	.oversampling_shift = 3,
};

static struct gpio_keys_button rx1950_gpio_keys_table[] = {
	{
		.code		= KEY_POWER,
		.gpio		= S3C2410_GPF(0),
		.active_low	= 1,
		.desc		= "Power button",
		.wakeup		= 1,
	},
	{
		.code		= KEY_F5,
		.gpio		= S3C2410_GPF(7),
		.active_low	= 1,
		.desc		= "Record button",
	},
	{
		.code		= KEY_F1,
		.gpio		= S3C2410_GPG(0),
		.active_low	= 1,
		.desc		= "Calendar button",
	},
	{
		.code		= KEY_F2,
		.gpio		= S3C2410_GPG(2),
		.active_low	= 1,
		.desc		= "Contacts button",
	},
	{
		.code		= KEY_F3,
		.gpio		= S3C2410_GPG(3),
		.active_low	= 1,
		.desc		= "Mail button",
	},
	{
		.code		= KEY_F4,
		.gpio		= S3C2410_GPG(7),
		.active_low	= 1,
		.desc		= "WLAN button",
	},
	{
		.code		= KEY_LEFT,
		.gpio		= S3C2410_GPG(10),
		.active_low	= 1,
		.desc		= "Left button",
	},
	{
		.code		= KEY_RIGHT,
		.gpio		= S3C2410_GPG(11),
		.active_low	= 1,
		.desc		= "Right button",
	},
	{
		.code		= KEY_UP,
		.gpio		= S3C2410_GPG(4),
		.active_low	= 1,
		.desc		= "Up button",
	},
	{
		.code		= KEY_DOWN,
		.gpio		= S3C2410_GPG(6),
		.active_low	= 1,
		.desc		= "Down button",
	},
	{
		.code		= KEY_ENTER,
		.gpio		= S3C2410_GPG(9),
		.active_low	= 1,
		.desc		= "Ok button"
	},
};

static struct gpio_keys_platform_data rx1950_gpio_keys_data = {
	.buttons = rx1950_gpio_keys_table,
	.nbuttons = ARRAY_SIZE(rx1950_gpio_keys_table),
};

static struct platform_device rx1950_device_gpiokeys = {
	.name = "gpio-keys",
	.dev.platform_data = &rx1950_gpio_keys_data,
};

static struct uda1380_platform_data uda1380_info = {
	.gpio_power	= S3C2410_GPJ(0),
	.gpio_reset	= S3C2410_GPD(0),
	.dac_clk	= UDA1380_DAC_CLK_SYSCLK,
};

static struct i2c_board_info rx1950_i2c_devices[] = {
	{
		I2C_BOARD_INFO("uda1380", 0x1a),
		.platform_data = &uda1380_info,
	},
};

static struct gpiod_lookup_table rx1950_audio_gpio_table = {
	.dev_id = "rx1950-audio",
	.table = {
		GPIO_LOOKUP("GPIOG", 12, "hp-gpio", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("GPIOA", 1, "speaker-power", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct platform_device rx1950_audio = {
	.name = "rx1950-audio",
	.id = -1,
};

static struct platform_device *rx1950_devices[] __initdata = {
	&s3c2410_device_dclk,
	&s3c_device_lcd,
	&s3c_device_wdt,
	&s3c_device_i2c0,
	&s3c_device_iis,
	&s3c_device_usbgadget,
	&s3c_device_rtc,
	&s3c_device_nand,
	&s3c_device_sdi,
	&s3c_device_adc,
	&s3c_device_ts,
	&samsung_device_pwm,
	&rx1950_backlight,
	&rx1950_device_gpiokeys,
	&power_supply,
	&rx1950_battery,
	&rx1950_leds,
	&rx1950_audio,
};

static void __init rx1950_map_io(void)
{
	s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc));
	s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);

	/* setup PM */

#ifdef CONFIG_PM_H1940
	memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 8);
#endif

	s3c_pm_init();
}

static void __init rx1950_init_time(void)
{
	s3c2442_init_clocks(16934000);
	s3c24xx_timer_init();
}

static void __init rx1950_init_machine(void)
{
	int i;

	s3c24xx_fb_set_platdata(&rx1950_lcd_cfg);
	s3c24xx_udc_set_platdata(&rx1950_udc_cfg);
	s3c24xx_ts_set_platdata(&rx1950_ts_cfg);
	gpiod_add_lookup_table(&rx1950_mmc_gpio_table);
	s3c24xx_mci_set_platdata(&rx1950_mmc_cfg);
	s3c_i2c0_set_platdata(NULL);
	s3c_nand_set_platdata(&rx1950_nand_info);

	/* Turn off suspend on both USB ports, and switch the
	 * selectable USB port to USB device mode. */
	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
						S3C2410_MISCCR_USBSUSPND0 |
						S3C2410_MISCCR_USBSUSPND1, 0x0);

	/* mmc power is disabled by default */
	WARN_ON(gpio_request(S3C2410_GPJ(1), "MMC power"));
	gpio_direction_output(S3C2410_GPJ(1), 0);

	for (i = 0; i < 8; i++)
		WARN_ON(gpio_request(S3C2410_GPC(i), "LCD power"));

	for (i = 10; i < 16; i++)
		WARN_ON(gpio_request(S3C2410_GPC(i), "LCD power"));

	for (i = 2; i < 8; i++)
		WARN_ON(gpio_request(S3C2410_GPD(i), "LCD power"));

	for (i = 11; i < 16; i++)
		WARN_ON(gpio_request(S3C2410_GPD(i), "LCD power"));

	WARN_ON(gpio_request(S3C2410_GPB(1), "LCD power"));

	WARN_ON(gpio_request(S3C2410_GPA(3), "Red blink"));
	WARN_ON(gpio_request(S3C2410_GPA(4), "Green blink"));
	WARN_ON(gpio_request(S3C2410_GPJ(6), "LED blink"));
	gpio_direction_output(S3C2410_GPA(3), 0);
	gpio_direction_output(S3C2410_GPA(4), 0);
	gpio_direction_output(S3C2410_GPJ(6), 0);

	pwm_add_table(rx1950_pwm_lookup, ARRAY_SIZE(rx1950_pwm_lookup));
	gpiod_add_lookup_table(&rx1950_udc_gpio_table);
	gpiod_add_lookup_table(&rx1950_audio_gpio_table);
	gpiod_add_lookup_table(&rx1950_bat_gpio_table);
	/* Configure the I2S pins (GPE0...GPE4) in correct mode */
	s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
			      S3C_GPIO_PULL_NONE);
	platform_add_devices(rx1950_devices, ARRAY_SIZE(rx1950_devices));

	i2c_register_board_info(0, rx1950_i2c_devices,
		ARRAY_SIZE(rx1950_i2c_devices));
}

/* H1940 and RX3715 need to reserve this for suspend */
static void __init rx1950_reserve(void)
{
	memblock_reserve(0x30003000, 0x1000);
	memblock_reserve(0x30081000, 0x1000);
}

MACHINE_START(RX1950, "HP iPAQ RX1950")
    /* Maintainers: Vasily Khoruzhick */
	.atag_offset = 0x100,
	.nr_irqs	= NR_IRQS_S3C2442,
	.map_io = rx1950_map_io,
	.reserve	= rx1950_reserve,
	.init_irq	= s3c2442_init_irq,
	.init_machine = rx1950_init_machine,
	.init_time	= rx1950_init_time,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2003-2004 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//
// https://www.handhelds.org/projects/rx3715.html

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/memblock.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/serial.h>
#include <linux/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand-ecc-sw-hamming.h>
#include <linux/mtd/partitions.h>

#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
#include <asm/mach/map.h>

#include <linux/platform_data/mtd-nand-s3c2410.h>
#include <linux/platform_data/fb-s3c2410.h>

#include <asm/irq.h>
#include <asm/mach-types.h>

#include "regs-gpio.h"
#include "gpio-samsung.h"
#include "gpio-cfg.h"

#include "cpu.h"
#include "devs.h"
#include "pm.h"

#include "s3c24xx.h"
#include "h1940.h"

static struct map_desc rx3715_iodesc[] __initdata = {
	/* dump ISA space somewhere unused */
	{
		.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
		.pfn		= __phys_to_pfn(S3C2410_CS3),
		.length		= SZ_1M,
		.type		= MT_DEVICE,
	},
};

static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
	[0] = {
		.hwport	     = 0,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x03,
		.ufcon	     = 0x51,
		.clk_sel	= S3C2410_UCON_CLKSEL3,
	},
	[1] = {
		.hwport	     = 1,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x03,
		.ufcon	     = 0x00,
		.clk_sel	= S3C2410_UCON_CLKSEL3,
	},
	/* IR port */
	[2] = {
		.hwport	     = 2,
		.uart_flags  = UPF_CONS_FLOW,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x43,
		.ufcon	     = 0x51,
		.clk_sel	= S3C2410_UCON_CLKSEL3,
	}
};

/* framebuffer lcd controller information */

static struct s3c2410fb_display rx3715_lcdcfg __initdata = {
	.lcdcon5 =	S3C2410_LCDCON5_INVVLINE |
			S3C2410_LCDCON5_FRM565 |
			S3C2410_LCDCON5_HWSWP,

	.type		= S3C2410_LCDCON1_TFT,
	.width		= 240,
	.height		= 320,

	.pixclock	= 260000,
	.xres		= 240,
	.yres		= 320,
	.bpp		= 16,
	.left_margin	= 36,
	.right_margin	= 36,
	.hsync_len	= 8,
	.upper_margin	= 6,
	.lower_margin	= 7,
	.vsync_len	= 3,
};

static struct s3c2410fb_mach_info rx3715_fb_info __initdata = {

	.displays =	&rx3715_lcdcfg,
	.num_displays =	1,
	.default_display = 0,

	.lpcsel =	0xf82,

	.gpccon =	0xaa955699,
	.gpccon_mask =	0xffc003cc,
	.gpccon_reg =	S3C2410_GPCCON,
	.gpcup =	0x0000ffff,
	.gpcup_mask =	0xffffffff,
	.gpcup_reg =	S3C2410_GPCUP,

	.gpdcon =	0xaa95aaa1,
	.gpdcon_mask =	0xffc0fff0,
	.gpdcon_reg =	S3C2410_GPDCON,
	.gpdup =	0x0000faff,
	.gpdup_mask =	0xffffffff,
	.gpdup_reg =	S3C2410_GPDUP,
};

static struct mtd_partition __initdata rx3715_nand_part[] = {
	[0] = {
		.name		= "Whole Flash",
		.offset		= 0,
		.size		= MTDPART_SIZ_FULL,
		.mask_flags	= MTD_WRITEABLE,
	}
};

static struct s3c2410_nand_set __initdata rx3715_nand_sets[] = {
	[0] = {
		.name		= "Internal",
		.nr_chips	= 1,
		.nr_partitions	= ARRAY_SIZE(rx3715_nand_part),
		.partitions	= rx3715_nand_part,
	},
};

static struct s3c2410_platform_nand __initdata rx3715_nand_info = {
	.tacls		= 25,
	.twrph0		= 50,
	.twrph1		= 15,
	.nr_sets	= ARRAY_SIZE(rx3715_nand_sets),
	.sets		= rx3715_nand_sets,
	.engine_type	= NAND_ECC_ENGINE_TYPE_SOFT,
};

static struct platform_device *rx3715_devices[] __initdata = {
	&s3c_device_ohci,
	&s3c_device_lcd,
	&s3c_device_wdt,
	&s3c_device_i2c0,
	&s3c_device_iis,
	&s3c_device_nand,
};

static void __init rx3715_map_io(void)
{
	s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
	s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
}

static void __init rx3715_init_time(void)
{
	s3c2440_init_clocks(16934000);
	s3c24xx_timer_init();
}

/* H1940 and RX3715 need to reserve this for suspend */
static void __init rx3715_reserve(void)
{
	memblock_reserve(0x30003000, 0x1000);
	memblock_reserve(0x30081000, 0x1000);
}

static void __init rx3715_init_machine(void)
{
#ifdef CONFIG_PM_H1940
	memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
#endif
	s3c_pm_init();

	s3c_nand_set_platdata(&rx3715_nand_info);
	s3c24xx_fb_set_platdata(&rx3715_fb_info);
	/* Configure the I2S pins (GPE0...GPE4) in correct mode */
	s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
			      S3C_GPIO_PULL_NONE);
	platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices));
}

MACHINE_START(RX3715, "IPAQ-RX3715")
	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2440,
	.map_io		= rx3715_map_io,
	.reserve	= rx3715_reserve,
	.init_irq	= s3c2440_init_irq,
	.init_machine	= rx3715_init_machine,
	.init_time	= rx3715_init_time,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Samsung's S3C2416 flattened device tree enabled machine
//
// Copyright (c) 2012 Heiko Stuebner <heiko@sntech.de>
//
// based on mach-exynos/mach-exynos4-dt.c
//
// Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
//		http://www.samsung.com
// Copyright (c) 2010-2011 Linaro Ltd.
//		www.linaro.org

#include <linux/clocksource.h>
#include <linux/irqchip.h>
#include <linux/serial_s3c.h>

#include <asm/mach/arch.h>
#include "map.h"

#include "cpu.h"
#include "pm.h"

#include "s3c24xx.h"

static void __init s3c2416_dt_map_io(void)
{
	s3c24xx_init_io(NULL, 0);
}

static void __init s3c2416_dt_machine_init(void)
{
	s3c_pm_init();
}

static const char *const s3c2416_dt_compat[] __initconst = {
	"samsung,s3c2416",
	"samsung,s3c2450",
	NULL
};

DT_MACHINE_START(S3C2416_DT, "Samsung S3C2416 (Flattened Device Tree)")
	/* Maintainer: Heiko Stuebner <heiko@sntech.de> */
	.dt_compat	= s3c2416_dt_compat,
	.map_io		= s3c2416_dt_map_io,
	.init_irq	= irqchip_init,
	.init_machine	= s3c2416_dt_machine_init,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Samsung's S3C64XX flattened device tree enabled machine
//
// Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/system_misc.h>

#include "cpu.h"
#include "map.h"

#include "s3c64xx.h"

/*
 * IO mapping for shared system controller IP.
 *
 * FIXME: Make remaining drivers use dynamic mapping.
 */
static struct map_desc s3c64xx_dt_iodesc[] __initdata = {
	{
		.virtual	= (unsigned long)S3C_VA_SYS,
		.pfn		= __phys_to_pfn(S3C64XX_PA_SYSCON),
		.length		= SZ_4K,
		.type		= MT_DEVICE,
	},
};

static void __init s3c64xx_dt_map_io(void)
{
	debug_ll_io_init();
	iotable_init(s3c64xx_dt_iodesc, ARRAY_SIZE(s3c64xx_dt_iodesc));

	s3c64xx_init_cpu();

	if (!soc_is_s3c64xx())
		panic("SoC is not S3C64xx!");
}

static const char *const s3c64xx_dt_compat[] __initconst = {
	"samsung,s3c6400",
	"samsung,s3c6410",
	NULL
};

DT_MACHINE_START(S3C6400_DT, "Samsung S3C64xx (Flattened Device Tree)")
	/* Maintainer: Tomasz Figa <tomasz.figa@gmail.com> */
	.dt_compat	= s3c64xx_dt_compat,
	.map_io		= s3c64xx_dt_map_io,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (C) 2010 Maurus Cuelenaere

#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/spi/spi_gpio.h>
#include <linux/platform_data/s3c-hsotg.h>

#include <asm/mach-types.h>
#include <asm/mach/map.h>

#include "map.h"
#include "regs-gpio.h"
#include "gpio-samsung.h"

#include "cpu.h"
#include "devs.h"
#include <linux/platform_data/i2c-s3c2410.h>
#include "gpio-cfg.h"
#include <linux/platform_data/hwmon-s3c.h>
#include <linux/platform_data/usb-ohci-s3c2410.h>
#include "sdhci.h"
#include <linux/platform_data/touchscreen-s3c2410.h>

#include <video/platform_lcd.h>

#include "s3c64xx.h"
#include "mach-smartq.h"
#include "regs-modem-s3c64xx.h"

#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("%s(%d, %d)\n", __func__, 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("%s: over-current irq (oc detected)\n", __func__);
		s3c2410_usb_report_oc(info, 3);
	} else {
		pr_debug("%s: over-current irq (oc cleared)\n", __func__);
		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_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 struct gpiod_lookup_table smartq_usb_otg_vbus_gpiod_table = {
	.dev_id = "gpio-vbus",
	.table = {
		GPIO_LOOKUP("GPL", 9, "vbus", GPIO_ACTIVE_LOW),
		{ },
	},
};

static struct platform_device smartq_usb_otg_vbus_dev = {
	.name			= "gpio-vbus",
};

static struct pwm_lookup smartq_pwm_lookup[] = {
	PWM_LOOKUP("samsung-pwm", 1, "pwm-backlight.0", NULL,
		   1000000000 / (1000 * 20), PWM_POLARITY_NORMAL),
};

static int 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 = {
	.max_brightness	= 1000,
	.dft_brightness	= 600,
	.init		= smartq_bl_init,
};

static struct platform_device smartq_backlight_device = {
	.name		= "pwm-backlight",
	.dev		= {
		.parent	= &samsung_device_pwm.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,
	.cd_type		= S3C_SDHCI_CD_PERMANENT,
};

static struct s3c_hwmon_pdata smartq_hwmon_pdata __initdata = {
	/* Battery voltage (?-4.2V) */
	.in[0] = &(struct s3c_hwmon_chcfg) {
		.name		= "smartq:battery-voltage",
		.mult		= 3300,
		.div		= 2048,
	},
	/* Reference voltage (1.2V) */
	.in[1] = &(struct s3c_hwmon_chcfg) {
		.name		= "smartq:reference-voltage",
		.mult		= 3300,
		.div		= 4096,
	},
};

static struct dwc2_hsotg_plat smartq_hsotg_pdata;

static int __init smartq_lcd_setup_gpio(void)
{
	int ret;

	ret = gpio_request(S3C64XX_GPM(3), "LCD power");
	if (ret < 0)
		return ret;

	/* turn power off */
	gpio_direction_output(S3C64XX_GPM(3), 0);

	return 0;
}

/* GPM0 -> CS */
static struct spi_gpio_platform_data smartq_lcd_control = {
	.num_chipselect	= 1,
};

static struct platform_device smartq_lcd_control_device = {
	.name			= "spi_gpio",
	.id			= 1,
	.dev.platform_data	= &smartq_lcd_control,
};

static struct gpiod_lookup_table smartq_lcd_control_gpiod_table = {
	.dev_id         = "spi_gpio",
	.table          = {
		GPIO_LOOKUP("GPIOM", 1,
			    "sck", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("GPIOM", 2,
			    "mosi", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("GPIOM", 3,
			    "miso", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("GPIOM", 0,
			    "cs", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static void smartq_lcd_power_set(struct plat_lcd_data *pd, unsigned int power)
{
	gpio_direction_output(S3C64XX_GPM(3), power);
}

static struct plat_lcd_data smartq_lcd_power_data = {
	.set_power	= smartq_lcd_power_set,
};

static struct platform_device smartq_lcd_power_device = {
	.name			= "platform-lcd",
	.dev.parent		= &s3c_device_fb.dev,
	.dev.platform_data	= &smartq_lcd_power_data,
};

static struct i2c_board_info smartq_i2c_devs[] __initdata = {
	{ I2C_BOARD_INFO("wm8987", 0x1a), },
};

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_hwmon,
	&s3c_device_i2c0,
	&s3c_device_ohci,
	&s3c_device_rtc,
	&samsung_device_pwm,
	&s3c_device_usb_hsotg,
	&s3c64xx_device_iis0,
	&smartq_backlight_device,
	&smartq_lcd_control_device,
	&smartq_lcd_power_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 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);

	pm_power_off = smartq_power_off;

	return ret;
}

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_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 struct map_desc smartq_iodesc[] __initdata = {};
void __init smartq_map_io(void)
{
	s3c64xx_init_io(smartq_iodesc, ARRAY_SIZE(smartq_iodesc));
	s3c64xx_set_xtal_freq(12000000);
	s3c64xx_set_xusbxti_freq(12000000);
	s3c24xx_init_uarts(smartq_uartcfgs, ARRAY_SIZE(smartq_uartcfgs));
	s3c64xx_set_timer_source(S3C64XX_PWM3, S3C64XX_PWM4);

	smartq_lcd_mode_set();
}

static struct gpiod_lookup_table smartq_audio_gpios = {
	.dev_id = "smartq-audio",
	.table = {
		GPIO_LOOKUP("GPL", 12, "headphone detect", 0),
		GPIO_LOOKUP("GPK", 12, "amplifiers shutdown", 0),
		{ },
	},
};

void __init smartq_machine_init(void)
{
	s3c_i2c0_set_platdata(NULL);
	dwc2_hsotg_set_platdata(&smartq_hsotg_pdata);
	s3c_hwmon_set_platdata(&smartq_hwmon_pdata);
	s3c_sdhci1_set_platdata(&smartq_internal_hsmmc_pdata);
	s3c_sdhci2_set_platdata(&smartq_internal_hsmmc_pdata);
	s3c64xx_ts_set_platdata(&smartq_touchscreen_pdata);

	i2c_register_board_info(0, smartq_i2c_devs,
				ARRAY_SIZE(smartq_i2c_devs));

	WARN_ON(smartq_lcd_setup_gpio());
	WARN_ON(smartq_power_off_init());
	WARN_ON(smartq_usb_host_init());
	WARN_ON(smartq_wifi_init());

	pwm_add_table(smartq_pwm_lookup, ARRAY_SIZE(smartq_pwm_lookup));
	gpiod_add_lookup_table(&smartq_lcd_control_gpiod_table);
	gpiod_add_lookup_table(&smartq_usb_otg_vbus_gpiod_table);
	platform_add_devices(smartq_devices, ARRAY_SIZE(smartq_devices));

	gpiod_add_lookup_table(&smartq_audio_gpios);
	platform_device_register_simple("smartq-audio", -1, NULL, 0);
}


code:
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * linux/arch/arm/mach-s3c64xx/mach-smartq.h
 *
 * Copyright (C) 2010 Maurus Cuelenaere
 */

#ifndef __MACH_SMARTQ_H
#define __MACH_SMARTQ_H __FILE__

#include <linux/init.h>

extern void __init smartq_map_io(void);
extern void __init smartq_machine_init(void);

#endif /* __MACH_SMARTQ_H */


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (C) 2010 Maurus Cuelenaere

#include <linux/fb.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/leds.h>
#include <linux/platform_device.h>

#include <asm/mach-types.h>
#include <asm/mach/arch.h>

#include <video/samsung_fimd.h>
#include "irqs.h"
#include "map.h"
#include "regs-gpio.h"
#include "gpio-samsung.h"

#include "cpu.h"
#include "devs.h"
#include "fb.h"
#include "gpio-cfg.h"

#include "s3c64xx.h"
#include "mach-smartq.h"

static struct gpio_led smartq5_leds[] = {
	{
		.name			= "smartq5:green",
		.active_low		= 1,
		.gpio			= S3C64XX_GPN(8),
	},
	{
		.name			= "smartq5:red",
		.active_low		= 1,
		.gpio			= S3C64XX_GPN(9),
	},
};

static struct gpio_led_platform_data smartq5_led_data = {
	.num_leds = ARRAY_SIZE(smartq5_leds),
	.leds = smartq5_leds,
};

static struct platform_device smartq5_leds_device = {
	.name			= "leds-gpio",
	.id			= -1,
	.dev.platform_data	= &smartq5_led_data,
};

/* Labels according to the SmartQ manual */
static struct gpio_keys_button smartq5_buttons[] = {
	{
		.gpio			= S3C64XX_GPL(14),
		.code			= KEY_POWER,
		.desc			= "Power",
		.active_low		= 1,
		.debounce_interval	= 5,
		.type                   = EV_KEY,
	},
	{
		.gpio			= S3C64XX_GPN(2),
		.code			= KEY_KPMINUS,
		.desc			= "Minus",
		.active_low		= 1,
		.debounce_interval	= 5,
		.type                   = EV_KEY,
	},
	{
		.gpio			= S3C64XX_GPN(12),
		.code			= KEY_KPPLUS,
		.desc			= "Plus",
		.active_low		= 1,
		.debounce_interval	= 5,
		.type                   = EV_KEY,
	},
	{
		.gpio			= S3C64XX_GPN(15),
		.code			= KEY_ENTER,
		.desc			= "Move",
		.active_low		= 1,
		.debounce_interval	= 5,
		.type                   = EV_KEY,
	},
};

static struct gpio_keys_platform_data smartq5_buttons_data  = {
	.buttons	= smartq5_buttons,
	.nbuttons	= ARRAY_SIZE(smartq5_buttons),
};

static struct platform_device smartq5_buttons_device  = {
	.name		= "gpio-keys",
	.id		= 0,
	.num_resources	= 0,
	.dev		= {
		.platform_data	= &smartq5_buttons_data,
	}
};

static struct s3c_fb_pd_win smartq5_fb_win0 = {
	.max_bpp	= 32,
	.default_bpp	= 16,
	.xres		= 800,
	.yres		= 480,
};

static struct fb_videomode smartq5_lcd_timing = {
	.left_margin	= 216,
	.right_margin	= 40,
	.upper_margin	= 35,
	.lower_margin	= 10,
	.hsync_len	= 1,
	.vsync_len	= 1,
	.xres		= 800,
	.yres		= 480,
	.refresh	= 80,
};

static struct s3c_fb_platdata smartq5_lcd_pdata __initdata = {
	.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
	.vtiming	= &smartq5_lcd_timing,
	.win[0]		= &smartq5_fb_win0,
	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC |
			  VIDCON1_INV_VDEN,
};

static struct platform_device *smartq5_devices[] __initdata = {
	&smartq5_leds_device,
	&smartq5_buttons_device,
};

static void __init smartq5_machine_init(void)
{
	s3c_fb_set_platdata(&smartq5_lcd_pdata);

	smartq_machine_init();

	platform_add_devices(smartq5_devices, ARRAY_SIZE(smartq5_devices));
}

MACHINE_START(SMARTQ5, "SmartQ 5")
	/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
	.atag_offset	= 0x100,
	.nr_irqs	= S3C64XX_NR_IRQS,
	.init_irq	= s3c6410_init_irq,
	.map_io		= smartq_map_io,
	.init_machine	= smartq5_machine_init,
	.init_time	= s3c64xx_timer_init,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (C) 2010 Maurus Cuelenaere

#include <linux/fb.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/leds.h>
#include <linux/platform_device.h>

#include <asm/mach-types.h>
#include <asm/mach/arch.h>

#include <video/samsung_fimd.h>
#include "irqs.h"
#include "map.h"
#include "regs-gpio.h"
#include "gpio-samsung.h"

#include "cpu.h"
#include "devs.h"
#include "fb.h"
#include "gpio-cfg.h"

#include "s3c64xx.h"
#include "mach-smartq.h"

static struct gpio_led smartq7_leds[] = {
	{
		.name			= "smartq7:red",
		.active_low		= 1,
		.gpio			= S3C64XX_GPN(8),
	},
	{
		.name			= "smartq7:green",
		.active_low		= 1,
		.gpio			= S3C64XX_GPN(9),
	},
};

static struct gpio_led_platform_data smartq7_led_data = {
	.num_leds = ARRAY_SIZE(smartq7_leds),
	.leds = smartq7_leds,
};

static struct platform_device smartq7_leds_device = {
	.name			= "leds-gpio",
	.id			= -1,
	.dev.platform_data	= &smartq7_led_data,
};

/* Labels according to the SmartQ manual */
static struct gpio_keys_button smartq7_buttons[] = {
	{
		.gpio			= S3C64XX_GPL(14),
		.code			= KEY_POWER,
		.desc			= "Power",
		.active_low		= 1,
		.debounce_interval	= 5,
		.type                   = EV_KEY,
	},
	{
		.gpio			= S3C64XX_GPN(2),
		.code			= KEY_FN,
		.desc			= "Function",
		.active_low		= 1,
		.debounce_interval	= 5,
		.type                   = EV_KEY,
	},
	{
		.gpio			= S3C64XX_GPN(3),
		.code			= KEY_KPMINUS,
		.desc			= "Minus",
		.active_low		= 1,
		.debounce_interval	= 5,
		.type                   = EV_KEY,
	},
	{
		.gpio			= S3C64XX_GPN(4),
		.code			= KEY_KPPLUS,
		.desc			= "Plus",
		.active_low		= 1,
		.debounce_interval	= 5,
		.type                   = EV_KEY,
	},
	{
		.gpio			= S3C64XX_GPN(12),
		.code			= KEY_ENTER,
		.desc			= "Enter",
		.active_low		= 1,
		.debounce_interval	= 5,
		.type                   = EV_KEY,
	},
	{
		.gpio			= S3C64XX_GPN(15),
		.code			= KEY_ESC,
		.desc			= "Cancel",
		.active_low		= 1,
		.debounce_interval	= 5,
		.type                   = EV_KEY,
	},
};

static struct gpio_keys_platform_data smartq7_buttons_data  = {
	.buttons	= smartq7_buttons,
	.nbuttons	= ARRAY_SIZE(smartq7_buttons),
};

static struct platform_device smartq7_buttons_device  = {
	.name		= "gpio-keys",
	.id		= 0,
	.num_resources	= 0,
	.dev		= {
		.platform_data	= &smartq7_buttons_data,
	}
};

static struct s3c_fb_pd_win smartq7_fb_win0 = {
	.max_bpp	= 32,
	.default_bpp	= 16,
	.xres		= 800,
	.yres		= 480,
};

static struct fb_videomode smartq7_lcd_timing = {
	.left_margin	= 3,
	.right_margin	= 5,
	.upper_margin	= 1,
	.lower_margin	= 20,
	.hsync_len	= 10,
	.vsync_len	= 3,
	.xres		= 800,
	.yres		= 480,
	.refresh	= 80,
};

static struct s3c_fb_platdata smartq7_lcd_pdata __initdata = {
	.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
	.vtiming	= &smartq7_lcd_timing,
	.win[0]		= &smartq7_fb_win0,
	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC |
			  VIDCON1_INV_VCLK,
};

static struct platform_device *smartq7_devices[] __initdata = {
	&smartq7_leds_device,
	&smartq7_buttons_device,
};

static void __init smartq7_machine_init(void)
{
	s3c_fb_set_platdata(&smartq7_lcd_pdata);

	smartq_machine_init();

	platform_add_devices(smartq7_devices, ARRAY_SIZE(smartq7_devices));
}

MACHINE_START(SMARTQ7, "SmartQ 7")
	/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
	.atag_offset	= 0x100,
	.nr_irqs	= S3C64XX_NR_IRQS,
	.init_irq	= s3c6410_init_irq,
	.map_io		= smartq_map_io,
	.init_machine	= smartq7_machine_init,
	.init_time	= s3c64xx_timer_init,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0+
//
// Copyright (C) 2004 by FS Forth-Systeme GmbH
// All rights reserved.
//
// @Author: Jonas Dietsche
//
// @History:
// derived from linux/arch/arm/mach-s3c2410/mach-bast.c, written by
// Ben Dooks <ben@simtec.co.uk>

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include "gpio-samsung.h"
#include "gpio-cfg.h"

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include <asm/irq.h>
#include <asm/mach-types.h>

#include <linux/platform_data/i2c-s3c2410.h>

#include "devs.h"
#include "cpu.h"

#include "s3c24xx.h"
#include "common-smdk-s3c24xx.h"

static struct map_desc smdk2410_iodesc[] __initdata = {
  /* nothing here yet */
};

#define UCON S3C2410_UCON_DEFAULT
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE

static struct s3c2410_uartcfg smdk2410_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 struct platform_device *smdk2410_devices[] __initdata = {
	&s3c_device_ohci,
	&s3c_device_lcd,
	&s3c_device_wdt,
	&s3c_device_i2c0,
	&s3c_device_iis,
};

static void __init smdk2410_map_io(void)
{
	s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
	s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
}

static void __init smdk2410_init_time(void)
{
	s3c2410_init_clocks(12000000);
	s3c24xx_timer_init();
}

static void __init smdk2410_init(void)
{
	s3c_i2c0_set_platdata(NULL);
	platform_add_devices(smdk2410_devices, ARRAY_SIZE(smdk2410_devices));
	/* Configure the I2S pins (GPE0...GPE4) in correct mode */
	s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
			      S3C_GPIO_PULL_NONE);
	smdk_machine_init();
}

MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
				    * to SMDK2410 */
	/* Maintainer: Jonas Dietsche */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2410,
	.map_io		= smdk2410_map_io,
	.init_irq	= s3c2410_init_irq,
	.init_machine	= smdk2410_init,
	.init_time	= smdk2410_init_time,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2006 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//
// Thanks to Dimity Andric (TomTom) and Steven Ryu (Samsung) for the
// loans of SMDK2413 to work with.

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/gpio/machine.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/memblock.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include <asm/hardware/iomd.h>
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/mach-types.h>

//#include <asm/debug-ll.h>
#include "hardware-s3c24xx.h"
#include "regs-gpio.h"

#include <linux/platform_data/usb-s3c2410_udc.h>
#include <linux/platform_data/i2c-s3c2410.h>
#include <linux/platform_data/fb-s3c2410.h>
#include "gpio-samsung.h"
#include "gpio-cfg.h"

#include "devs.h"
#include "cpu.h"

#include "s3c24xx.h"
#include "common-smdk-s3c24xx.h"

static struct map_desc smdk2413_iodesc[] __initdata = {
};

static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
	[0] = {
		.hwport	     = 0,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x03,
		.ufcon	     = 0x51,
	},
	[1] = {
		.hwport	     = 1,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x03,
		.ufcon	     = 0x51,
	},
	/* IR port */
	[2] = {
		.hwport	     = 2,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x43,
		.ufcon	     = 0x51,
	}
};

static struct s3c2410_udc_mach_info smdk2413_udc_cfg __initdata = {
};

static struct gpiod_lookup_table smdk2413_udc_gpio_table = {
	.dev_id = "s3c2410-usbgadget",
	.table = {
		GPIO_LOOKUP("GPIOF", 2, "pullup", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct platform_device *smdk2413_devices[] __initdata = {
	&s3c_device_ohci,
	&s3c_device_wdt,
	&s3c_device_i2c0,
	&s3c_device_iis,
	&s3c_device_usbgadget,
	&s3c2412_device_dma,
};

static void __init smdk2413_fixup(struct tag *tags, char **cmdline)
{
	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
		memblock_add(0x30000000, SZ_64M);
	}
}

static void __init smdk2413_map_io(void)
{
	s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
	s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
}

static void __init smdk2413_init_time(void)
{
	s3c2412_init_clocks(12000000);
	s3c24xx_timer_init();
}

static void __init smdk2413_machine_init(void)
{	/* Turn off suspend on both USB ports, and switch the
	 * selectable USB port to USB device mode. */

	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
			      S3C2410_MISCCR_USBSUSPND0 |
			      S3C2410_MISCCR_USBSUSPND1, 0x0);

	gpiod_add_lookup_table(&smdk2413_udc_gpio_table);
 	s3c24xx_udc_set_platdata(&smdk2413_udc_cfg);
	s3c_i2c0_set_platdata(NULL);
	/* Configure the I2S pins (GPE0...GPE4) in correct mode */
	s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
			      S3C_GPIO_PULL_NONE);

	platform_add_devices(smdk2413_devices, ARRAY_SIZE(smdk2413_devices));
	smdk_machine_init();
}

MACHINE_START(S3C2413, "S3C2413")
	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2412,

	.fixup		= smdk2413_fixup,
	.init_irq	= s3c2412_init_irq,
	.map_io		= smdk2413_map_io,
	.init_machine	= smdk2413_machine_init,
	.init_time	= s3c24xx_timer_init,
MACHINE_END

MACHINE_START(SMDK2412, "SMDK2412")
	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2412,

	.fixup		= smdk2413_fixup,
	.init_irq	= s3c2412_init_irq,
	.map_io		= smdk2413_map_io,
	.init_machine	= smdk2413_machine_init,
	.init_time	= s3c24xx_timer_init,
MACHINE_END

MACHINE_START(SMDK2413, "SMDK2413")
	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2412,

	.fixup		= smdk2413_fixup,
	.init_irq	= s3c2412_init_irq,
	.map_io		= smdk2413_map_io,
	.init_machine	= smdk2413_machine_init,
	.init_time	= smdk2413_init_time,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2009 Yauhen Kharuzhy <jekhor@gmail.com>,
//	as part of OpenInkpot project
// Copyright (c) 2009 Promwad Innovation Company
//	Yauhen Kharuzhy <yauhen.kharuzhy@promwad.com>

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/mtd/partitions.h>
#include <linux/gpio.h>
#include <linux/fb.h>
#include <linux/delay.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include <video/samsung_fimd.h>
#include <asm/irq.h>
#include <asm/mach-types.h>

#include "hardware-s3c24xx.h"
#include "regs-gpio.h"
#include "regs-s3c2443-clock.h"
#include "gpio-samsung.h"

#include <linux/platform_data/leds-s3c24xx.h>
#include <linux/platform_data/i2c-s3c2410.h>

#include "gpio-cfg.h"
#include "devs.h"
#include "cpu.h"
#include <linux/platform_data/mtd-nand-s3c2410.h>
#include "sdhci.h"
#include <linux/platform_data/usb-s3c2410_udc.h>
#include <linux/platform_data/s3c-hsudc.h>

#include "fb.h"

#include "s3c24xx.h"
#include "common-smdk-s3c24xx.h"

static struct map_desc smdk2416_iodesc[] __initdata = {
	/* ISA IO Space map (memory space selected by A24) */

	{
		.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
		.pfn		= __phys_to_pfn(S3C2410_CS2),
		.length		= 0x10000,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
		.pfn		= __phys_to_pfn(S3C2410_CS2 + (1<<24)),
		.length		= SZ_4M,
		.type		= MT_DEVICE,
	}
};

#define UCON (S3C2410_UCON_DEFAULT	| \
		S3C2440_UCON_PCLK	| \
		S3C2443_UCON_RXERR_IRQEN)

#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE)

#define UFCON (S3C2410_UFCON_RXTRIG8	| \
		S3C2410_UFCON_FIFOMODE	| \
		S3C2440_UFCON_TXTRIG16)

static struct s3c2410_uartcfg smdk2416_uartcfgs[] __initdata = {
	[0] = {
		.hwport	     = 0,
		.flags	     = 0,
		.ucon	     = UCON,
		.ulcon	     = ULCON,
		.ufcon	     = UFCON,
	},
	[1] = {
		.hwport	     = 1,
		.flags	     = 0,
		.ucon	     = UCON,
		.ulcon	     = ULCON,
		.ufcon	     = UFCON,
	},
	/* IR port */
	[2] = {
		.hwport	     = 2,
		.flags	     = 0,
		.ucon	     = UCON,
		.ulcon	     = ULCON | 0x50,
		.ufcon	     = UFCON,
	},
	[3] = {
		.hwport	     = 3,
		.flags	     = 0,
		.ucon	     = UCON,
		.ulcon	     = ULCON,
		.ufcon	     = UFCON,
	}
};

static void smdk2416_hsudc_gpio_init(void)
{
	s3c_gpio_setpull(S3C2410_GPH(14), S3C_GPIO_PULL_UP);
	s3c_gpio_setpull(S3C2410_GPF(2), S3C_GPIO_PULL_NONE);
	s3c_gpio_cfgpin(S3C2410_GPH(14), S3C_GPIO_SFN(1));
	s3c2410_modify_misccr(S3C2416_MISCCR_SEL_SUSPND, 0);
}

static void smdk2416_hsudc_gpio_uninit(void)
{
	s3c2410_modify_misccr(S3C2416_MISCCR_SEL_SUSPND, 1);
	s3c_gpio_setpull(S3C2410_GPH(14), S3C_GPIO_PULL_NONE);
	s3c_gpio_cfgpin(S3C2410_GPH(14), S3C_GPIO_SFN(0));
}

static struct s3c24xx_hsudc_platdata smdk2416_hsudc_platdata = {
	.epnum = 9,
	.gpio_init = smdk2416_hsudc_gpio_init,
	.gpio_uninit = smdk2416_hsudc_gpio_uninit,
};

static struct s3c_fb_pd_win smdk2416_fb_win[] = {
	[0] = {
		.default_bpp	= 16,
		.max_bpp	= 32,
		.xres           = 800,
		.yres           = 480,
	},
};

static struct fb_videomode smdk2416_lcd_timing = {
	.pixclock	= 41094,
	.left_margin	= 8,
	.right_margin	= 13,
	.upper_margin	= 7,
	.lower_margin	= 5,
	.hsync_len	= 3,
	.vsync_len	= 1,
	.xres           = 800,
	.yres           = 480,
};

static void s3c2416_fb_gpio_setup_24bpp(void)
{
	unsigned int gpio;

	for (gpio = S3C2410_GPC(1); gpio <= S3C2410_GPC(4); gpio++) {
		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
	}

	for (gpio = S3C2410_GPC(8); gpio <= S3C2410_GPC(15); gpio++) {
		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
	}

	for (gpio = S3C2410_GPD(0); gpio <= S3C2410_GPD(15); gpio++) {
		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
	}
}

static struct s3c_fb_platdata smdk2416_fb_platdata = {
	.win[0]		= &smdk2416_fb_win[0],
	.vtiming	= &smdk2416_lcd_timing,
	.setup_gpio	= s3c2416_fb_gpio_setup_24bpp,
	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
};

static struct s3c_sdhci_platdata smdk2416_hsmmc0_pdata __initdata = {
	.max_width		= 4,
	.cd_type		= S3C_SDHCI_CD_GPIO,
	.ext_cd_gpio		= S3C2410_GPF(1),
	.ext_cd_gpio_invert	= 1,
};

static struct s3c_sdhci_platdata smdk2416_hsmmc1_pdata __initdata = {
	.max_width		= 4,
	.cd_type		= S3C_SDHCI_CD_NONE,
};

static struct platform_device *smdk2416_devices[] __initdata = {
	&s3c_device_fb,
	&s3c_device_wdt,
	&s3c_device_ohci,
	&s3c_device_i2c0,
	&s3c_device_hsmmc0,
	&s3c_device_hsmmc1,
	&s3c_device_usb_hsudc,
	&s3c2443_device_dma,
};

static void __init smdk2416_init_time(void)
{
	s3c2416_init_clocks(12000000);
	s3c24xx_timer_init();
}

static void __init smdk2416_map_io(void)
{
	s3c24xx_init_io(smdk2416_iodesc, ARRAY_SIZE(smdk2416_iodesc));
	s3c24xx_init_uarts(smdk2416_uartcfgs, ARRAY_SIZE(smdk2416_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
}

static void __init smdk2416_machine_init(void)
{
	s3c_i2c0_set_platdata(NULL);
	s3c_fb_set_platdata(&smdk2416_fb_platdata);

	s3c_sdhci0_set_platdata(&smdk2416_hsmmc0_pdata);
	s3c_sdhci1_set_platdata(&smdk2416_hsmmc1_pdata);

	s3c24xx_hsudc_set_platdata(&smdk2416_hsudc_platdata);

	gpio_request(S3C2410_GPB(4), "USBHost Power");
	gpio_direction_output(S3C2410_GPB(4), 1);

	gpio_request(S3C2410_GPB(3), "Display Power");
	gpio_direction_output(S3C2410_GPB(3), 1);

	gpio_request(S3C2410_GPB(1), "Display Reset");
	gpio_direction_output(S3C2410_GPB(1), 1);

	platform_add_devices(smdk2416_devices, ARRAY_SIZE(smdk2416_devices));
	smdk_machine_init();
}

MACHINE_START(SMDK2416, "SMDK2416")
	/* Maintainer: Yauhen Kharuzhy <jekhor@gmail.com> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2416,

	.init_irq	= s3c2416_init_irq,
	.map_io		= smdk2416_map_io,
	.init_machine	= smdk2416_machine_init,
	.init_time	= smdk2416_init_time,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
// linux/arch/arm/mach-s3c2440/mach-smdk2440.c
//
// Copyright (c) 2004-2005 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//
// http://www.fluff.org/ben/smdk2440/
//
// Thanks to Dimity Andric and TomTom for the loan of an SMDK2440.

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/platform_device.h>
#include <linux/io.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include <asm/irq.h>
#include <asm/mach-types.h>

#include "regs-gpio.h"
#include "gpio-samsung.h"
#include "gpio-cfg.h"

#include <linux/platform_data/fb-s3c2410.h>
#include <linux/platform_data/i2c-s3c2410.h>

#include "devs.h"
#include "cpu.h"

#include "s3c24xx.h"
#include "common-smdk-s3c24xx.h"

static struct map_desc smdk2440_iodesc[] __initdata = {
	/* ISA IO Space map (memory space selected by A24) */

	{
		.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
		.pfn		= __phys_to_pfn(S3C2410_CS2),
		.length		= 0x10000,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
		.pfn		= __phys_to_pfn(S3C2410_CS2 + (1<<24)),
		.length		= SZ_4M,
		.type		= MT_DEVICE,
	}
};

#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE

static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = {
	[0] = {
		.hwport	     = 0,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x03,
		.ufcon	     = 0x51,
	},
	[1] = {
		.hwport	     = 1,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x03,
		.ufcon	     = 0x51,
	},
	/* IR port */
	[2] = {
		.hwport	     = 2,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x43,
		.ufcon	     = 0x51,
	}
};

/* LCD driver info */

static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {

	.lcdcon5	= S3C2410_LCDCON5_FRM565 |
			  S3C2410_LCDCON5_INVVLINE |
			  S3C2410_LCDCON5_INVVFRAME |
			  S3C2410_LCDCON5_PWREN |
			  S3C2410_LCDCON5_HWSWP,

	.type		= S3C2410_LCDCON1_TFT,

	.width		= 240,
	.height		= 320,

	.pixclock	= 166667, /* HCLK 60 MHz, divisor 10 */
	.xres		= 240,
	.yres		= 320,
	.bpp		= 16,
	.left_margin	= 20,
	.right_margin	= 8,
	.hsync_len	= 4,
	.upper_margin	= 8,
	.lower_margin	= 7,
	.vsync_len	= 4,
};

static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = {
	.displays	= &smdk2440_lcd_cfg,
	.num_displays	= 1,
	.default_display = 0,

#if 0
	/* currently setup by downloader */
	.gpccon		= 0xaa940659,
	.gpccon_mask	= 0xffffffff,
	.gpcup		= 0x0000ffff,
	.gpcup_mask	= 0xffffffff,
	.gpdcon		= 0xaa84aaa0,
	.gpdcon_mask	= 0xffffffff,
	.gpdup		= 0x0000faff,
	.gpdup_mask	= 0xffffffff,

	.gpccon_reg	= S3C2410_GPCCON,
	.gpcup_reg	= S3C2410_GPCUP,
	.gpdcon_reg	= S3C2410_GPDCON,
	.gpdup_reg	= S3C2410_GPDUP,
#endif

	.lpcsel		= ((0xCE6) & ~7) | 1<<4,
};

static struct platform_device *smdk2440_devices[] __initdata = {
	&s3c_device_ohci,
	&s3c_device_lcd,
	&s3c_device_wdt,
	&s3c_device_i2c0,
	&s3c_device_iis,
};

static void __init smdk2440_map_io(void)
{
	s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
	s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
}

static void __init smdk2440_init_time(void)
{
	s3c2440_init_clocks(16934400);
	s3c24xx_timer_init();
}

static void __init smdk2440_machine_init(void)
{
	s3c24xx_fb_set_platdata(&smdk2440_fb_info);
	s3c_i2c0_set_platdata(NULL);
	/* Configure the I2S pins (GPE0...GPE4) in correct mode */
	s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
			      S3C_GPIO_PULL_NONE);
	platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
	smdk_machine_init();
}

MACHINE_START(S3C2440, "SMDK2440")
	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2440,

	.init_irq	= s3c2440_init_irq,
	.map_io		= smdk2440_map_io,
	.init_machine	= smdk2440_machine_init,
	.init_time	= smdk2440_init_time,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2007 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//
// http://www.fluff.org/ben/smdk2443/
//
// Thanks to Samsung for the loan of an SMDK2443

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/platform_device.h>
#include <linux/io.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include <asm/irq.h>
#include <asm/mach-types.h>

#include "regs-gpio.h"

#include <linux/platform_data/fb-s3c2410.h>
#include <linux/platform_data/i2c-s3c2410.h>

#include "devs.h"
#include "cpu.h"

#include "s3c24xx.h"
#include "common-smdk-s3c24xx.h"

static struct map_desc smdk2443_iodesc[] __initdata = {
	/* ISA IO Space map (memory space selected by A24) */

	{
		.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
		.pfn		= __phys_to_pfn(S3C2410_CS2),
		.length		= 0x10000,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
		.pfn		= __phys_to_pfn(S3C2410_CS2 + (1<<24)),
		.length		= SZ_4M,
		.type		= MT_DEVICE,
	}
};

#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE

static struct s3c2410_uartcfg smdk2443_uartcfgs[] __initdata = {
	[0] = {
		.hwport	     = 0,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x03,
		.ufcon	     = 0x51,
	},
	[1] = {
		.hwport	     = 1,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x03,
		.ufcon	     = 0x51,
	},
	/* IR port */
	[2] = {
		.hwport	     = 2,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x43,
		.ufcon	     = 0x51,
	},
	[3] = {
		.hwport	     = 3,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x03,
		.ufcon	     = 0x51,
	}
};

static struct platform_device *smdk2443_devices[] __initdata = {
	&s3c_device_wdt,
	&s3c_device_i2c0,
	&s3c_device_hsmmc1,
	&s3c2443_device_dma,
};

static void __init smdk2443_map_io(void)
{
	s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc));
	s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
}

static void __init smdk2443_init_time(void)
{
	s3c2443_init_clocks(12000000);
	s3c24xx_timer_init();
}

static void __init smdk2443_machine_init(void)
{
	s3c_i2c0_set_platdata(NULL);
	platform_add_devices(smdk2443_devices, ARRAY_SIZE(smdk2443_devices));
	smdk_machine_init();
}

MACHINE_START(SMDK2443, "SMDK2443")
	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2443,
	.init_irq	= s3c2443_init_irq,
	.map_io		= smdk2443_map_io,
	.init_machine	= smdk2443_machine_init,
	.init_time	= smdk2443_init_time,
MACHINE_END