Index: linux-2.6.21/include/asm-arm/arch-s3c2440/hxd8.h =================================================================== --- linux-2.6.21.orig/include/asm-arm/arch-s3c2440/hxd8.h 2007-05-18 13:32:17.000000000 +0800 +++ linux-2.6.21/include/asm-arm/arch-s3c2440/hxd8.h 2007-05-24 18:19:52.000000000 +0800 @@ -12,5 +12,5 @@ #define HXD8_GPIO_PCF50606 S3C2410_GPF6 #define HXD8_IRQ_PCF50606 IRQ_EINT6 - +#define HXD8_NAND_CHIP_SELECT 1 #endif Index: linux-2.6.21/arch/arm/mach-s3c2440/mach-hxd8.c =================================================================== --- linux-2.6.21.orig/arch/arm/mach-s3c2440/mach-hxd8.c 2007-05-18 13:32:17.000000000 +0800 +++ linux-2.6.21/arch/arm/mach-s3c2440/mach-hxd8.c 2007-05-24 18:40:45.000000000 +0800 @@ -133,17 +133,62 @@ [0] = { .name = "hxd8-nand", .nr_chips = 1, +#if HXD8_NAND_CHIP_SELECT + .working_index = 0, +#endif }, [1] = { .name = "hxd8-nand-1", .nr_chips = 1, +#if HXD8_NAND_CHIP_SELECT + .working_index = 1, +#endif }, [2] = { .name = "hxd8-nand-2", .nr_chips = 1, +#if HXD8_NAND_CHIP_SELECT + .working_index = 2, +#endif }, }; +#if HXD8_NAND_CHIP_SELECT +static void hxd8_nand_chip_select_init(void) +{ + /* Nand Flash 3G glue logic initialization + * nCE1 ~ nCE4 as output mode + */ + s3c2410_gpio_cfgpin(S3C2410_GPA14, S3C2410_GPA14_OUT); + s3c2410_gpio_cfgpin(S3C2410_GPA15, S3C2410_GPA15_OUT); + s3c2410_gpio_cfgpin(S3C2410_GPA16, S3C2410_GPA16_OUT); + s3c2410_gpio_setpin(S3C2410_GPA14, 1); + s3c2410_gpio_setpin(S3C2410_GPA15, 1); + s3c2410_gpio_setpin(S3C2410_GPA16, 1); + s3c2410_gpio_cfgpin(S3C2410_GPG1, S3C2410_GPG1_OUTP); + s3c2410_gpio_setpin(S3C2410_GPG1, 0); + /* RnB 2~4 as input mode */ + s3c2410_gpio_cfgpin(S3C2410_GPC5, S3C2410_GPG5_INP); + s3c2410_gpio_cfgpin(S3C2410_GPC6, S3C2410_GPG6_INP); + s3c2410_gpio_cfgpin(S3C2410_GPC7, S3C2410_GPG7_INP); +} + +static void hxd8_select_chip(struct s3c2410_nand_set * nset, + int chip) +{ + int sel = (chip == -1) ? 0 : nset->working_index; + + BUG_ON(sel > 3 || sel < -1); + s3c2410_gpio_setpin(S3C2410_GPG1, (sel == 0) ? 0 : 1); + s3c2410_gpio_setpin(S3C2410_GPA15, (sel == 1) ? 0 : 1); + s3c2410_gpio_setpin(S3C2410_GPA16, (sel == 2) ? 0 : 1); + s3c2410_gpio_setpin(S3C2410_GPA14, (sel == 3) ? 0 : 1); +} +#else +#define hxd8_select_chip NULL +#define hxd8_nand_chip_select_init() do { } while(0) +#endif + /* choose a set of timings which should suit most 512Mbit * chips and beyond. */ @@ -154,6 +199,7 @@ .twrph1 = 20, .nr_sets = ARRAY_SIZE(hxd8_nand_sets), .sets = hxd8_nand_sets, + .select_chip = hxd8_select_chip, }; /* PMU configuration */ @@ -386,8 +432,10 @@ platform_device_register(&hxd8_pmu_dev); s3c2410_pm_init(); + hxd8_nand_chip_select_init(); } + MACHINE_START(HXD8, "HXD8") /* Maintainer: Harald Welte */ .phys_io = S3C2410_PA_UART, Index: linux-2.6.21/include/asm-arm/arch-s3c2410/nand.h =================================================================== --- linux-2.6.21.orig/include/asm-arm/arch-s3c2410/nand.h 2007-04-26 11:08:32.000000000 +0800 +++ linux-2.6.21/include/asm-arm/arch-s3c2410/nand.h 2007-05-18 13:55:02.000000000 +0800 @@ -20,13 +20,16 @@ * nr_map = map for low-layer logical to physical chip numbers (option) * partitions = mtd partition list */ - +#include struct s3c2410_nand_set { int nr_chips; int nr_partitions; char *name; int *nr_map; struct mtd_partition *partitions; +#if HXD8_NAND_CHIP_SELECT + int working_index; +#endif }; struct s3c2410_platform_nand { Index: linux-2.6.21/drivers/mtd/nand/s3c2410.c =================================================================== --- linux-2.6.21.orig/drivers/mtd/nand/s3c2410.c 2007-05-18 13:32:17.000000000 +0800 +++ linux-2.6.21/drivers/mtd/nand/s3c2410.c 2007-05-24 17:54:41.000000000 +0800 @@ -63,6 +63,7 @@ #include #include +#include #ifdef CONFIG_MTD_NAND_S3C2410_HWECC static int hardware_ecc = 1; #else @@ -254,6 +255,13 @@ if (chip == -1) { cur |= info->sel_bit; +#if HXD8_NAND_CHIP_SELECT + /* GPIO return to default when unselect chip*/ + if (info->platform != NULL) { + if (info->platform->select_chip != NULL) + (info->platform->select_chip) (nmtd->set, chip); + } +#endif } else { if (nmtd->set != NULL && chip > nmtd->set->nr_chips) { dev_err(info->device, "invalid chip %d\n", chip); @@ -323,9 +331,26 @@ static int s3c2440_nand_devready(struct mtd_info *mtd) { struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); + struct s3c2410_nand_mtd *nmtd = s3c2410_nand_mtd_toours(mtd); + +#if HXD8_NAND_CHIP_SELECT + switch(nmtd->set->working_index){ + case 0: + return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY; + case 1: + return (s3c2410_gpio_getpin(S3C2410_GPC6)>>6); + case 2: + return (s3c2410_gpio_getpin(S3C2410_GPC7)>>7); + case 3: + return (s3c2410_gpio_getpin(S3C2410_GPC5)>>5); + default: + return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY; + } +#endif return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY; } + static int s3c2412_nand_devready(struct mtd_info *mtd) { struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);