--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // SPDX-License-Identifier: GPL-2.0
+ //
+ // Copyright (c) 2006 Simtec Electronics
+ // Ben Dooks <ben@simtec.co.uk>
+ //
+ // Common code for SMDK2410 and SMDK2440 boards
+ //
+ // http://www.fluff.org/ben/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/gpio.h>
+ #include <linux/gpio/machine.h>
+ #include <linux/device.h>
+ #include <linux/platform_device.h>
+
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/rawnand.h>
+ #include <linux/mtd/nand_ecc.h>
+ #include <linux/mtd/partitions.h>
+ #include <linux/io.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/mach/irq.h>
+
+ #include <asm/mach-types.h>
+ #include <asm/irq.h>
+
+ #include "regs-gpio.h"
+ #include "gpio-samsung.h"
+ #include <linux/platform_data/leds-s3c24xx.h>
+ #include <linux/platform_data/mtd-nand-s3c2410.h>
+
+ #include "gpio-cfg.h"
+ #include "devs.h"
+ #include "pm.h"
+
+ #include "common-smdk-s3c24xx.h"
+
+ /* LED devices */
+
+ static struct gpiod_lookup_table smdk_led4_gpio_table = {
+ .dev_id = "s3c24xx_led.0",
+ .table = {
+ GPIO_LOOKUP("GPF", 4, NULL, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN),
+ { },
+ },
+ };
+
+ static struct gpiod_lookup_table smdk_led5_gpio_table = {
+ .dev_id = "s3c24xx_led.1",
+ .table = {
+ GPIO_LOOKUP("GPF", 5, NULL, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN),
+ { },
+ },
+ };
+
+ static struct gpiod_lookup_table smdk_led6_gpio_table = {
+ .dev_id = "s3c24xx_led.2",
+ .table = {
+ GPIO_LOOKUP("GPF", 6, NULL, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN),
+ { },
+ },
+ };
+
+ static struct gpiod_lookup_table smdk_led7_gpio_table = {
+ .dev_id = "s3c24xx_led.3",
+ .table = {
+ GPIO_LOOKUP("GPF", 7, NULL, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN),
+ { },
+ },
+ };
+
+ static struct s3c24xx_led_platdata smdk_pdata_led4 = {
+ .name = "led4",
+ .def_trigger = "timer",
+ };
+
+ static struct s3c24xx_led_platdata smdk_pdata_led5 = {
+ .name = "led5",
+ .def_trigger = "nand-disk",
+ };
+
+ static struct s3c24xx_led_platdata smdk_pdata_led6 = {
+ .name = "led6",
+ };
+
+ static struct s3c24xx_led_platdata smdk_pdata_led7 = {
+ .name = "led7",
+ };
+
+ static struct platform_device smdk_led4 = {
+ .name = "s3c24xx_led",
+ .id = 0,
+ .dev = {
+ .platform_data = &smdk_pdata_led4,
+ },
+ };
+
+ static struct platform_device smdk_led5 = {
+ .name = "s3c24xx_led",
+ .id = 1,
+ .dev = {
+ .platform_data = &smdk_pdata_led5,
+ },
+ };
+
+ static struct platform_device smdk_led6 = {
+ .name = "s3c24xx_led",
+ .id = 2,
+ .dev = {
+ .platform_data = &smdk_pdata_led6,
+ },
+ };
+
+ static struct platform_device smdk_led7 = {
+ .name = "s3c24xx_led",
+ .id = 3,
+ .dev = {
+ .platform_data = &smdk_pdata_led7,
+ },
+ };
+
+ /* NAND parititon from 2.4.18-swl5 */
+
+ static struct mtd_partition smdk_default_nand_part[] = {
+ [0] = {
+ .name = "Boot Agent",
+ .size = SZ_16K,
+ .offset = 0,
+ },
+ [1] = {
+ .name = "S3C2410 flash partition 1",
+ .offset = 0,
+ .size = SZ_2M,
+ },
+ [2] = {
+ .name = "S3C2410 flash partition 2",
+ .offset = SZ_4M,
+ .size = SZ_4M,
+ },
+ [3] = {
+ .name = "S3C2410 flash partition 3",
+ .offset = SZ_8M,
+ .size = SZ_2M,
+ },
+ [4] = {
+ .name = "S3C2410 flash partition 4",
+ .offset = SZ_1M * 10,
+ .size = SZ_4M,
+ },
+ [5] = {
+ .name = "S3C2410 flash partition 5",
+ .offset = SZ_1M * 14,
+ .size = SZ_1M * 10,
+ },
+ [6] = {
+ .name = "S3C2410 flash partition 6",
+ .offset = SZ_1M * 24,
+ .size = SZ_1M * 24,
+ },
+ [7] = {
+ .name = "S3C2410 flash partition 7",
+ .offset = SZ_1M * 48,
+ .size = MTDPART_SIZ_FULL,
+ }
+ };
+
+ static struct s3c2410_nand_set smdk_nand_sets[] = {
+ [0] = {
+ .name = "NAND",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(smdk_default_nand_part),
+ .partitions = smdk_default_nand_part,
+ },
+ };
+
+ /* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+ */
+
+ static struct s3c2410_platform_nand smdk_nand_info = {
+ .tacls = 20,
+ .twrph0 = 60,
+ .twrph1 = 20,
+ .nr_sets = ARRAY_SIZE(smdk_nand_sets),
+ .sets = smdk_nand_sets,
++ .engine_type = NAND_ECC_ENGINE_TYPE_SOFT,
+ };
+
+ /* devices we initialise */
+
+ static struct platform_device __initdata *smdk_devs[] = {
+ &s3c_device_nand,
+ &smdk_led4,
+ &smdk_led5,
+ &smdk_led6,
+ &smdk_led7,
+ };
+
+ void __init smdk_machine_init(void)
+ {
+ if (machine_is_smdk2443())
+ smdk_nand_info.twrph0 = 50;
+
+ s3c_nand_set_platdata(&smdk_nand_info);
+
+ /* Disable pull-up on the LED lines */
+ s3c_gpio_setpull(S3C2410_GPF(4), S3C_GPIO_PULL_NONE);
+ s3c_gpio_setpull(S3C2410_GPF(5), S3C_GPIO_PULL_NONE);
+ s3c_gpio_setpull(S3C2410_GPF(6), S3C_GPIO_PULL_NONE);
+ s3c_gpio_setpull(S3C2410_GPF(7), S3C_GPIO_PULL_NONE);
+
+ /* Add lookups for the lines */
+ gpiod_add_lookup_table(&smdk_led4_gpio_table);
+ gpiod_add_lookup_table(&smdk_led5_gpio_table);
+ gpiod_add_lookup_table(&smdk_led6_gpio_table);
+ gpiod_add_lookup_table(&smdk_led7_gpio_table);
+
+ platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
+
+ s3c_pm_init();
+ }
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // 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.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,
+ }, {
+ .virtual = (u32)S3C24XX_VA_ISA_WORD,
+ .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,
+ .map_io = anubis_map_io,
+ .init_machine = anubis_init,
+ .init_irq = s3c2440_init_irq,
+ .init_time = anubis_init_time,
+ MACHINE_END
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // 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.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,
+ .map_io = at2440evb_map_io,
+ .init_machine = at2440evb_init,
+ .init_irq = s3c2440_init_irq,
+ .init_time = at2440evb_init_time,
+ MACHINE_END
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // 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.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,
+ }, {
+ .virtual = (u32)S3C24XX_VA_ISA_WORD,
+ .pfn = PA_CS3(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,
+ .map_io = bast_map_io,
+ .init_irq = s3c2410_init_irq,
+ .init_machine = bast_init,
+ .init_time = bast_init_time,
+ MACHINE_END
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // 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.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)
+ {
+ long delay = 0;
+ char led;
+
+ led = (state) ? 1 : 0;
+ gpio_direction_output(GTA02_GPIO_AUX_LED, led);
+
+ return delay;
+ }
+
+
+ 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(>a02_charger_work,
+ GTA02_CHARGER_CONFIGURE_TIMEOUT);
+
+ return;
+ }
+
+ if (irq == PCF50633_IRQ_USBREM) {
+ cancel_delayed_work_sync(>a02_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(>a02_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 = >a02_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 = >a02_nor_flash_data,
+ },
+ .resource = >a02_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 = >a02_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,
+ .pullup_pin = GTA02_GPIO_USB_PULLUP,
+ };
+
+ /* 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 = >a02_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,
+ >a02_nor_flash,
+ &s3c24xx_pwm_device,
+ &s3c_device_iis,
+ &s3c_device_i2c0,
+ >a02_dfbmcs320_device,
+ >a02_buttons_device,
+ &s3c_device_adc,
+ &s3c_device_ts,
+ >a02_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(>a02_charger_work, gta02_charger_worker);
+ #endif
+
+ s3c24xx_udc_set_platdata(>a02_udc_cfg);
+ s3c24xx_ts_set_platdata(>a02_ts_info);
+ s3c_ohci_set_platdata(>a02_usb_info);
+ s3c_nand_set_platdata(>a02_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(>a02_audio_gpio_table);
+ gpiod_add_lookup_table(>a02_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,
+ .map_io = gta02_map_io,
+ .init_irq = s3c2442_init_irq,
+ .init_machine = gta02_machine_init,
+ .init_time = gta02_init_time,
+ MACHINE_END
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // SPDX-License-Identifier: GPL-2.0
+ //
+ // mach-hmt.c - Platform code for Airgoo HMT
+ //
+ // Copyright 2009 Peter Korsgaard <jacmet@sunsite.dk>
+
+ #include <linux/kernel.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/leds.h>
+ #include <linux/pwm.h>
+ #include <linux/pwm_backlight.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/mach/irq.h>
+
+ #include <video/samsung_fimd.h>
+ #include "map.h"
+ #include <mach/irqs.h>
+
+ #include <asm/irq.h>
+ #include <asm/mach-types.h>
+
+ #include <linux/platform_data/i2c-s3c2410.h>
+ #include "gpio-samsung.h"
+ #include "fb.h"
+ #include <linux/platform_data/mtd-nand-s3c2410.h>
+
+ #include "devs.h"
+ #include "cpu.h"
+
+ #include "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 hmt_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 pwm_lookup hmt_pwm_lookup[] = {
+ PWM_LOOKUP("samsung-pwm", 1, "pwm-backlight.0", NULL,
+ 1000000000 / (100 * 256 * 20), PWM_POLARITY_NORMAL),
+ };
+
+ static int hmt_bl_init(struct device *dev)
+ {
+ int ret;
+
+ ret = gpio_request(S3C64XX_GPB(4), "lcd backlight enable");
+ if (!ret)
+ ret = gpio_direction_output(S3C64XX_GPB(4), 0);
+
+ return ret;
+ }
+
+ static int hmt_bl_notify(struct device *dev, int brightness)
+ {
+ /*
+ * translate from CIELUV/CIELAB L*->brightness, E.G. from
+ * perceived luminance to light output. Assumes range 0..25600
+ */
+ if (brightness < 0x800) {
+ /* Y = Yn * L / 903.3 */
+ brightness = (100*256 * brightness + 231245/2) / 231245;
+ } else {
+ /* Y = Yn * ((L + 16) / 116 )^3 */
+ int t = (brightness*4 + 16*1024 + 58)/116;
+ brightness = 25 * ((t * t * t + 0x100000/2) / 0x100000);
+ }
+
+ gpio_set_value(S3C64XX_GPB(4), brightness);
+
+ return brightness;
+ }
+
+ static void hmt_bl_exit(struct device *dev)
+ {
+ gpio_free(S3C64XX_GPB(4));
+ }
+
+ static struct platform_pwm_backlight_data hmt_backlight_data = {
+ .max_brightness = 100 * 256,
+ .dft_brightness = 40 * 256,
+ .init = hmt_bl_init,
+ .notify = hmt_bl_notify,
+ .exit = hmt_bl_exit,
+
+ };
+
+ static struct platform_device hmt_backlight_device = {
+ .name = "pwm-backlight",
+ .dev = {
+ .parent = &samsung_device_pwm.dev,
+ .platform_data = &hmt_backlight_data,
+ },
+ };
+
+ static struct s3c_fb_pd_win hmt_fb_win0 = {
+ .max_bpp = 32,
+ .default_bpp = 16,
+ .xres = 800,
+ .yres = 480,
+ };
+
+ static struct fb_videomode hmt_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 hmt_lcd_pdata __initdata = {
+ .setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
+ .vtiming = &hmt_lcd_timing,
+ .win[0] = &hmt_fb_win0,
+ .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+ .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+ };
+
+ static struct mtd_partition hmt_nand_part[] = {
+ [0] = {
+ .name = "uboot",
+ .size = SZ_512K,
+ .offset = 0,
+ },
+ [1] = {
+ .name = "uboot-env1",
+ .size = SZ_256K,
+ .offset = SZ_512K,
+ },
+ [2] = {
+ .name = "uboot-env2",
+ .size = SZ_256K,
+ .offset = SZ_512K + SZ_256K,
+ },
+ [3] = {
+ .name = "kernel",
+ .size = SZ_2M,
+ .offset = SZ_1M,
+ },
+ [4] = {
+ .name = "rootfs",
+ .size = MTDPART_SIZ_FULL,
+ .offset = SZ_1M + SZ_2M,
+ },
+ };
+
+ static struct s3c2410_nand_set hmt_nand_sets[] = {
+ [0] = {
+ .name = "nand",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(hmt_nand_part),
+ .partitions = hmt_nand_part,
+ },
+ };
+
+ static struct s3c2410_platform_nand hmt_nand_info = {
+ .tacls = 25,
+ .twrph0 = 55,
+ .twrph1 = 40,
+ .nr_sets = ARRAY_SIZE(hmt_nand_sets),
+ .sets = hmt_nand_sets,
++ .engine_type = NAND_ECC_ENGINE_TYPE_SOFT,
+ };
+
+ static struct gpio_led hmt_leds[] = {
+ { /* left function keys */
+ .name = "left:blue",
+ .gpio = S3C64XX_GPO(12),
+ .default_trigger = "default-on",
+ },
+ { /* right function keys - red */
+ .name = "right:red",
+ .gpio = S3C64XX_GPO(13),
+ },
+ { /* right function keys - green */
+ .name = "right:green",
+ .gpio = S3C64XX_GPO(14),
+ },
+ { /* right function keys - blue */
+ .name = "right:blue",
+ .gpio = S3C64XX_GPO(15),
+ .default_trigger = "default-on",
+ },
+ };
+
+ static struct gpio_led_platform_data hmt_led_data = {
+ .num_leds = ARRAY_SIZE(hmt_leds),
+ .leds = hmt_leds,
+ };
+
+ static struct platform_device hmt_leds_device = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev.platform_data = &hmt_led_data,
+ };
+
+ static struct map_desc hmt_iodesc[] = {};
+
+ static struct platform_device *hmt_devices[] __initdata = {
+ &s3c_device_i2c0,
+ &s3c_device_nand,
+ &s3c_device_fb,
+ &s3c_device_ohci,
+ &samsung_device_pwm,
+ &hmt_backlight_device,
+ &hmt_leds_device,
+ };
+
+ static void __init hmt_map_io(void)
+ {
+ s3c64xx_init_io(hmt_iodesc, ARRAY_SIZE(hmt_iodesc));
+ s3c64xx_set_xtal_freq(12000000);
+ s3c24xx_init_uarts(hmt_uartcfgs, ARRAY_SIZE(hmt_uartcfgs));
+ s3c64xx_set_timer_source(S3C64XX_PWM3, S3C64XX_PWM4);
+ }
+
+ static void __init hmt_machine_init(void)
+ {
+ s3c_i2c0_set_platdata(NULL);
+ s3c_fb_set_platdata(&hmt_lcd_pdata);
+ s3c_nand_set_platdata(&hmt_nand_info);
+
+ gpio_request(S3C64XX_GPC(7), "usb power");
+ gpio_direction_output(S3C64XX_GPC(7), 0);
+ gpio_request(S3C64XX_GPM(0), "usb power");
+ gpio_direction_output(S3C64XX_GPM(0), 1);
+ gpio_request(S3C64XX_GPK(7), "usb power");
+ gpio_direction_output(S3C64XX_GPK(7), 1);
+ gpio_request(S3C64XX_GPF(13), "usb power");
+ gpio_direction_output(S3C64XX_GPF(13), 1);
+
+ pwm_add_table(hmt_pwm_lookup, ARRAY_SIZE(hmt_pwm_lookup));
+ platform_add_devices(hmt_devices, ARRAY_SIZE(hmt_devices));
+ }
+
+ MACHINE_START(HMT, "Airgoo-HMT")
+ /* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */
+ .atag_offset = 0x100,
+ .nr_irqs = S3C64XX_NR_IRQS,
+ .init_irq = s3c6410_init_irq,
+ .map_io = hmt_map_io,
+ .init_machine = hmt_machine_init,
+ .init_time = s3c64xx_timer_init,
+ MACHINE_END
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // SPDX-License-Identifier: GPL-2.0
+ //
+ // Copyright 2007 Simtec Electronics
+ // Ben Dooks <ben@simtec.co.uk>
+ //
+ // http://armlinux.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/gpio/machine.h>
+ #include <linux/syscore_ops.h>
+ #include <linux/serial_core.h>
+ #include <linux/serial_s3c.h>
+ #include <linux/platform_device.h>
+ #include <linux/i2c.h>
+
+ #include <video/ili9320.h>
+
+ #include <linux/spi/spi.h>
+ #include <linux/spi/spi_gpio.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/mach/irq.h>
+
+ #include <linux/platform_data/mtd-nand-s3c2410.h>
+ #include <linux/platform_data/i2c-s3c2410.h>
+
+ #include "hardware-s3c24xx.h"
+ #include "regs-gpio.h"
+ #include <linux/platform_data/fb-s3c2410.h>
+ #include "gpio-samsung.h"
+
+ #include <asm/mach-types.h>
+
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/rawnand.h>
+ #include <linux/mtd/nand_ecc.h>
+ #include <linux/mtd/partitions.h>
+
+ #include "gpio-cfg.h"
+ #include "devs.h"
+ #include "cpu.h"
+ #include "pm.h"
+ #include <linux/platform_data/usb-s3c2410_udc.h>
+
+ #include "s3c24xx.h"
+ #include "s3c2412-power.h"
+
+ static struct map_desc jive_iodesc[] __initdata = {
+ };
+
+ #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 jive_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,
+ }
+ };
+
+ /* Jive flash assignment
+ *
+ * 0x00000000-0x00028000 : uboot
+ * 0x00028000-0x0002c000 : uboot env
+ * 0x0002c000-0x00030000 : spare
+ * 0x00030000-0x00200000 : zimage A
+ * 0x00200000-0x01600000 : cramfs A
+ * 0x01600000-0x017d0000 : zimage B
+ * 0x017d0000-0x02bd0000 : cramfs B
+ * 0x02bd0000-0x03fd0000 : yaffs
+ */
+ static struct mtd_partition __initdata jive_imageA_nand_part[] = {
+
+ #ifdef CONFIG_MACH_JIVE_SHOW_BOOTLOADER
+ /* Don't allow access to the bootloader from linux */
+ {
+ .name = "uboot",
+ .offset = 0,
+ .size = (160 * SZ_1K),
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+
+ /* spare */
+ {
+ .name = "spare",
+ .offset = (176 * SZ_1K),
+ .size = (16 * SZ_1K),
+ },
+ #endif
+
+ /* booted images */
+ {
+ .name = "kernel (ro)",
+ .offset = (192 * SZ_1K),
+ .size = (SZ_2M) - (192 * SZ_1K),
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "root (ro)",
+ .offset = (SZ_2M),
+ .size = (20 * SZ_1M),
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+
+ /* yaffs */
+ {
+ .name = "yaffs",
+ .offset = (44 * SZ_1M),
+ .size = (20 * SZ_1M),
+ },
+
+ /* bootloader environment */
+ {
+ .name = "env",
+ .offset = (160 * SZ_1K),
+ .size = (16 * SZ_1K),
+ },
+
+ /* upgrade images */
+ {
+ .name = "zimage",
+ .offset = (22 * SZ_1M),
+ .size = (2 * SZ_1M) - (192 * SZ_1K),
+ }, {
+ .name = "cramfs",
+ .offset = (24 * SZ_1M) - (192*SZ_1K),
+ .size = (20 * SZ_1M),
+ },
+ };
+
+ static struct mtd_partition __initdata jive_imageB_nand_part[] = {
+
+ #ifdef CONFIG_MACH_JIVE_SHOW_BOOTLOADER
+ /* Don't allow access to the bootloader from linux */
+ {
+ .name = "uboot",
+ .offset = 0,
+ .size = (160 * SZ_1K),
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+
+ /* spare */
+ {
+ .name = "spare",
+ .offset = (176 * SZ_1K),
+ .size = (16 * SZ_1K),
+ },
+ #endif
+
+ /* booted images */
+ {
+ .name = "kernel (ro)",
+ .offset = (22 * SZ_1M),
+ .size = (2 * SZ_1M) - (192 * SZ_1K),
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "root (ro)",
+ .offset = (24 * SZ_1M) - (192 * SZ_1K),
+ .size = (20 * SZ_1M),
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+
+ /* yaffs */
+ {
+ .name = "yaffs",
+ .offset = (44 * SZ_1M),
+ .size = (20 * SZ_1M),
+ },
+
+ /* bootloader environment */
+ {
+ .name = "env",
+ .offset = (160 * SZ_1K),
+ .size = (16 * SZ_1K),
+ },
+
+ /* upgrade images */
+ {
+ .name = "zimage",
+ .offset = (192 * SZ_1K),
+ .size = (2 * SZ_1M) - (192 * SZ_1K),
+ }, {
+ .name = "cramfs",
+ .offset = (2 * SZ_1M),
+ .size = (20 * SZ_1M),
+ },
+ };
+
+ static struct s3c2410_nand_set __initdata jive_nand_sets[] = {
+ [0] = {
+ .name = "flash",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(jive_imageA_nand_part),
+ .partitions = jive_imageA_nand_part,
+ },
+ };
+
+ static struct s3c2410_platform_nand __initdata jive_nand_info = {
+ /* set taken from osiris nand timings, possibly still conservative */
+ .tacls = 30,
+ .twrph0 = 55,
+ .twrph1 = 40,
+ .sets = jive_nand_sets,
+ .nr_sets = ARRAY_SIZE(jive_nand_sets),
++ .engine_type = NAND_ECC_ENGINE_TYPE_SOFT,
+ };
+
+ static int __init jive_mtdset(char *options)
+ {
+ struct s3c2410_nand_set *nand = &jive_nand_sets[0];
+ unsigned long set;
+
+ if (options == NULL || options[0] == '\0')
+ return 0;
+
+ if (kstrtoul(options, 10, &set)) {
+ printk(KERN_ERR "failed to parse mtdset=%s\n", options);
+ return 0;
+ }
+
+ switch (set) {
+ case 1:
+ nand->nr_partitions = ARRAY_SIZE(jive_imageB_nand_part);
+ nand->partitions = jive_imageB_nand_part;
+ case 0:
+ /* this is already setup in the nand info */
+ break;
+ default:
+ printk(KERN_ERR "Unknown mtd set %ld specified,"
+ "using default.", set);
+ }
+
+ return 0;
+ }
+
+ /* parse the mtdset= option given to the kernel command line */
+ __setup("mtdset=", jive_mtdset);
+
+ /* LCD timing and setup */
+
+ #define LCD_XRES (240)
+ #define LCD_YRES (320)
+ #define LCD_LEFT_MARGIN (12)
+ #define LCD_RIGHT_MARGIN (12)
+ #define LCD_LOWER_MARGIN (12)
+ #define LCD_UPPER_MARGIN (12)
+ #define LCD_VSYNC (2)
+ #define LCD_HSYNC (2)
+
+ #define LCD_REFRESH (60)
+
+ #define LCD_HTOT (LCD_HSYNC + LCD_LEFT_MARGIN + LCD_XRES + LCD_RIGHT_MARGIN)
+ #define LCD_VTOT (LCD_VSYNC + LCD_LOWER_MARGIN + LCD_YRES + LCD_UPPER_MARGIN)
+
+ static struct s3c2410fb_display jive_vgg2432a4_display[] = {
+ [0] = {
+ .width = LCD_XRES,
+ .height = LCD_YRES,
+ .xres = LCD_XRES,
+ .yres = LCD_YRES,
+ .left_margin = LCD_LEFT_MARGIN,
+ .right_margin = LCD_RIGHT_MARGIN,
+ .upper_margin = LCD_UPPER_MARGIN,
+ .lower_margin = LCD_LOWER_MARGIN,
+ .hsync_len = LCD_HSYNC,
+ .vsync_len = LCD_VSYNC,
+
+ .pixclock = (1000000000000LL /
+ (LCD_REFRESH * LCD_HTOT * LCD_VTOT)),
+
+ .bpp = 16,
+ .type = (S3C2410_LCDCON1_TFT16BPP |
+ S3C2410_LCDCON1_TFT),
+
+ .lcdcon5 = (S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_INVVDEN |
+ S3C2410_LCDCON5_PWREN),
+ },
+ };
+
+ /* todo - put into gpio header */
+
+ #define S3C2410_GPCCON_MASK(x) (3 << ((x) * 2))
+ #define S3C2410_GPDCON_MASK(x) (3 << ((x) * 2))
+
+ static struct s3c2410fb_mach_info jive_lcd_config = {
+ .displays = jive_vgg2432a4_display,
+ .num_displays = ARRAY_SIZE(jive_vgg2432a4_display),
+ .default_display = 0,
+
+ /* Enable VD[2..7], VD[10..15], VD[18..23] and VCLK, syncs, VDEN
+ * and disable the pull down resistors on pins we are using for LCD
+ * data. */
+
+ .gpcup = (0xf << 1) | (0x3f << 10),
+ .gpcup_reg = S3C2410_GPCUP,
+
+ .gpccon = (S3C2410_GPC1_VCLK | S3C2410_GPC2_VLINE |
+ S3C2410_GPC3_VFRAME | S3C2410_GPC4_VM |
+ S3C2410_GPC10_VD2 | S3C2410_GPC11_VD3 |
+ S3C2410_GPC12_VD4 | S3C2410_GPC13_VD5 |
+ S3C2410_GPC14_VD6 | S3C2410_GPC15_VD7),
+
+ .gpccon_mask = (S3C2410_GPCCON_MASK(1) | S3C2410_GPCCON_MASK(2) |
+ S3C2410_GPCCON_MASK(3) | S3C2410_GPCCON_MASK(4) |
+ S3C2410_GPCCON_MASK(10) | S3C2410_GPCCON_MASK(11) |
+ S3C2410_GPCCON_MASK(12) | S3C2410_GPCCON_MASK(13) |
+ S3C2410_GPCCON_MASK(14) | S3C2410_GPCCON_MASK(15)),
+
+ .gpccon_reg = S3C2410_GPCCON,
+
+ .gpdup = (0x3f << 2) | (0x3f << 10),
+
+ .gpdup_reg = S3C2410_GPDUP,
+
+ .gpdcon = (S3C2410_GPD2_VD10 | S3C2410_GPD3_VD11 |
+ S3C2410_GPD4_VD12 | S3C2410_GPD5_VD13 |
+ S3C2410_GPD6_VD14 | S3C2410_GPD7_VD15 |
+ S3C2410_GPD10_VD18 | S3C2410_GPD11_VD19 |
+ S3C2410_GPD12_VD20 | S3C2410_GPD13_VD21 |
+ S3C2410_GPD14_VD22 | S3C2410_GPD15_VD23),
+
+ .gpdcon_mask = (S3C2410_GPDCON_MASK(2) | S3C2410_GPDCON_MASK(3) |
+ S3C2410_GPDCON_MASK(4) | S3C2410_GPDCON_MASK(5) |
+ S3C2410_GPDCON_MASK(6) | S3C2410_GPDCON_MASK(7) |
+ S3C2410_GPDCON_MASK(10) | S3C2410_GPDCON_MASK(11)|
+ S3C2410_GPDCON_MASK(12) | S3C2410_GPDCON_MASK(13)|
+ S3C2410_GPDCON_MASK(14) | S3C2410_GPDCON_MASK(15)),
+
+ .gpdcon_reg = S3C2410_GPDCON,
+ };
+
+ /* ILI9320 support. */
+
+ static void jive_lcm_reset(unsigned int set)
+ {
+ printk(KERN_DEBUG "%s(%d)\n", __func__, set);
+
+ gpio_set_value(S3C2410_GPG(13), set);
+ }
+
+ #undef LCD_UPPER_MARGIN
+ #define LCD_UPPER_MARGIN 2
+
+ static struct ili9320_platdata jive_lcm_config = {
+ .hsize = LCD_XRES,
+ .vsize = LCD_YRES,
+
+ .reset = jive_lcm_reset,
+ .suspend = ILI9320_SUSPEND_DEEP,
+
+ .entry_mode = ILI9320_ENTRYMODE_ID(3) | ILI9320_ENTRYMODE_BGR,
+ .display2 = (ILI9320_DISPLAY2_FP(LCD_UPPER_MARGIN) |
+ ILI9320_DISPLAY2_BP(LCD_LOWER_MARGIN)),
+ .display3 = 0x0,
+ .display4 = 0x0,
+ .rgb_if1 = (ILI9320_RGBIF1_RIM_RGB18 |
+ ILI9320_RGBIF1_RM | ILI9320_RGBIF1_CLK_RGBIF),
+ .rgb_if2 = ILI9320_RGBIF2_DPL,
+ .interface2 = 0x0,
+ .interface3 = 0x3,
+ .interface4 = (ILI9320_INTERFACE4_RTNE(16) |
+ ILI9320_INTERFACE4_DIVE(1)),
+ .interface5 = 0x0,
+ .interface6 = 0x0,
+ };
+
+ /* LCD SPI support */
+
+ static struct spi_gpio_platform_data jive_lcd_spi = {
+ .num_chipselect = 1,
+ };
+
+ static struct platform_device jive_device_lcdspi = {
+ .name = "spi_gpio",
+ .id = 1,
+ .dev.platform_data = &jive_lcd_spi,
+ };
+
+ static struct gpiod_lookup_table jive_lcdspi_gpiod_table = {
+ .dev_id = "spi_gpio",
+ .table = {
+ GPIO_LOOKUP("GPIOG", 8,
+ "sck", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("GPIOB", 8,
+ "mosi", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("GPIOB", 7,
+ "cs", GPIO_ACTIVE_HIGH),
+ { },
+ },
+ };
+
+ /* WM8750 audio code SPI definition */
+
+ static struct spi_gpio_platform_data jive_wm8750_spi = {
+ .num_chipselect = 1,
+ };
+
+ static struct platform_device jive_device_wm8750 = {
+ .name = "spi_gpio",
+ .id = 2,
+ .dev.platform_data = &jive_wm8750_spi,
+ };
+
+ static struct gpiod_lookup_table jive_wm8750_gpiod_table = {
+ .dev_id = "spi_gpio",
+ .table = {
+ GPIO_LOOKUP("GPIOB", 4,
+ "sck", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("GPIOB", 9,
+ "mosi", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("GPIOH", 10,
+ "cs", GPIO_ACTIVE_HIGH),
+ { },
+ },
+ };
+
+ /* JIVE SPI devices. */
+
+ static struct spi_board_info __initdata jive_spi_devs[] = {
+ [0] = {
+ .modalias = "VGG2432A4",
+ .bus_num = 1,
+ .chip_select = 0,
+ .mode = SPI_MODE_3, /* CPOL=1, CPHA=1 */
+ .max_speed_hz = 100000,
+ .platform_data = &jive_lcm_config,
+ }, {
+ .modalias = "WM8750",
+ .bus_num = 2,
+ .chip_select = 0,
+ .mode = SPI_MODE_0, /* CPOL=0, CPHA=0 */
+ .max_speed_hz = 100000,
+ },
+ };
+
+ /* I2C bus and device configuration. */
+
+ static struct s3c2410_platform_i2c jive_i2c_cfg __initdata = {
+ .frequency = 80 * 1000,
+ .flags = S3C_IICFLG_FILTER,
+ .sda_delay = 2,
+ };
+
+ static struct i2c_board_info jive_i2c_devs[] __initdata = {
+ [0] = {
+ I2C_BOARD_INFO("lis302dl", 0x1c),
+ .irq = IRQ_EINT14,
+ },
+ };
+
+ /* The platform devices being used. */
+
+ static struct platform_device *jive_devices[] __initdata = {
+ &s3c_device_ohci,
+ &s3c_device_rtc,
+ &s3c_device_wdt,
+ &s3c_device_i2c0,
+ &s3c_device_lcd,
+ &jive_device_lcdspi,
+ &jive_device_wm8750,
+ &s3c_device_nand,
+ &s3c_device_usbgadget,
+ &s3c2412_device_dma,
+ };
+
+ static struct s3c2410_udc_mach_info jive_udc_cfg __initdata = {
+ .vbus_pin = S3C2410_GPG(1), /* detect is on GPG1 */
+ };
+
+ /* Jive power management device */
+
+ #ifdef CONFIG_PM
+ static int jive_pm_suspend(void)
+ {
+ /* Write the magic value u-boot uses to check for resume into
+ * the INFORM0 register, and ensure INFORM1 is set to the
+ * correct address to resume from. */
+
+ __raw_writel(0x2BED, S3C2412_INFORM0);
+ __raw_writel(__pa_symbol(s3c_cpu_resume), S3C2412_INFORM1);
+
+ return 0;
+ }
+
+ static void jive_pm_resume(void)
+ {
+ __raw_writel(0x0, S3C2412_INFORM0);
+ }
+
+ #else
+ #define jive_pm_suspend NULL
+ #define jive_pm_resume NULL
+ #endif
+
+ static struct syscore_ops jive_pm_syscore_ops = {
+ .suspend = jive_pm_suspend,
+ .resume = jive_pm_resume,
+ };
+
+ static void __init jive_map_io(void)
+ {
+ s3c24xx_init_io(jive_iodesc, ARRAY_SIZE(jive_iodesc));
+ s3c24xx_init_uarts(jive_uartcfgs, ARRAY_SIZE(jive_uartcfgs));
+ s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
+ }
+
+ static void __init jive_init_time(void)
+ {
+ s3c2412_init_clocks(12000000);
+ s3c24xx_timer_init();
+ }
+
+ static void jive_power_off(void)
+ {
+ printk(KERN_INFO "powering system down...\n");
+
+ gpio_request_one(S3C2410_GPC(5), GPIOF_OUT_INIT_HIGH, NULL);
+ gpio_free(S3C2410_GPC(5));
+ }
+
+ static void __init jive_machine_init(void)
+ {
+ /* register system core operations for managing low level suspend */
+
+ register_syscore_ops(&jive_pm_syscore_ops);
+
+ /* write our sleep configurations for the IO. Pull down all unused
+ * IO, ensure that we have turned off all peripherals we do not
+ * need, and configure the ones we do need. */
+
+ /* Port B sleep */
+
+ __raw_writel(S3C2412_SLPCON_IN(0) |
+ S3C2412_SLPCON_PULL(1) |
+ S3C2412_SLPCON_HIGH(2) |
+ S3C2412_SLPCON_PULL(3) |
+ S3C2412_SLPCON_PULL(4) |
+ S3C2412_SLPCON_PULL(5) |
+ S3C2412_SLPCON_PULL(6) |
+ S3C2412_SLPCON_HIGH(7) |
+ S3C2412_SLPCON_PULL(8) |
+ S3C2412_SLPCON_PULL(9) |
+ S3C2412_SLPCON_PULL(10), S3C2412_GPBSLPCON);
+
+ /* Port C sleep */
+
+ __raw_writel(S3C2412_SLPCON_PULL(0) |
+ S3C2412_SLPCON_PULL(1) |
+ S3C2412_SLPCON_PULL(2) |
+ S3C2412_SLPCON_PULL(3) |
+ S3C2412_SLPCON_PULL(4) |
+ S3C2412_SLPCON_PULL(5) |
+ S3C2412_SLPCON_LOW(6) |
+ S3C2412_SLPCON_PULL(6) |
+ S3C2412_SLPCON_PULL(7) |
+ S3C2412_SLPCON_PULL(8) |
+ S3C2412_SLPCON_PULL(9) |
+ S3C2412_SLPCON_PULL(10) |
+ S3C2412_SLPCON_PULL(11) |
+ S3C2412_SLPCON_PULL(12) |
+ S3C2412_SLPCON_PULL(13) |
+ S3C2412_SLPCON_PULL(14) |
+ S3C2412_SLPCON_PULL(15), S3C2412_GPCSLPCON);
+
+ /* Port D sleep */
+
+ __raw_writel(S3C2412_SLPCON_ALL_PULL, S3C2412_GPDSLPCON);
+
+ /* Port F sleep */
+
+ __raw_writel(S3C2412_SLPCON_LOW(0) |
+ S3C2412_SLPCON_LOW(1) |
+ S3C2412_SLPCON_LOW(2) |
+ S3C2412_SLPCON_EINT(3) |
+ S3C2412_SLPCON_EINT(4) |
+ S3C2412_SLPCON_EINT(5) |
+ S3C2412_SLPCON_EINT(6) |
+ S3C2412_SLPCON_EINT(7), S3C2412_GPFSLPCON);
+
+ /* Port G sleep */
+
+ __raw_writel(S3C2412_SLPCON_IN(0) |
+ S3C2412_SLPCON_IN(1) |
+ S3C2412_SLPCON_IN(2) |
+ S3C2412_SLPCON_IN(3) |
+ S3C2412_SLPCON_IN(4) |
+ S3C2412_SLPCON_IN(5) |
+ S3C2412_SLPCON_IN(6) |
+ S3C2412_SLPCON_IN(7) |
+ S3C2412_SLPCON_PULL(8) |
+ S3C2412_SLPCON_PULL(9) |
+ S3C2412_SLPCON_IN(10) |
+ S3C2412_SLPCON_PULL(11) |
+ S3C2412_SLPCON_PULL(12) |
+ S3C2412_SLPCON_PULL(13) |
+ S3C2412_SLPCON_IN(14) |
+ S3C2412_SLPCON_PULL(15), S3C2412_GPGSLPCON);
+
+ /* Port H sleep */
+
+ __raw_writel(S3C2412_SLPCON_PULL(0) |
+ S3C2412_SLPCON_PULL(1) |
+ S3C2412_SLPCON_PULL(2) |
+ S3C2412_SLPCON_PULL(3) |
+ S3C2412_SLPCON_PULL(4) |
+ S3C2412_SLPCON_PULL(5) |
+ S3C2412_SLPCON_PULL(6) |
+ S3C2412_SLPCON_IN(7) |
+ S3C2412_SLPCON_IN(8) |
+ S3C2412_SLPCON_PULL(9) |
+ S3C2412_SLPCON_IN(10), S3C2412_GPHSLPCON);
+
+ /* initialise the power management now we've setup everything. */
+
+ s3c_pm_init();
+
+ /** TODO - check that this is after the cmdline option! */
+ s3c_nand_set_platdata(&jive_nand_info);
+
+ gpio_request(S3C2410_GPG(13), "lcm reset");
+ gpio_direction_output(S3C2410_GPG(13), 0);
+
+ gpio_request_one(S3C2410_GPB(6), GPIOF_OUT_INIT_LOW, NULL);
+ gpio_free(S3C2410_GPB(6));
+
+ /* 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);
+
+ s3c24xx_udc_set_platdata(&jive_udc_cfg);
+ s3c24xx_fb_set_platdata(&jive_lcd_config);
+
+ spi_register_board_info(jive_spi_devs, ARRAY_SIZE(jive_spi_devs));
+
+ s3c_i2c0_set_platdata(&jive_i2c_cfg);
+ i2c_register_board_info(0, jive_i2c_devs, ARRAY_SIZE(jive_i2c_devs));
+
+ pm_power_off = jive_power_off;
+
+ gpiod_add_lookup_table(&jive_lcdspi_gpiod_table);
+ gpiod_add_lookup_table(&jive_wm8750_gpiod_table);
+ platform_add_devices(jive_devices, ARRAY_SIZE(jive_devices));
+ }
+
+ MACHINE_START(JIVE, "JIVE")
+ /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
+ .atag_offset = 0x100,
+
+ .init_irq = s3c2412_init_irq,
+ .map_io = jive_map_io,
+ .init_machine = jive_machine_init,
+ .init_time = jive_init_time,
+ MACHINE_END
--- /dev/null
- .ecc_mode = NAND_ECC_HW,
+ // 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> and
+ // Michel Pollet <buserror@gmail.com>
+ //
+ // For product information, visit https://code.google.com/p/mini2440/
+
+ #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/input.h>
+ #include <linux/io.h>
+ #include <linux/serial_core.h>
+ #include <linux/serial_s3c.h>
+ #include <linux/dm9000.h>
+ #include <linux/property.h>
+ #include <linux/platform_device.h>
+ #include <linux/gpio_keys.h>
+ #include <linux/i2c.h>
+ #include <linux/mmc/host.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+
+ #include <linux/platform_data/fb-s3c2410.h>
+ #include <asm/mach-types.h>
+
+ #include "regs-gpio.h"
+ #include <linux/platform_data/leds-s3c24xx.h>
+ #include <mach/irqs.h>
+ #include "gpio-samsung.h"
+ #include <linux/platform_data/mtd-nand-s3c2410.h>
+ #include <linux/platform_data/i2c-s3c2410.h>
+ #include <linux/platform_data/mmc-s3cmci.h>
+ #include <linux/platform_data/usb-s3c2410_udc.h>
+
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/rawnand.h>
+ #include <linux/mtd/nand_ecc.h>
+ #include <linux/mtd/partitions.h>
+
+ #include "gpio-cfg.h"
+ #include "devs.h"
+ #include "cpu.h"
+
+ #include <sound/s3c24xx_uda134x.h>
+
+ #include "s3c24xx.h"
+
+ #define MACH_MINI2440_DM9K_BASE (S3C2410_CS4 + 0x300)
+
+ static struct map_desc mini2440_iodesc[] __initdata = {
+ /* nothing to declare, move along */
+ };
+
+ #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 mini2440_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,
+ },
+ };
+
+ /* USB device UDC support */
+
+ static struct s3c2410_udc_mach_info mini2440_udc_cfg __initdata = {
+ .pullup_pin = S3C2410_GPC(5),
+ };
+
+
+ /* LCD timing and setup */
+
+ /*
+ * This macro simplifies the table bellow
+ */
+ #define _LCD_DECLARE(_clock, _xres, margin_left, margin_right, hsync, \
+ _yres, margin_top, margin_bottom, vsync, refresh) \
+ .width = _xres, \
+ .xres = _xres, \
+ .height = _yres, \
+ .yres = _yres, \
+ .left_margin = margin_left, \
+ .right_margin = margin_right, \
+ .upper_margin = margin_top, \
+ .lower_margin = margin_bottom, \
+ .hsync_len = hsync, \
+ .vsync_len = vsync, \
+ .pixclock = ((_clock*100000000000LL) / \
+ ((refresh) * \
+ (hsync + margin_left + _xres + margin_right) * \
+ (vsync + margin_top + _yres + margin_bottom))), \
+ .bpp = 16,\
+ .type = (S3C2410_LCDCON1_TFT16BPP |\
+ S3C2410_LCDCON1_TFT)
+
+ static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
+ [0] = { /* mini2440 + 3.5" TFT + touchscreen */
+ _LCD_DECLARE(
+ 7, /* The 3.5 is quite fast */
+ 240, 21, 38, 6, /* x timing */
+ 320, 4, 4, 2, /* y timing */
+ 60), /* refresh rate */
+ .lcdcon5 = (S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_INVVDEN |
+ S3C2410_LCDCON5_PWREN),
+ },
+ [1] = { /* mini2440 + 7" TFT + touchscreen */
+ _LCD_DECLARE(
+ 10, /* the 7" runs slower */
+ 800, 40, 40, 48, /* x timing */
+ 480, 29, 3, 3, /* y timing */
+ 50), /* refresh rate */
+ .lcdcon5 = (S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_PWREN),
+ },
+ /* The VGA shield can outout at several resolutions. All share
+ * the same timings, however, anything smaller than 1024x768
+ * will only be displayed in the top left corner of a 1024x768
+ * XGA output unless you add optional dip switches to the shield.
+ * Therefore timings for other resolutions have been omitted here.
+ */
+ [2] = {
+ _LCD_DECLARE(
+ 10,
+ 1024, 1, 2, 2, /* y timing */
+ 768, 200, 16, 16, /* x timing */
+ 24), /* refresh rate, maximum stable,
+ * tested with the FPGA shield
+ */
+ .lcdcon5 = (S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_HWSWP),
+ },
+ /* mini2440 + 3.5" TFT (LCD-W35i, LQ035Q1DG06 type) + touchscreen*/
+ [3] = {
+ _LCD_DECLARE(
+ /* clock */
+ 7,
+ /* xres, margin_right, margin_left, hsync */
+ 320, 68, 66, 4,
+ /* yres, margin_top, margin_bottom, vsync */
+ 240, 4, 4, 9,
+ /* refresh rate */
+ 60),
+ .lcdcon5 = (S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVDEN |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVCLK |
+ S3C2410_LCDCON5_HWSWP),
+ },
+ };
+
+ /* todo - put into gpio header */
+
+ #define S3C2410_GPCCON_MASK(x) (3 << ((x) * 2))
+ #define S3C2410_GPDCON_MASK(x) (3 << ((x) * 2))
+
+ static struct s3c2410fb_mach_info mini2440_fb_info __initdata = {
+ .displays = &mini2440_lcd_cfg[0], /* not constant! see init */
+ .num_displays = 1,
+ .default_display = 0,
+
+ /* Enable VD[2..7], VD[10..15], VD[18..23] and VCLK, syncs, VDEN
+ * and disable the pull down resistors on pins we are using for LCD
+ * data.
+ */
+
+ .gpcup = (0xf << 1) | (0x3f << 10),
+
+ .gpccon = (S3C2410_GPC1_VCLK | S3C2410_GPC2_VLINE |
+ S3C2410_GPC3_VFRAME | S3C2410_GPC4_VM |
+ S3C2410_GPC10_VD2 | S3C2410_GPC11_VD3 |
+ S3C2410_GPC12_VD4 | S3C2410_GPC13_VD5 |
+ S3C2410_GPC14_VD6 | S3C2410_GPC15_VD7),
+
+ .gpccon_mask = (S3C2410_GPCCON_MASK(1) | S3C2410_GPCCON_MASK(2) |
+ S3C2410_GPCCON_MASK(3) | S3C2410_GPCCON_MASK(4) |
+ S3C2410_GPCCON_MASK(10) | S3C2410_GPCCON_MASK(11) |
+ S3C2410_GPCCON_MASK(12) | S3C2410_GPCCON_MASK(13) |
+ S3C2410_GPCCON_MASK(14) | S3C2410_GPCCON_MASK(15)),
+
+ .gpccon_reg = S3C2410_GPCCON,
+ .gpcup_reg = S3C2410_GPCUP,
+
+ .gpdup = (0x3f << 2) | (0x3f << 10),
+
+ .gpdcon = (S3C2410_GPD2_VD10 | S3C2410_GPD3_VD11 |
+ S3C2410_GPD4_VD12 | S3C2410_GPD5_VD13 |
+ S3C2410_GPD6_VD14 | S3C2410_GPD7_VD15 |
+ S3C2410_GPD10_VD18 | S3C2410_GPD11_VD19 |
+ S3C2410_GPD12_VD20 | S3C2410_GPD13_VD21 |
+ S3C2410_GPD14_VD22 | S3C2410_GPD15_VD23),
+
+ .gpdcon_mask = (S3C2410_GPDCON_MASK(2) | S3C2410_GPDCON_MASK(3) |
+ S3C2410_GPDCON_MASK(4) | S3C2410_GPDCON_MASK(5) |
+ S3C2410_GPDCON_MASK(6) | S3C2410_GPDCON_MASK(7) |
+ S3C2410_GPDCON_MASK(10) | S3C2410_GPDCON_MASK(11)|
+ S3C2410_GPDCON_MASK(12) | S3C2410_GPDCON_MASK(13)|
+ S3C2410_GPDCON_MASK(14) | S3C2410_GPDCON_MASK(15)),
+
+ .gpdcon_reg = S3C2410_GPDCON,
+ .gpdup_reg = S3C2410_GPDUP,
+ };
+
+ /* MMC/SD */
+
+ static struct s3c24xx_mci_pdata mini2440_mmc_cfg __initdata = {
+ .wprotect_invert = 1,
+ .set_power = s3c24xx_mci_def_set_power,
+ .ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34,
+ };
+
+ static struct gpiod_lookup_table mini2440_mmc_gpio_table = {
+ .dev_id = "s3c2410-sdi",
+ .table = {
+ /* Card detect S3C2410_GPG(8) */
+ GPIO_LOOKUP("GPIOG", 8, "cd", GPIO_ACTIVE_LOW),
+ /* Write protect S3C2410_GPH(8) */
+ GPIO_LOOKUP("GPIOH", 8, "wp", GPIO_ACTIVE_HIGH),
+ /* 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),
+ { },
+ },
+ };
+
+ /* NAND Flash on MINI2440 board */
+
+ static struct mtd_partition mini2440_default_nand_part[] __initdata = {
+ [0] = {
+ .name = "u-boot",
+ .size = SZ_256K,
+ .offset = 0,
+ },
+ [1] = {
+ .name = "u-boot-env",
+ .size = SZ_128K,
+ .offset = SZ_256K,
+ },
+ [2] = {
+ .name = "kernel",
+ /* 5 megabytes, for a kernel with no modules
+ * or a uImage with a ramdisk attached
+ */
+ .size = 0x00500000,
+ .offset = SZ_256K + SZ_128K,
+ },
+ [3] = {
+ .name = "root",
+ .offset = SZ_256K + SZ_128K + 0x00500000,
+ .size = MTDPART_SIZ_FULL,
+ },
+ };
+
+ static struct s3c2410_nand_set mini2440_nand_sets[] __initdata = {
+ [0] = {
+ .name = "nand",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(mini2440_default_nand_part),
+ .partitions = mini2440_default_nand_part,
+ .flash_bbt = 1, /* we use u-boot to create a BBT */
+ },
+ };
+
+ static struct s3c2410_platform_nand mini2440_nand_info __initdata = {
+ .tacls = 0,
+ .twrph0 = 25,
+ .twrph1 = 15,
+ .nr_sets = ARRAY_SIZE(mini2440_nand_sets),
+ .sets = mini2440_nand_sets,
+ .ignore_unset_ecc = 1,
++ .engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST,
+ };
+
+ /* DM9000AEP 10/100 ethernet controller */
+
+ static struct resource mini2440_dm9k_resource[] = {
+ [0] = DEFINE_RES_MEM(MACH_MINI2440_DM9K_BASE, 4),
+ [1] = DEFINE_RES_MEM(MACH_MINI2440_DM9K_BASE + 4, 4),
+ [2] = DEFINE_RES_NAMED(IRQ_EINT7, 1, NULL, IORESOURCE_IRQ
+ | IORESOURCE_IRQ_HIGHEDGE),
+ };
+
+ /*
+ * The DM9000 has no eeprom, and it's MAC address is set by
+ * the bootloader before starting the kernel.
+ */
+ static struct dm9000_plat_data mini2440_dm9k_pdata = {
+ .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
+ };
+
+ static struct platform_device mini2440_device_eth = {
+ .name = "dm9000",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(mini2440_dm9k_resource),
+ .resource = mini2440_dm9k_resource,
+ .dev = {
+ .platform_data = &mini2440_dm9k_pdata,
+ },
+ };
+
+ /* CON5
+ * +--+ /-----\
+ * | | | |
+ * | | | BAT |
+ * | | \_____/
+ * | |
+ * | | +----+ +----+
+ * | | | K5 | | K1 |
+ * | | +----+ +----+
+ * | | +----+ +----+
+ * | | | K4 | | K2 |
+ * | | +----+ +----+
+ * | | +----+ +----+
+ * | | | K6 | | K3 |
+ * | | +----+ +----+
+ * .....
+ */
+ static struct gpio_keys_button mini2440_buttons[] = {
+ {
+ .gpio = S3C2410_GPG(0), /* K1 */
+ .code = KEY_F1,
+ .desc = "Button 1",
+ .active_low = 1,
+ },
+ {
+ .gpio = S3C2410_GPG(3), /* K2 */
+ .code = KEY_F2,
+ .desc = "Button 2",
+ .active_low = 1,
+ },
+ {
+ .gpio = S3C2410_GPG(5), /* K3 */
+ .code = KEY_F3,
+ .desc = "Button 3",
+ .active_low = 1,
+ },
+ {
+ .gpio = S3C2410_GPG(6), /* K4 */
+ .code = KEY_POWER,
+ .desc = "Power",
+ .active_low = 1,
+ },
+ {
+ .gpio = S3C2410_GPG(7), /* K5 */
+ .code = KEY_F5,
+ .desc = "Button 5",
+ .active_low = 1,
+ },
+ #if 0
+ /* this pin is also known as TCLK1 and seems to already
+ * marked as "in use" somehow in the kernel -- possibly wrongly
+ */
+ {
+ .gpio = S3C2410_GPG(11), /* K6 */
+ .code = KEY_F6,
+ .desc = "Button 6",
+ .active_low = 1,
+ },
+ #endif
+ };
+
+ static struct gpio_keys_platform_data mini2440_button_data = {
+ .buttons = mini2440_buttons,
+ .nbuttons = ARRAY_SIZE(mini2440_buttons),
+ };
+
+ static struct platform_device mini2440_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &mini2440_button_data,
+ }
+ };
+
+ /* LEDS */
+
+ static struct gpiod_lookup_table mini2440_led1_gpio_table = {
+ .dev_id = "s3c24xx_led.1",
+ .table = {
+ GPIO_LOOKUP("GPB", 5, NULL, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN),
+ { },
+ },
+ };
+
+ static struct gpiod_lookup_table mini2440_led2_gpio_table = {
+ .dev_id = "s3c24xx_led.2",
+ .table = {
+ GPIO_LOOKUP("GPB", 6, NULL, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN),
+ { },
+ },
+ };
+
+ static struct gpiod_lookup_table mini2440_led3_gpio_table = {
+ .dev_id = "s3c24xx_led.3",
+ .table = {
+ GPIO_LOOKUP("GPB", 7, NULL, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN),
+ { },
+ },
+ };
+
+ static struct gpiod_lookup_table mini2440_led4_gpio_table = {
+ .dev_id = "s3c24xx_led.4",
+ .table = {
+ GPIO_LOOKUP("GPB", 8, NULL, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN),
+ { },
+ },
+ };
+
+ static struct gpiod_lookup_table mini2440_backlight_gpio_table = {
+ .dev_id = "s3c24xx_led.5",
+ .table = {
+ GPIO_LOOKUP("GPG", 4, NULL, GPIO_ACTIVE_HIGH),
+ { },
+ },
+ };
+
+ static struct s3c24xx_led_platdata mini2440_led1_pdata = {
+ .name = "led1",
+ .def_trigger = "heartbeat",
+ };
+
+ static struct s3c24xx_led_platdata mini2440_led2_pdata = {
+ .name = "led2",
+ .def_trigger = "nand-disk",
+ };
+
+ static struct s3c24xx_led_platdata mini2440_led3_pdata = {
+ .name = "led3",
+ .def_trigger = "mmc0",
+ };
+
+ static struct s3c24xx_led_platdata mini2440_led4_pdata = {
+ .name = "led4",
+ .def_trigger = "",
+ };
+
+ static struct s3c24xx_led_platdata mini2440_led_backlight_pdata = {
+ .name = "backlight",
+ .def_trigger = "backlight",
+ };
+
+ static struct platform_device mini2440_led1 = {
+ .name = "s3c24xx_led",
+ .id = 1,
+ .dev = {
+ .platform_data = &mini2440_led1_pdata,
+ },
+ };
+
+ static struct platform_device mini2440_led2 = {
+ .name = "s3c24xx_led",
+ .id = 2,
+ .dev = {
+ .platform_data = &mini2440_led2_pdata,
+ },
+ };
+
+ static struct platform_device mini2440_led3 = {
+ .name = "s3c24xx_led",
+ .id = 3,
+ .dev = {
+ .platform_data = &mini2440_led3_pdata,
+ },
+ };
+
+ static struct platform_device mini2440_led4 = {
+ .name = "s3c24xx_led",
+ .id = 4,
+ .dev = {
+ .platform_data = &mini2440_led4_pdata,
+ },
+ };
+
+ static struct platform_device mini2440_led_backlight = {
+ .name = "s3c24xx_led",
+ .id = 5,
+ .dev = {
+ .platform_data = &mini2440_led_backlight_pdata,
+ },
+ };
+
+ /* AUDIO */
+
+ static struct s3c24xx_uda134x_platform_data mini2440_audio_pins = {
+ .l3_clk = S3C2410_GPB(4),
+ .l3_mode = S3C2410_GPB(2),
+ .l3_data = S3C2410_GPB(3),
+ .model = UDA134X_UDA1341
+ };
+
+ static struct platform_device mini2440_audio = {
+ .name = "s3c24xx_uda134x",
+ .id = 0,
+ .dev = {
+ .platform_data = &mini2440_audio_pins,
+ },
+ };
+
+ /*
+ * I2C devices
+ */
+ static const struct property_entry mini2440_at24_properties[] = {
+ PROPERTY_ENTRY_U32("pagesize", 16),
+ { }
+ };
+
+ static struct i2c_board_info mini2440_i2c_devs[] __initdata = {
+ {
+ I2C_BOARD_INFO("24c08", 0x50),
+ .properties = mini2440_at24_properties,
+ },
+ };
+
+ static struct uda134x_platform_data s3c24xx_uda134x = {
+ .l3 = {
+ .gpio_clk = S3C2410_GPB(4),
+ .gpio_data = S3C2410_GPB(3),
+ .gpio_mode = S3C2410_GPB(2),
+ .use_gpios = 1,
+ .data_hold = 1,
+ .data_setup = 1,
+ .clock_high = 1,
+ .mode_hold = 1,
+ .mode = 1,
+ .mode_setup = 1,
+ },
+ .model = UDA134X_UDA1341,
+ };
+
+ static struct platform_device uda1340_codec = {
+ .name = "uda134x-codec",
+ .id = -1,
+ .dev = {
+ .platform_data = &s3c24xx_uda134x,
+ },
+ };
+
+ static struct platform_device *mini2440_devices[] __initdata = {
+ &s3c_device_ohci,
+ &s3c_device_wdt,
+ &s3c_device_i2c0,
+ &s3c_device_rtc,
+ &s3c_device_usbgadget,
+ &mini2440_device_eth,
+ &mini2440_led1,
+ &mini2440_led2,
+ &mini2440_led3,
+ &mini2440_led4,
+ &mini2440_button_device,
+ &s3c_device_nand,
+ &s3c_device_sdi,
+ &s3c2440_device_dma,
+ &s3c_device_iis,
+ &uda1340_codec,
+ &mini2440_audio,
+ };
+
+ static void __init mini2440_map_io(void)
+ {
+ s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc));
+ s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs));
+ s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
+ }
+
+ static void __init mini2440_init_time(void)
+ {
+ s3c2440_init_clocks(12000000);
+ s3c24xx_timer_init();
+ }
+
+ /*
+ * mini2440_features string
+ *
+ * t = Touchscreen present
+ * b = backlight control
+ * c = camera [TODO]
+ * 0-9 LCD configuration
+ *
+ */
+ static char mini2440_features_str[12] __initdata = "0tb";
+
+ static int __init mini2440_features_setup(char *str)
+ {
+ if (str)
+ strlcpy(mini2440_features_str, str,
+ sizeof(mini2440_features_str));
+ return 1;
+ }
+
+ __setup("mini2440=", mini2440_features_setup);
+
+ #define FEATURE_SCREEN (1 << 0)
+ #define FEATURE_BACKLIGHT (1 << 1)
+ #define FEATURE_TOUCH (1 << 2)
+ #define FEATURE_CAMERA (1 << 3)
+
+ struct mini2440_features_t {
+ int count;
+ int done;
+ int lcd_index;
+ struct platform_device *optional[8];
+ };
+
+ static void __init mini2440_parse_features(
+ struct mini2440_features_t *features,
+ const char *features_str)
+ {
+ const char *fp = features_str;
+
+ features->count = 0;
+ features->done = 0;
+ features->lcd_index = -1;
+
+ while (*fp) {
+ char f = *fp++;
+
+ switch (f) {
+ case '0'...'9': /* tft screen */
+ if (features->done & FEATURE_SCREEN) {
+ pr_info("MINI2440: '%c' ignored, screen type already set\n",
+ f);
+ } else {
+ int li = f - '0';
+
+ if (li >= ARRAY_SIZE(mini2440_lcd_cfg))
+ pr_info("MINI2440: '%c' out of range LCD mode\n",
+ f);
+ else {
+ features->optional[features->count++] =
+ &s3c_device_lcd;
+ features->lcd_index = li;
+ }
+ }
+ features->done |= FEATURE_SCREEN;
+ break;
+ case 'b':
+ if (features->done & FEATURE_BACKLIGHT)
+ pr_info("MINI2440: '%c' ignored, backlight already set\n",
+ f);
+ else {
+ features->optional[features->count++] =
+ &mini2440_led_backlight;
+ }
+ features->done |= FEATURE_BACKLIGHT;
+ break;
+ case 't':
+ pr_info("MINI2440: '%c' ignored, touchscreen not compiled in\n",
+ f);
+ break;
+ case 'c':
+ if (features->done & FEATURE_CAMERA)
+ pr_info("MINI2440: '%c' ignored, camera already registered\n",
+ f);
+ else
+ features->optional[features->count++] =
+ &s3c_device_camif;
+ features->done |= FEATURE_CAMERA;
+ break;
+ }
+ }
+ }
+
+ static void __init mini2440_init(void)
+ {
+ struct mini2440_features_t features = { 0 };
+ int i;
+
+ pr_info("MINI2440: Option string mini2440=%s\n",
+ mini2440_features_str);
+
+ /* Parse the feature string */
+ mini2440_parse_features(&features, mini2440_features_str);
+
+ /* turn LCD on */
+ s3c_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);
+
+ /* Turn the backlight early on */
+ WARN_ON(gpio_request_one(S3C2410_GPG(4), GPIOF_OUT_INIT_HIGH, NULL));
+ gpio_free(S3C2410_GPG(4));
+
+ /* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s */
+ gpio_request_one(S3C2410_GPB(1), GPIOF_IN, NULL);
+ s3c_gpio_setpull(S3C2410_GPB(1), S3C_GPIO_PULL_UP);
+ gpio_free(S3C2410_GPB(1));
+
+ /* mark the key as input, without pullups (there is one on the board) */
+ for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) {
+ s3c_gpio_setpull(mini2440_buttons[i].gpio, S3C_GPIO_PULL_UP);
+ s3c_gpio_cfgpin(mini2440_buttons[i].gpio, S3C2410_GPIO_INPUT);
+ }
+
+ /* 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);
+
+ if (features.lcd_index != -1) {
+ int li;
+
+ mini2440_fb_info.displays =
+ &mini2440_lcd_cfg[features.lcd_index];
+
+ pr_info("MINI2440: LCD");
+ for (li = 0; li < ARRAY_SIZE(mini2440_lcd_cfg); li++)
+ if (li == features.lcd_index)
+ pr_cont(" [%d:%dx%d]", li,
+ mini2440_lcd_cfg[li].width,
+ mini2440_lcd_cfg[li].height);
+ else
+ pr_cont(" %d:%dx%d", li,
+ mini2440_lcd_cfg[li].width,
+ mini2440_lcd_cfg[li].height);
+ pr_cont("\n");
+ s3c24xx_fb_set_platdata(&mini2440_fb_info);
+ }
+
+ s3c24xx_udc_set_platdata(&mini2440_udc_cfg);
+ gpiod_add_lookup_table(&mini2440_mmc_gpio_table);
+ s3c24xx_mci_set_platdata(&mini2440_mmc_cfg);
+ s3c_nand_set_platdata(&mini2440_nand_info);
+ s3c_i2c0_set_platdata(NULL);
+
+ i2c_register_board_info(0, mini2440_i2c_devs,
+ ARRAY_SIZE(mini2440_i2c_devs));
+
+ /* Disable pull-up on the LED lines */
+ s3c_gpio_setpull(S3C2410_GPB(5), S3C_GPIO_PULL_NONE);
+ s3c_gpio_setpull(S3C2410_GPB(6), S3C_GPIO_PULL_NONE);
+ s3c_gpio_setpull(S3C2410_GPB(7), S3C_GPIO_PULL_NONE);
+ s3c_gpio_setpull(S3C2410_GPB(8), S3C_GPIO_PULL_NONE);
+ s3c_gpio_setpull(S3C2410_GPG(4), S3C_GPIO_PULL_NONE);
+
+ /* Add lookups for the lines */
+ gpiod_add_lookup_table(&mini2440_led1_gpio_table);
+ gpiod_add_lookup_table(&mini2440_led2_gpio_table);
+ gpiod_add_lookup_table(&mini2440_led3_gpio_table);
+ gpiod_add_lookup_table(&mini2440_led4_gpio_table);
+ gpiod_add_lookup_table(&mini2440_backlight_gpio_table);
+
+ platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));
+
+ if (features.count) /* the optional features */
+ platform_add_devices(features.optional, features.count);
+
+ }
+
+
+ MACHINE_START(MINI2440, "MINI2440")
+ /* Maintainer: Michel Pollet <buserror@gmail.com> */
+ .atag_offset = 0x100,
+ .map_io = mini2440_map_io,
+ .init_machine = mini2440_init,
+ .init_irq = s3c2440_init_irq,
+ .init_time = mini2440_init_time,
+ MACHINE_END
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // 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/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 <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/mmc-sdhci-s3c.h>
+ #include "sdhci.h"
+ #include <linux/platform_data/touchscreen-s3c2410.h>
+ #include <mach/irqs.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 mini6410_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 mini6410_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 mini6410_dm9k_pdata = {
+ .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
+ };
+
+ static struct platform_device mini6410_device_eth = {
+ .name = "dm9000",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(mini6410_dm9k_resource),
+ .resource = mini6410_dm9k_resource,
+ .dev = {
+ .platform_data = &mini6410_dm9k_pdata,
+ },
+ };
+
+ static struct mtd_partition mini6410_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 mini6410_nand_sets[] = {
+ [0] = {
+ .name = "nand",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(mini6410_nand_part),
+ .partitions = mini6410_nand_part,
+ },
+ };
+
+ static struct s3c2410_platform_nand mini6410_nand_info = {
+ .tacls = 25,
+ .twrph0 = 55,
+ .twrph1 = 40,
+ .nr_sets = ARRAY_SIZE(mini6410_nand_sets),
+ .sets = mini6410_nand_sets,
++ .engine_type = NAND_ECC_ENGINE_TYPE_SOFT,
+ };
+
+ static struct s3c_fb_pd_win mini6410_lcd_type0_fb_win = {
+ .max_bpp = 32,
+ .default_bpp = 16,
+ .xres = 480,
+ .yres = 272,
+ };
+
+ static struct fb_videomode mini6410_lcd_type0_timing = {
+ /* 4.3" 480x272 */
+ .left_margin = 3,
+ .right_margin = 2,
+ .upper_margin = 1,
+ .lower_margin = 1,
+ .hsync_len = 40,
+ .vsync_len = 1,
+ .xres = 480,
+ .yres = 272,
+ };
+
+ static struct s3c_fb_pd_win mini6410_lcd_type1_fb_win = {
+ .max_bpp = 32,
+ .default_bpp = 16,
+ .xres = 800,
+ .yres = 480,
+ };
+
+ static struct fb_videomode mini6410_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 mini6410_lcd_pdata[] __initdata = {
+ {
+ .setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
+ .vtiming = &mini6410_lcd_type0_timing,
+ .win[0] = &mini6410_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 = &mini6410_lcd_type1_timing,
+ .win[0] = &mini6410_lcd_type1_fb_win,
+ .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+ .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+ },
+ { },
+ };
+
+ static void mini6410_lcd_power_set(struct plat_lcd_data *pd,
+ unsigned int power)
+ {
+ if (power)
+ gpio_direction_output(S3C64XX_GPE(0), 1);
+ else
+ gpio_direction_output(S3C64XX_GPE(0), 0);
+ }
+
+ static struct plat_lcd_data mini6410_lcd_power_data = {
+ .set_power = mini6410_lcd_power_set,
+ };
+
+ static struct platform_device mini6410_lcd_powerdev = {
+ .name = "platform-lcd",
+ .dev.parent = &s3c_device_fb.dev,
+ .dev.platform_data = &mini6410_lcd_power_data,
+ };
+
+ static struct s3c_sdhci_platdata mini6410_hsmmc1_pdata = {
+ .max_width = 4,
+ .cd_type = S3C_SDHCI_CD_GPIO,
+ .ext_cd_gpio = S3C64XX_GPN(10),
+ .ext_cd_gpio_invert = true,
+ };
+
+ static struct platform_device *mini6410_devices[] __initdata = {
+ &mini6410_device_eth,
+ &s3c_device_hsmmc0,
+ &s3c_device_hsmmc1,
+ &s3c_device_ohci,
+ &s3c_device_nand,
+ &s3c_device_fb,
+ &mini6410_lcd_powerdev,
+ &s3c_device_adc,
+ };
+
+ static void __init mini6410_map_io(void)
+ {
+ u32 tmp;
+
+ s3c64xx_init_io(NULL, 0);
+ s3c64xx_set_xtal_freq(12000000);
+ s3c24xx_init_uarts(mini6410_uartcfgs, ARRAY_SIZE(mini6410_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);
+ }
+
+ /*
+ * mini6410_features string
+ *
+ * 0-9 LCD configuration
+ *
+ */
+ static char mini6410_features_str[12] __initdata = "0";
+
+ static int __init mini6410_features_setup(char *str)
+ {
+ if (str)
+ strlcpy(mini6410_features_str, str,
+ sizeof(mini6410_features_str));
+ return 1;
+ }
+
+ __setup("mini6410=", mini6410_features_setup);
+
+ #define FEATURE_SCREEN (1 << 0)
+
+ struct mini6410_features_t {
+ int done;
+ int lcd_index;
+ };
+
+ static void mini6410_parse_features(
+ struct mini6410_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 "MINI6410: '%c' ignored, "
+ "screen type already set\n", f);
+ } else {
+ int li = f - '0';
+ if (li >= ARRAY_SIZE(mini6410_lcd_pdata))
+ printk(KERN_INFO "MINI6410: '%c' out "
+ "of range LCD mode\n", f);
+ else {
+ features->lcd_index = li;
+ }
+ }
+ features->done |= FEATURE_SCREEN;
+ break;
+ }
+ }
+ }
+
+ static void __init mini6410_machine_init(void)
+ {
+ u32 cs1;
+ struct mini6410_features_t features = { 0 };
+
+ printk(KERN_INFO "MINI6410: Option string mini6410=%s\n",
+ mini6410_features_str);
+
+ /* Parse the feature string */
+ mini6410_parse_features(&features, mini6410_features_str);
+
+ printk(KERN_INFO "MINI6410: selected LCD display is %dx%d\n",
+ mini6410_lcd_pdata[features.lcd_index].win[0]->xres,
+ mini6410_lcd_pdata[features.lcd_index].win[0]->yres);
+
+ s3c_nand_set_platdata(&mini6410_nand_info);
+ s3c_fb_set_platdata(&mini6410_lcd_pdata[features.lcd_index]);
+ s3c_sdhci1_set_platdata(&mini6410_hsmmc1_pdata);
+ 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");
+ gpio_request(S3C64XX_GPE(0), "LCD power");
+
+ platform_add_devices(mini6410_devices, ARRAY_SIZE(mini6410_devices));
+ }
+
+ MACHINE_START(MINI6410, "MINI6410")
+ /* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
+ .atag_offset = 0x100,
+ .nr_irqs = S3C64XX_NR_IRQS,
+ .init_irq = s3c6410_init_irq,
+ .map_io = mini6410_map_io,
+ .init_machine = mini6410_machine_init,
+ .init_time = s3c64xx_timer_init,
+ MACHINE_END
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // 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.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,
+ }, {
+ .virtual = (u32)S3C24XX_VA_ISA_WORD,
+ .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,
+ .map_io = osiris_map_io,
+ .init_irq = s3c2440_init_irq,
+ .init_machine = osiris_init,
+ .init_time = osiris_init_time,
+ MACHINE_END
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // 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.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,
+ .map_io = qt2410_map_io,
+ .init_irq = s3c2410_init_irq,
+ .init_machine = qt2410_machine_init,
+ .init_time = qt2410_init_time,
+ MACHINE_END
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // 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 <mach/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
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // 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 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;
+ break;
+ }
+
+ 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,
+ .gpio_charge_finished = S3C2410_GPF(3),
+ .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),
+ };
+
+ 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_request(1, "RX1950 LCD");
+ if (IS_ERR(lcd_pwm)) {
+ dev_err(dev, "Unable to request PWM for LCD power!\n");
+ return PTR_ERR(lcd_pwm);
+ }
+
+ /*
+ * This is only required to initialize .polarity; all other values are
+ * fixed in this driver.
+ */
+ pwm_init_state(lcd_pwm, &lcd_pwm_state);
+
+ lcd_pwm_state.period = LCD_PWM_PERIOD;
+ 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_free(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 = {
+ .vbus_pin = S3C2410_GPG(5),
+ .vbus_pin_inverted = 1,
+ .pullup_pin = S3C2410_GPJ(5),
+ };
+
+ 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_audio_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,
+ .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
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // 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.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_WORD,
+ .pfn = __phys_to_pfn(S3C2410_CS3),
+ .length = SZ_1M,
+ .type = MT_DEVICE,
+ }, {
+ .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,
+ .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
--- /dev/null
- .ecc_mode = NAND_ECC_SOFT,
+ // SPDX-License-Identifier: GPL-2.0
+ //
+ // (C) 2006 Thomas Gleixner <tglx@linutronix.de>
+ //
+ // Derived from mach-smdk2413.c - (C) 2006 Simtec Electronics
+
+ #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/mtd.h>
+ #include <linux/mtd/rawnand.h>
+ #include <linux/mtd/nand_ecc.h>
+ #include <linux/mtd/partitions.h>
+ #include <linux/memblock.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/mach/irq.h>
+
+ #include <asm/setup.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 <linux/platform_data/mtd-nand-s3c2410.h>
+
+ #include "devs.h"
+ #include "cpu.h"
+
+ #include "s3c24xx.h"
+
+ static struct map_desc vstms_iodesc[] __initdata = {
+ };
+
+ static struct s3c2410_uartcfg vstms_uartcfgs[] __initdata = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ },
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ }
+ };
+
+ static struct mtd_partition __initdata vstms_nand_part[] = {
+ [0] = {
+ .name = "Boot Agent",
+ .size = 0x7C000,
+ .offset = 0,
+ },
+ [1] = {
+ .name = "UBoot Config",
+ .offset = 0x7C000,
+ .size = 0x4000,
+ },
+ [2] = {
+ .name = "Kernel",
+ .offset = 0x80000,
+ .size = 0x200000,
+ },
+ [3] = {
+ .name = "RFS",
+ .offset = 0x280000,
+ .size = 0x3d80000,
+ },
+ };
+
+ static struct s3c2410_nand_set __initdata vstms_nand_sets[] = {
+ [0] = {
+ .name = "NAND",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(vstms_nand_part),
+ .partitions = vstms_nand_part,
+ },
+ };
+
+ /* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+ */
+
+ static struct s3c2410_platform_nand __initdata vstms_nand_info = {
+ .tacls = 20,
+ .twrph0 = 60,
+ .twrph1 = 20,
+ .nr_sets = ARRAY_SIZE(vstms_nand_sets),
+ .sets = vstms_nand_sets,
++ .engine_type = NAND_ECC_ENGINE_TYPE_SOFT,
+ };
+
+ static struct platform_device *vstms_devices[] __initdata = {
+ &s3c_device_ohci,
+ &s3c_device_wdt,
+ &s3c_device_i2c0,
+ &s3c_device_iis,
+ &s3c_device_rtc,
+ &s3c_device_nand,
+ &s3c2412_device_dma,
+ };
+
+ static void __init vstms_fixup(struct tag *tags, char **cmdline)
+ {
+ if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
+ memblock_add(0x30000000, SZ_64M);
+ }
+ }
+
+ static void __init vstms_map_io(void)
+ {
+ s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
+ s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
+ s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
+ }
+
+ static void __init vstms_init_time(void)
+ {
+ s3c2412_init_clocks(12000000);
+ s3c24xx_timer_init();
+ }
+
+ static void __init vstms_init(void)
+ {
+ s3c_i2c0_set_platdata(NULL);
+ s3c_nand_set_platdata(&vstms_nand_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(vstms_devices, ARRAY_SIZE(vstms_devices));
+ }
+
+ MACHINE_START(VSTMS, "VSTMS")
+ .atag_offset = 0x100,
+
+ .fixup = vstms_fixup,
+ .init_irq = s3c2412_init_irq,
+ .init_machine = vstms_init,
+ .map_io = vstms_map_io,
+ .init_time = vstms_init_time,
+ MACHINE_END
config MMC_SDHCI_S3C
tristate "SDHCI support on Samsung S3C SoC"
- depends on MMC_SDHCI && (PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS)
+ depends on MMC_SDHCI
- depends on PLAT_SAMSUNG || COMPILE_TEST
++ depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
help
This selects the Secure Digital Host Controller Interface (SDHCI)
often referrered to as the HSMMC block in some of the Samsung S3C
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/spi/s3c24xx.h>
+ #include <linux/spi/s3c24xx-fiq.h>
#include <linux/module.h>
- #include <plat/regs-spi.h>
-
#include <asm/fiq.h>
- #include "spi-s3c24xx-fiq.h"
+ #include "spi-s3c24xx-regs.h"
/**
- * s3c24xx_spi_devstate - per device data
+ * struct s3c24xx_spi_devstate - per device data
* @hz: Last frequency calculated for @sppre field.
* @mode: Last mode setting for the @spcon field.
* @spcon: Value to write to the SPCON register.