code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2003-2009 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/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/platform_device.h>
#include <linux/ata_platform.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/sm501.h>
#include <linux/sm501-regs.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 <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 <net/ax88796.h>

#include "devs.h"
#include "cpu.h"
#include <linux/platform_data/asoc-s3c24xx_simtec.h>

#include "anubis.h"
#include "s3c24xx.h"
#include "simtec.h"

#define COPYRIGHT ", Copyright 2005-2009 Simtec Electronics"

static struct map_desc anubis_iodesc[] __initdata = {
  /* ISA IO areas */

  {
	.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
	.pfn		= __phys_to_pfn(0x0),
	.length		= SZ_4M,
	.type		= MT_DEVICE,
  },

  /* we could possibly compress the next set down into a set of smaller tables
   * pagetables, but that would mean using an L2 section, and it still means
   * we cannot actually feed the same register to an LDR due to 16K spacing
   */

  /* CPLD control registers */

  {
	.virtual	= (u32)ANUBIS_VA_CTRL1,
	.pfn		= __phys_to_pfn(ANUBIS_PA_CTRL1),
	.length		= SZ_4K,
	.type		= MT_DEVICE,
  }, {
	.virtual	= (u32)ANUBIS_VA_IDREG,
	.pfn		= __phys_to_pfn(ANUBIS_PA_IDREG),
	.length		= SZ_4K,
	.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 anubis_uartcfgs[] __initdata = {
	[0] = {
		.hwport	     = 0,
		.flags	     = 0,
		.ucon	     = UCON,
		.ulcon	     = ULCON,
		.ufcon	     = UFCON,
		.clk_sel	= S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
	},
	[1] = {
		.hwport	     = 2,
		.flags	     = 0,
		.ucon	     = UCON,
		.ulcon	     = ULCON,
		.ufcon	     = UFCON,
		.clk_sel	= S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
	},
};

/* NAND Flash on Anubis board */

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

static struct mtd_partition __initdata anubis_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 anubis_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 Anubis 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 anubis_nand_sets[] = {
	[1] = {
		.name		= "External",
		.nr_chips	= 1,
		.nr_map		= external_map,
		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
		.partitions	= anubis_default_nand_part,
	},
	[0] = {
		.name		= "chip0",
		.nr_chips	= 1,
		.nr_map		= chip0_map,
		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
		.partitions	= anubis_default_nand_part,
	},
	[2] = {
		.name		= "chip1",
		.nr_chips	= 1,
		.nr_map		= chip1_map,
		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
		.partitions	= anubis_default_nand_part,
	},
};

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

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

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

	tmp = __raw_readb(ANUBIS_VA_CTRL1);
	tmp &= ~ANUBIS_CTRL1_NANDSEL;
	tmp |= slot;

	pr_debug("anubis_nand: ctrl1 now %02x\n", tmp);

	__raw_writeb(tmp, ANUBIS_VA_CTRL1);
}

static struct s3c2410_platform_nand __initdata anubis_nand_info = {
	.tacls		= 25,
	.twrph0		= 55,
	.twrph1		= 40,
	.nr_sets	= ARRAY_SIZE(anubis_nand_sets),
	.sets		= anubis_nand_sets,
	.select_chip	= anubis_nand_select,
	.engine_type	= NAND_ECC_ENGINE_TYPE_SOFT,
};

/* IDE channels */

static struct pata_platform_info anubis_ide_platdata = {
	.ioport_shift	= 5,
};

static struct resource anubis_ide0_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_CS3, 8 * 32),
	[2] = DEFINE_RES_MEM(S3C2410_CS3 + (1 << 26) + (6 * 32), 32),
	[3] = DEFINE_RES_IRQ(ANUBIS_IRQ_IDE0),
};

static struct platform_device anubis_device_ide0 = {
	.name		= "pata_platform",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(anubis_ide0_resource),
	.resource	= anubis_ide0_resource,
	.dev	= {
		.platform_data = &anubis_ide_platdata,
		.coherent_dma_mask = ~0,
	},
};

static struct resource anubis_ide1_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_CS4, 8 * 32),
	[1] = DEFINE_RES_MEM(S3C2410_CS4 + (1 << 26) + (6 * 32), 32),
	[2] = DEFINE_RES_IRQ(ANUBIS_IRQ_IDE0),
};

static struct platform_device anubis_device_ide1 = {
	.name		= "pata_platform",
	.id		= 1,
	.num_resources	= ARRAY_SIZE(anubis_ide1_resource),
	.resource	= anubis_ide1_resource,
	.dev	= {
		.platform_data = &anubis_ide_platdata,
		.coherent_dma_mask = ~0,
	},
};

/* Asix AX88796 10/100 ethernet controller */

static struct ax_plat_data anubis_asix_platdata = {
	.flags		= AXFLG_MAC_FROMDEV,
	.wordlength	= 2,
	.dcr_val	= 0x48,
	.rcr_val	= 0x40,
};

static struct resource anubis_asix_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_CS5, 0x20 * 0x20),
	[1] = DEFINE_RES_IRQ(ANUBIS_IRQ_ASIX),
};

static struct platform_device anubis_device_asix = {
	.name		= "ax88796",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(anubis_asix_resource),
	.resource	= anubis_asix_resource,
	.dev		= {
		.platform_data = &anubis_asix_platdata,
	}
};

/* SM501 */

static struct resource anubis_sm501_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_CS2, SZ_8M),
	[1] = DEFINE_RES_MEM(S3C2410_CS2 + SZ_64M - SZ_2M, SZ_2M),
	[2] = DEFINE_RES_IRQ(IRQ_EINT0),
};

static struct sm501_initdata anubis_sm501_initdata = {
	.gpio_high	= {
		.set	= 0x3F000000,		/* 24bit panel */
		.mask	= 0x0,
	},
	.misc_timing	= {
		.set	= 0x010100,		/* SDRAM timing */
		.mask	= 0x1F1F00,
	},
	.misc_control	= {
		.set	= SM501_MISC_PNL_24BIT,
		.mask	= 0,
	},

	.devices	= SM501_USE_GPIO,

	/* set the SDRAM and bus clocks */
	.mclk		= 72 * MHZ,
	.m1xclk		= 144 * MHZ,
};

static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = {
	[0] = {
		.bus_num	= 1,
		.pin_scl	= 44,
		.pin_sda	= 45,
	},
	[1] = {
		.bus_num	= 2,
		.pin_scl	= 40,
		.pin_sda	= 41,
	},
};

static struct sm501_platdata anubis_sm501_platdata = {
	.init		= &anubis_sm501_initdata,
	.gpio_base	= -1,
	.gpio_i2c	= anubis_sm501_gpio_i2c,
	.gpio_i2c_nr	= ARRAY_SIZE(anubis_sm501_gpio_i2c),
};

static struct platform_device anubis_device_sm501 = {
	.name		= "sm501",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(anubis_sm501_resource),
	.resource	= anubis_sm501_resource,
	.dev		= {
		.platform_data = &anubis_sm501_platdata,
	},
};

/* Standard Anubis devices */

static struct platform_device *anubis_devices[] __initdata = {
	&s3c2410_device_dclk,
	&s3c_device_ohci,
	&s3c_device_wdt,
	&s3c_device_adc,
	&s3c_device_i2c0,
 	&s3c_device_rtc,
	&s3c_device_nand,
	&anubis_device_ide0,
	&anubis_device_ide1,
	&anubis_device_asix,
	&anubis_device_sm501,
};

/* I2C devices. */

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

/* Audio setup */
static struct s3c24xx_audio_simtec_pdata __initdata anubis_audio = {
	.have_mic	= 1,
	.have_lout	= 1,
	.output_cdclk	= 1,
	.use_mpllin	= 1,
	.amp_gpio	= S3C2410_GPB(2),
	.amp_gain[0]	= S3C2410_GPD(10),
	.amp_gain[1]	= S3C2410_GPD(11),
};

static void __init anubis_map_io(void)
{
	s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
	s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);

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

	if ((__raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK) >= 4) {
		printk(KERN_INFO "ANUBIS-B detected (revision %d)\n",
		       __raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK);
		anubis_nand_sets[0].partitions = anubis_default_nand_part_large;
		anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large);
	} else {
		/* ensure that the GPIO is setup */
		gpio_request_one(S3C2410_GPA(0), GPIOF_OUT_INIT_HIGH, NULL);
		gpio_free(S3C2410_GPA(0));
	}
}

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

static void __init anubis_init(void)
{
	s3c_i2c0_set_platdata(NULL);
	s3c_nand_set_platdata(&anubis_nand_info);
	simtec_audio_add(NULL, false, &anubis_audio);

	platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices));

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

MACHINE_START(ANUBIS, "Simtec-Anubis")
	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2440,
	.map_io		= anubis_map_io,
	.init_machine	= anubis_init,
	.init_irq	= s3c2440_init_irq,
	.init_time	= anubis_init_time,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2008 Openmoko, Inc.
// Copyright 2008 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//	http://armlinux.simtec.co.uk/
// Copyright 2009 Kwangwoo Lee
//	Kwangwoo Lee <kwangwoo.lee@gmail.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/i2c.h>
#include <linux/fb.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/dm9000.h>

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

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

#include "map.h"

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

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

#include "devs.h"
#include "cpu.h"
#include "irqs.h"
#include "regs-gpio.h"
#include "gpio-samsung.h"

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

/* DM9000 */
#define ANW6410_PA_DM9000	(0x18000000)

/* A hardware buffer to control external devices is mapped at 0x30000000.
 * It can not be read. So current status must be kept in anw6410_extdev_status.
 */
#define ANW6410_VA_EXTDEV	S3C_ADDR(0x02000000)
#define ANW6410_PA_EXTDEV	(0x30000000)

#define ANW6410_EN_DM9000	(1<<11)
#define ANW6410_EN_LCD		(1<<14)

static __u32 anw6410_extdev_status;

static struct s3c2410_uartcfg anw6410_uartcfgs[] __initdata = {
	[0] = {
		.hwport	     = 0,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x03,
		.ufcon	     = 0x51,
	},
	[1] = {
		.hwport	     = 1,
		.flags	     = 0,
		.ucon	     = 0x3c5,
		.ulcon	     = 0x03,
		.ufcon	     = 0x51,
	},
};

/* framebuffer and LCD setup. */
static void __init anw6410_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);
}

/* GPF1 = LCD panel power
 * GPF4 = LCD backlight control
 */
static void anw6410_lcd_power_set(struct plat_lcd_data *pd,
				   unsigned int power)
{
	if (power) {
		anw6410_extdev_status |= (ANW6410_EN_LCD << 16);
		__raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);

		gpio_direction_output(S3C64XX_GPF(1), 1);
		gpio_direction_output(S3C64XX_GPF(4), 1);
	} else {
		anw6410_extdev_status &= ~(ANW6410_EN_LCD << 16);
		__raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);

		gpio_direction_output(S3C64XX_GPF(1), 0);
		gpio_direction_output(S3C64XX_GPF(4), 0);
	}
}

static struct plat_lcd_data anw6410_lcd_power_data = {
	.set_power	= anw6410_lcd_power_set,
};

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

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

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

/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
static struct s3c_fb_platdata anw6410_lcd_pdata __initdata = {
	.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
	.vtiming	= &anw6410_lcd_timing,
	.win[0]		= &anw6410_fb_win0,
	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
};

/* DM9000AEP 10/100 ethernet controller */
static void __init anw6410_dm9000_enable(void)
{
	anw6410_extdev_status |= (ANW6410_EN_DM9000 << 16);
	__raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
}

static struct resource anw6410_dm9000_resource[] = {
	[0] = DEFINE_RES_MEM(ANW6410_PA_DM9000, 4),
	[1] = DEFINE_RES_MEM(ANW6410_PA_DM9000 + 4, 501),
	[2] = DEFINE_RES_NAMED(IRQ_EINT(15), 1, NULL, IORESOURCE_IRQ \
					| IRQF_TRIGGER_HIGH),
};

static struct dm9000_plat_data anw6410_dm9000_pdata = {
	.flags	  = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
	/* dev_addr can be set to provide hwaddr. */
};

static struct platform_device anw6410_device_eth = {
	.name	= "dm9000",
	.id	= -1,
	.num_resources	= ARRAY_SIZE(anw6410_dm9000_resource),
	.resource	= anw6410_dm9000_resource,
	.dev	= {
		.platform_data  = &anw6410_dm9000_pdata,
	},
};

static struct map_desc anw6410_iodesc[] __initdata = {
	{
		.virtual	= (unsigned long)ANW6410_VA_EXTDEV,
		.pfn		= __phys_to_pfn(ANW6410_PA_EXTDEV),
		.length		= SZ_64K,
		.type		= MT_DEVICE,
	},
};

static struct platform_device *anw6410_devices[] __initdata = {
	&s3c_device_fb,
	&anw6410_lcd_powerdev,
	&anw6410_device_eth,
};

static void __init anw6410_map_io(void)
{
	s3c64xx_init_io(anw6410_iodesc, ARRAY_SIZE(anw6410_iodesc));
	s3c64xx_set_xtal_freq(12000000);
	s3c24xx_init_uarts(anw6410_uartcfgs, ARRAY_SIZE(anw6410_uartcfgs));
	s3c64xx_set_timer_source(S3C64XX_PWM3, S3C64XX_PWM4);

	anw6410_lcd_mode_set();
}

static void __init anw6410_machine_init(void)
{
	s3c_fb_set_platdata(&anw6410_lcd_pdata);

	gpio_request(S3C64XX_GPF(1), "panel power");
	gpio_request(S3C64XX_GPF(4), "LCD backlight");

	anw6410_dm9000_enable();

	platform_add_devices(anw6410_devices, ARRAY_SIZE(anw6410_devices));
}

MACHINE_START(ANW6410, "A&W6410")
	/* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
	.atag_offset	= 0x100,
	.nr_irqs	= S3C64XX_NR_IRQS,
	.init_irq	= s3c6410_init_irq,
	.map_io		= anw6410_map_io,
	.init_machine	= anw6410_machine_init,
	.init_time	= s3c64xx_timer_init,
MACHINE_END

repo_name: angery/linux


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2008 Ramax Lo <ramaxlo@gmail.com>
//      Based on mach-anubis.c by Ben Dooks <ben@simtec.co.uk>
//      and modifications by SBZ <sbz@spgui.org> and
//      Weibing <http://weibing.blogbus.com>
//
// For product information, visit http://www.arm.com/

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

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.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 <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 "devs.h"
#include "cpu.h"
#include <linux/platform_data/mmc-s3cmci.h>

#include "s3c24xx.h"

static struct map_desc at2440evb_iodesc[] __initdata = {
	/* Nothing here */
};

#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 at2440evb_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,
	},
};

/* NAND Flash on AT2440EVB board */

static struct mtd_partition __initdata at2440evb_default_nand_part[] = {
	[0] = {
		.name	= "Boot Agent",
		.size	= SZ_256K,
		.offset	= 0,
	},
	[1] = {
		.name	= "Kernel",
		.size	= SZ_2M,
		.offset	= SZ_256K,
	},
	[2] = {
		.name	= "Root",
		.offset	= SZ_256K + SZ_2M,
		.size	= MTDPART_SIZ_FULL,
	},
};

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

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

/* DM9000AEP 10/100 ethernet controller */

static struct resource at2440evb_dm9k_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_CS3, 4),
	[1] = DEFINE_RES_MEM(S3C2410_CS3 + 4, 4),
	[2] = DEFINE_RES_NAMED(IRQ_EINT7, 1, NULL, IORESOURCE_IRQ \
					| IORESOURCE_IRQ_HIGHEDGE),
};

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

static struct platform_device at2440evb_device_eth = {
	.name		= "dm9000",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(at2440evb_dm9k_resource),
	.resource	= at2440evb_dm9k_resource,
	.dev		= {
		.platform_data	= &at2440evb_dm9k_pdata,
	},
};

static struct s3c24xx_mci_pdata at2440evb_mci_pdata __initdata = {
	.set_power	= s3c24xx_mci_def_set_power,
};

static struct gpiod_lookup_table at2440evb_mci_gpio_table = {
	.dev_id = "s3c2410-sdi",
	.table = {
		/* Card detect S3C2410_GPG(10) */
		GPIO_LOOKUP("GPIOG", 10, "cd", 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),
		{ },
	},
};

/* 7" LCD panel */

static struct s3c2410fb_display at2440evb_lcd_cfg __initdata = {

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

	.type		= S3C2410_LCDCON1_TFT,

	.width		= 800,
	.height		= 480,

	.pixclock	= 33333, /* HCLK 60 MHz, divisor 2 */
	.xres		= 800,
	.yres		= 480,
	.bpp		= 16,
	.left_margin	= 88,
	.right_margin	= 40,
	.hsync_len	= 128,
	.upper_margin	= 32,
	.lower_margin	= 11,
	.vsync_len	= 2,
};

static struct s3c2410fb_mach_info at2440evb_fb_info __initdata = {
	.displays	= &at2440evb_lcd_cfg,
	.num_displays	= 1,
	.default_display = 0,
};

static struct platform_device *at2440evb_devices[] __initdata = {
	&s3c_device_ohci,
	&s3c_device_wdt,
	&s3c_device_adc,
	&s3c_device_i2c0,
	&s3c_device_rtc,
	&s3c_device_nand,
	&s3c_device_sdi,
	&s3c_device_lcd,
	&at2440evb_device_eth,
};

static void __init at2440evb_map_io(void)
{
	s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc));
	s3c24xx_init_uarts(at2440evb_uartcfgs, ARRAY_SIZE(at2440evb_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
}

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

static void __init at2440evb_init(void)
{
	s3c24xx_fb_set_platdata(&at2440evb_fb_info);
	gpiod_add_lookup_table(&at2440evb_mci_gpio_table);
	s3c24xx_mci_set_platdata(&at2440evb_mci_pdata);
	s3c_nand_set_platdata(&at2440evb_nand_info);
	s3c_i2c0_set_platdata(NULL);

	platform_add_devices(at2440evb_devices, ARRAY_SIZE(at2440evb_devices));
}

MACHINE_START(AT2440EVB, "AT2440EVB")
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2440,
	.map_io		= at2440evb_map_io,
	.init_machine	= at2440evb_init,
	.init_irq	= s3c2440_init_irq,
	.init_time	= at2440evb_init_time,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2003-2008 Simtec Electronics
//   Ben Dooks <ben@simtec.co.uk>
//
// http://www.simtec.co.uk/products/EB2410ITX/

#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/syscore_ops.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/platform_device.h>
#include <linux/dm9000.h>
#include <linux/ata_platform.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/serial_8250.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 <linux/platform_data/asoc-s3c24xx_simtec.h>
#include <linux/platform_data/hwmon-s3c.h>
#include <linux/platform_data/i2c-s3c2410.h>
#include <linux/platform_data/mtd-nand-s3c2410.h>

#include <net/ax88796.h>

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

#include <linux/platform_data/fb-s3c2410.h>
#include "regs-gpio.h"
#include "gpio-samsung.h"

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

#include "bast.h"
#include "s3c24xx.h"
#include "simtec.h"

#define COPYRIGHT ", Copyright 2004-2008 Simtec Electronics"

/* macros for virtual address mods for the io space entries */
#define VA_C5(item) ((unsigned long)(item) + BAST_VAM_CS5)
#define VA_C4(item) ((unsigned long)(item) + BAST_VAM_CS4)
#define VA_C3(item) ((unsigned long)(item) + BAST_VAM_CS3)
#define VA_C2(item) ((unsigned long)(item) + BAST_VAM_CS2)

/* macros to modify the physical addresses for io space */

#define PA_CS2(item) (__phys_to_pfn((item) + S3C2410_CS2))
#define PA_CS3(item) (__phys_to_pfn((item) + S3C2410_CS3))
#define PA_CS4(item) (__phys_to_pfn((item) + S3C2410_CS4))
#define PA_CS5(item) (__phys_to_pfn((item) + S3C2410_CS5))

static struct map_desc bast_iodesc[] __initdata = {
  /* ISA IO areas */
  {
	  .virtual	= (u32)S3C24XX_VA_ISA_BYTE,
	  .pfn		= PA_CS2(BAST_PA_ISAIO),
	  .length	= SZ_16M,
	  .type		= MT_DEVICE,
  },
  /* bast CPLD control registers, and external interrupt controls */
  {
	  .virtual	= (u32)BAST_VA_CTRL1,
	  .pfn		= __phys_to_pfn(BAST_PA_CTRL1),
	  .length	= SZ_1M,
	  .type		= MT_DEVICE,
  }, {
	  .virtual	= (u32)BAST_VA_CTRL2,
	  .pfn		= __phys_to_pfn(BAST_PA_CTRL2),
	  .length	= SZ_1M,
	  .type		= MT_DEVICE,
  }, {
	  .virtual	= (u32)BAST_VA_CTRL3,
	  .pfn		= __phys_to_pfn(BAST_PA_CTRL3),
	  .length	= SZ_1M,
	  .type		= MT_DEVICE,
  }, {
	  .virtual	= (u32)BAST_VA_CTRL4,
	  .pfn		= __phys_to_pfn(BAST_PA_CTRL4),
	  .length	= SZ_1M,
	  .type		= MT_DEVICE,
  },
  /* PC104 IRQ mux */
  {
	  .virtual	= (u32)BAST_VA_PC104_IRQREQ,
	  .pfn		= __phys_to_pfn(BAST_PA_PC104_IRQREQ),
	  .length	= SZ_1M,
	  .type		= MT_DEVICE,
  }, {
	  .virtual	= (u32)BAST_VA_PC104_IRQRAW,
	  .pfn		= __phys_to_pfn(BAST_PA_PC104_IRQRAW),
	  .length	= SZ_1M,
	  .type		= MT_DEVICE,
  }, {
	  .virtual	= (u32)BAST_VA_PC104_IRQMASK,
	  .pfn		= __phys_to_pfn(BAST_PA_PC104_IRQMASK),
	  .length	= SZ_1M,
	  .type		= MT_DEVICE,
  },

  /* peripheral space... one for each of fast/slow/byte/16bit */
  /* note, ide is only decoded in word space, even though some registers
   * are only 8bit */

  /* slow, byte */
  { VA_C2(BAST_VA_ISAIO),   PA_CS2(BAST_PA_ISAIO),    SZ_16M, MT_DEVICE },
  { VA_C2(BAST_VA_ISAMEM),  PA_CS2(BAST_PA_ISAMEM),   SZ_16M, MT_DEVICE },
  { VA_C2(BAST_VA_SUPERIO), PA_CS2(BAST_PA_SUPERIO),  SZ_1M,  MT_DEVICE },

  /* slow, word */
  { VA_C3(BAST_VA_ISAIO),   PA_CS3(BAST_PA_ISAIO),    SZ_16M, MT_DEVICE },
  { VA_C3(BAST_VA_ISAMEM),  PA_CS3(BAST_PA_ISAMEM),   SZ_16M, MT_DEVICE },
  { VA_C3(BAST_VA_SUPERIO), PA_CS3(BAST_PA_SUPERIO),  SZ_1M,  MT_DEVICE },

  /* fast, byte */
  { VA_C4(BAST_VA_ISAIO),   PA_CS4(BAST_PA_ISAIO),    SZ_16M, MT_DEVICE },
  { VA_C4(BAST_VA_ISAMEM),  PA_CS4(BAST_PA_ISAMEM),   SZ_16M, MT_DEVICE },
  { VA_C4(BAST_VA_SUPERIO), PA_CS4(BAST_PA_SUPERIO),  SZ_1M,  MT_DEVICE },

  /* fast, word */
  { VA_C5(BAST_VA_ISAIO),   PA_CS5(BAST_PA_ISAIO),    SZ_16M, MT_DEVICE },
  { VA_C5(BAST_VA_ISAMEM),  PA_CS5(BAST_PA_ISAMEM),   SZ_16M, MT_DEVICE },
  { VA_C5(BAST_VA_SUPERIO), PA_CS5(BAST_PA_SUPERIO),  SZ_1M,  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 bast_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,
	}
};

/* NAND Flash on BAST board */

#ifdef CONFIG_PM
static int bast_pm_suspend(void)
{
	/* ensure that an nRESET is not generated on resume. */
	gpio_direction_output(S3C2410_GPA(21), 1);
	return 0;
}

static void bast_pm_resume(void)
{
	s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
}

#else
#define bast_pm_suspend NULL
#define bast_pm_resume NULL
#endif

static struct syscore_ops bast_pm_syscore_ops = {
	.suspend	= bast_pm_suspend,
	.resume		= bast_pm_resume,
};

static int smartmedia_map[] = { 0 };
static int chip0_map[] = { 1 };
static int chip1_map[] = { 2 };
static int chip2_map[] = { 3 };

static struct mtd_partition __initdata bast_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	= "user",
		.offset	= SZ_4M,
		.size	= MTDPART_SIZ_FULL,
	}
};

/* the bast has 4 selectable slots for nand-flash, the three
 * on-board chip areas, as well as the external SmartMedia
 * slot.
 *
 * Note, there is no current hot-plug support for the SmartMedia
 * socket.
*/

static struct s3c2410_nand_set __initdata bast_nand_sets[] = {
	[0] = {
		.name		= "SmartMedia",
		.nr_chips	= 1,
		.nr_map		= smartmedia_map,
		.options        = NAND_SCAN_SILENT_NODEV,
		.nr_partitions	= ARRAY_SIZE(bast_default_nand_part),
		.partitions	= bast_default_nand_part,
	},
	[1] = {
		.name		= "chip0",
		.nr_chips	= 1,
		.nr_map		= chip0_map,
		.nr_partitions	= ARRAY_SIZE(bast_default_nand_part),
		.partitions	= bast_default_nand_part,
	},
	[2] = {
		.name		= "chip1",
		.nr_chips	= 1,
		.nr_map		= chip1_map,
		.options        = NAND_SCAN_SILENT_NODEV,
		.nr_partitions	= ARRAY_SIZE(bast_default_nand_part),
		.partitions	= bast_default_nand_part,
	},
	[3] = {
		.name		= "chip2",
		.nr_chips	= 1,
		.nr_map		= chip2_map,
		.options        = NAND_SCAN_SILENT_NODEV,
		.nr_partitions	= ARRAY_SIZE(bast_default_nand_part),
		.partitions	= bast_default_nand_part,
	}
};

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

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

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

	tmp = __raw_readb(BAST_VA_CTRL2);
	tmp &= BAST_CPLD_CTLR2_IDERST;
	tmp |= slot;
	tmp |= BAST_CPLD_CTRL2_WNAND;

	pr_debug("bast_nand: ctrl2 now %02x\n", tmp);

	__raw_writeb(tmp, BAST_VA_CTRL2);
}

static struct s3c2410_platform_nand __initdata bast_nand_info = {
	.tacls		= 30,
	.twrph0		= 60,
	.twrph1		= 60,
	.nr_sets	= ARRAY_SIZE(bast_nand_sets),
	.sets		= bast_nand_sets,
	.select_chip	= bast_nand_select,
	.engine_type	= NAND_ECC_ENGINE_TYPE_SOFT,
};

/* DM9000 */

static struct resource bast_dm9k_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_DM9000, 4),
	[1] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_DM9000 + 0x40, 0x40),
	[2] = DEFINE_RES_NAMED(BAST_IRQ_DM9000 , 1, NULL, IORESOURCE_IRQ \
					| IORESOURCE_IRQ_HIGHLEVEL),
};

/* for the moment we limit ourselves to 16bit IO until some
 * better IO routines can be written and tested
*/

static struct dm9000_plat_data bast_dm9k_platdata = {
	.flags		= DM9000_PLATF_16BITONLY,
};

static struct platform_device bast_device_dm9k = {
	.name		= "dm9000",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(bast_dm9k_resource),
	.resource	= bast_dm9k_resource,
	.dev		= {
		.platform_data = &bast_dm9k_platdata,
	}
};

/* serial devices */

#define SERIAL_BASE  (S3C2410_CS2 + BAST_PA_SUPERIO)
#define SERIAL_FLAGS (UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SHARE_IRQ)
#define SERIAL_CLK   (1843200)

static struct plat_serial8250_port bast_sio_data[] = {
	[0] = {
		.mapbase	= SERIAL_BASE + 0x2f8,
		.irq		= BAST_IRQ_PCSERIAL1,
		.flags		= SERIAL_FLAGS,
		.iotype		= UPIO_MEM,
		.regshift	= 0,
		.uartclk	= SERIAL_CLK,
	},
	[1] = {
		.mapbase	= SERIAL_BASE + 0x3f8,
		.irq		= BAST_IRQ_PCSERIAL2,
		.flags		= SERIAL_FLAGS,
		.iotype		= UPIO_MEM,
		.regshift	= 0,
		.uartclk	= SERIAL_CLK,
	},
	{ }
};

static struct platform_device bast_sio = {
	.name			= "serial8250",
	.id			= PLAT8250_DEV_PLATFORM,
	.dev			= {
		.platform_data	= &bast_sio_data,
	},
};

/* we have devices on the bus which cannot work much over the
 * standard 100KHz i2c bus frequency
*/

static struct s3c2410_platform_i2c __initdata bast_i2c_info = {
	.flags		= 0,
	.slave_addr	= 0x10,
	.frequency	= 100*1000,
};

/* Asix AX88796 10/100 ethernet controller */

static struct ax_plat_data bast_asix_platdata = {
	.flags		= AXFLG_MAC_FROMDEV,
	.wordlength	= 2,
	.dcr_val	= 0x48,
	.rcr_val	= 0x40,
};

static struct resource bast_asix_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_ASIXNET, 0x18 * 0x20),
	[1] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20), 1),
	[2] = DEFINE_RES_IRQ(BAST_IRQ_ASIX),
};

static struct platform_device bast_device_asix = {
	.name		= "ax88796",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(bast_asix_resource),
	.resource	= bast_asix_resource,
	.dev		= {
		.platform_data = &bast_asix_platdata
	}
};

/* Asix AX88796 10/100 ethernet controller parallel port */

static struct resource bast_asixpp_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20), \
					0x30 * 0x20),
};

static struct platform_device bast_device_axpp = {
	.name		= "ax88796-pp",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(bast_asixpp_resource),
	.resource	= bast_asixpp_resource,
};

/* LCD/VGA controller */

static struct s3c2410fb_display __initdata bast_lcd_info[] = {
	{
		.type		= S3C2410_LCDCON1_TFT,
		.width		= 640,
		.height		= 480,

		.pixclock	= 33333,
		.xres		= 640,
		.yres		= 480,
		.bpp		= 4,
		.left_margin	= 40,
		.right_margin	= 20,
		.hsync_len	= 88,
		.upper_margin	= 30,
		.lower_margin	= 32,
		.vsync_len	= 3,

		.lcdcon5	= 0x00014b02,
	},
	{
		.type		= S3C2410_LCDCON1_TFT,
		.width		= 640,
		.height		= 480,

		.pixclock	= 33333,
		.xres		= 640,
		.yres		= 480,
		.bpp		= 8,
		.left_margin	= 40,
		.right_margin	= 20,
		.hsync_len	= 88,
		.upper_margin	= 30,
		.lower_margin	= 32,
		.vsync_len	= 3,

		.lcdcon5	= 0x00014b02,
	},
	{
		.type		= S3C2410_LCDCON1_TFT,
		.width		= 640,
		.height		= 480,

		.pixclock	= 33333,
		.xres		= 640,
		.yres		= 480,
		.bpp		= 16,
		.left_margin	= 40,
		.right_margin	= 20,
		.hsync_len	= 88,
		.upper_margin	= 30,
		.lower_margin	= 32,
		.vsync_len	= 3,

		.lcdcon5	= 0x00014b02,
	},
};

/* LCD/VGA controller */

static struct s3c2410fb_mach_info __initdata bast_fb_info = {

	.displays = bast_lcd_info,
	.num_displays = ARRAY_SIZE(bast_lcd_info),
	.default_display = 1,
};

/* I2C devices fitted. */

static struct i2c_board_info bast_i2c_devs[] __initdata = {
	{
		I2C_BOARD_INFO("tlv320aic23", 0x1a),
	}, {
		I2C_BOARD_INFO("simtec-pmu", 0x6b),
	}, {
		I2C_BOARD_INFO("ch7013", 0x75),
	},
};

static struct s3c_hwmon_pdata bast_hwmon_info = {
	/* LCD contrast (0-6.6V) */
	.in[0] = &(struct s3c_hwmon_chcfg) {
		.name		= "lcd-contrast",
		.mult		= 3300,
		.div		= 512,
	},
	/* LED current feedback */
	.in[1] = &(struct s3c_hwmon_chcfg) {
		.name		= "led-feedback",
		.mult		= 3300,
		.div		= 1024,
	},
	/* LCD feedback (0-6.6V) */
	.in[2] = &(struct s3c_hwmon_chcfg) {
		.name		= "lcd-feedback",
		.mult		= 3300,
		.div		= 512,
	},
	/* Vcore (1.8-2.0V), Vref 3.3V  */
	.in[3] = &(struct s3c_hwmon_chcfg) {
		.name		= "vcore",
		.mult		= 3300,
		.div		= 1024,
	},
};

/* Standard BAST devices */
// cat /sys/devices/platform/s3c24xx-adc/s3c-hwmon/in_0

static struct platform_device *bast_devices[] __initdata = {
	&s3c2410_device_dclk,
	&s3c_device_ohci,
	&s3c_device_lcd,
	&s3c_device_wdt,
	&s3c_device_i2c0,
 	&s3c_device_rtc,
	&s3c_device_nand,
	&s3c_device_adc,
	&s3c_device_hwmon,
	&bast_device_dm9k,
	&bast_device_asix,
	&bast_device_axpp,
	&bast_sio,
};

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

static struct s3c24xx_audio_simtec_pdata __initdata bast_audio = {
	.have_mic	= 1,
	.have_lout	= 1,
};

static void __init bast_map_io(void)
{
	s3c_hwmon_set_platdata(&bast_hwmon_info);

	s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
	s3c24xx_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
}

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

static void __init bast_init(void)
{
	register_syscore_ops(&bast_pm_syscore_ops);

	s3c_i2c0_set_platdata(&bast_i2c_info);
	s3c_nand_set_platdata(&bast_nand_info);
	s3c24xx_fb_set_platdata(&bast_fb_info);
	platform_add_devices(bast_devices, ARRAY_SIZE(bast_devices));

	i2c_register_board_info(0, bast_i2c_devs,
				ARRAY_SIZE(bast_i2c_devs));

	usb_simtec_init();
	nor_simtec_init();
	simtec_audio_add(NULL, true, &bast_audio);

	WARN_ON(gpio_request(S3C2410_GPA(21), "bast nreset"));

	s3c_cpufreq_setboard(&bast_cpufreq);
}

MACHINE_START(BAST, "Simtec-BAST")
	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2410,
	.map_io		= bast_map_io,
	.init_irq	= s3c2410_init_irq,
	.init_machine	= bast_init,
	.init_time	= bast_init_time,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0
//
// Speyside modules for Cragganmore - board data probing
//
// Copyright 2011 Wolfson Microelectronics plc
//	Mark Brown <broonie@opensource.wolfsonmicro.com>

#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/gpio/machine.h>

#include <linux/mfd/wm831x/irq.h>
#include <linux/mfd/wm831x/gpio.h>
#include <linux/mfd/wm8994/pdata.h>
#include <linux/mfd/arizona/pdata.h>

#include <linux/regulator/machine.h>

#include <sound/wm0010.h>
#include <sound/wm2200.h>
#include <sound/wm5100.h>
#include <sound/wm8996.h>
#include <sound/wm8962.h>
#include <sound/wm9081.h>

#include <linux/platform_data/spi-s3c64xx.h>

#include "cpu.h"
#include "irqs.h"

#include "crag6410.h"

static struct wm0010_pdata wm0010_pdata = {
	.gpio_reset = S3C64XX_GPN(6),
	.reset_active_high = 1, /* Active high for Glenfarclas Rev 2 */
};

static struct spi_board_info wm1253_devs[] = {
	[0] = {
		.modalias	= "wm0010",
		.max_speed_hz	= 26 * 1000 * 1000,
		.bus_num	= 0,
		.chip_select	= 0,
		.mode		= SPI_MODE_0,
		.irq		= S3C_EINT(4),
		.platform_data = &wm0010_pdata,
	},
};

static struct spi_board_info balblair_devs[] = {
	[0] = {
		.modalias	= "wm0010",
		.max_speed_hz	= 26 * 1000 * 1000,
		.bus_num	= 0,
		.chip_select	= 0,
		.mode		= SPI_MODE_0,
		.irq		= S3C_EINT(4),
		.platform_data = &wm0010_pdata,
	},
};

static struct wm5100_pdata wm5100_pdata = {
	.ldo_ena = S3C64XX_GPN(7),
	.irq_flags = IRQF_TRIGGER_HIGH,
	.gpio_base = CODEC_GPIO_BASE,

	.in_mode = {
		WM5100_IN_DIFF,
		WM5100_IN_DIFF,
		WM5100_IN_DIFF,
		WM5100_IN_SE,
	},

	.hp_pol = CODEC_GPIO_BASE + 3,
	.jack_modes = {
		{ WM5100_MICDET_MICBIAS3, 0, 0 },
		{ WM5100_MICDET_MICBIAS2, 1, 1 },
	},

	.gpio_defaults = {
		0,
		0,
		0,
		0,
		0x2, /* IRQ: CMOS output */
		0x3, /* CLKOUT: CMOS output */
	},
};

static struct wm8996_retune_mobile_config wm8996_retune[] = {
	{
		.name = "Sub LPF",
		.rate = 48000,
		.regs = {
			0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
			0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
			0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
		},
	},
	{
		.name = "Sub HPF",
		.rate = 48000,
		.regs = {
			0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
			0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
			0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
		},
	},
};

static struct wm8996_pdata wm8996_pdata __initdata = {
	.ldo_ena = S3C64XX_GPN(7),
	.gpio_base = CODEC_GPIO_BASE,
	.micdet_def = 1,
	.inl_mode = WM8996_DIFFERRENTIAL_1,
	.inr_mode = WM8996_DIFFERRENTIAL_1,

	.irq_flags = IRQF_TRIGGER_RISING,

	.gpio_default = {
		0x8001, /* GPIO1 == ADCLRCLK1 */
		0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
		0x0141, /* GPIO3 == HP_SEL */
		0x0002, /* GPIO4 == IRQ */
		0x020e, /* GPIO5 == CLKOUT */
	},

	.retune_mobile_cfgs = wm8996_retune,
	.num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
};

static struct wm8962_pdata wm8962_pdata __initdata = {
	.gpio_init = {
		0,
		WM8962_GPIO_FN_OPCLK,
		WM8962_GPIO_FN_DMICCLK,
		0,
		0x8000 | WM8962_GPIO_FN_DMICDAT,
		WM8962_GPIO_FN_IRQ,    /* Open drain mode */
	},
	.in4_dc_measure = true,
};

static struct wm9081_pdata wm9081_pdata __initdata = {
	.irq_high = false,
	.irq_cmos = false,
};

static const struct i2c_board_info wm1254_devs[] = {
	{ I2C_BOARD_INFO("wm8996", 0x1a),
	  .platform_data = &wm8996_pdata,
	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
	},
	{ I2C_BOARD_INFO("wm9081", 0x6c),
	  .platform_data = &wm9081_pdata, },
};

static const struct i2c_board_info wm1255_devs[] = {
	{ I2C_BOARD_INFO("wm5100", 0x1a),
	  .platform_data = &wm5100_pdata,
	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
	},
	{ I2C_BOARD_INFO("wm9081", 0x6c),
	  .platform_data = &wm9081_pdata, },
};

static const struct i2c_board_info wm1259_devs[] = {
	{ I2C_BOARD_INFO("wm8962", 0x1a),
	  .platform_data = &wm8962_pdata,
	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
	},
};

static struct regulator_init_data wm8994_ldo1 = {
	.supply_regulator = "WALLVDD",
};

static struct regulator_init_data wm8994_ldo2 = {
	.supply_regulator = "WALLVDD",
};

static struct wm8994_pdata wm8994_pdata = {
	.gpio_base = CODEC_GPIO_BASE,
	.micb2_delay = 150,
	.gpio_defaults = {
		0x3,          /* IRQ out, active high, CMOS */
	},
	.ldo = {
		 { .init_data = &wm8994_ldo1, },
		 { .init_data = &wm8994_ldo2, },
	},
};

static const struct i2c_board_info wm1277_devs[] = {
	{ I2C_BOARD_INFO("wm8958", 0x1a),  /* WM8958 is the superset */
	  .platform_data = &wm8994_pdata,
	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
	  .dev_name = "wm8958",
	},
};

static struct gpiod_lookup_table wm8994_gpiod_table = {
	.dev_id = "i2c-wm8958", /* I2C device name */
	.table = {
		GPIO_LOOKUP("GPION", 6,
			    "wlf,ldo1ena", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("GPION", 4,
			    "wlf,ldo2ena", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct arizona_pdata wm5102_reva_pdata = {
	.gpio_base = CODEC_GPIO_BASE,
	.irq_flags = IRQF_TRIGGER_HIGH,
	.micd_pol_gpio = CODEC_GPIO_BASE + 4,
	.micd_rate = 6,
	.gpio_defaults = {
		[2] = 0x10000, /* AIF3TXLRCLK */
		[3] = 0x4,     /* OPCLK */
	},
};

static struct spi_board_info wm5102_reva_spi_devs[] = {
	[0] = {
		.modalias	= "wm5102",
		.max_speed_hz	= 10 * 1000 * 1000,
		.bus_num	= 0,
		.chip_select	= 1,
		.mode		= SPI_MODE_0,
		.irq		= GLENFARCLAS_PMIC_IRQ_BASE +
				  WM831X_IRQ_GPIO_2,
		.platform_data = &wm5102_reva_pdata,
	},
};

static struct gpiod_lookup_table wm5102_reva_gpiod_table = {
	.dev_id = "spi0.1", /* SPI device name */
	.table = {
		GPIO_LOOKUP("GPION", 7,
			    "wlf,ldoena", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct arizona_pdata wm5102_pdata = {
	.gpio_base = CODEC_GPIO_BASE,
	.irq_flags = IRQF_TRIGGER_HIGH,
	.micd_pol_gpio = CODEC_GPIO_BASE + 2,
	.gpio_defaults = {
		[2] = 0x10000, /* AIF3TXLRCLK */
		[3] = 0x4,     /* OPCLK */
	},
};

static struct spi_board_info wm5102_spi_devs[] = {
	[0] = {
		.modalias	= "wm5102",
		.max_speed_hz	= 10 * 1000 * 1000,
		.bus_num	= 0,
		.chip_select	= 1,
		.mode		= SPI_MODE_0,
		.irq		= GLENFARCLAS_PMIC_IRQ_BASE +
				  WM831X_IRQ_GPIO_2,
		.platform_data = &wm5102_pdata,
	},
};

static struct gpiod_lookup_table wm5102_gpiod_table = {
	.dev_id = "spi0.1", /* SPI device name */
	.table = {
		GPIO_LOOKUP("GPION", 7,
			    "wlf,ldo1ena", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct spi_board_info wm5110_spi_devs[] = {
	[0] = {
		.modalias	= "wm5110",
		.max_speed_hz	= 10 * 1000 * 1000,
		.bus_num	= 0,
		.chip_select	= 1,
		.mode		= SPI_MODE_0,
		.irq		= GLENFARCLAS_PMIC_IRQ_BASE +
				  WM831X_IRQ_GPIO_2,
		.platform_data = &wm5102_reva_pdata,
	},
};

static const struct i2c_board_info wm6230_i2c_devs[] = {
	{ I2C_BOARD_INFO("wm9081", 0x6c),
	  .platform_data = &wm9081_pdata, },
};

static struct wm2200_pdata wm2200_pdata = {
	.ldo_ena = S3C64XX_GPN(7),
	.gpio_defaults = {
		[2] = 0x0005,  /* GPIO3 24.576MHz output clock */
	},
};

static const struct i2c_board_info wm2200_i2c[] = {
	{ I2C_BOARD_INFO("wm2200", 0x3a),
	  .platform_data = &wm2200_pdata, },
};

static const struct {
	u8 id;
	u8 rev;
	const char *name;
	const struct i2c_board_info *i2c_devs;
	int num_i2c_devs;
	const struct spi_board_info *spi_devs;
	int num_spi_devs;

	struct gpiod_lookup_table *gpiod_table;
} gf_mods[] = {
	{ .id = 0x01, .rev = 0xff, .name = "1250-EV1 Springbank" },
	{ .id = 0x02, .rev = 0xff, .name = "1251-EV1 Jura" },
	{ .id = 0x03, .rev = 0xff, .name = "1252-EV1 Glenlivet" },
	{ .id = 0x06, .rev = 0xff, .name = "WM8997-6721-CS96-EV1 Lapraoig" },
	{ .id = 0x07, .rev = 0xff, .name = "WM5110-6271 Deanston",
	  .spi_devs = wm5110_spi_devs,
	  .num_spi_devs = ARRAY_SIZE(wm5110_spi_devs) },
	{ .id = 0x08, .rev = 0xff, .name = "WM8903-6102 Tamdhu" },
	{ .id = 0x09, .rev = 0xff, .name = "WM1811A-6305 Adelphi" },
	{ .id = 0x0a, .rev = 0xff, .name = "WM8996-6272 Blackadder" },
	{ .id = 0x0b, .rev = 0xff, .name = "WM8994-6235 Benromach" },
	{ .id = 0x11, .rev = 0xff, .name = "6249-EV2 Glenfarclas", },
	{ .id = 0x14, .rev = 0xff, .name = "6271-EV1 Lochnagar" },
	{ .id = 0x15, .rev = 0xff, .name = "6320-EV1 Bells",
	  .i2c_devs = wm6230_i2c_devs,
	  .num_i2c_devs = ARRAY_SIZE(wm6230_i2c_devs) },
	{ .id = 0x21, .rev = 0xff, .name = "1275-EV1 Mortlach" },
	{ .id = 0x25, .rev = 0xff, .name = "1274-EV1 Glencadam" },
	{ .id = 0x31, .rev = 0xff, .name = "1253-EV1 Tomatin",
	  .spi_devs = wm1253_devs, .num_spi_devs = ARRAY_SIZE(wm1253_devs) },
	{ .id = 0x32, .rev = 0xff, .name = "XXXX-EV1 Caol Illa" },
	{ .id = 0x33, .rev = 0xff, .name = "XXXX-EV1 Oban" },
	{ .id = 0x34, .rev = 0xff, .name = "WM0010-6320-CS42 Balblair",
	  .spi_devs = balblair_devs,
	  .num_spi_devs = ARRAY_SIZE(balblair_devs) },
	{ .id = 0x39, .rev = 0xff, .name = "1254-EV1 Dallas Dhu",
	  .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) },
	{ .id = 0x3a, .rev = 0xff, .name = "1259-EV1 Tobermory",
	  .i2c_devs = wm1259_devs, .num_i2c_devs = ARRAY_SIZE(wm1259_devs) },
	{ .id = 0x3b, .rev = 0xff, .name = "1255-EV1 Kilchoman",
	  .i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
	{ .id = 0x3c, .rev = 0xff, .name = "1273-EV1 Longmorn" },
	{ .id = 0x3d, .rev = 0xff, .name = "1277-EV1 Littlemill",
	  .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs),
	  .gpiod_table = &wm8994_gpiod_table },
	{ .id = 0x3e, .rev = 0, .name = "WM5102-6271-EV1-CS127 Amrut",
	  .spi_devs = wm5102_reva_spi_devs,
	  .num_spi_devs = ARRAY_SIZE(wm5102_reva_spi_devs),
	  .gpiod_table = &wm5102_reva_gpiod_table },
	{ .id = 0x3e, .rev = -1, .name = "WM5102-6271-EV1-CS127 Amrut",
	  .spi_devs = wm5102_spi_devs,
	  .num_spi_devs = ARRAY_SIZE(wm5102_spi_devs),
	  .gpiod_table = &wm5102_gpiod_table },
	{ .id = 0x3f, .rev = -1, .name = "WM2200-6271-CS90-M-REV1",
	  .i2c_devs = wm2200_i2c, .num_i2c_devs = ARRAY_SIZE(wm2200_i2c) },
};

static int wlf_gf_module_probe(struct i2c_client *i2c)
{
	int ret, i, j, id, rev;

	ret = i2c_smbus_read_byte_data(i2c, 0);
	if (ret < 0) {
		dev_err(&i2c->dev, "Failed to read ID: %d\n", ret);
		return ret;
	}

	id = (ret & 0xfe) >> 2;
	rev = ret & 0x3;
	for (i = 0; i < ARRAY_SIZE(gf_mods); i++)
		if (id == gf_mods[i].id && (gf_mods[i].rev == 0xff ||
					    rev == gf_mods[i].rev))
			break;

	gpiod_add_lookup_table(&wm5102_reva_gpiod_table);
	gpiod_add_lookup_table(&wm5102_gpiod_table);
	gpiod_add_lookup_table(&wm8994_gpiod_table);

	if (i < ARRAY_SIZE(gf_mods)) {
		dev_info(&i2c->dev, "%s revision %d\n",
			 gf_mods[i].name, rev + 1);

		for (j = 0; j < gf_mods[i].num_i2c_devs; j++) {
			if (IS_ERR(i2c_new_client_device(i2c->adapter,
							 &(gf_mods[i].i2c_devs[j]))))
				dev_err(&i2c->dev, "Failed to register\n");
		}

		spi_register_board_info(gf_mods[i].spi_devs,
					gf_mods[i].num_spi_devs);

		if (gf_mods[i].gpiod_table)
			gpiod_add_lookup_table(gf_mods[i].gpiod_table);
	} else {
		dev_warn(&i2c->dev, "Unknown module ID 0x%x revision %d\n",
			 id, rev + 1);
	}

	return 0;
}

static const struct i2c_device_id wlf_gf_module_id[] = {
	{ "wlf-gf-module", 0 },
	{ }
};

static struct i2c_driver wlf_gf_module_driver = {
	.driver = {
		.name = "wlf-gf-module"
	},
	.probe_new = wlf_gf_module_probe,
	.id_table = wlf_gf_module_id,
};

static int __init wlf_gf_module_register(void)
{
	if (!soc_is_s3c64xx())
		return 0;

	return i2c_add_driver(&wlf_gf_module_driver);
}
device_initcall(wlf_gf_module_register);


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2011 Wolfson Microelectronics plc
//	Mark Brown <broonie@opensource.wolfsonmicro.com>
//
// Copyright 2011 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>

#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/io.h>
#include <linux/init.h>
#include <linux/input-event-codes.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/leds.h>
#include <linux/delay.h>
#include <linux/mmc/host.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/dm9000.h>
#include <linux/gpio_keys.h>
#include <linux/gpio/driver.h>
#include <linux/spi/spi.h>

#include <linux/platform_data/pca953x.h>
#include <linux/platform_data/s3c-hsotg.h>

#include <video/platform_lcd.h>

#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/pdata.h>
#include <linux/mfd/wm831x/irq.h>
#include <linux/mfd/wm831x/gpio.h>

#include <sound/wm1250-ev1.h>

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

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

#include "fb.h"
#include "sdhci.h"
#include "gpio-cfg.h"
#include <linux/platform_data/spi-s3c64xx.h>

#include "keypad.h"
#include "devs.h"
#include "cpu.h"
#include <linux/soc/samsung/s3c-adc.h>
#include <linux/platform_data/i2c-s3c2410.h>
#include "pm.h"

#include "s3c64xx.h"
#include "crag6410.h"
#include "regs-gpio-memport-s3c64xx.h"
#include "regs-modem-s3c64xx.h"
#include "regs-sys-s3c64xx.h"

/* serial port setup */

#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 crag6410_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,
	},
};

static struct pwm_lookup crag6410_pwm_lookup[] = {
	PWM_LOOKUP("samsung-pwm", 0, "pwm-backlight", NULL, 100000,
		   PWM_POLARITY_NORMAL),
};

static struct platform_pwm_backlight_data crag6410_backlight_data = {
	.max_brightness	= 1000,
	.dft_brightness	= 600,
};

static struct platform_device crag6410_backlight_device = {
	.name		= "pwm-backlight",
	.id		= -1,
	.dev		= {
		.parent	= &samsung_device_pwm.dev,
		.platform_data = &crag6410_backlight_data,
	},
};

static void crag6410_lcd_power_set(struct plat_lcd_data *pd, unsigned int power)
{
	pr_debug("%s: setting power %d\n", __func__, power);

	if (power) {
		gpio_set_value(S3C64XX_GPB(0), 1);
		msleep(1);
		s3c_gpio_cfgpin(S3C64XX_GPF(14), S3C_GPIO_SFN(2));
	} else {
		gpio_direction_output(S3C64XX_GPF(14), 0);
		gpio_set_value(S3C64XX_GPB(0), 0);
	}
}

static struct platform_device crag6410_lcd_powerdev = {
	.name			= "platform-lcd",
	.id			= -1,
	.dev.parent		= &s3c_device_fb.dev,
	.dev.platform_data	= &(struct plat_lcd_data) {
		.set_power	= crag6410_lcd_power_set,
	},
};

/* 640x480 URT */
static struct s3c_fb_pd_win crag6410_fb_win0 = {
	.max_bpp	= 32,
	.default_bpp	= 16,
	.xres		= 640,
	.yres		= 480,
	.virtual_y	= 480 * 2,
	.virtual_x	= 640,
};

static struct fb_videomode crag6410_lcd_timing = {
	.left_margin	= 150,
	.right_margin	= 80,
	.upper_margin	= 40,
	.lower_margin	= 5,
	.hsync_len	= 40,
	.vsync_len	= 5,
	.xres		= 640,
	.yres		= 480,
};

/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
static struct s3c_fb_platdata crag6410_lcd_pdata = {
	.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
	.vtiming	= &crag6410_lcd_timing,
	.win[0]		= &crag6410_fb_win0,
	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
};

/* 2x6 keypad */

static uint32_t crag6410_keymap[] = {
	/* KEY(row, col, keycode) */
	KEY(0, 0, KEY_VOLUMEUP),
	KEY(0, 1, KEY_HOME),
	KEY(0, 2, KEY_VOLUMEDOWN),
	KEY(0, 3, KEY_HELP),
	KEY(0, 4, KEY_MENU),
	KEY(0, 5, KEY_MEDIA),
	KEY(1, 0, 232),
	KEY(1, 1, KEY_DOWN),
	KEY(1, 2, KEY_LEFT),
	KEY(1, 3, KEY_UP),
	KEY(1, 4, KEY_RIGHT),
	KEY(1, 5, KEY_CAMERA),
};

static struct matrix_keymap_data crag6410_keymap_data = {
	.keymap		= crag6410_keymap,
	.keymap_size	= ARRAY_SIZE(crag6410_keymap),
};

static struct samsung_keypad_platdata crag6410_keypad_data = {
	.keymap_data	= &crag6410_keymap_data,
	.rows		= 2,
	.cols		= 6,
};

static struct gpio_keys_button crag6410_gpio_keys[] = {
	[0] = {
		.code	= KEY_SUSPEND,
		.gpio	= S3C64XX_GPL(10),	/* EINT 18 */
		.type	= EV_KEY,
		.wakeup	= 1,
		.active_low = 1,
	},
	[1] = {
		.code	= SW_FRONT_PROXIMITY,
		.gpio	= S3C64XX_GPN(11),	/* EINT 11 */
		.type	= EV_SW,
	},
};

static struct gpio_keys_platform_data crag6410_gpio_keydata = {
	.buttons	= crag6410_gpio_keys,
	.nbuttons	= ARRAY_SIZE(crag6410_gpio_keys),
};

static struct platform_device crag6410_gpio_keydev = {
	.name		= "gpio-keys",
	.id		= 0,
	.dev.platform_data = &crag6410_gpio_keydata,
};

static struct resource crag6410_dm9k_resource[] = {
	[0] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN5, 2),
	[1] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN5 + (1 << 8), 2),
	[2] = DEFINE_RES_NAMED(S3C_EINT(17), 1, NULL, IORESOURCE_IRQ \
				| IORESOURCE_IRQ_HIGHLEVEL),
};

static struct dm9000_plat_data mini6410_dm9k_pdata = {
	.flags	= DM9000_PLATF_16BITONLY,
};

static struct platform_device crag6410_dm9k_device = {
	.name		= "dm9000",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(crag6410_dm9k_resource),
	.resource	= crag6410_dm9k_resource,
	.dev.platform_data = &mini6410_dm9k_pdata,
};

static struct resource crag6410_mmgpio_resource[] = {
	[0] = DEFINE_RES_MEM_NAMED(S3C64XX_PA_XM0CSN4, 1, "dat"),
};

static struct platform_device crag6410_mmgpio = {
	.name		= "basic-mmio-gpio",
	.id		= -1,
	.resource	= crag6410_mmgpio_resource,
	.num_resources	= ARRAY_SIZE(crag6410_mmgpio_resource),
	.dev.platform_data = &(struct bgpio_pdata) {
		.base	= MMGPIO_GPIO_BASE,
	},
};

static struct platform_device speyside_device = {
	.name		= "speyside",
	.id		= -1,
};

static struct platform_device lowland_device = {
	.name		= "lowland",
	.id		= -1,
};

static struct platform_device tobermory_device = {
	.name		= "tobermory",
	.id		= -1,
};

static struct platform_device littlemill_device = {
	.name		= "littlemill",
	.id		= -1,
};

static struct platform_device bells_wm2200_device = {
	.name		= "bells",
	.id		= 0,
};

static struct platform_device bells_wm5102_device = {
	.name		= "bells",
	.id		= 1,
};

static struct platform_device bells_wm5110_device = {
	.name		= "bells",
	.id		= 2,
};

static struct regulator_consumer_supply wallvdd_consumers[] = {
	REGULATOR_SUPPLY("SPKVDD", "1-001a"),
	REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
	REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
	REGULATOR_SUPPLY("SPKVDDL", "1-001a"),
	REGULATOR_SUPPLY("SPKVDDR", "1-001a"),

	REGULATOR_SUPPLY("SPKVDDL", "spi0.1"),
	REGULATOR_SUPPLY("SPKVDDR", "spi0.1"),

	REGULATOR_SUPPLY("DC1VDD", "0-0034"),
	REGULATOR_SUPPLY("DC2VDD", "0-0034"),
	REGULATOR_SUPPLY("DC3VDD", "0-0034"),
	REGULATOR_SUPPLY("LDO1VDD", "0-0034"),
	REGULATOR_SUPPLY("LDO2VDD", "0-0034"),
	REGULATOR_SUPPLY("LDO4VDD", "0-0034"),
	REGULATOR_SUPPLY("LDO5VDD", "0-0034"),
	REGULATOR_SUPPLY("LDO6VDD", "0-0034"),
	REGULATOR_SUPPLY("LDO7VDD", "0-0034"),
	REGULATOR_SUPPLY("LDO8VDD", "0-0034"),
	REGULATOR_SUPPLY("LDO9VDD", "0-0034"),
	REGULATOR_SUPPLY("LDO10VDD", "0-0034"),
	REGULATOR_SUPPLY("LDO11VDD", "0-0034"),

	REGULATOR_SUPPLY("DC1VDD", "1-0034"),
	REGULATOR_SUPPLY("DC2VDD", "1-0034"),
	REGULATOR_SUPPLY("DC3VDD", "1-0034"),
	REGULATOR_SUPPLY("LDO1VDD", "1-0034"),
	REGULATOR_SUPPLY("LDO2VDD", "1-0034"),
	REGULATOR_SUPPLY("LDO4VDD", "1-0034"),
	REGULATOR_SUPPLY("LDO5VDD", "1-0034"),
	REGULATOR_SUPPLY("LDO6VDD", "1-0034"),
	REGULATOR_SUPPLY("LDO7VDD", "1-0034"),
	REGULATOR_SUPPLY("LDO8VDD", "1-0034"),
	REGULATOR_SUPPLY("LDO9VDD", "1-0034"),
	REGULATOR_SUPPLY("LDO10VDD", "1-0034"),
	REGULATOR_SUPPLY("LDO11VDD", "1-0034"),
};

static struct regulator_init_data wallvdd_data = {
	.constraints = {
		.always_on = 1,
	},
	.num_consumer_supplies = ARRAY_SIZE(wallvdd_consumers),
	.consumer_supplies = wallvdd_consumers,
};

static struct fixed_voltage_config wallvdd_pdata = {
	.supply_name = "WALLVDD",
	.microvolts = 5000000,
	.init_data = &wallvdd_data,
};

static struct platform_device wallvdd_device = {
	.name		= "reg-fixed-voltage",
	.id		= -1,
	.dev = {
		.platform_data = &wallvdd_pdata,
	},
};

static struct platform_device *crag6410_devices[] __initdata = {
	&s3c_device_hsmmc0,
	&s3c_device_hsmmc2,
	&s3c_device_i2c0,
	&s3c_device_i2c1,
	&s3c_device_fb,
	&s3c_device_ohci,
	&s3c_device_usb_hsotg,
	&samsung_device_pwm,
	&s3c64xx_device_iis0,
	&s3c64xx_device_iis1,
	&samsung_device_keypad,
	&crag6410_gpio_keydev,
	&crag6410_dm9k_device,
	&s3c64xx_device_spi0,
	&crag6410_mmgpio,
	&crag6410_lcd_powerdev,
	&crag6410_backlight_device,
	&speyside_device,
	&tobermory_device,
	&littlemill_device,
	&lowland_device,
	&bells_wm2200_device,
	&bells_wm5102_device,
	&bells_wm5110_device,
	&wallvdd_device,
};

static struct pca953x_platform_data crag6410_pca_data = {
	.gpio_base	= PCA935X_GPIO_BASE,
	.irq_base	= -1,
};

/* VDDARM is controlled by DVS1 connected to GPK(0) */
static struct wm831x_buckv_pdata vddarm_pdata = {
	.dvs_control_src = 1,
};

static struct regulator_consumer_supply vddarm_consumers[] = {
	REGULATOR_SUPPLY("vddarm", NULL),
};

static struct regulator_init_data vddarm = {
	.constraints = {
		.name = "VDDARM",
		.min_uV = 1000000,
		.max_uV = 1300000,
		.always_on = 1,
		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
	},
	.num_consumer_supplies = ARRAY_SIZE(vddarm_consumers),
	.consumer_supplies = vddarm_consumers,
	.supply_regulator = "WALLVDD",
	.driver_data = &vddarm_pdata,
};

static struct regulator_consumer_supply vddint_consumers[] = {
	REGULATOR_SUPPLY("vddint", NULL),
};

static struct regulator_init_data vddint = {
	.constraints = {
		.name = "VDDINT",
		.min_uV = 1000000,
		.max_uV = 1200000,
		.always_on = 1,
		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
	},
	.num_consumer_supplies = ARRAY_SIZE(vddint_consumers),
	.consumer_supplies = vddint_consumers,
	.supply_regulator = "WALLVDD",
};

static struct regulator_init_data vddmem = {
	.constraints = {
		.name = "VDDMEM",
		.always_on = 1,
	},
};

static struct regulator_init_data vddsys = {
	.constraints = {
		.name = "VDDSYS,VDDEXT,VDDPCM,VDDSS",
		.always_on = 1,
	},
};

static struct regulator_consumer_supply vddmmc_consumers[] = {
	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.1"),
	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
};

static struct regulator_init_data vddmmc = {
	.constraints = {
		.name = "VDDMMC,UH",
		.always_on = 1,
	},
	.num_consumer_supplies = ARRAY_SIZE(vddmmc_consumers),
	.consumer_supplies = vddmmc_consumers,
	.supply_regulator = "WALLVDD",
};

static struct regulator_init_data vddotgi = {
	.constraints = {
		.name = "VDDOTGi",
		.always_on = 1,
	},
	.supply_regulator = "WALLVDD",
};

static struct regulator_init_data vddotg = {
	.constraints = {
		.name = "VDDOTG",
		.always_on = 1,
	},
	.supply_regulator = "WALLVDD",
};

static struct regulator_init_data vddhi = {
	.constraints = {
		.name = "VDDHI",
		.always_on = 1,
	},
	.supply_regulator = "WALLVDD",
};

static struct regulator_init_data vddadc = {
	.constraints = {
		.name = "VDDADC,VDDDAC",
		.always_on = 1,
	},
	.supply_regulator = "WALLVDD",
};

static struct regulator_init_data vddmem0 = {
	.constraints = {
		.name = "VDDMEM0",
		.always_on = 1,
	},
	.supply_regulator = "WALLVDD",
};

static struct regulator_init_data vddpll = {
	.constraints = {
		.name = "VDDPLL",
		.always_on = 1,
	},
	.supply_regulator = "WALLVDD",
};

static struct regulator_init_data vddlcd = {
	.constraints = {
		.name = "VDDLCD",
		.always_on = 1,
	},
	.supply_regulator = "WALLVDD",
};

static struct regulator_init_data vddalive = {
	.constraints = {
		.name = "VDDALIVE",
		.always_on = 1,
	},
	.supply_regulator = "WALLVDD",
};

static struct wm831x_backup_pdata banff_backup_pdata = {
	.charger_enable = 1,
	.vlim = 2500,  /* mV */
	.ilim = 200,   /* uA */
};

static struct wm831x_status_pdata banff_red_led = {
	.name = "banff:red:",
	.default_src = WM831X_STATUS_MANUAL,
};

static struct wm831x_status_pdata banff_green_led = {
	.name = "banff:green:",
	.default_src = WM831X_STATUS_MANUAL,
};

static struct wm831x_touch_pdata touch_pdata = {
	.data_irq = S3C_EINT(26),
	.pd_irq = S3C_EINT(27),
};

static struct wm831x_pdata crag_pmic_pdata = {
	.wm831x_num = 1,
	.irq_base = BANFF_PMIC_IRQ_BASE,
	.gpio_base = BANFF_PMIC_GPIO_BASE,
	.soft_shutdown = true,

	.backup = &banff_backup_pdata,

	.gpio_defaults = {
		/* GPIO5: DVS1_REQ - CMOS, DBVDD, active high */
		[4] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA | 0x8,
		/* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
		[10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6,
		/* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
		[11] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x7,
	},

	.dcdc = {
		&vddarm,  /* DCDC1 */
		&vddint,  /* DCDC2 */
		&vddmem,  /* DCDC3 */
	},

	.ldo = {
		&vddsys,   /* LDO1 */
		&vddmmc,   /* LDO2 */
		NULL,      /* LDO3 */
		&vddotgi,  /* LDO4 */
		&vddotg,   /* LDO5 */
		&vddhi,    /* LDO6 */
		&vddadc,   /* LDO7 */
		&vddmem0,  /* LDO8 */
		&vddpll,   /* LDO9 */
		&vddlcd,   /* LDO10 */
		&vddalive, /* LDO11 */
	},

	.status = {
		&banff_green_led,
		&banff_red_led,
	},

	.touch = &touch_pdata,
};

/*
 * VDDARM is eventually ending up as a regulator hanging on the MFD cell device
 * "wm831x-buckv.1" spawn from drivers/mfd/wm831x-core.c.
 *
 * From the note on the platform data we can see that this is clearly DVS1
 * and assigned as dcdc1 resource to the MFD core which sets .id of the cell
 * spawning the DVS1 platform device to 1, then the cell platform device
 * name is calculated from 10*instance + id resulting in the device name
 * "wm831x-buckv.11"
 */
static struct gpiod_lookup_table crag_pmic_gpiod_table = {
	.dev_id = "wm831x-buckv.11",
	.table = {
		GPIO_LOOKUP("GPIOK", 0, "dvs", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct i2c_board_info i2c_devs0[] = {
	{ I2C_BOARD_INFO("24c08", 0x50), },
	{ I2C_BOARD_INFO("tca6408", 0x20),
	  .platform_data = &crag6410_pca_data,
	},
	{ I2C_BOARD_INFO("wm8312", 0x34),
	  .platform_data = &crag_pmic_pdata,
	  .irq = S3C_EINT(23),
	},
};

static struct s3c2410_platform_i2c i2c0_pdata = {
	.frequency = 400000,
};

static struct regulator_consumer_supply pvdd_1v2_consumers[] = {
	REGULATOR_SUPPLY("DCVDD", "spi0.0"),
	REGULATOR_SUPPLY("AVDD", "spi0.0"),
	REGULATOR_SUPPLY("AVDD", "spi0.1"),
};

static struct regulator_init_data pvdd_1v2 = {
	.constraints = {
		.name = "PVDD_1V2",
		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
	},

	.consumer_supplies = pvdd_1v2_consumers,
	.num_consumer_supplies = ARRAY_SIZE(pvdd_1v2_consumers),
};

static struct regulator_consumer_supply pvdd_1v8_consumers[] = {
	REGULATOR_SUPPLY("LDOVDD", "1-001a"),
	REGULATOR_SUPPLY("PLLVDD", "1-001a"),
	REGULATOR_SUPPLY("DBVDD", "1-001a"),
	REGULATOR_SUPPLY("DBVDD1", "1-001a"),
	REGULATOR_SUPPLY("DBVDD2", "1-001a"),
	REGULATOR_SUPPLY("DBVDD3", "1-001a"),
	REGULATOR_SUPPLY("CPVDD", "1-001a"),
	REGULATOR_SUPPLY("AVDD2", "1-001a"),
	REGULATOR_SUPPLY("DCVDD", "1-001a"),
	REGULATOR_SUPPLY("AVDD", "1-001a"),
	REGULATOR_SUPPLY("DBVDD", "spi0.0"),

	REGULATOR_SUPPLY("DBVDD", "1-003a"),
	REGULATOR_SUPPLY("LDOVDD", "1-003a"),
	REGULATOR_SUPPLY("CPVDD", "1-003a"),
	REGULATOR_SUPPLY("AVDD", "1-003a"),
	REGULATOR_SUPPLY("DBVDD1", "spi0.1"),
	REGULATOR_SUPPLY("DBVDD2", "spi0.1"),
	REGULATOR_SUPPLY("DBVDD3", "spi0.1"),
	REGULATOR_SUPPLY("LDOVDD", "spi0.1"),
	REGULATOR_SUPPLY("CPVDD", "spi0.1"),
};

static struct regulator_init_data pvdd_1v8 = {
	.constraints = {
		.name = "PVDD_1V8",
		.always_on = 1,
	},

	.consumer_supplies = pvdd_1v8_consumers,
	.num_consumer_supplies = ARRAY_SIZE(pvdd_1v8_consumers),
};

static struct regulator_consumer_supply pvdd_3v3_consumers[] = {
	REGULATOR_SUPPLY("MICVDD", "1-001a"),
	REGULATOR_SUPPLY("AVDD1", "1-001a"),
};

static struct regulator_init_data pvdd_3v3 = {
	.constraints = {
		.name = "PVDD_3V3",
		.always_on = 1,
	},

	.consumer_supplies = pvdd_3v3_consumers,
	.num_consumer_supplies = ARRAY_SIZE(pvdd_3v3_consumers),
};

static struct wm831x_pdata glenfarclas_pmic_pdata = {
	.wm831x_num = 2,
	.irq_base = GLENFARCLAS_PMIC_IRQ_BASE,
	.gpio_base = GLENFARCLAS_PMIC_GPIO_BASE,
	.soft_shutdown = true,

	.gpio_defaults = {
		/* GPIO1-3: IRQ inputs, rising edge triggered, CMOS */
		[0] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
		[1] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
		[2] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
	},

	.dcdc = {
		&pvdd_1v2,  /* DCDC1 */
		&pvdd_1v8,  /* DCDC2 */
		&pvdd_3v3,  /* DCDC3 */
	},

	.disable_touch = true,
};

static struct wm1250_ev1_pdata wm1250_ev1_pdata = {
	.gpios = {
		[WM1250_EV1_GPIO_CLK_ENA] = S3C64XX_GPN(12),
		[WM1250_EV1_GPIO_CLK_SEL0] = S3C64XX_GPL(12),
		[WM1250_EV1_GPIO_CLK_SEL1] = S3C64XX_GPL(13),
		[WM1250_EV1_GPIO_OSR] = S3C64XX_GPL(14),
		[WM1250_EV1_GPIO_MASTER] = S3C64XX_GPL(8),
	},
};

static struct i2c_board_info i2c_devs1[] = {
	{ I2C_BOARD_INFO("wm8311", 0x34),
	  .irq = S3C_EINT(0),
	  .platform_data = &glenfarclas_pmic_pdata },

	{ I2C_BOARD_INFO("wlf-gf-module", 0x20) },
	{ I2C_BOARD_INFO("wlf-gf-module", 0x22) },
	{ I2C_BOARD_INFO("wlf-gf-module", 0x24) },
	{ I2C_BOARD_INFO("wlf-gf-module", 0x25) },
	{ I2C_BOARD_INFO("wlf-gf-module", 0x26) },

	{ I2C_BOARD_INFO("wm1250-ev1", 0x27),
	  .platform_data = &wm1250_ev1_pdata },
};

static struct s3c2410_platform_i2c i2c1_pdata = {
	.frequency = 400000,
	.bus_num = 1,
};

static void __init crag6410_map_io(void)
{
	s3c64xx_init_io(NULL, 0);
	s3c64xx_set_xtal_freq(12000000);
	s3c24xx_init_uarts(crag6410_uartcfgs, ARRAY_SIZE(crag6410_uartcfgs));
	s3c64xx_set_timer_source(S3C64XX_PWM3, S3C64XX_PWM4);

	/* LCD type and Bypass set by bootloader */
}

static struct s3c_sdhci_platdata crag6410_hsmmc2_pdata = {
	.max_width		= 4,
	.cd_type		= S3C_SDHCI_CD_PERMANENT,
	.host_caps		= MMC_CAP_POWER_OFF_CARD,
};

static void crag6410_cfg_sdhci0(struct platform_device *dev, int width)
{
	/* Set all the necessary GPG pins to special-function 2 */
	s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width, S3C_GPIO_SFN(2));

	/* force card-detected for prototype 0 */
	s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_DOWN);
}

static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata = {
	.max_width		= 4,
	.cd_type		= S3C_SDHCI_CD_INTERNAL,
	.cfg_gpio		= crag6410_cfg_sdhci0,
	.host_caps		= MMC_CAP_POWER_OFF_CARD,
};

static const struct gpio_led gpio_leds[] = {
	{
		.name = "d13:green:",
		.gpio = MMGPIO_GPIO_BASE + 0,
		.default_state = LEDS_GPIO_DEFSTATE_ON,
	},
	{
		.name = "d14:green:",
		.gpio = MMGPIO_GPIO_BASE + 1,
		.default_state = LEDS_GPIO_DEFSTATE_ON,
	},
	{
		.name = "d15:green:",
		.gpio = MMGPIO_GPIO_BASE + 2,
		.default_state = LEDS_GPIO_DEFSTATE_ON,
	},
	{
		.name = "d16:green:",
		.gpio = MMGPIO_GPIO_BASE + 3,
		.default_state = LEDS_GPIO_DEFSTATE_ON,
	},
	{
		.name = "d17:green:",
		.gpio = MMGPIO_GPIO_BASE + 4,
		.default_state = LEDS_GPIO_DEFSTATE_ON,
	},
	{
		.name = "d18:green:",
		.gpio = MMGPIO_GPIO_BASE + 5,
		.default_state = LEDS_GPIO_DEFSTATE_ON,
	},
	{
		.name = "d19:green:",
		.gpio = MMGPIO_GPIO_BASE + 6,
		.default_state = LEDS_GPIO_DEFSTATE_ON,
	},
	{
		.name = "d20:green:",
		.gpio = MMGPIO_GPIO_BASE + 7,
		.default_state = LEDS_GPIO_DEFSTATE_ON,
	},
};

static const struct gpio_led_platform_data gpio_leds_pdata = {
	.leds = gpio_leds,
	.num_leds = ARRAY_SIZE(gpio_leds),
};

static struct dwc2_hsotg_plat crag6410_hsotg_pdata;

static struct gpiod_lookup_table crag_spi0_gpiod_table = {
	.dev_id = "s3c6410-spi.0",
	.table = {
		GPIO_LOOKUP_IDX("GPIOC", 3, "cs", 0, GPIO_ACTIVE_LOW),
		GPIO_LOOKUP_IDX("GPION", 5, "cs", 1, GPIO_ACTIVE_LOW),
		{ },
	},
};

static void __init crag6410_machine_init(void)
{
	/* Open drain IRQs need pullups */
	s3c_gpio_setpull(S3C64XX_GPM(0), S3C_GPIO_PULL_UP);
	s3c_gpio_setpull(S3C64XX_GPN(0), S3C_GPIO_PULL_UP);

	gpio_request(S3C64XX_GPB(0), "LCD power");
	gpio_direction_output(S3C64XX_GPB(0), 0);

	gpio_request(S3C64XX_GPF(14), "LCD PWM");
	gpio_direction_output(S3C64XX_GPF(14), 0);  /* turn off */

	gpio_request(S3C64XX_GPB(1), "SD power");
	gpio_direction_output(S3C64XX_GPB(1), 0);

	gpio_request(S3C64XX_GPF(10), "nRESETSEL");
	gpio_direction_output(S3C64XX_GPF(10), 1);

	s3c_sdhci0_set_platdata(&crag6410_hsmmc0_pdata);
	s3c_sdhci2_set_platdata(&crag6410_hsmmc2_pdata);

	s3c_i2c0_set_platdata(&i2c0_pdata);
	s3c_i2c1_set_platdata(&i2c1_pdata);
	s3c_fb_set_platdata(&crag6410_lcd_pdata);
	dwc2_hsotg_set_platdata(&crag6410_hsotg_pdata);

	gpiod_add_lookup_table(&crag_pmic_gpiod_table);
	i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));

	samsung_keypad_set_platdata(&crag6410_keypad_data);

	gpiod_add_lookup_table(&crag_spi0_gpiod_table);
	s3c64xx_spi0_set_platdata(0, 2);

	pwm_add_table(crag6410_pwm_lookup, ARRAY_SIZE(crag6410_pwm_lookup));
	platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));

	gpio_led_register_device(-1, &gpio_leds_pdata);

	regulator_has_full_constraints();

	s3c64xx_pm_init();
}

MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
	/* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
	.atag_offset	= 0x100,
	.nr_irqs	= S3C64XX_NR_IRQS,
	.init_irq	= s3c6410_init_irq,
	.map_io		= crag6410_map_io,
	.init_machine	= crag6410_machine_init,
	.init_time	= s3c64xx_timer_init,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0+
//
// S3C2442 Machine Support for Openmoko GTA02 / FreeRunner.
//
// Copyright (C) 2006-2009 by Openmoko, Inc.
// Authors: Harald Welte <laforge@openmoko.org>
//          Andy Green <andy@openmoko.org>
//          Werner Almesberger <werner@openmoko.org>
// All rights reserved.

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/gpio/machine.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/input.h>
#include <linux/io.h>
#include <linux/i2c.h>

#include <linux/mmc/host.h>

#include <linux/mfd/pcf50633/adc.h>
#include <linux/mfd/pcf50633/backlight.h>
#include <linux/mfd/pcf50633/core.h>
#include <linux/mfd/pcf50633/gpio.h>
#include <linux/mfd/pcf50633/mbc.h>
#include <linux/mfd/pcf50633/pmic.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 <linux/mtd/physmap.h>

#include <linux/regulator/machine.h>

#include <linux/spi/spi.h>
#include <linux/spi/s3c24xx.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 <linux/platform_data/i2c-s3c2410.h>
#include <linux/platform_data/mtd-nand-s3c2410.h>
#include <linux/platform_data/touchscreen-s3c2410.h>
#include <linux/platform_data/usb-ohci-s3c2410.h>
#include <linux/platform_data/usb-s3c2410_udc.h>
#include <linux/platform_data/fb-s3c2410.h>

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

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

#include "s3c24xx.h"
#include "gta02.h"

static struct pcf50633 *gta02_pcf;

/*
 * This gets called frequently when we paniced.
 */

static long gta02_panic_blink(int state)
{
	char led;

	led = (state) ? 1 : 0;
	gpio_direction_output(GTA02_GPIO_AUX_LED, led);

	return 0;
}

static struct map_desc gta02_iodesc[] __initdata = {
	{
		.virtual	= 0xe0000000,
		.pfn		= __phys_to_pfn(S3C2410_CS3 + 0x01000000),
		.length		= SZ_1M,
		.type		= MT_DEVICE
	},
};

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

static struct s3c2410_uartcfg gta02_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,
	},
};

#ifdef CONFIG_CHARGER_PCF50633
/*
 * On GTA02 the 1A charger features a 48K resistor to 0V on the ID pin.
 * We use this to recognize that we can pull 1A from the USB socket.
 *
 * These constants are the measured pcf50633 ADC levels with the 1A
 * charger / 48K resistor, and with no pulldown resistor.
 */

#define ADC_NOM_CHG_DETECT_1A 6
#define ADC_NOM_CHG_DETECT_USB 43

#ifdef CONFIG_PCF50633_ADC
static void
gta02_configure_pmu_for_charger(struct pcf50633 *pcf, void *unused, int res)
{
	int  ma;

	/* Interpret charger type */
	if (res < ((ADC_NOM_CHG_DETECT_USB + ADC_NOM_CHG_DETECT_1A) / 2)) {

		/*
		 * Sanity - stop GPO driving out now that we have a 1A charger
		 * GPO controls USB Host power generation on GTA02
		 */
		pcf50633_gpio_set(pcf, PCF50633_GPO, 0);

		ma = 1000;
	} else
		ma = 100;

	pcf50633_mbc_usb_curlim_set(pcf, ma);
}
#endif

static struct delayed_work gta02_charger_work;
static int gta02_usb_vbus_draw;

static void gta02_charger_worker(struct work_struct *work)
{
	if (gta02_usb_vbus_draw) {
		pcf50633_mbc_usb_curlim_set(gta02_pcf, gta02_usb_vbus_draw);
		return;
	}

#ifdef CONFIG_PCF50633_ADC
	pcf50633_adc_async_read(gta02_pcf,
				PCF50633_ADCC1_MUX_ADCIN1,
				PCF50633_ADCC1_AVERAGE_16,
				gta02_configure_pmu_for_charger,
				NULL);
#else
	/*
	 * If the PCF50633 ADC is disabled we fallback to a
	 * 100mA limit for safety.
	 */
	pcf50633_mbc_usb_curlim_set(gta02_pcf, 100);
#endif
}

#define GTA02_CHARGER_CONFIGURE_TIMEOUT ((3000 * HZ) / 1000)

static void gta02_pmu_event_callback(struct pcf50633 *pcf, int irq)
{
	if (irq == PCF50633_IRQ_USBINS) {
		schedule_delayed_work(&gta02_charger_work,
				      GTA02_CHARGER_CONFIGURE_TIMEOUT);

		return;
	}

	if (irq == PCF50633_IRQ_USBREM) {
		cancel_delayed_work_sync(&gta02_charger_work);
		gta02_usb_vbus_draw = 0;
	}
}

static void gta02_udc_vbus_draw(unsigned int ma)
{
	if (!gta02_pcf)
		return;

	gta02_usb_vbus_draw = ma;

	schedule_delayed_work(&gta02_charger_work,
			      GTA02_CHARGER_CONFIGURE_TIMEOUT);
}
#else /* !CONFIG_CHARGER_PCF50633 */
#define gta02_pmu_event_callback	NULL
#define gta02_udc_vbus_draw		NULL
#endif

static char *gta02_batteries[] = {
	"battery",
};

static struct pcf50633_bl_platform_data gta02_backlight_data = {
	.default_brightness = 0x3f,
	.default_brightness_limit = 0,
	.ramp_time = 5,
};

static struct pcf50633_platform_data gta02_pcf_pdata = {
	.resumers = {
		[0] =	PCF50633_INT1_USBINS |
			PCF50633_INT1_USBREM |
			PCF50633_INT1_ALARM,
		[1] =	PCF50633_INT2_ONKEYF,
		[2] =	PCF50633_INT3_ONKEY1S,
		[3] =	PCF50633_INT4_LOWSYS |
			PCF50633_INT4_LOWBAT |
			PCF50633_INT4_HIGHTMP,
	},

	.batteries = gta02_batteries,
	.num_batteries = ARRAY_SIZE(gta02_batteries),

	.charger_reference_current_ma = 1000,

	.backlight_data = &gta02_backlight_data,

	.reg_init_data = {
		[PCF50633_REGULATOR_AUTO] = {
			.constraints = {
				.min_uV = 3300000,
				.max_uV = 3300000,
				.valid_modes_mask = REGULATOR_MODE_NORMAL,
				.always_on = 1,
				.apply_uV = 1,
			},
		},
		[PCF50633_REGULATOR_DOWN1] = {
			.constraints = {
				.min_uV = 1300000,
				.max_uV = 1600000,
				.valid_modes_mask = REGULATOR_MODE_NORMAL,
				.always_on = 1,
				.apply_uV = 1,
			},
		},
		[PCF50633_REGULATOR_DOWN2] = {
			.constraints = {
				.min_uV = 1800000,
				.max_uV = 1800000,
				.valid_modes_mask = REGULATOR_MODE_NORMAL,
				.apply_uV = 1,
				.always_on = 1,
			},
		},
		[PCF50633_REGULATOR_HCLDO] = {
			.constraints = {
				.min_uV = 2000000,
				.max_uV = 3300000,
				.valid_modes_mask = REGULATOR_MODE_NORMAL,
				.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
						REGULATOR_CHANGE_STATUS,
			},
		},
		[PCF50633_REGULATOR_LDO1] = {
			.constraints = {
				.min_uV = 3300000,
				.max_uV = 3300000,
				.valid_modes_mask = REGULATOR_MODE_NORMAL,
				.valid_ops_mask = REGULATOR_CHANGE_STATUS,
				.apply_uV = 1,
			},
		},
		[PCF50633_REGULATOR_LDO2] = {
			.constraints = {
				.min_uV = 3300000,
				.max_uV = 3300000,
				.valid_modes_mask = REGULATOR_MODE_NORMAL,
				.apply_uV = 1,
			},
		},
		[PCF50633_REGULATOR_LDO3] = {
			.constraints = {
				.min_uV = 3000000,
				.max_uV = 3000000,
				.valid_modes_mask = REGULATOR_MODE_NORMAL,
				.apply_uV = 1,
			},
		},
		[PCF50633_REGULATOR_LDO4] = {
			.constraints = {
				.min_uV = 3200000,
				.max_uV = 3200000,
				.valid_modes_mask = REGULATOR_MODE_NORMAL,
				.valid_ops_mask = REGULATOR_CHANGE_STATUS,
				.apply_uV = 1,
			},
		},
		[PCF50633_REGULATOR_LDO5] = {
			.constraints = {
				.min_uV = 3000000,
				.max_uV = 3000000,
				.valid_modes_mask = REGULATOR_MODE_NORMAL,
				.valid_ops_mask = REGULATOR_CHANGE_STATUS,
				.apply_uV = 1,
			},
		},
		[PCF50633_REGULATOR_LDO6] = {
			.constraints = {
				.min_uV = 3000000,
				.max_uV = 3000000,
				.valid_modes_mask = REGULATOR_MODE_NORMAL,
			},
		},
		[PCF50633_REGULATOR_MEMLDO] = {
			.constraints = {
				.min_uV = 1800000,
				.max_uV = 1800000,
				.valid_modes_mask = REGULATOR_MODE_NORMAL,
			},
		},

	},
	.mbc_event_callback = gta02_pmu_event_callback,
};

/* NOR Flash. */

#define GTA02_FLASH_BASE	0x18000000 /* GCS3 */
#define GTA02_FLASH_SIZE	0x200000 /* 2MBytes */

static struct physmap_flash_data gta02_nor_flash_data = {
	.width		= 2,
};

static struct resource gta02_nor_flash_resource =
	DEFINE_RES_MEM(GTA02_FLASH_BASE, GTA02_FLASH_SIZE);

static struct platform_device gta02_nor_flash = {
	.name		= "physmap-flash",
	.id		= 0,
	.dev		= {
		.platform_data	= &gta02_nor_flash_data,
	},
	.resource	= &gta02_nor_flash_resource,
	.num_resources	= 1,
};

static struct platform_device s3c24xx_pwm_device = {
	.name		= "s3c24xx_pwm",
	.num_resources	= 0,
};

static struct platform_device gta02_dfbmcs320_device = {
	.name = "dfbmcs320",
};

static struct i2c_board_info gta02_i2c_devs[] __initdata = {
	{
		I2C_BOARD_INFO("pcf50633", 0x73),
		.irq = GTA02_IRQ_PCF50633,
		.platform_data = &gta02_pcf_pdata,
	},
	{
		I2C_BOARD_INFO("wm8753", 0x1a),
	},
};

static struct s3c2410_nand_set __initdata gta02_nand_sets[] = {
	[0] = {
		/*
		 * This name is also hard-coded in the boot loaders, so
		 * changing it would would require all users to upgrade
		 * their boot loaders, some of which are stored in a NOR
		 * that is considered to be immutable.
		 */
		.name		= "neo1973-nand",
		.nr_chips	= 1,
		.flash_bbt	= 1,
	},
};

/*
 * Choose a set of timings derived from S3C@2442B MCP54
 * data sheet (K5D2G13ACM-D075 MCP Memory).
 */

static struct s3c2410_platform_nand __initdata gta02_nand_info = {
	.tacls		= 0,
	.twrph0		= 25,
	.twrph1		= 15,
	.nr_sets	= ARRAY_SIZE(gta02_nand_sets),
	.sets		= gta02_nand_sets,
	.engine_type	= NAND_ECC_ENGINE_TYPE_SOFT,
};

/* Get PMU to set USB current limit accordingly. */
static struct s3c2410_udc_mach_info gta02_udc_cfg __initdata = {
	.vbus_draw	= gta02_udc_vbus_draw,
};

static struct gpiod_lookup_table gta02_udc_gpio_table = {
	.dev_id = "s3c2410-usbgadget",
	.table = {
		GPIO_LOOKUP("GPIOB", 9, "pullup", GPIO_ACTIVE_HIGH),
		{ },
	},
};

/* USB */
static struct s3c2410_hcd_info gta02_usb_info __initdata = {
	.port[0]	= {
		.flags	= S3C_HCDFLG_USED,
	},
	.port[1]	= {
		.flags	= 0,
	},
};

/* Touchscreen */
static struct s3c2410_ts_mach_info gta02_ts_info = {
	.delay			= 10000,
	.presc			= 0xff, /* slow as we can go */
	.oversampling_shift	= 2,
};

/* Buttons */
static struct gpio_keys_button gta02_buttons[] = {
	{
		.gpio = GTA02_GPIO_AUX_KEY,
		.code = KEY_PHONE,
		.desc = "Aux",
		.type = EV_KEY,
		.debounce_interval = 100,
	},
	{
		.gpio = GTA02_GPIO_HOLD_KEY,
		.code = KEY_PAUSE,
		.desc = "Hold",
		.type = EV_KEY,
		.debounce_interval = 100,
	},
};

static struct gpio_keys_platform_data gta02_buttons_pdata = {
	.buttons = gta02_buttons,
	.nbuttons = ARRAY_SIZE(gta02_buttons),
};

static struct platform_device gta02_buttons_device = {
	.name = "gpio-keys",
	.id = -1,
	.dev = {
		.platform_data = &gta02_buttons_pdata,
	},
};

static struct gpiod_lookup_table gta02_audio_gpio_table = {
	.dev_id = "neo1973-audio",
	.table = {
		GPIO_LOOKUP("GPIOJ", 2, "amp-shut", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("GPIOJ", 1, "hp", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct platform_device gta02_audio = {
	.name = "neo1973-audio",
	.id = -1,
};

static struct gpiod_lookup_table gta02_mmc_gpio_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),
		{ },
	},
};

static void __init gta02_map_io(void)
{
	s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc));
	s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs));
	s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
}

/* These are the guys that don't need to be children of PMU. */

static struct platform_device *gta02_devices[] __initdata = {
	&s3c_device_ohci,
	&s3c_device_wdt,
	&s3c_device_sdi,
	&s3c_device_usbgadget,
	&s3c_device_nand,
	&gta02_nor_flash,
	&s3c24xx_pwm_device,
	&s3c_device_iis,
	&s3c_device_i2c0,
	&gta02_dfbmcs320_device,
	&gta02_buttons_device,
	&s3c_device_adc,
	&s3c_device_ts,
	&gta02_audio,
};

static void gta02_poweroff(void)
{
	pcf50633_reg_set_bit_mask(gta02_pcf, PCF50633_REG_OOCSHDWN, 1, 1);
}

static void __init gta02_machine_init(void)
{
	/* Set the panic callback to turn AUX LED on or off. */
	panic_blink = gta02_panic_blink;

	s3c_pm_init();

#ifdef CONFIG_CHARGER_PCF50633
	INIT_DELAYED_WORK(&gta02_charger_work, gta02_charger_worker);
#endif

	s3c24xx_udc_set_platdata(&gta02_udc_cfg);
	s3c24xx_ts_set_platdata(&gta02_ts_info);
	s3c_ohci_set_platdata(&gta02_usb_info);
	s3c_nand_set_platdata(&gta02_nand_info);
	s3c_i2c0_set_platdata(NULL);

	i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs));

	/* 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(&gta02_udc_gpio_table);
	gpiod_add_lookup_table(&gta02_audio_gpio_table);
	gpiod_add_lookup_table(&gta02_mmc_gpio_table);
	platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
	pm_power_off = gta02_poweroff;

	regulator_has_full_constraints();
}

static void __init gta02_init_time(void)
{
	s3c2442_init_clocks(12000000);
	s3c24xx_timer_init();
}

MACHINE_START(NEO1973_GTA02, "GTA02")
	/* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_IRQS_S3C2442,
	.map_io		= gta02_map_io,
	.init_irq	= s3c2442_init_irq,
	.init_machine	= gta02_machine_init,
	.init_time	= gta02_init_time,
MACHINE_END