aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig12
-rw-r--r--arch/arm/configs/mx51_defconfig1
-rw-r--r--arch/arm/include/asm/hardware/cache-l2x0.h13
-rw-r--r--arch/arm/include/asm/memblock.h7
-rw-r--r--arch/arm/include/asm/outercache.h24
-rw-r--r--arch/arm/kernel/machine_kexec.c3
-rw-r--r--arch/arm/kernel/vmlinux.lds.S1
-rw-r--r--arch/arm/mach-imx/mach-mx27_3ds.c38
-rw-r--r--arch/arm/mach-ixp2000/core.c2
-rw-r--r--arch/arm/mach-mx25/Kconfig1
-rw-r--r--arch/arm/mach-mx25/mach-mx25_3ds.c10
-rw-r--r--arch/arm/mach-mx3/Kconfig2
-rw-r--r--arch/arm/mach-mx3/devices.c16
-rw-r--r--arch/arm/mach-mx3/mach-mx31_3ds.c38
-rw-r--r--arch/arm/mach-mx3/mach-mx35_3ds.c16
-rw-r--r--arch/arm/mach-mx5/Kconfig2
-rw-r--r--arch/arm/mach-mx5/Makefile1
-rw-r--r--arch/arm/mach-mx5/board-mx51_babbage.c49
-rw-r--r--arch/arm/mach-mx5/clock-mx51.c22
-rw-r--r--arch/arm/mach-mx5/cpu_op-mx51.c29
-rw-r--r--arch/arm/mach-mx5/cpu_op-mx51.h14
-rw-r--r--arch/arm/mach-mx5/devices-imx51.h2
-rw-r--r--arch/arm/mach-omap2/omap4-common.c13
-rw-r--r--arch/arm/mach-s3c2410/include/mach/gpio.h10
-rw-r--r--arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h2
-rw-r--r--arch/arm/mach-s3c2410/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-s3c2412/s3c2412.c3
-rw-r--r--arch/arm/mach-s3c2416/Kconfig6
-rw-r--r--arch/arm/mach-s3c2416/Makefile2
-rw-r--r--arch/arm/mach-s3c2416/irq.c2
-rw-r--r--arch/arm/mach-s3c2416/pm.c84
-rw-r--r--arch/arm/mach-s3c2416/s3c2416.c3
-rw-r--r--arch/arm/mach-s3c2440/s3c244x.c3
-rw-r--r--arch/arm/mach-s3c2443/s3c2443.c3
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-s3c64xx/Kconfig21
-rw-r--r--arch/arm/mach-s3c64xx/Makefile1
-rw-r--r--arch/arm/mach-s3c64xx/dev-audio.c63
-rw-r--r--arch/arm/mach-s3c64xx/gpiolib.c8
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-s3c64xx/mach-mini6410.c357
-rw-r--r--arch/arm/mach-s3c64xx/mach-real6410.c198
-rw-r--r--arch/arm/mach-s3c64xx/setup-fb-24bpp.c13
-rw-r--r--arch/arm/mach-s3c64xx/setup-ide.c11
-rw-r--r--arch/arm/mach-s3c64xx/setup-keypad.c16
-rw-r--r--arch/arm/mach-s3c64xx/setup-sdhci-gpio.c41
-rw-r--r--arch/arm/mach-s5p6442/Kconfig1
-rw-r--r--arch/arm/mach-s5p6442/clock.c28
-rw-r--r--arch/arm/mach-s5p6442/dev-audio.c30
-rw-r--r--arch/arm/mach-s5p6442/dev-spi.c6
-rw-r--r--arch/arm/mach-s5p6442/dma.c2
-rw-r--r--arch/arm/mach-s5p6442/include/mach/regs-clock.h1
-rw-r--r--arch/arm/mach-s5p6442/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-s5p64x0/Kconfig2
-rw-r--r--arch/arm/mach-s5p64x0/clock-s5p6440.c19
-rw-r--r--arch/arm/mach-s5p64x0/clock-s5p6450.c19
-rw-r--r--arch/arm/mach-s5p64x0/clock.c18
-rw-r--r--arch/arm/mach-s5p64x0/dev-audio.c26
-rw-r--r--arch/arm/mach-s5p64x0/dev-spi.c38
-rw-r--r--arch/arm/mach-s5p64x0/dma.c2
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/regs-clock.h2
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-s5p64x0/setup-i2c0.c12
-rw-r--r--arch/arm/mach-s5p64x0/setup-i2c1.c12
-rw-r--r--arch/arm/mach-s5pc100/Kconfig1
-rw-r--r--arch/arm/mach-s5pc100/Makefile2
-rw-r--r--arch/arm/mach-s5pc100/clock.c174
-rw-r--r--arch/arm/mach-s5pc100/dev-audio.c86
-rw-r--r--arch/arm/mach-s5pc100/dev-spi.c22
-rw-r--r--arch/arm/mach-s5pc100/dma.c4
-rw-r--r--arch/arm/mach-s5pc100/gpiolib.c216
-rw-r--r--arch/arm/mach-s5pc100/include/mach/gpio.h7
-rw-r--r--arch/arm/mach-s5pc100/include/mach/irqs.h13
-rw-r--r--arch/arm/mach-s5pc100/include/mach/map.h2
-rw-r--r--arch/arm/mach-s5pc100/include/mach/regs-gpio.h49
-rw-r--r--arch/arm/mach-s5pc100/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-s5pc100/irq-gpio.c266
-rw-r--r--arch/arm/mach-s5pc100/mach-smdkc100.c4
-rw-r--r--arch/arm/mach-s5pc100/setup-fb-24bpp.c30
-rw-r--r--arch/arm/mach-s5pc100/setup-i2c0.c6
-rw-r--r--arch/arm/mach-s5pc100/setup-i2c1.c6
-rw-r--r--arch/arm/mach-s5pc100/setup-ide.c41
-rw-r--r--arch/arm/mach-s5pc100/setup-keypad.c15
-rw-r--r--arch/arm/mach-s5pc100/setup-sdhci-gpio.c35
-rw-r--r--arch/arm/mach-s5pv210/Kconfig37
-rw-r--r--arch/arm/mach-s5pv210/Makefile3
-rw-r--r--arch/arm/mach-s5pv210/clock.c207
-rw-r--r--arch/arm/mach-s5pv210/cpu.c15
-rw-r--r--arch/arm/mach-s5pv210/cpufreq.c484
-rw-r--r--arch/arm/mach-s5pv210/dev-audio.c86
-rw-r--r--arch/arm/mach-s5pv210/dev-spi.c19
-rw-r--r--arch/arm/mach-s5pv210/dma.c4
-rw-r--r--arch/arm/mach-s5pv210/gpiolib.c14
-rw-r--r--arch/arm/mach-s5pv210/include/mach/irqs.h12
-rw-r--r--arch/arm/mach-s5pv210/include/mach/map.h12
-rw-r--r--arch/arm/mach-s5pv210/include/mach/pm-core.h43
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-clock.h39
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-gpio.h7
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-sys.h19
-rw-r--r--arch/arm/mach-s5pv210/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-s5pv210/mach-aquila.c169
-rw-r--r--arch/arm/mach-s5pv210/mach-goni.c381
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkc110.c4
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkv210.c4
-rw-r--r--arch/arm/mach-s5pv210/mach-torbreck.c131
-rw-r--r--arch/arm/mach-s5pv210/pm.c166
-rw-r--r--arch/arm/mach-s5pv210/setup-fb-24bpp.c34
-rw-r--r--arch/arm/mach-s5pv210/setup-i2c0.c6
-rw-r--r--arch/arm/mach-s5pv210/setup-i2c1.c6
-rw-r--r--arch/arm/mach-s5pv210/setup-i2c2.c6
-rw-r--r--arch/arm/mach-s5pv210/setup-ide.c49
-rw-r--r--arch/arm/mach-s5pv210/setup-keypad.c14
-rw-r--r--arch/arm/mach-s5pv210/setup-sdhci-gpio.c57
-rw-r--r--arch/arm/mach-s5pv210/sleep.S170
-rw-r--r--arch/arm/mach-s5pv310/Kconfig95
-rw-r--r--arch/arm/mach-s5pv310/Makefile10
-rw-r--r--arch/arm/mach-s5pv310/clock.c635
-rw-r--r--arch/arm/mach-s5pv310/cpu.c47
-rw-r--r--arch/arm/mach-s5pv310/gpiolib.c304
-rw-r--r--arch/arm/mach-s5pv310/hotplug.c144
-rw-r--r--arch/arm/mach-s5pv310/include/mach/irqs.h44
-rw-r--r--arch/arm/mach-s5pv310/include/mach/map.h19
-rw-r--r--arch/arm/mach-s5pv310/include/mach/regs-clock.h32
-rw-r--r--arch/arm/mach-s5pv310/include/mach/regs-gpio.h42
-rw-r--r--arch/arm/mach-s5pv310/include/mach/regs-srom.h50
-rw-r--r--arch/arm/mach-s5pv310/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-s5pv310/irq-combiner.c6
-rw-r--r--arch/arm/mach-s5pv310/irq-eint.c228
-rw-r--r--arch/arm/mach-s5pv310/mach-smdkc210.c202
-rw-r--r--arch/arm/mach-s5pv310/mach-smdkv310.c121
-rw-r--r--arch/arm/mach-s5pv310/mach-universal_c210.c81
-rw-r--r--arch/arm/mach-s5pv310/setup-i2c0.c6
-rw-r--r--arch/arm/mach-s5pv310/setup-i2c1.c6
-rw-r--r--arch/arm/mach-s5pv310/setup-i2c2.c6
-rw-r--r--arch/arm/mach-s5pv310/setup-i2c3.c23
-rw-r--r--arch/arm/mach-s5pv310/setup-i2c4.c23
-rw-r--r--arch/arm/mach-s5pv310/setup-i2c5.c23
-rw-r--r--arch/arm/mach-s5pv310/setup-i2c6.c23
-rw-r--r--arch/arm/mach-s5pv310/setup-i2c7.c23
-rw-r--r--arch/arm/mach-s5pv310/setup-sdhci-gpio.c152
-rw-r--r--arch/arm/mach-s5pv310/setup-sdhci.c69
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1100.c5
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c326
-rw-r--r--arch/arm/mach-shmobile/clock-sh7367.c2
-rw-r--r--arch/arm/mach-shmobile/clock-sh7372.c78
-rw-r--r--arch/arm/mach-shmobile/clock-sh7377.c2
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h10
-rw-r--r--arch/arm/mach-shmobile/intc-sh7372.c28
-rw-r--r--arch/arm/mach-shmobile/pfc-sh7372.c8
-rw-r--r--arch/arm/mach-shmobile/setup-sh7367.c1
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c94
-rw-r--r--arch/arm/mach-shmobile/setup-sh7377.c1
-rw-r--r--arch/arm/mach-u300/clock.c6
-rw-r--r--arch/arm/mach-u300/core.c47
-rw-r--r--arch/arm/mach-u300/include/mach/u300-regs.h2
-rw-r--r--arch/arm/mach-ux500/cpu.c45
-rw-r--r--arch/arm/mm/Kconfig8
-rw-r--r--arch/arm/mm/cache-fa.S12
-rw-r--r--arch/arm/mm/cache-l2x0.c78
-rw-r--r--arch/arm/mm/cache-v3.S10
-rw-r--r--arch/arm/mm/cache-v4.S10
-rw-r--r--arch/arm/mm/cache-v4wb.S12
-rw-r--r--arch/arm/mm/cache-v4wt.S12
-rw-r--r--arch/arm/mm/fault-armv.c28
-rw-r--r--arch/arm/mm/init.c155
-rw-r--r--arch/arm/mm/mmu.c73
-rw-r--r--arch/arm/mm/proc-arm1020.S15
-rw-r--r--arch/arm/mm/proc-arm1020e.S15
-rw-r--r--arch/arm/mm/proc-arm1022.S15
-rw-r--r--arch/arm/mm/proc-arm1026.S15
-rw-r--r--arch/arm/mm/proc-arm920.S12
-rw-r--r--arch/arm/mm/proc-arm922.S12
-rw-r--r--arch/arm/mm/proc-arm925.S12
-rw-r--r--arch/arm/mm/proc-arm926.S12
-rw-r--r--arch/arm/mm/proc-arm940.S12
-rw-r--r--arch/arm/mm/proc-arm946.S12
-rw-r--r--arch/arm/mm/proc-feroceon.S13
-rw-r--r--arch/arm/mm/proc-xsc3.S12
-rw-r--r--arch/arm/mm/proc-xscale.S12
-rw-r--r--arch/arm/plat-mxc/Makefile1
-rw-r--r--arch/arm/plat-mxc/cpufreq.c206
-rw-r--r--arch/arm/plat-mxc/devices/Kconfig6
-rw-r--r--arch/arm/plat-mxc/devices/Makefile1
-rw-r--r--arch/arm/plat-mxc/devices/platform-gpio_keys.c27
-rw-r--r--arch/arm/plat-mxc/gpio.c32
-rw-r--r--arch/arm/plat-mxc/include/mach/devices-common.h4
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx51.h2
-rw-r--r--arch/arm/plat-mxc/include/mach/mx31.h1
-rw-r--r--arch/arm/plat-mxc/include/mach/mx35.h2
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc.h13
-rw-r--r--arch/arm/plat-pxa/include/plat/pxa3xx_nand.h18
-rw-r--r--arch/arm/plat-s3c24xx/common-smdk.c2
-rw-r--r--arch/arm/plat-s3c24xx/gpiolib.c8
-rw-r--r--arch/arm/plat-s5p/Kconfig5
-rw-r--r--arch/arm/plat-s5p/Makefile3
-rw-r--r--arch/arm/plat-s5p/clock.c29
-rw-r--r--arch/arm/plat-s5p/include/plat/irqs.h18
-rw-r--r--arch/arm/plat-s5p/include/plat/map-s5p.h40
-rw-r--r--arch/arm/plat-s5p/include/plat/s5p-clock.h4
-rw-r--r--arch/arm/plat-s5p/irq-eint.c10
-rw-r--r--arch/arm/plat-s5p/irq-gpioint.c237
-rw-r--r--arch/arm/plat-s5p/irq-pm.c93
-rw-r--r--arch/arm/plat-s5p/pm.c52
-rw-r--r--arch/arm/plat-samsung/Kconfig25
-rw-r--r--arch/arm/plat-samsung/Makefile5
-rw-r--r--arch/arm/plat-samsung/dev-hsmmc.c8
-rw-r--r--arch/arm/plat-samsung/dev-hsmmc1.c8
-rw-r--r--arch/arm/plat-samsung/dev-hsmmc2.c8
-rw-r--r--arch/arm/plat-samsung/dev-hsmmc3.c12
-rw-r--r--arch/arm/plat-samsung/dev-i2c2.c4
-rw-r--r--arch/arm/plat-samsung/dev-i2c3.c68
-rw-r--r--arch/arm/plat-samsung/dev-i2c4.c68
-rw-r--r--arch/arm/plat-samsung/dev-i2c5.c68
-rw-r--r--arch/arm/plat-samsung/dev-i2c6.c68
-rw-r--r--arch/arm/plat-samsung/dev-i2c7.c68
-rw-r--r--arch/arm/plat-samsung/gpio-config.c50
-rw-r--r--arch/arm/plat-samsung/gpio.c8
-rw-r--r--arch/arm/plat-samsung/include/plat/audio.h9
-rw-r--r--arch/arm/plat-samsung/include/plat/devs.h7
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h6
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-cfg.h56
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-core.h15
-rw-r--r--arch/arm/plat-samsung/include/plat/iic.h10
-rw-r--r--arch/arm/plat-samsung/include/plat/map-base.h4
-rw-r--r--arch/arm/plat-samsung/include/plat/nand-core.h28
-rw-r--r--arch/arm/plat-samsung/include/plat/sdhci.h64
-rw-r--r--arch/arm/plat-samsung/pm-gpio.c4
-rw-r--r--arch/arm/plat-samsung/s3c-pl330.c34
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h97
-rw-r--r--arch/powerpc/Kconfig7
-rw-r--r--arch/powerpc/include/asm/fsl_lbc.h34
-rw-r--r--arch/powerpc/sysdev/fsl_lbc.c244
-rw-r--r--arch/sh/boards/mach-ap325rxa/setup.c29
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c60
-rw-r--r--arch/sh/boards/mach-kfr2r09/setup.c29
-rw-r--r--arch/sh/boards/mach-migor/setup.c58
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c54
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c4
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c83
-rw-r--r--drivers/mtd/chips/cfi_probe.c2
-rw-r--r--drivers/mtd/chips/cfi_util.c7
-rw-r--r--drivers/mtd/devices/block2mtd.c1
-rw-r--r--drivers/mtd/devices/m25p80.c6
-rw-r--r--drivers/mtd/devices/phram.c2
-rw-r--r--drivers/mtd/maps/Kconfig9
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/bcm963xx-flash.c271
-rw-r--r--drivers/mtd/maps/gpio-addr-flash.c10
-rw-r--r--drivers/mtd/maps/pcmciamtd.c4
-rw-r--r--drivers/mtd/maps/physmap_of.c20
-rw-r--r--drivers/mtd/mtd_blkdevs.c68
-rw-r--r--drivers/mtd/mtdchar.c111
-rw-r--r--drivers/mtd/mtdpart.c154
-rw-r--r--drivers/mtd/nand/Kconfig15
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/bf5xx_nand.c14
-rw-r--r--drivers/mtd/nand/davinci_nand.c11
-rw-r--r--drivers/mtd/nand/denali.c1
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c484
-rw-r--r--drivers/mtd/nand/fsl_upm.c10
-rw-r--r--drivers/mtd/nand/fsmc_nand.c866
-rw-r--r--drivers/mtd/nand/mpc5121_nfc.c11
-rw-r--r--drivers/mtd/nand/nand_base.c338
-rw-r--r--drivers/mtd/nand/nand_bbt.c250
-rw-r--r--drivers/mtd/nand/nand_ids.c31
-rw-r--r--drivers/mtd/nand/nandsim.c19
-rw-r--r--drivers/mtd/nand/ndfc.c8
-rw-r--r--drivers/mtd/nand/omap2.c4
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c348
-rw-r--r--drivers/mtd/nand/r852.c30
-rw-r--r--drivers/mtd/nand/r852.h2
-rw-r--r--drivers/mtd/ofpart.c2
-rw-r--r--drivers/mtd/onenand/Kconfig7
-rw-r--r--drivers/mtd/onenand/onenand_base.c7
-rw-r--r--drivers/mtd/onenand/samsung.c133
-rw-r--r--drivers/mtd/sm_ftl.h8
-rw-r--r--drivers/video/sh_mipi_dsi.c32
-rw-r--r--drivers/video/sh_mobile_hdmi.c629
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c348
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h41
-rw-r--r--fs/compat.c1
-rw-r--r--fs/jffs2/build.c2
-rw-r--r--fs/jffs2/compr.c6
-rw-r--r--fs/jffs2/compr.h4
-rw-r--r--fs/jffs2/compr_lzo.c4
-rw-r--r--fs/jffs2/compr_rtime.c6
-rw-r--r--fs/jffs2/compr_rubin.c11
-rw-r--r--fs/jffs2/compr_zlib.c6
-rw-r--r--fs/jffs2/dir.c3
-rw-r--r--fs/jffs2/erase.c2
-rw-r--r--fs/jffs2/fs.c22
-rw-r--r--fs/jffs2/gc.c7
-rw-r--r--fs/jffs2/jffs2_fs_sb.h1
-rw-r--r--fs/jffs2/nodelist.c8
-rw-r--r--fs/jffs2/nodelist.h3
-rw-r--r--fs/jffs2/scan.c12
-rw-r--r--include/linux/mtd/bbm.h4
-rw-r--r--include/linux/mtd/cfi.h1
-rw-r--r--include/linux/mtd/fsmc.h181
-rw-r--r--include/linux/mtd/inftl.h14
-rw-r--r--include/linux/mtd/mtd.h15
-rw-r--r--include/linux/mtd/nand.h426
-rw-r--r--include/linux/mtd/partitions.h7
-rw-r--r--include/mtd/mtd-abi.h16
-rw-r--r--include/mtd/mtd-user.h2
-rw-r--r--include/video/sh_mobile_lcdc.h5
-rw-r--r--ipc/shm.c1
307 files changed, 12275 insertions, 3239 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b527bf5701c9..a19a5266d5fc 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -720,9 +720,11 @@ config ARCH_S5PC100
720config ARCH_S5PV210 720config ARCH_S5PV210
721 bool "Samsung S5PV210/S5PC110" 721 bool "Samsung S5PV210/S5PC110"
722 select CPU_V7 722 select CPU_V7
723 select ARCH_SPARSEMEM_ENABLE
723 select GENERIC_GPIO 724 select GENERIC_GPIO
724 select HAVE_CLK 725 select HAVE_CLK
725 select ARM_L1_CACHE_SHIFT_6 726 select ARM_L1_CACHE_SHIFT_6
727 select ARCH_HAS_CPUFREQ
726 select ARCH_USES_GETTIMEOFFSET 728 select ARCH_USES_GETTIMEOFFSET
727 select HAVE_S3C2410_I2C 729 select HAVE_S3C2410_I2C
728 select HAVE_S3C_RTC 730 select HAVE_S3C_RTC
@@ -733,9 +735,13 @@ config ARCH_S5PV210
733config ARCH_S5PV310 735config ARCH_S5PV310
734 bool "Samsung S5PV310/S5PC210" 736 bool "Samsung S5PV310/S5PC210"
735 select CPU_V7 737 select CPU_V7
738 select ARCH_SPARSEMEM_ENABLE
736 select GENERIC_GPIO 739 select GENERIC_GPIO
737 select HAVE_CLK 740 select HAVE_CLK
738 select GENERIC_CLOCKEVENTS 741 select GENERIC_CLOCKEVENTS
742 select HAVE_S3C_RTC
743 select HAVE_S3C2410_I2C
744 select HAVE_S3C2410_WATCHDOG
739 help 745 help
740 Samsung S5PV310 series based systems 746 Samsung S5PV310 series based systems
741 747
@@ -1662,6 +1668,12 @@ if ARCH_HAS_CPUFREQ
1662 1668
1663source "drivers/cpufreq/Kconfig" 1669source "drivers/cpufreq/Kconfig"
1664 1670
1671config CPU_FREQ_IMX
1672 tristate "CPUfreq driver for i.MX CPUs"
1673 depends on ARCH_MXC && CPU_FREQ
1674 help
1675 This enables the CPUfreq driver for i.MX CPUs.
1676
1665config CPU_FREQ_SA1100 1677config CPU_FREQ_SA1100
1666 bool 1678 bool
1667 1679
diff --git a/arch/arm/configs/mx51_defconfig b/arch/arm/configs/mx51_defconfig
index 163cfee7644c..5c7a87260fab 100644
--- a/arch/arm/configs/mx51_defconfig
+++ b/arch/arm/configs/mx51_defconfig
@@ -82,6 +82,7 @@ CONFIG_FEC=y
82CONFIG_INPUT_FF_MEMLESS=m 82CONFIG_INPUT_FF_MEMLESS=m
83# CONFIG_INPUT_MOUSEDEV_PSAUX is not set 83# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
84CONFIG_INPUT_EVDEV=y 84CONFIG_INPUT_EVDEV=y
85CONFIG_KEYBOARD_GPIO=y
85CONFIG_INPUT_EVBUG=m 86CONFIG_INPUT_EVBUG=m
86CONFIG_MOUSE_PS2=m 87CONFIG_MOUSE_PS2=m
87CONFIG_MOUSE_PS2_ELANTECH=y 88CONFIG_MOUSE_PS2_ELANTECH=y
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index 6bcba48800fe..cc42d5fdee17 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -21,9 +21,6 @@
21#define __ASM_ARM_HARDWARE_L2X0_H 21#define __ASM_ARM_HARDWARE_L2X0_H
22 22
23#define L2X0_CACHE_ID 0x000 23#define L2X0_CACHE_ID 0x000
24#define L2X0_CACHE_ID_PART_MASK (0xf << 6)
25#define L2X0_CACHE_ID_PART_L210 (1 << 6)
26#define L2X0_CACHE_ID_PART_L310 (3 << 6)
27#define L2X0_CACHE_TYPE 0x004 24#define L2X0_CACHE_TYPE 0x004
28#define L2X0_CTRL 0x100 25#define L2X0_CTRL 0x100
29#define L2X0_AUX_CTRL 0x104 26#define L2X0_AUX_CTRL 0x104
@@ -53,6 +50,16 @@
53#define L2X0_LINE_DATA 0xF10 50#define L2X0_LINE_DATA 0xF10
54#define L2X0_LINE_TAG 0xF30 51#define L2X0_LINE_TAG 0xF30
55#define L2X0_DEBUG_CTRL 0xF40 52#define L2X0_DEBUG_CTRL 0xF40
53#define L2X0_PREFETCH_CTRL 0xF60
54#define L2X0_POWER_CTRL 0xF80
55#define L2X0_DYNAMIC_CLK_GATING_EN (1 << 1)
56#define L2X0_STNDBY_MODE_EN (1 << 0)
57
58/* Registers shifts and masks */
59#define L2X0_CACHE_ID_PART_MASK (0xf << 6)
60#define L2X0_CACHE_ID_PART_L210 (1 << 6)
61#define L2X0_CACHE_ID_PART_L310 (3 << 6)
62#define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x3 << 17)
56 63
57#ifndef __ASSEMBLY__ 64#ifndef __ASSEMBLY__
58extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); 65extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
diff --git a/arch/arm/include/asm/memblock.h b/arch/arm/include/asm/memblock.h
index fdbc43b2e6c0..b8da2e415e4e 100644
--- a/arch/arm/include/asm/memblock.h
+++ b/arch/arm/include/asm/memblock.h
@@ -1,13 +1,6 @@
1#ifndef _ASM_ARM_MEMBLOCK_H 1#ifndef _ASM_ARM_MEMBLOCK_H
2#define _ASM_ARM_MEMBLOCK_H 2#define _ASM_ARM_MEMBLOCK_H
3 3
4#ifdef CONFIG_MMU
5extern phys_addr_t lowmem_end_addr;
6#define MEMBLOCK_REAL_LIMIT lowmem_end_addr
7#else
8#define MEMBLOCK_REAL_LIMIT 0
9#endif
10
11struct meminfo; 4struct meminfo;
12struct machine_desc; 5struct machine_desc;
13 6
diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h
index 25f76bae57ab..fc1900925275 100644
--- a/arch/arm/include/asm/outercache.h
+++ b/arch/arm/include/asm/outercache.h
@@ -25,6 +25,9 @@ struct outer_cache_fns {
25 void (*inv_range)(unsigned long, unsigned long); 25 void (*inv_range)(unsigned long, unsigned long);
26 void (*clean_range)(unsigned long, unsigned long); 26 void (*clean_range)(unsigned long, unsigned long);
27 void (*flush_range)(unsigned long, unsigned long); 27 void (*flush_range)(unsigned long, unsigned long);
28 void (*flush_all)(void);
29 void (*inv_all)(void);
30 void (*disable)(void);
28#ifdef CONFIG_OUTER_CACHE_SYNC 31#ifdef CONFIG_OUTER_CACHE_SYNC
29 void (*sync)(void); 32 void (*sync)(void);
30#endif 33#endif
@@ -50,6 +53,24 @@ static inline void outer_flush_range(unsigned long start, unsigned long end)
50 outer_cache.flush_range(start, end); 53 outer_cache.flush_range(start, end);
51} 54}
52 55
56static inline void outer_flush_all(void)
57{
58 if (outer_cache.flush_all)
59 outer_cache.flush_all();
60}
61
62static inline void outer_inv_all(void)
63{
64 if (outer_cache.inv_all)
65 outer_cache.inv_all();
66}
67
68static inline void outer_disable(void)
69{
70 if (outer_cache.disable)
71 outer_cache.disable();
72}
73
53#else 74#else
54 75
55static inline void outer_inv_range(unsigned long start, unsigned long end) 76static inline void outer_inv_range(unsigned long start, unsigned long end)
@@ -58,6 +79,9 @@ static inline void outer_clean_range(unsigned long start, unsigned long end)
58{ } 79{ }
59static inline void outer_flush_range(unsigned long start, unsigned long end) 80static inline void outer_flush_range(unsigned long start, unsigned long end)
60{ } 81{ }
82static inline void outer_flush_all(void) { }
83static inline void outer_inv_all(void) { }
84static inline void outer_disable(void) { }
61 85
62#endif 86#endif
63 87
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index 1fc74cbd1a19..3a8fd5140d7a 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -78,7 +78,10 @@ void machine_kexec(struct kimage *image)
78 local_fiq_disable(); 78 local_fiq_disable();
79 setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/ 79 setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
80 flush_cache_all(); 80 flush_cache_all();
81 outer_flush_all();
82 outer_disable();
81 cpu_proc_fin(); 83 cpu_proc_fin();
84 outer_inv_all();
82 flush_cache_all(); 85 flush_cache_all();
83 cpu_reset(reboot_code_buffer_phys); 86 cpu_reset(reboot_code_buffer_phys);
84} 87}
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 1953e3d21abf..cead8893b46b 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -113,6 +113,7 @@ SECTIONS
113 *(.rodata.*) 113 *(.rodata.*)
114 *(.glue_7) 114 *(.glue_7)
115 *(.glue_7t) 115 *(.glue_7t)
116 . = ALIGN(4);
116 *(.got) /* Global offset table */ 117 *(.got) /* Global offset table */
117 ARM_CPU_KEEP(PROC_INFO) 118 ARM_CPU_KEEP(PROC_INFO)
118 } 119 }
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index b8bbd31aa850..84a5ba03f1ba 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -23,16 +23,20 @@
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/gpio.h> 24#include <linux/gpio.h>
25#include <linux/input/matrix_keypad.h> 25#include <linux/input/matrix_keypad.h>
26#include <linux/irq.h>
26#include <asm/mach-types.h> 27#include <asm/mach-types.h>
27#include <asm/mach/arch.h> 28#include <asm/mach/arch.h>
28#include <asm/mach/time.h> 29#include <asm/mach/time.h>
29#include <mach/hardware.h> 30#include <mach/hardware.h>
30#include <mach/common.h> 31#include <mach/common.h>
31#include <mach/iomux-mx27.h> 32#include <mach/iomux-mx27.h>
33#include <mach/mmc.h>
32 34
33#include "devices-imx27.h" 35#include "devices-imx27.h"
34#include "devices.h" 36#include "devices.h"
35 37
38#define SD1_EN_GPIO (GPIO_PORTB + 25)
39
36static const int mx27pdk_pins[] __initconst = { 40static const int mx27pdk_pins[] __initconst = {
37 /* UART1 */ 41 /* UART1 */
38 PE12_PF_UART1_TXD, 42 PE12_PF_UART1_TXD,
@@ -58,6 +62,14 @@ static const int mx27pdk_pins[] __initconst = {
58 PD15_AOUT_FEC_COL, 62 PD15_AOUT_FEC_COL,
59 PD16_AIN_FEC_TX_ER, 63 PD16_AIN_FEC_TX_ER,
60 PF23_AIN_FEC_TX_EN, 64 PF23_AIN_FEC_TX_EN,
65 /* SDHC1 */
66 PE18_PF_SD1_D0,
67 PE19_PF_SD1_D1,
68 PE20_PF_SD1_D2,
69 PE21_PF_SD1_D3,
70 PE22_PF_SD1_CMD,
71 PE23_PF_SD1_CLK,
72 SD1_EN_GPIO | GPIO_GPIO | GPIO_OUT,
61}; 73};
62 74
63static const struct imxuart_platform_data uart_pdata __initconst = { 75static const struct imxuart_platform_data uart_pdata __initconst = {
@@ -85,13 +97,39 @@ static struct matrix_keymap_data mx27_3ds_keymap_data = {
85 .keymap_size = ARRAY_SIZE(mx27_3ds_keymap), 97 .keymap_size = ARRAY_SIZE(mx27_3ds_keymap),
86}; 98};
87 99
100static int mx27_3ds_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
101 void *data)
102{
103 return request_irq(IRQ_GPIOB(26), detect_irq, IRQF_TRIGGER_FALLING |
104 IRQF_TRIGGER_RISING, "sdhc1-card-detect", data);
105}
106
107static void mx27_3ds_sdhc1_exit(struct device *dev, void *data)
108{
109 free_irq(IRQ_GPIOB(26), data);
110}
111
112static struct imxmmc_platform_data sdhc1_pdata = {
113 .init = mx27_3ds_sdhc1_init,
114 .exit = mx27_3ds_sdhc1_exit,
115};
116
117static void mx27_3ds_sdhc1_enable_level_translator(void)
118{
119 /* Turn on TXB0108 OE pin */
120 gpio_request(SD1_EN_GPIO, "sd1_enable");
121 gpio_direction_output(SD1_EN_GPIO, 1);
122}
123
88static void __init mx27pdk_init(void) 124static void __init mx27pdk_init(void)
89{ 125{
90 mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins), 126 mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
91 "mx27pdk"); 127 "mx27pdk");
128 mx27_3ds_sdhc1_enable_level_translator();
92 imx27_add_imx_uart0(&uart_pdata); 129 imx27_add_imx_uart0(&uart_pdata);
93 imx27_add_fec(NULL); 130 imx27_add_fec(NULL);
94 mxc_register_device(&imx_kpp_device, &mx27_3ds_keymap_data); 131 mxc_register_device(&imx_kpp_device, &mx27_3ds_keymap_data);
132 mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
95} 133}
96 134
97static void __init mx27pdk_timer_init(void) 135static void __init mx27pdk_timer_init(void)
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index babb22597163..e24e3d05397f 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -197,7 +197,7 @@ unsigned long ixp2000_gettimeoffset (void)
197 return offset / ticks_per_usec; 197 return offset / ticks_per_usec;
198} 198}
199 199
200static int ixp2000_timer_interrupt(int irq, void *dev_id) 200static irqreturn_t ixp2000_timer_interrupt(int irq, void *dev_id)
201{ 201{
202 /* clear timer 1 */ 202 /* clear timer 1 */
203 ixp2000_reg_wrb(IXP2000_T1_CLR, 1); 203 ixp2000_reg_wrb(IXP2000_T1_CLR, 1);
diff --git a/arch/arm/mach-mx25/Kconfig b/arch/arm/mach-mx25/Kconfig
index aa57e35ce3cd..38ca09a5df9d 100644
--- a/arch/arm/mach-mx25/Kconfig
+++ b/arch/arm/mach-mx25/Kconfig
@@ -6,6 +6,7 @@ config MACH_MX25_3DS
6 bool "Support MX25PDK (3DS) Platform" 6 bool "Support MX25PDK (3DS) Platform"
7 select IMX_HAVE_PLATFORM_IMX_UART 7 select IMX_HAVE_PLATFORM_IMX_UART
8 select IMX_HAVE_PLATFORM_MXC_NAND 8 select IMX_HAVE_PLATFORM_MXC_NAND
9 select IMX_HAVE_PLATFORM_ESDHC
9 10
10config MACH_EUKREA_CPUIMX25 11config MACH_EUKREA_CPUIMX25
11 bool "Support Eukrea CPUIMX25 Platform" 12 bool "Support Eukrea CPUIMX25 Platform"
diff --git a/arch/arm/mach-mx25/mach-mx25_3ds.c b/arch/arm/mach-mx25/mach-mx25_3ds.c
index 80805107a73e..f8be1eb0c062 100644
--- a/arch/arm/mach-mx25/mach-mx25_3ds.c
+++ b/arch/arm/mach-mx25/mach-mx25_3ds.c
@@ -96,6 +96,14 @@ static struct pad_desc mx25pdk_pads[] = {
96 MX25_PAD_KPP_COL1__KPP_COL1, 96 MX25_PAD_KPP_COL1__KPP_COL1,
97 MX25_PAD_KPP_COL2__KPP_COL2, 97 MX25_PAD_KPP_COL2__KPP_COL2,
98 MX25_PAD_KPP_COL3__KPP_COL3, 98 MX25_PAD_KPP_COL3__KPP_COL3,
99
100 /* SD1 */
101 MX25_PAD_SD1_CMD__SD1_CMD,
102 MX25_PAD_SD1_CLK__SD1_CLK,
103 MX25_PAD_SD1_DATA0__SD1_DATA0,
104 MX25_PAD_SD1_DATA1__SD1_DATA1,
105 MX25_PAD_SD1_DATA2__SD1_DATA2,
106 MX25_PAD_SD1_DATA3__SD1_DATA3,
99}; 107};
100 108
101static const struct fec_platform_data mx25_fec_pdata __initconst = { 109static const struct fec_platform_data mx25_fec_pdata __initconst = {
@@ -193,6 +201,8 @@ static void __init mx25pdk_init(void)
193 mx25pdk_fec_reset(); 201 mx25pdk_fec_reset();
194 imx25_add_fec(&mx25_fec_pdata); 202 imx25_add_fec(&mx25_fec_pdata);
195 mxc_register_device(&mx25_kpp_device, &mx25pdk_keymap_data); 203 mxc_register_device(&mx25_kpp_device, &mx25pdk_keymap_data);
204
205 imx25_add_esdhc(0, NULL);
196} 206}
197 207
198static void __init mx25pdk_timer_init(void) 208static void __init mx25pdk_timer_init(void)
diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
index 096fd33f8ab9..5000ac1f93e3 100644
--- a/arch/arm/mach-mx3/Kconfig
+++ b/arch/arm/mach-mx3/Kconfig
@@ -143,8 +143,10 @@ config MACH_ARMADILLO5X0
143config MACH_MX35_3DS 143config MACH_MX35_3DS
144 bool "Support MX35PDK platform" 144 bool "Support MX35PDK platform"
145 select ARCH_MX35 145 select ARCH_MX35
146 select MXC_DEBUG_BOARD
146 select IMX_HAVE_PLATFORM_IMX_UART 147 select IMX_HAVE_PLATFORM_IMX_UART
147 select IMX_HAVE_PLATFORM_MXC_NAND 148 select IMX_HAVE_PLATFORM_MXC_NAND
149 select IMX_HAVE_PLATFORM_ESDHC
148 default n 150 default n
149 help 151 help
150 Include support for MX35PDK platform. This includes specific 152 Include support for MX35PDK platform. This includes specific
diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c
index f4dff11aaee7..d4da9496089a 100644
--- a/arch/arm/mach-mx3/devices.c
+++ b/arch/arm/mach-mx3/devices.c
@@ -72,24 +72,24 @@ struct platform_device mxc_w1_master_device = {
72#ifdef CONFIG_ARCH_MX31 72#ifdef CONFIG_ARCH_MX31
73static struct resource mxcsdhc0_resources[] = { 73static struct resource mxcsdhc0_resources[] = {
74 { 74 {
75 .start = MMC_SDHC1_BASE_ADDR, 75 .start = MX31_MMC_SDHC1_BASE_ADDR,
76 .end = MMC_SDHC1_BASE_ADDR + SZ_16K - 1, 76 .end = MX31_MMC_SDHC1_BASE_ADDR + SZ_16K - 1,
77 .flags = IORESOURCE_MEM, 77 .flags = IORESOURCE_MEM,
78 }, { 78 }, {
79 .start = MXC_INT_MMC_SDHC1, 79 .start = MX31_INT_MMC_SDHC1,
80 .end = MXC_INT_MMC_SDHC1, 80 .end = MX31_INT_MMC_SDHC1,
81 .flags = IORESOURCE_IRQ, 81 .flags = IORESOURCE_IRQ,
82 }, 82 },
83}; 83};
84 84
85static struct resource mxcsdhc1_resources[] = { 85static struct resource mxcsdhc1_resources[] = {
86 { 86 {
87 .start = MMC_SDHC2_BASE_ADDR, 87 .start = MX31_MMC_SDHC2_BASE_ADDR,
88 .end = MMC_SDHC2_BASE_ADDR + SZ_16K - 1, 88 .end = MX31_MMC_SDHC2_BASE_ADDR + SZ_16K - 1,
89 .flags = IORESOURCE_MEM, 89 .flags = IORESOURCE_MEM,
90 }, { 90 }, {
91 .start = MXC_INT_MMC_SDHC2, 91 .start = MX31_INT_MMC_SDHC2,
92 .end = MXC_INT_MMC_SDHC2, 92 .end = MX31_INT_MMC_SDHC2,
93 .flags = IORESOURCE_IRQ, 93 .flags = IORESOURCE_IRQ,
94 }, 94 },
95}; 95};
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c
index 5c1d0e86c91e..0ad9e7821082 100644
--- a/arch/arm/mach-mx3/mach-mx31_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx31_3ds.c
@@ -38,39 +38,9 @@
38#include "devices-imx31.h" 38#include "devices-imx31.h"
39#include "devices.h" 39#include "devices.h"
40 40
41/* Definitions for components on the Debug board */
42
43/* Base address of CPLD controller on the Debug board */
44#define DEBUG_BASE_ADDRESS CS5_IO_ADDRESS(MX3x_CS5_BASE_ADDR)
45
46/* LAN9217 ethernet base address */
47#define LAN9217_BASE_ADDR MX3x_CS5_BASE_ADDR
48
49/* CPLD config and interrupt base address */
50#define CPLD_ADDR (DEBUG_BASE_ADDRESS + 0x20000)
51
52/* status, interrupt */
53#define CPLD_INT_STATUS_REG (CPLD_ADDR + 0x10)
54#define CPLD_INT_MASK_REG (CPLD_ADDR + 0x38)
55#define CPLD_INT_RESET_REG (CPLD_ADDR + 0x20)
56/* magic word for debug CPLD */
57#define CPLD_MAGIC_NUMBER1_REG (CPLD_ADDR + 0x40)
58#define CPLD_MAGIC_NUMBER2_REG (CPLD_ADDR + 0x48)
59/* CPLD code version */
60#define CPLD_CODE_VER_REG (CPLD_ADDR + 0x50)
61/* magic word for debug CPLD */
62#define CPLD_MAGIC_NUMBER3_REG (CPLD_ADDR + 0x58)
63
64/* CPLD IRQ line for external uart, external ethernet etc */ 41/* CPLD IRQ line for external uart, external ethernet etc */
65#define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX31_PIN_GPIO1_1) 42#define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX31_PIN_GPIO1_1)
66 43
67#define MXC_EXP_IO_BASE (MXC_BOARD_IRQ_START)
68#define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_EXP_IO_BASE)
69
70#define EXPIO_INT_ENET (MXC_EXP_IO_BASE + 0)
71
72#define MXC_MAX_EXP_IO_LINES 16
73
74/* 44/*
75 * This file contains the board-specific initialization routines. 45 * This file contains the board-specific initialization routines.
76 */ 46 */
@@ -272,7 +242,7 @@ static void __init mxc_board_init(void)
272 imx31_add_imx_uart0(&uart_pdata); 242 imx31_add_imx_uart0(&uart_pdata);
273 imx31_add_mxc_nand(&mx31_3ds_nand_board_info); 243 imx31_add_mxc_nand(&mx31_3ds_nand_board_info);
274 244
275 imx31_add_spi_imx0(&spi1_pdata); 245 imx31_add_spi_imx1(&spi1_pdata);
276 spi_register_board_info(mx31_3ds_spi_devs, 246 spi_register_board_info(mx31_3ds_spi_devs,
277 ARRAY_SIZE(mx31_3ds_spi_devs)); 247 ARRAY_SIZE(mx31_3ds_spi_devs));
278 248
@@ -281,9 +251,9 @@ static void __init mxc_board_init(void)
281 mx31_3ds_usbotg_init(); 251 mx31_3ds_usbotg_init();
282 mxc_register_device(&mxc_otg_udc_device, &usbotg_pdata); 252 mxc_register_device(&mxc_otg_udc_device, &usbotg_pdata);
283 253
284 if (!mxc_expio_init(CS5_BASE_ADDR, EXPIO_PARENT_INT)) 254 if (mxc_expio_init(MX31_CS5_BASE_ADDR, EXPIO_PARENT_INT))
285 printk(KERN_WARNING "Init of the debugboard failed, all " 255 printk(KERN_WARNING "Init of the debug board failed, all "
286 "devices on the board are unusable.\n"); 256 "devices on the debug board are unusable.\n");
287} 257}
288 258
289static void __init mx31_3ds_timer_init(void) 259static void __init mx31_3ds_timer_init(void)
diff --git a/arch/arm/mach-mx3/mach-mx35_3ds.c b/arch/arm/mach-mx3/mach-mx35_3ds.c
index 05f628d90725..b66a75aa2e88 100644
--- a/arch/arm/mach-mx3/mach-mx35_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx35_3ds.c
@@ -38,11 +38,15 @@
38#include <mach/hardware.h> 38#include <mach/hardware.h>
39#include <mach/common.h> 39#include <mach/common.h>
40#include <mach/iomux-mx35.h> 40#include <mach/iomux-mx35.h>
41#include <mach/irqs.h>
42#include <mach/3ds_debugboard.h>
41#include <mach/mxc_ehci.h> 43#include <mach/mxc_ehci.h>
42 44
43#include "devices-imx35.h" 45#include "devices-imx35.h"
44#include "devices.h" 46#include "devices.h"
45 47
48#define EXPIO_PARENT_INT (MXC_INTERNAL_IRQS + GPIO_PORTA + 1)
49
46static const struct imxuart_platform_data uart_pdata __initconst = { 50static const struct imxuart_platform_data uart_pdata __initconst = {
47 .flags = IMXUART_HAVE_RTSCTS, 51 .flags = IMXUART_HAVE_RTSCTS,
48}; 52};
@@ -108,6 +112,13 @@ static struct pad_desc mx35pdk_pads[] = {
108 /* USBH1 */ 112 /* USBH1 */
109 MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR, 113 MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR,
110 MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC, 114 MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC,
115 /* SDCARD */
116 MX35_PAD_SD1_CMD__ESDHC1_CMD,
117 MX35_PAD_SD1_CLK__ESDHC1_CLK,
118 MX35_PAD_SD1_DATA0__ESDHC1_DAT0,
119 MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
120 MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
121 MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
111}; 122};
112 123
113/* OTG config */ 124/* OTG config */
@@ -140,6 +151,11 @@ static void __init mxc_board_init(void)
140 mxc_register_device(&mxc_usbh1, &usb_host_pdata); 151 mxc_register_device(&mxc_usbh1, &usb_host_pdata);
141 152
142 imx35_add_mxc_nand(&mx35pdk_nand_board_info); 153 imx35_add_mxc_nand(&mx35pdk_nand_board_info);
154 imx35_add_esdhc(0, NULL);
155
156 if (mxc_expio_init(MX35_CS5_BASE_ADDR, EXPIO_PARENT_INT))
157 pr_warn("Init of the debugboard failed, all "
158 "devices on the debugboard are unusable.\n");
143} 159}
144 160
145static void __init mx35pdk_timer_init(void) 161static void __init mx35pdk_timer_init(void)
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index a2df9ac37996..3ec910a7a182 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -6,6 +6,7 @@ config ARCH_MX51
6 select MXC_TZIC 6 select MXC_TZIC
7 select ARCH_MXC_IOMUX_V3 7 select ARCH_MXC_IOMUX_V3
8 select ARCH_MXC_AUDMUX_V2 8 select ARCH_MXC_AUDMUX_V2
9 select ARCH_HAS_CPUFREQ
9 10
10comment "MX5 platforms:" 11comment "MX5 platforms:"
11 12
@@ -13,6 +14,7 @@ config MACH_MX51_BABBAGE
13 bool "Support MX51 BABBAGE platforms" 14 bool "Support MX51 BABBAGE platforms"
14 select IMX_HAVE_PLATFORM_IMX_I2C 15 select IMX_HAVE_PLATFORM_IMX_I2C
15 select IMX_HAVE_PLATFORM_IMX_UART 16 select IMX_HAVE_PLATFORM_IMX_UART
17 select IMX_HAVE_PLATFORM_ESDHC
16 help 18 help
17 Include support for MX51 Babbage platform, also known as MX51EVK in 19 Include support for MX51 Babbage platform, also known as MX51EVK in
18 u-boot. This includes specific configurations for the board and its 20 u-boot. This includes specific configurations for the board and its
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 1769c161a60d..462f177eddfe 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -5,6 +5,7 @@
5# Object file lists. 5# Object file lists.
6obj-y := cpu.o mm.o clock-mx51.o devices.o 6obj-y := cpu.o mm.o clock-mx51.o devices.o
7 7
8obj-$(CONFIG_CPU_FREQ_IMX) += cpu_op-mx51.o
8obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o 9obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
9obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o 10obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
10obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o 11obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index 0821fe9b3b27..acbe30df2e69 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. 2 * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com> 3 * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
4 * 4 *
5 * The code contained herein is licensed under the GNU General Public 5 * The code contained herein is licensed under the GNU General Public
@@ -18,6 +18,8 @@
18#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/fsl_devices.h> 19#include <linux/fsl_devices.h>
20#include <linux/fec.h> 20#include <linux/fec.h>
21#include <linux/gpio_keys.h>
22#include <linux/input.h>
21 23
22#include <mach/common.h> 24#include <mach/common.h>
23#include <mach/hardware.h> 25#include <mach/hardware.h>
@@ -32,11 +34,13 @@
32 34
33#include "devices-imx51.h" 35#include "devices-imx51.h"
34#include "devices.h" 36#include "devices.h"
37#include "cpu_op-mx51.h"
35 38
36#define BABBAGE_USB_HUB_RESET (0*32 + 7) /* GPIO_1_7 */ 39#define BABBAGE_USB_HUB_RESET (0*32 + 7) /* GPIO_1_7 */
37#define BABBAGE_USBH1_STP (0*32 + 27) /* GPIO_1_27 */ 40#define BABBAGE_USBH1_STP (0*32 + 27) /* GPIO_1_27 */
38#define BABBAGE_PHY_RESET (1*32 + 5) /* GPIO_2_5 */ 41#define BABBAGE_PHY_RESET (1*32 + 5) /* GPIO_2_5 */
39#define BABBAGE_FEC_PHY_RESET (1*32 + 14) /* GPIO_2_14 */ 42#define BABBAGE_FEC_PHY_RESET (1*32 + 14) /* GPIO_2_14 */
43#define BABBAGE_POWER_KEY (1*32 + 21) /* GPIO_2_21 */
40 44
41/* USB_CTRL_1 */ 45/* USB_CTRL_1 */
42#define MX51_USB_CTRL_1_OFFSET 0x10 46#define MX51_USB_CTRL_1_OFFSET 0x10
@@ -46,6 +50,21 @@
46#define MX51_USB_PLL_DIV_19_2_MHZ 0x01 50#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
47#define MX51_USB_PLL_DIV_24_MHZ 0x02 51#define MX51_USB_PLL_DIV_24_MHZ 0x02
48 52
53static struct gpio_keys_button babbage_buttons[] = {
54 {
55 .gpio = BABBAGE_POWER_KEY,
56 .code = BTN_0,
57 .desc = "PWR",
58 .active_low = 1,
59 .wakeup = 1,
60 },
61};
62
63static const struct gpio_keys_platform_data imx_button_data __initconst = {
64 .buttons = babbage_buttons,
65 .nbuttons = ARRAY_SIZE(babbage_buttons),
66};
67
49static struct pad_desc mx51babbage_pads[] = { 68static struct pad_desc mx51babbage_pads[] = {
50 /* UART1 */ 69 /* UART1 */
51 MX51_PAD_UART1_RXD__UART1_RXD, 70 MX51_PAD_UART1_RXD__UART1_RXD,
@@ -112,6 +131,22 @@ static struct pad_desc mx51babbage_pads[] = {
112 131
113 /* FEC PHY reset line */ 132 /* FEC PHY reset line */
114 MX51_PAD_EIM_A20__GPIO_2_14, 133 MX51_PAD_EIM_A20__GPIO_2_14,
134
135 /* SD 1 */
136 MX51_PAD_SD1_CMD__SD1_CMD,
137 MX51_PAD_SD1_CLK__SD1_CLK,
138 MX51_PAD_SD1_DATA0__SD1_DATA0,
139 MX51_PAD_SD1_DATA1__SD1_DATA1,
140 MX51_PAD_SD1_DATA2__SD1_DATA2,
141 MX51_PAD_SD1_DATA3__SD1_DATA3,
142
143 /* SD 2 */
144 MX51_PAD_SD2_CMD__SD2_CMD,
145 MX51_PAD_SD2_CLK__SD2_CLK,
146 MX51_PAD_SD2_DATA0__SD2_DATA0,
147 MX51_PAD_SD2_DATA1__SD2_DATA1,
148 MX51_PAD_SD2_DATA2__SD2_DATA2,
149 MX51_PAD_SD2_DATA3__SD2_DATA3,
115}; 150};
116 151
117/* Serial ports */ 152/* Serial ports */
@@ -281,13 +316,22 @@ __setup("otg_mode=", babbage_otg_mode);
281static void __init mxc_board_init(void) 316static void __init mxc_board_init(void)
282{ 317{
283 struct pad_desc usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP; 318 struct pad_desc usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
319 struct pad_desc power_key = MX51_PAD_EIM_A27__GPIO_2_21;
284 320
321#if defined(CONFIG_CPU_FREQ_IMX)
322 get_cpu_op = mx51_get_cpu_op;
323#endif
285 mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads, 324 mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
286 ARRAY_SIZE(mx51babbage_pads)); 325 ARRAY_SIZE(mx51babbage_pads));
287 mxc_init_imx_uart(); 326 mxc_init_imx_uart();
288 babbage_fec_reset(); 327 babbage_fec_reset();
289 imx51_add_fec(NULL); 328 imx51_add_fec(NULL);
290 329
330 /* Set the PAD settings for the pwr key. */
331 power_key.pad_ctrl = MX51_GPIO_PAD_CTRL_2;
332 mxc_iomux_v3_setup_pad(&power_key);
333 imx51_add_gpio_keys(&imx_button_data);
334
291 imx51_add_imx_i2c(0, &babbage_i2c_data); 335 imx51_add_imx_i2c(0, &babbage_i2c_data);
292 imx51_add_imx_i2c(1, &babbage_i2c_data); 336 imx51_add_imx_i2c(1, &babbage_i2c_data);
293 mxc_register_device(&mxc_hsi2c_device, &babbage_hsi2c_data); 337 mxc_register_device(&mxc_hsi2c_device, &babbage_hsi2c_data);
@@ -304,6 +348,9 @@ static void __init mxc_board_init(void)
304 /* setback USBH1_STP to be function */ 348 /* setback USBH1_STP to be function */
305 mxc_iomux_v3_setup_pad(&usbh1stp); 349 mxc_iomux_v3_setup_pad(&usbh1stp);
306 babbage_usbhub_reset(); 350 babbage_usbhub_reset();
351
352 imx51_add_esdhc(0, NULL);
353 imx51_add_esdhc(1, NULL);
307} 354}
308 355
309static void __init mx51_babbage_timer_init(void) 356static void __init mx51_babbage_timer_init(void)
diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
index f2aae92cf0e2..8ac36d882927 100644
--- a/arch/arm/mach-mx5/clock-mx51.c
+++ b/arch/arm/mach-mx5/clock-mx51.c
@@ -362,7 +362,7 @@ static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
362 return 0; 362 return 0;
363} 363}
364 364
365static unsigned long clk_arm_get_rate(struct clk *clk) 365static unsigned long clk_cpu_get_rate(struct clk *clk)
366{ 366{
367 u32 cacrr, div; 367 u32 cacrr, div;
368 unsigned long parent_rate; 368 unsigned long parent_rate;
@@ -374,6 +374,22 @@ static unsigned long clk_arm_get_rate(struct clk *clk)
374 return parent_rate / div; 374 return parent_rate / div;
375} 375}
376 376
377static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)
378{
379 u32 reg, cpu_podf;
380 unsigned long parent_rate;
381
382 parent_rate = clk_get_rate(clk->parent);
383 cpu_podf = parent_rate / rate - 1;
384 /* use post divider to change freq */
385 reg = __raw_readl(MXC_CCM_CACRR);
386 reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
387 reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
388 __raw_writel(reg, MXC_CCM_CACRR);
389
390 return 0;
391}
392
377static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent) 393static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
378{ 394{
379 u32 reg, mux; 395 u32 reg, mux;
@@ -736,7 +752,8 @@ static struct clk periph_apm_clk = {
736 752
737static struct clk cpu_clk = { 753static struct clk cpu_clk = {
738 .parent = &pll1_sw_clk, 754 .parent = &pll1_sw_clk,
739 .get_rate = clk_arm_get_rate, 755 .get_rate = clk_cpu_get_rate,
756 .set_rate = clk_cpu_set_rate,
740}; 757};
741 758
742static struct clk ahb_clk = { 759static struct clk ahb_clk = {
@@ -1064,6 +1081,7 @@ static struct clk_lookup lookups[] = {
1064 _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk) 1081 _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
1065 _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk) 1082 _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
1066 _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk) 1083 _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
1084 _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
1067}; 1085};
1068 1086
1069static void clk_tree_init(void) 1087static void clk_tree_init(void)
diff --git a/arch/arm/mach-mx5/cpu_op-mx51.c b/arch/arm/mach-mx5/cpu_op-mx51.c
new file mode 100644
index 000000000000..9d34c3d4c024
--- /dev/null
+++ b/arch/arm/mach-mx5/cpu_op-mx51.c
@@ -0,0 +1,29 @@
1/*
2 * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
3 */
4
5/*
6 * The code contained herein is licensed under the GNU General Public
7 * License. You may obtain a copy of the GNU General Public License
8 * Version 2 or later at the following locations:
9 *
10 * http://www.opensource.org/licenses/gpl-license.html
11 * http://www.gnu.org/copyleft/gpl.html
12 */
13
14#include <linux/types.h>
15#include <mach/hardware.h>
16#include <linux/kernel.h>
17
18static struct cpu_op mx51_cpu_op[] = {
19 {
20 .cpu_rate = 160000000,},
21 {
22 .cpu_rate = 800000000,},
23};
24
25struct cpu_op *mx51_get_cpu_op(int *op)
26{
27 *op = ARRAY_SIZE(mx51_cpu_op);
28 return mx51_cpu_op;
29}
diff --git a/arch/arm/mach-mx5/cpu_op-mx51.h b/arch/arm/mach-mx5/cpu_op-mx51.h
new file mode 100644
index 000000000000..97477fecb469
--- /dev/null
+++ b/arch/arm/mach-mx5/cpu_op-mx51.h
@@ -0,0 +1,14 @@
1/*
2 * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
3 */
4
5/*
6 * The code contained herein is licensed under the GNU General Public
7 * License. You may obtain a copy of the GNU General Public License
8 * Version 2 or later at the following locations:
9 *
10 * http://www.opensource.org/licenses/gpl-license.html
11 * http://www.gnu.org/copyleft/gpl.html
12 */
13
14extern struct cpu_op *mx51_get_cpu_op(int *op);
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
index 5cc910e60538..8c50cb5d05f5 100644
--- a/arch/arm/mach-mx5/devices-imx51.h
+++ b/arch/arm/mach-mx5/devices-imx51.h
@@ -13,6 +13,8 @@ extern const struct imx_fec_data imx51_fec_data __initconst;
13#define imx51_add_fec(pdata) \ 13#define imx51_add_fec(pdata) \
14 imx_add_fec(&imx51_fec_data, pdata) 14 imx_add_fec(&imx51_fec_data, pdata)
15 15
16#define imx51_add_gpio_keys(pdata) imx_add_gpio_keys(pdata)
17
16extern const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst; 18extern const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst;
17#define imx51_add_imx_i2c(id, pdata) \ 19#define imx51_add_imx_i2c(id, pdata) \
18 imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata) 20 imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 923f9f5f91ce..2f895553e6a8 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -44,6 +44,13 @@ void __init gic_init_irq(void)
44} 44}
45 45
46#ifdef CONFIG_CACHE_L2X0 46#ifdef CONFIG_CACHE_L2X0
47
48static void omap4_l2x0_disable(void)
49{
50 /* Disable PL310 L2 Cache controller */
51 omap_smc1(0x102, 0x0);
52}
53
47static int __init omap_l2_cache_init(void) 54static int __init omap_l2_cache_init(void)
48{ 55{
49 /* 56 /*
@@ -70,6 +77,12 @@ static int __init omap_l2_cache_init(void)
70 else 77 else
71 l2x0_init(l2cache_base, 0x0e070000, 0xc0000fff); 78 l2x0_init(l2cache_base, 0x0e070000, 0xc0000fff);
72 79
80 /*
81 * Override default outer_cache.disable with a OMAP4
82 * specific one
83 */
84 outer_cache.disable = omap4_l2x0_disable;
85
73 return 0; 86 return 0;
74} 87}
75early_initcall(omap_l2_cache_init); 88early_initcall(omap_l2_cache_init);
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio.h b/arch/arm/mach-s3c2410/include/mach/gpio.h
index b649bf2ccd5c..f7f6b07df30e 100644
--- a/arch/arm/mach-s3c2410/include/mach/gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/gpio.h
@@ -22,6 +22,8 @@
22 22
23#ifdef CONFIG_CPU_S3C244X 23#ifdef CONFIG_CPU_S3C244X
24#define ARCH_NR_GPIOS (32 * 9 + CONFIG_S3C24XX_GPIO_EXTRA) 24#define ARCH_NR_GPIOS (32 * 9 + CONFIG_S3C24XX_GPIO_EXTRA)
25#elif defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2416)
26#define ARCH_NR_GPIOS (32 * 12 + CONFIG_S3C24XX_GPIO_EXTRA)
25#else 27#else
26#define ARCH_NR_GPIOS (256 + CONFIG_S3C24XX_GPIO_EXTRA) 28#define ARCH_NR_GPIOS (256 + CONFIG_S3C24XX_GPIO_EXTRA)
27#endif 29#endif
@@ -30,8 +32,10 @@
30#include <mach/gpio-nrs.h> 32#include <mach/gpio-nrs.h>
31#include <mach/gpio-fns.h> 33#include <mach/gpio-fns.h>
32 34
33#ifdef CONFIG_CPU_S3C24XX 35#ifdef CONFIG_CPU_S3C244X
34#define S3C_GPIO_END (S3C2410_GPIO_BANKJ + 32) 36#define S3C_GPIO_END (S3C2410_GPJ(0) + 32)
37#elif defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2416)
38#define S3C_GPIO_END (S3C2410_GPM(0) + 32)
35#else 39#else
36#define S3C_GPIO_END (S3C2410_GPIO_BANKH + 32) 40#define S3C_GPIO_END (S3C2410_GPH(0) + 32)
37#endif 41#endif
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
index 08ab9dfb6ae6..101aeea22310 100644
--- a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
+++ b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
@@ -118,6 +118,8 @@
118#define S3C2443_SCLKCON_UARTCLK (1<<8) 118#define S3C2443_SCLKCON_UARTCLK (1<<8)
119#define S3C2443_SCLKCON_USBHOST (1<<1) 119#define S3C2443_SCLKCON_USBHOST (1<<1)
120 120
121#define S3C2443_PWRCFG_SLEEP (1<<15)
122
121#include <asm/div64.h> 123#include <asm/div64.h>
122 124
123static inline unsigned int 125static inline unsigned int
diff --git a/arch/arm/mach-s3c2410/include/mach/vmalloc.h b/arch/arm/mach-s3c2410/include/mach/vmalloc.h
index 54297eb0bf5e..7a311e8dddba 100644
--- a/arch/arm/mach-s3c2410/include/mach/vmalloc.h
+++ b/arch/arm/mach-s3c2410/include/mach/vmalloc.h
@@ -15,6 +15,6 @@
15#ifndef __ASM_ARCH_VMALLOC_H 15#ifndef __ASM_ARCH_VMALLOC_H
16#define __ASM_ARCH_VMALLOC_H 16#define __ASM_ARCH_VMALLOC_H
17 17
18#define VMALLOC_END 0xE0000000UL 18#define VMALLOC_END 0xF6000000UL
19 19
20#endif /* __ASM_ARCH_VMALLOC_H */ 20#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c
index bef39f77729d..4c6df51ddf33 100644
--- a/arch/arm/mach-s3c2412/s3c2412.c
+++ b/arch/arm/mach-s3c2412/s3c2412.c
@@ -51,6 +51,7 @@
51#include <plat/clock.h> 51#include <plat/clock.h>
52#include <plat/pm.h> 52#include <plat/pm.h>
53#include <plat/pll.h> 53#include <plat/pll.h>
54#include <plat/nand-core.h>
54 55
55#ifndef CONFIG_CPU_S3C2412_ONLY 56#ifndef CONFIG_CPU_S3C2412_ONLY
56void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO; 57void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
@@ -92,7 +93,7 @@ void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no)
92 /* rename devices that are s3c2412/s3c2413 specific */ 93 /* rename devices that are s3c2412/s3c2413 specific */
93 s3c_device_sdi.name = "s3c2412-sdi"; 94 s3c_device_sdi.name = "s3c2412-sdi";
94 s3c_device_lcd.name = "s3c2412-lcd"; 95 s3c_device_lcd.name = "s3c2412-lcd";
95 s3c_device_nand.name = "s3c2412-nand"; 96 s3c_nand_setname("s3c2412-nand");
96 97
97 /* alter IRQ of SDI controller */ 98 /* alter IRQ of SDI controller */
98 99
diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig
index 657e4fe17f39..87b9c9f003bd 100644
--- a/arch/arm/mach-s3c2416/Kconfig
+++ b/arch/arm/mach-s3c2416/Kconfig
@@ -25,6 +25,11 @@ config S3C2416_DMA
25 help 25 help
26 Internal config node for S3C2416 DMA support 26 Internal config node for S3C2416 DMA support
27 27
28config S3C2416_PM
29 bool
30 help
31 Internal config node to apply S3C2416 power management
32
28menu "S3C2416 Machines" 33menu "S3C2416 Machines"
29 34
30config MACH_SMDK2416 35config MACH_SMDK2416
@@ -33,6 +38,7 @@ config MACH_SMDK2416
33 select S3C_DEV_FB 38 select S3C_DEV_FB
34 select S3C_DEV_HSMMC 39 select S3C_DEV_HSMMC
35 select S3C_DEV_HSMMC1 40 select S3C_DEV_HSMMC1
41 select S3C2416_PM if PM
36 help 42 help
37 Say Y here if you are using an SMDK2416 43 Say Y here if you are using an SMDK2416
38 44
diff --git a/arch/arm/mach-s3c2416/Makefile b/arch/arm/mach-s3c2416/Makefile
index 6c12c7bf40ad..ef038d62ffdb 100644
--- a/arch/arm/mach-s3c2416/Makefile
+++ b/arch/arm/mach-s3c2416/Makefile
@@ -11,7 +11,7 @@ obj- :=
11 11
12obj-$(CONFIG_CPU_S3C2416) += s3c2416.o clock.o 12obj-$(CONFIG_CPU_S3C2416) += s3c2416.o clock.o
13obj-$(CONFIG_CPU_S3C2416) += irq.o 13obj-$(CONFIG_CPU_S3C2416) += irq.o
14 14obj-$(CONFIG_S3C2416_PM) += pm.o
15#obj-$(CONFIG_S3C2416_DMA) += dma.o 15#obj-$(CONFIG_S3C2416_DMA) += dma.o
16 16
17# Machine support 17# Machine support
diff --git a/arch/arm/mach-s3c2416/irq.c b/arch/arm/mach-s3c2416/irq.c
index 89f521d59d06..084d121f368c 100644
--- a/arch/arm/mach-s3c2416/irq.c
+++ b/arch/arm/mach-s3c2416/irq.c
@@ -243,6 +243,8 @@ static int __init s3c2416_irq_add(struct sys_device *sysdev)
243 243
244static struct sysdev_driver s3c2416_irq_driver = { 244static struct sysdev_driver s3c2416_irq_driver = {
245 .add = s3c2416_irq_add, 245 .add = s3c2416_irq_add,
246 .suspend = s3c24xx_irq_suspend,
247 .resume = s3c24xx_irq_resume,
246}; 248};
247 249
248static int __init s3c2416_irq_init(void) 250static int __init s3c2416_irq_init(void)
diff --git a/arch/arm/mach-s3c2416/pm.c b/arch/arm/mach-s3c2416/pm.c
new file mode 100644
index 000000000000..4a04205b04d5
--- /dev/null
+++ b/arch/arm/mach-s3c2416/pm.c
@@ -0,0 +1,84 @@
1/* linux/arch/arm/mach-s3c2416/pm.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * S3C2416 - PM support (Based on Ben Dooks' S3C2412 PM support)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/sysdev.h>
14#include <linux/io.h>
15
16#include <asm/cacheflush.h>
17
18#include <mach/regs-power.h>
19#include <mach/regs-s3c2443-clock.h>
20
21#include <plat/cpu.h>
22#include <plat/pm.h>
23
24extern void s3c2412_sleep_enter(void);
25
26static void s3c2416_cpu_suspend(void)
27{
28 flush_cache_all();
29
30 /* enable wakeup sources regardless of battery state */
31 __raw_writel(S3C2443_PWRCFG_SLEEP, S3C2443_PWRCFG);
32
33 /* set the mode as sleep, 2BED represents "Go to BED" */
34 __raw_writel(0x2BED, S3C2443_PWRMODE);
35
36 s3c2412_sleep_enter();
37}
38
39static void s3c2416_pm_prepare(void)
40{
41 /*
42 * write the magic value u-boot uses to check for resume into
43 * the INFORM0 register, and ensure INFORM1 is set to the
44 * correct address to resume from.
45 */
46 __raw_writel(0x2BED, S3C2412_INFORM0);
47 __raw_writel(virt_to_phys(s3c_cpu_resume), S3C2412_INFORM1);
48}
49
50static int s3c2416_pm_add(struct sys_device *sysdev)
51{
52 pm_cpu_prep = s3c2416_pm_prepare;
53 pm_cpu_sleep = s3c2416_cpu_suspend;
54
55 return 0;
56}
57
58static int s3c2416_pm_suspend(struct sys_device *dev, pm_message_t state)
59{
60 return 0;
61}
62
63static int s3c2416_pm_resume(struct sys_device *dev)
64{
65 /* unset the return-from-sleep amd inform flags */
66 __raw_writel(0x0, S3C2443_PWRMODE);
67 __raw_writel(0x0, S3C2412_INFORM0);
68 __raw_writel(0x0, S3C2412_INFORM1);
69
70 return 0;
71}
72
73static struct sysdev_driver s3c2416_pm_driver = {
74 .add = s3c2416_pm_add,
75 .suspend = s3c2416_pm_suspend,
76 .resume = s3c2416_pm_resume,
77};
78
79static __init int s3c2416_pm_init(void)
80{
81 return sysdev_driver_register(&s3c2416_sysclass, &s3c2416_pm_driver);
82}
83
84arch_initcall(s3c2416_pm_init);
diff --git a/arch/arm/mach-s3c2416/s3c2416.c b/arch/arm/mach-s3c2416/s3c2416.c
index bc30245e133b..63f39cdc0972 100644
--- a/arch/arm/mach-s3c2416/s3c2416.c
+++ b/arch/arm/mach-s3c2416/s3c2416.c
@@ -56,6 +56,7 @@
56 56
57#include <plat/iic-core.h> 57#include <plat/iic-core.h>
58#include <plat/fb-core.h> 58#include <plat/fb-core.h>
59#include <plat/nand-core.h>
59 60
60static struct map_desc s3c2416_iodesc[] __initdata = { 61static struct map_desc s3c2416_iodesc[] __initdata = {
61 IODESC_ENT(WATCHDOG), 62 IODESC_ENT(WATCHDOG),
@@ -100,7 +101,7 @@ void __init s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no)
100{ 101{
101 s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no); 102 s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
102 103
103 s3c_device_nand.name = "s3c2416-nand"; 104 s3c_nand_setname("s3c2412-nand");
104} 105}
105 106
106/* s3c2416_map_io 107/* s3c2416_map_io
diff --git a/arch/arm/mach-s3c2440/s3c244x.c b/arch/arm/mach-s3c2440/s3c244x.c
index 5e4a97e76533..90c1707b9c95 100644
--- a/arch/arm/mach-s3c2440/s3c244x.c
+++ b/arch/arm/mach-s3c2440/s3c244x.c
@@ -44,6 +44,7 @@
44#include <plat/cpu.h> 44#include <plat/cpu.h>
45#include <plat/pm.h> 45#include <plat/pm.h>
46#include <plat/pll.h> 46#include <plat/pll.h>
47#include <plat/nand-core.h>
47 48
48static struct map_desc s3c244x_iodesc[] __initdata = { 49static struct map_desc s3c244x_iodesc[] __initdata = {
49 IODESC_ENT(CLKPWR), 50 IODESC_ENT(CLKPWR),
@@ -68,7 +69,7 @@ void __init s3c244x_map_io(void)
68 69
69 s3c_device_sdi.name = "s3c2440-sdi"; 70 s3c_device_sdi.name = "s3c2440-sdi";
70 s3c_device_i2c0.name = "s3c2440-i2c"; 71 s3c_device_i2c0.name = "s3c2440-i2c";
71 s3c_device_nand.name = "s3c2440-nand"; 72 s3c_nand_setname("s3c2440-nand");
72 s3c_device_ts.name = "s3c2440-ts"; 73 s3c_device_ts.name = "s3c2440-ts";
73 s3c_device_usbgadget.name = "s3c2440-usbgadget"; 74 s3c_device_usbgadget.name = "s3c2440-usbgadget";
74} 75}
diff --git a/arch/arm/mach-s3c2443/s3c2443.c b/arch/arm/mach-s3c2443/s3c2443.c
index 839b6b2ced74..33d18dd1ebd5 100644
--- a/arch/arm/mach-s3c2443/s3c2443.c
+++ b/arch/arm/mach-s3c2443/s3c2443.c
@@ -36,6 +36,7 @@
36#include <plat/devs.h> 36#include <plat/devs.h>
37#include <plat/cpu.h> 37#include <plat/cpu.h>
38#include <plat/fb-core.h> 38#include <plat/fb-core.h>
39#include <plat/nand-core.h>
39 40
40static struct map_desc s3c2443_iodesc[] __initdata = { 41static struct map_desc s3c2443_iodesc[] __initdata = {
41 IODESC_ENT(WATCHDOG), 42 IODESC_ENT(WATCHDOG),
@@ -62,7 +63,7 @@ int __init s3c2443_init(void)
62 63
63 s3c24xx_reset_hook = s3c2443_hard_reset; 64 s3c24xx_reset_hook = s3c2443_hard_reset;
64 65
65 s3c_device_nand.name = "s3c2412-nand"; 66 s3c_nand_setname("s3c2412-nand");
66 s3c_fb_setname("s3c2443-fb"); 67 s3c_fb_setname("s3c2443-fb");
67 68
68 /* change WDT IRQ number */ 69 /* change WDT IRQ number */
diff --git a/arch/arm/mach-s3c24a0/include/mach/vmalloc.h b/arch/arm/mach-s3c24a0/include/mach/vmalloc.h
index 914656820794..6480b15277f3 100644
--- a/arch/arm/mach-s3c24a0/include/mach/vmalloc.h
+++ b/arch/arm/mach-s3c24a0/include/mach/vmalloc.h
@@ -12,6 +12,6 @@
12#ifndef __ASM_ARCH_VMALLOC_H 12#ifndef __ASM_ARCH_VMALLOC_H
13#define __ASM_ARCH_VMALLOC_H 13#define __ASM_ARCH_VMALLOC_H
14 14
15#define VMALLOC_END (0xe0000000UL) 15#define VMALLOC_END 0xF6000000UL
16 16
17#endif /* __ASM_ARCH_VMALLOC_H */ 17#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index 546db5cb8929..1ca7bdc6485c 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -98,12 +98,33 @@ config MACH_ANW6410
98 help 98 help
99 Machine support for the A&W6410 99 Machine support for the A&W6410
100 100
101config MACH_MINI6410
102 bool "MINI6410"
103 select CPU_S3C6410
104 select S3C_DEV_HSMMC
105 select S3C_DEV_HSMMC1
106 select S3C64XX_SETUP_SDHCI
107 select S3C_DEV_USB_HOST
108 select S3C_DEV_NAND
109 select S3C_DEV_FB
110 select S3C64XX_SETUP_FB_24BPP
111 select SAMSUNG_DEV_ADC
112 select SAMSUNG_DEV_TS
113 help
114 Machine support for the FriendlyARM MINI6410
115
101config MACH_REAL6410 116config MACH_REAL6410
102 bool "REAL6410" 117 bool "REAL6410"
103 select CPU_S3C6410 118 select CPU_S3C6410
104 select S3C_DEV_HSMMC 119 select S3C_DEV_HSMMC
105 select S3C_DEV_HSMMC1 120 select S3C_DEV_HSMMC1
106 select S3C64XX_SETUP_SDHCI 121 select S3C64XX_SETUP_SDHCI
122 select S3C_DEV_FB
123 select S3C64XX_SETUP_FB_24BPP
124 select S3C_DEV_NAND
125 select SAMSUNG_DEV_ADC
126 select SAMSUNG_DEV_TS
127 select S3C_DEV_USB_HOST
107 help 128 help
108 Machine support for the CoreWind REAL6410 129 Machine support for the CoreWind REAL6410
109 130
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
index 90221a2e0c55..4657363f0674 100644
--- a/arch/arm/mach-s3c64xx/Makefile
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_MACH_ANW6410) += mach-anw6410.o
53obj-$(CONFIG_MACH_SMDK6400) += mach-smdk6400.o 53obj-$(CONFIG_MACH_SMDK6400) += mach-smdk6400.o
54obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o 54obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o
55obj-$(CONFIG_MACH_REAL6410) += mach-real6410.o 55obj-$(CONFIG_MACH_REAL6410) += mach-real6410.o
56obj-$(CONFIG_MACH_MINI6410) += mach-mini6410.o
56obj-$(CONFIG_MACH_NCP) += mach-ncp.o 57obj-$(CONFIG_MACH_NCP) += mach-ncp.o
57obj-$(CONFIG_MACH_HMT) += mach-hmt.o 58obj-$(CONFIG_MACH_HMT) += mach-hmt.o
58obj-$(CONFIG_MACH_SMARTQ) += mach-smartq.o 59obj-$(CONFIG_MACH_SMARTQ) += mach-smartq.o
diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c
index 3838335f125b..76426a32c013 100644
--- a/arch/arm/mach-s3c64xx/dev-audio.c
+++ b/arch/arm/mach-s3c64xx/dev-audio.c
@@ -22,27 +22,16 @@
22#include <plat/audio.h> 22#include <plat/audio.h>
23#include <plat/gpio-cfg.h> 23#include <plat/gpio-cfg.h>
24 24
25#include <mach/gpio-bank-c.h>
26#include <mach/gpio-bank-d.h>
27#include <mach/gpio-bank-e.h>
28#include <mach/gpio-bank-h.h>
29
30static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev) 25static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev)
31{ 26{
27 unsigned int base;
28
32 switch (pdev->id) { 29 switch (pdev->id) {
33 case 0: 30 case 0:
34 s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); 31 base = S3C64XX_GPD(0);
35 s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK);
36 s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK);
37 s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI);
38 s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0);
39 break; 32 break;
40 case 1: 33 case 1:
41 s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK); 34 base = S3C64XX_GPE(0);
42 s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK);
43 s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK);
44 s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI);
45 s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0);
46 break; 35 break;
47 default: 36 default:
48 printk(KERN_DEBUG "Invalid I2S Controller number: %d\n", 37 printk(KERN_DEBUG "Invalid I2S Controller number: %d\n",
@@ -50,18 +39,17 @@ static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev)
50 return -EINVAL; 39 return -EINVAL;
51 } 40 }
52 41
42 s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(3));
43
53 return 0; 44 return 0;
54} 45}
55 46
56static int s3c64xx_i2sv4_cfg_gpio(struct platform_device *pdev) 47static int s3c64xx_i2sv4_cfg_gpio(struct platform_device *pdev)
57{ 48{
58 s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0); 49 s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C_GPIO_SFN(5));
59 s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1); 50 s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C_GPIO_SFN(5));
60 s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2); 51 s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C_GPIO_SFN(5));
61 s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK); 52 s3c_gpio_cfgpin_range(S3C64XX_GPH(6), 4, S3C_GPIO_SFN(5));
62 s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK);
63 s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK);
64 s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI);
65 53
66 return 0; 54 return 0;
67} 55}
@@ -170,20 +158,14 @@ EXPORT_SYMBOL(s3c64xx_device_iisv4);
170 158
171static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev) 159static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
172{ 160{
161 unsigned int base;
162
173 switch (pdev->id) { 163 switch (pdev->id) {
174 case 0: 164 case 0:
175 s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_PCM0_SCLK); 165 base = S3C64XX_GPD(0);
176 s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_PCM0_EXTCLK);
177 s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_PCM0_FSYNC);
178 s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_PCM0_SIN);
179 s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_PCM0_SOUT);
180 break; 166 break;
181 case 1: 167 case 1:
182 s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_PCM1_SCLK); 168 base = S3C64XX_GPE(0);
183 s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_PCM1_EXTCLK);
184 s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_PCM1_FSYNC);
185 s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_PCM1_SIN);
186 s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_PCM1_SOUT);
187 break; 169 break;
188 default: 170 default:
189 printk(KERN_DEBUG "Invalid PCM Controller number: %d\n", 171 printk(KERN_DEBUG "Invalid PCM Controller number: %d\n",
@@ -191,6 +173,7 @@ static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
191 return -EINVAL; 173 return -EINVAL;
192 } 174 }
193 175
176 s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(2));
194 return 0; 177 return 0;
195} 178}
196 179
@@ -264,24 +247,12 @@ EXPORT_SYMBOL(s3c64xx_device_pcm1);
264 247
265static int s3c64xx_ac97_cfg_gpd(struct platform_device *pdev) 248static int s3c64xx_ac97_cfg_gpd(struct platform_device *pdev)
266{ 249{
267 s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_AC97_BITCLK); 250 return s3c_gpio_cfgpin_range(S3C64XX_GPD(0), 5, S3C_GPIO_SFN(4));
268 s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_AC97_nRESET);
269 s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_AC97_SYNC);
270 s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_AC97_SDI);
271 s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_AC97_SDO);
272
273 return 0;
274} 251}
275 252
276static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev) 253static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev)
277{ 254{
278 s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_AC97_BITCLK); 255 return s3c_gpio_cfgpin_range(S3C64XX_GPE(0), 5, S3C_GPIO_SFN(4));
279 s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_AC97_nRESET);
280 s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_AC97_SYNC);
281 s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_AC97_SDI);
282 s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_AC97_SDO);
283
284 return 0;
285} 256}
286 257
287static struct resource s3c64xx_ac97_resource[] = { 258static struct resource s3c64xx_ac97_resource[] = {
diff --git a/arch/arm/mach-s3c64xx/gpiolib.c b/arch/arm/mach-s3c64xx/gpiolib.c
index 300dee4a667b..fd99a82e82c4 100644
--- a/arch/arm/mach-s3c64xx/gpiolib.c
+++ b/arch/arm/mach-s3c64xx/gpiolib.c
@@ -195,11 +195,6 @@ static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
195 .get_pull = s3c_gpio_getpull_updown, 195 .get_pull = s3c_gpio_getpull_updown,
196}; 196};
197 197
198int s3c64xx_gpio2int_gpn(struct gpio_chip *chip, unsigned pin)
199{
200 return IRQ_EINT(0) + pin;
201}
202
203static struct s3c_gpio_chip gpio_2bit[] = { 198static struct s3c_gpio_chip gpio_2bit[] = {
204 { 199 {
205 .base = S3C64XX_GPF_BASE, 200 .base = S3C64XX_GPF_BASE,
@@ -227,12 +222,13 @@ static struct s3c_gpio_chip gpio_2bit[] = {
227 }, 222 },
228 }, { 223 }, {
229 .base = S3C64XX_GPN_BASE, 224 .base = S3C64XX_GPN_BASE,
225 .irq_base = IRQ_EINT(0),
230 .config = &gpio_2bit_cfg_eint10, 226 .config = &gpio_2bit_cfg_eint10,
231 .chip = { 227 .chip = {
232 .base = S3C64XX_GPN(0), 228 .base = S3C64XX_GPN(0),
233 .ngpio = S3C64XX_GPIO_N_NR, 229 .ngpio = S3C64XX_GPIO_N_NR,
234 .label = "GPN", 230 .label = "GPN",
235 .to_irq = s3c64xx_gpio2int_gpn, 231 .to_irq = samsung_gpiolib_to_irq,
236 }, 232 },
237 }, { 233 }, {
238 .base = S3C64XX_GPO_BASE, 234 .base = S3C64XX_GPO_BASE,
diff --git a/arch/arm/mach-s3c64xx/include/mach/vmalloc.h b/arch/arm/mach-s3c64xx/include/mach/vmalloc.h
index bc0e91389864..23f75e556a30 100644
--- a/arch/arm/mach-s3c64xx/include/mach/vmalloc.h
+++ b/arch/arm/mach-s3c64xx/include/mach/vmalloc.h
@@ -15,6 +15,6 @@
15#ifndef __ASM_ARCH_VMALLOC_H 15#ifndef __ASM_ARCH_VMALLOC_H
16#define __ASM_ARCH_VMALLOC_H 16#define __ASM_ARCH_VMALLOC_H
17 17
18#define VMALLOC_END 0xE0000000UL 18#define VMALLOC_END 0xF6000000UL
19 19
20#endif /* __ASM_ARCH_VMALLOC_H */ 20#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
new file mode 100644
index 000000000000..249c62956471
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -0,0 +1,357 @@
1/* linux/arch/arm/mach-s3c64xx/mach-mini6410.c
2 *
3 * Copyright 2010 Darius Augulis <augulis.darius@gmail.com>
4 * Copyright 2008 Openmoko, Inc.
5 * Copyright 2008 Simtec Electronics
6 * Ben Dooks <ben@simtec.co.uk>
7 * http://armlinux.simtec.co.uk/
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13*/
14
15#include <linux/init.h>
16#include <linux/interrupt.h>
17#include <linux/fb.h>
18#include <linux/gpio.h>
19#include <linux/kernel.h>
20#include <linux/list.h>
21#include <linux/dm9000.h>
22#include <linux/mtd/mtd.h>
23#include <linux/mtd/partitions.h>
24#include <linux/serial_core.h>
25#include <linux/types.h>
26
27#include <asm/mach-types.h>
28#include <asm/mach/arch.h>
29#include <asm/mach/map.h>
30
31#include <mach/map.h>
32#include <mach/regs-fb.h>
33#include <mach/regs-gpio.h>
34#include <mach/regs-modem.h>
35#include <mach/regs-srom.h>
36#include <mach/s3c6410.h>
37
38#include <plat/adc.h>
39#include <plat/cpu.h>
40#include <plat/devs.h>
41#include <plat/fb.h>
42#include <plat/nand.h>
43#include <plat/regs-serial.h>
44#include <plat/ts.h>
45
46#include <video/platform_lcd.h>
47
48#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
49#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
50#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
51
52static struct s3c2410_uartcfg mini6410_uartcfgs[] __initdata = {
53 [0] = {
54 .hwport = 0,
55 .flags = 0,
56 .ucon = UCON,
57 .ulcon = ULCON,
58 .ufcon = UFCON,
59 },
60 [1] = {
61 .hwport = 1,
62 .flags = 0,
63 .ucon = UCON,
64 .ulcon = ULCON,
65 .ufcon = UFCON,
66 },
67 [2] = {
68 .hwport = 2,
69 .flags = 0,
70 .ucon = UCON,
71 .ulcon = ULCON,
72 .ufcon = UFCON,
73 },
74 [3] = {
75 .hwport = 3,
76 .flags = 0,
77 .ucon = UCON,
78 .ulcon = ULCON,
79 .ufcon = UFCON,
80 },
81};
82
83/* DM9000AEP 10/100 ethernet controller */
84
85static struct resource mini6410_dm9k_resource[] = {
86 [0] = {
87 .start = S3C64XX_PA_XM0CSN1,
88 .end = S3C64XX_PA_XM0CSN1 + 1,
89 .flags = IORESOURCE_MEM
90 },
91 [1] = {
92 .start = S3C64XX_PA_XM0CSN1 + 4,
93 .end = S3C64XX_PA_XM0CSN1 + 5,
94 .flags = IORESOURCE_MEM
95 },
96 [2] = {
97 .start = S3C_EINT(7),
98 .end = S3C_EINT(7),
99 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL
100 }
101};
102
103static struct dm9000_plat_data mini6410_dm9k_pdata = {
104 .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
105};
106
107static struct platform_device mini6410_device_eth = {
108 .name = "dm9000",
109 .id = -1,
110 .num_resources = ARRAY_SIZE(mini6410_dm9k_resource),
111 .resource = mini6410_dm9k_resource,
112 .dev = {
113 .platform_data = &mini6410_dm9k_pdata,
114 },
115};
116
117static struct mtd_partition mini6410_nand_part[] = {
118 [0] = {
119 .name = "uboot",
120 .size = SZ_1M,
121 .offset = 0,
122 },
123 [1] = {
124 .name = "kernel",
125 .size = SZ_2M,
126 .offset = SZ_1M,
127 },
128 [2] = {
129 .name = "rootfs",
130 .size = MTDPART_SIZ_FULL,
131 .offset = SZ_1M + SZ_2M,
132 },
133};
134
135static struct s3c2410_nand_set mini6410_nand_sets[] = {
136 [0] = {
137 .name = "nand",
138 .nr_chips = 1,
139 .nr_partitions = ARRAY_SIZE(mini6410_nand_part),
140 .partitions = mini6410_nand_part,
141 },
142};
143
144static struct s3c2410_platform_nand mini6410_nand_info = {
145 .tacls = 25,
146 .twrph0 = 55,
147 .twrph1 = 40,
148 .nr_sets = ARRAY_SIZE(mini6410_nand_sets),
149 .sets = mini6410_nand_sets,
150};
151
152static struct s3c_fb_pd_win mini6410_fb_win[] = {
153 {
154 .win_mode = { /* 4.3" 480x272 */
155 .left_margin = 3,
156 .right_margin = 2,
157 .upper_margin = 1,
158 .lower_margin = 1,
159 .hsync_len = 40,
160 .vsync_len = 1,
161 .xres = 480,
162 .yres = 272,
163 },
164 .max_bpp = 32,
165 .default_bpp = 16,
166 }, {
167 .win_mode = { /* 7.0" 800x480 */
168 .left_margin = 8,
169 .right_margin = 13,
170 .upper_margin = 7,
171 .lower_margin = 5,
172 .hsync_len = 3,
173 .vsync_len = 1,
174 .xres = 800,
175 .yres = 480,
176 },
177 .max_bpp = 32,
178 .default_bpp = 16,
179 },
180};
181
182static struct s3c_fb_platdata mini6410_lcd_pdata __initdata = {
183 .setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
184 .win[0] = &mini6410_fb_win[0],
185 .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
186 .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
187};
188
189static void mini6410_lcd_power_set(struct plat_lcd_data *pd,
190 unsigned int power)
191{
192 if (power)
193 gpio_direction_output(S3C64XX_GPE(0), 1);
194 else
195 gpio_direction_output(S3C64XX_GPE(0), 0);
196}
197
198static struct plat_lcd_data mini6410_lcd_power_data = {
199 .set_power = mini6410_lcd_power_set,
200};
201
202static struct platform_device mini6410_lcd_powerdev = {
203 .name = "platform-lcd",
204 .dev.parent = &s3c_device_fb.dev,
205 .dev.platform_data = &mini6410_lcd_power_data,
206};
207
208static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
209 .delay = 10000,
210 .presc = 49,
211 .oversampling_shift = 2,
212};
213
214static struct platform_device *mini6410_devices[] __initdata = {
215 &mini6410_device_eth,
216 &s3c_device_hsmmc0,
217 &s3c_device_hsmmc1,
218 &s3c_device_ohci,
219 &s3c_device_nand,
220 &s3c_device_fb,
221 &mini6410_lcd_powerdev,
222 &s3c_device_adc,
223 &s3c_device_ts,
224};
225
226static void __init mini6410_map_io(void)
227{
228 u32 tmp;
229
230 s3c64xx_init_io(NULL, 0);
231 s3c24xx_init_clocks(12000000);
232 s3c24xx_init_uarts(mini6410_uartcfgs, ARRAY_SIZE(mini6410_uartcfgs));
233
234 /* set the LCD type */
235 tmp = __raw_readl(S3C64XX_SPCON);
236 tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
237 tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
238 __raw_writel(tmp, S3C64XX_SPCON);
239
240 /* remove the LCD bypass */
241 tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
242 tmp &= ~MIFPCON_LCD_BYPASS;
243 __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
244}
245
246/*
247 * mini6410_features string
248 *
249 * 0-9 LCD configuration
250 *
251 */
252static char mini6410_features_str[12] __initdata = "0";
253
254static int __init mini6410_features_setup(char *str)
255{
256 if (str)
257 strlcpy(mini6410_features_str, str,
258 sizeof(mini6410_features_str));
259 return 1;
260}
261
262__setup("mini6410=", mini6410_features_setup);
263
264#define FEATURE_SCREEN (1 << 0)
265
266struct mini6410_features_t {
267 int done;
268 int lcd_index;
269};
270
271static void mini6410_parse_features(
272 struct mini6410_features_t *features,
273 const char *features_str)
274{
275 const char *fp = features_str;
276
277 features->done = 0;
278 features->lcd_index = 0;
279
280 while (*fp) {
281 char f = *fp++;
282
283 switch (f) {
284 case '0'...'9': /* tft screen */
285 if (features->done & FEATURE_SCREEN) {
286 printk(KERN_INFO "MINI6410: '%c' ignored, "
287 "screen type already set\n", f);
288 } else {
289 int li = f - '0';
290 if (li >= ARRAY_SIZE(mini6410_fb_win))
291 printk(KERN_INFO "MINI6410: '%c' out "
292 "of range LCD mode\n", f);
293 else {
294 features->lcd_index = li;
295 }
296 }
297 features->done |= FEATURE_SCREEN;
298 break;
299 }
300 }
301}
302
303static void __init mini6410_machine_init(void)
304{
305 u32 cs1;
306 struct mini6410_features_t features = { 0 };
307
308 printk(KERN_INFO "MINI6410: Option string mini6410=%s\n",
309 mini6410_features_str);
310
311 /* Parse the feature string */
312 mini6410_parse_features(&features, mini6410_features_str);
313
314 mini6410_lcd_pdata.win[0] = &mini6410_fb_win[features.lcd_index];
315
316 printk(KERN_INFO "MINI6410: selected LCD display is %dx%d\n",
317 mini6410_lcd_pdata.win[0]->win_mode.xres,
318 mini6410_lcd_pdata.win[0]->win_mode.yres);
319
320 s3c_nand_set_platdata(&mini6410_nand_info);
321 s3c_fb_set_platdata(&mini6410_lcd_pdata);
322 s3c24xx_ts_set_platdata(&s3c_ts_platform);
323
324 /* configure nCS1 width to 16 bits */
325
326 cs1 = __raw_readl(S3C64XX_SROM_BW) &
327 ~(S3C64XX_SROM_BW__CS_MASK << S3C64XX_SROM_BW__NCS1__SHIFT);
328 cs1 |= ((1 << S3C64XX_SROM_BW__DATAWIDTH__SHIFT) |
329 (1 << S3C64XX_SROM_BW__WAITENABLE__SHIFT) |
330 (1 << S3C64XX_SROM_BW__BYTEENABLE__SHIFT)) <<
331 S3C64XX_SROM_BW__NCS1__SHIFT;
332 __raw_writel(cs1, S3C64XX_SROM_BW);
333
334 /* set timing for nCS1 suitable for ethernet chip */
335
336 __raw_writel((0 << S3C64XX_SROM_BCX__PMC__SHIFT) |
337 (6 << S3C64XX_SROM_BCX__TACP__SHIFT) |
338 (4 << S3C64XX_SROM_BCX__TCAH__SHIFT) |
339 (1 << S3C64XX_SROM_BCX__TCOH__SHIFT) |
340 (13 << S3C64XX_SROM_BCX__TACC__SHIFT) |
341 (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) |
342 (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1);
343
344 gpio_request(S3C64XX_GPF(15), "LCD power");
345 gpio_request(S3C64XX_GPE(0), "LCD power");
346
347 platform_add_devices(mini6410_devices, ARRAY_SIZE(mini6410_devices));
348}
349
350MACHINE_START(MINI6410, "MINI6410")
351 /* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
352 .boot_params = S3C64XX_PA_SDRAM + 0x100,
353 .init_irq = s3c6410_init_irq,
354 .map_io = mini6410_map_io,
355 .init_machine = mini6410_machine_init,
356 .timer = &s3c24xx_timer,
357MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index 4b4475da8ec6..f9ef9b5c5f5a 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -12,23 +12,39 @@
12 * 12 *
13*/ 13*/
14 14
15#include <linux/kernel.h> 15#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/fb.h>
18#include <linux/gpio.h>
19#include <linux/kernel.h>
18#include <linux/list.h> 20#include <linux/list.h>
19#include <linux/init.h>
20#include <linux/dm9000.h> 21#include <linux/dm9000.h>
21#include <linux/serial_core.h> 22#include <linux/mtd/mtd.h>
23#include <linux/mtd/partitions.h>
22#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/serial_core.h>
26#include <linux/types.h>
27
23#include <asm/mach-types.h> 28#include <asm/mach-types.h>
24#include <asm/mach/arch.h> 29#include <asm/mach/arch.h>
25#include <asm/mach/map.h> 30#include <asm/mach/map.h>
31
26#include <mach/map.h> 32#include <mach/map.h>
27#include <mach/s3c6410.h> 33#include <mach/regs-fb.h>
34#include <mach/regs-gpio.h>
35#include <mach/regs-modem.h>
28#include <mach/regs-srom.h> 36#include <mach/regs-srom.h>
37#include <mach/s3c6410.h>
38
39#include <plat/adc.h>
29#include <plat/cpu.h> 40#include <plat/cpu.h>
30#include <plat/devs.h> 41#include <plat/devs.h>
42#include <plat/fb.h>
43#include <plat/nand.h>
31#include <plat/regs-serial.h> 44#include <plat/regs-serial.h>
45#include <plat/ts.h>
46
47#include <video/platform_lcd.h>
32 48
33#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK) 49#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
34#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB) 50#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
@@ -99,22 +115,192 @@ static struct platform_device real6410_device_eth = {
99 }, 115 },
100}; 116};
101 117
118static struct s3c_fb_pd_win real6410_fb_win[] = {
119 {
120 .win_mode = { /* 4.3" 480x272 */
121 .left_margin = 3,
122 .right_margin = 2,
123 .upper_margin = 1,
124 .lower_margin = 1,
125 .hsync_len = 40,
126 .vsync_len = 1,
127 .xres = 480,
128 .yres = 272,
129 },
130 .max_bpp = 32,
131 .default_bpp = 16,
132 }, {
133 .win_mode = { /* 7.0" 800x480 */
134 .left_margin = 8,
135 .right_margin = 13,
136 .upper_margin = 7,
137 .lower_margin = 5,
138 .hsync_len = 3,
139 .vsync_len = 1,
140 .xres = 800,
141 .yres = 480,
142 },
143 .max_bpp = 32,
144 .default_bpp = 16,
145 },
146};
147
148static struct s3c_fb_platdata real6410_lcd_pdata __initdata = {
149 .setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
150 .win[0] = &real6410_fb_win[0],
151 .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
152 .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
153};
154
155static struct mtd_partition real6410_nand_part[] = {
156 [0] = {
157 .name = "uboot",
158 .size = SZ_1M,
159 .offset = 0,
160 },
161 [1] = {
162 .name = "kernel",
163 .size = SZ_2M,
164 .offset = SZ_1M,
165 },
166 [2] = {
167 .name = "rootfs",
168 .size = MTDPART_SIZ_FULL,
169 .offset = SZ_1M + SZ_2M,
170 },
171};
172
173static struct s3c2410_nand_set real6410_nand_sets[] = {
174 [0] = {
175 .name = "nand",
176 .nr_chips = 1,
177 .nr_partitions = ARRAY_SIZE(real6410_nand_part),
178 .partitions = real6410_nand_part,
179 },
180};
181
182static struct s3c2410_platform_nand real6410_nand_info = {
183 .tacls = 25,
184 .twrph0 = 55,
185 .twrph1 = 40,
186 .nr_sets = ARRAY_SIZE(real6410_nand_sets),
187 .sets = real6410_nand_sets,
188};
189
102static struct platform_device *real6410_devices[] __initdata = { 190static struct platform_device *real6410_devices[] __initdata = {
103 &real6410_device_eth, 191 &real6410_device_eth,
104 &s3c_device_hsmmc0, 192 &s3c_device_hsmmc0,
105 &s3c_device_hsmmc1, 193 &s3c_device_hsmmc1,
194 &s3c_device_fb,
195 &s3c_device_nand,
196 &s3c_device_adc,
197 &s3c_device_ts,
198 &s3c_device_ohci,
199};
200
201static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
202 .delay = 10000,
203 .presc = 49,
204 .oversampling_shift = 2,
106}; 205};
107 206
108static void __init real6410_map_io(void) 207static void __init real6410_map_io(void)
109{ 208{
209 u32 tmp;
210
110 s3c64xx_init_io(NULL, 0); 211 s3c64xx_init_io(NULL, 0);
111 s3c24xx_init_clocks(12000000); 212 s3c24xx_init_clocks(12000000);
112 s3c24xx_init_uarts(real6410_uartcfgs, ARRAY_SIZE(real6410_uartcfgs)); 213 s3c24xx_init_uarts(real6410_uartcfgs, ARRAY_SIZE(real6410_uartcfgs));
214
215 /* set the LCD type */
216 tmp = __raw_readl(S3C64XX_SPCON);
217 tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
218 tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
219 __raw_writel(tmp, S3C64XX_SPCON);
220
221 /* remove the LCD bypass */
222 tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
223 tmp &= ~MIFPCON_LCD_BYPASS;
224 __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
225}
226
227/*
228 * real6410_features string
229 *
230 * 0-9 LCD configuration
231 *
232 */
233static char real6410_features_str[12] __initdata = "0";
234
235static int __init real6410_features_setup(char *str)
236{
237 if (str)
238 strlcpy(real6410_features_str, str,
239 sizeof(real6410_features_str));
240 return 1;
241}
242
243__setup("real6410=", real6410_features_setup);
244
245#define FEATURE_SCREEN (1 << 0)
246
247struct real6410_features_t {
248 int done;
249 int lcd_index;
250};
251
252static void real6410_parse_features(
253 struct real6410_features_t *features,
254 const char *features_str)
255{
256 const char *fp = features_str;
257
258 features->done = 0;
259 features->lcd_index = 0;
260
261 while (*fp) {
262 char f = *fp++;
263
264 switch (f) {
265 case '0'...'9': /* tft screen */
266 if (features->done & FEATURE_SCREEN) {
267 printk(KERN_INFO "REAL6410: '%c' ignored, "
268 "screen type already set\n", f);
269 } else {
270 int li = f - '0';
271 if (li >= ARRAY_SIZE(real6410_fb_win))
272 printk(KERN_INFO "REAL6410: '%c' out "
273 "of range LCD mode\n", f);
274 else {
275 features->lcd_index = li;
276 }
277 }
278 features->done |= FEATURE_SCREEN;
279 break;
280 }
281 }
113} 282}
114 283
115static void __init real6410_machine_init(void) 284static void __init real6410_machine_init(void)
116{ 285{
117 u32 cs1; 286 u32 cs1;
287 struct real6410_features_t features = { 0 };
288
289 printk(KERN_INFO "REAL6410: Option string real6410=%s\n",
290 real6410_features_str);
291
292 /* Parse the feature string */
293 real6410_parse_features(&features, real6410_features_str);
294
295 real6410_lcd_pdata.win[0] = &real6410_fb_win[features.lcd_index];
296
297 printk(KERN_INFO "REAL6410: selected LCD display is %dx%d\n",
298 real6410_lcd_pdata.win[0]->win_mode.xres,
299 real6410_lcd_pdata.win[0]->win_mode.yres);
300
301 s3c_fb_set_platdata(&real6410_lcd_pdata);
302 s3c_nand_set_platdata(&real6410_nand_info);
303 s3c24xx_ts_set_platdata(&s3c_ts_platform);
118 304
119 /* configure nCS1 width to 16 bits */ 305 /* configure nCS1 width to 16 bits */
120 306
@@ -136,6 +322,8 @@ static void __init real6410_machine_init(void)
136 (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) | 322 (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) |
137 (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1); 323 (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1);
138 324
325 gpio_request(S3C64XX_GPF(15), "LCD power");
326
139 platform_add_devices(real6410_devices, ARRAY_SIZE(real6410_devices)); 327 platform_add_devices(real6410_devices, ARRAY_SIZE(real6410_devices));
140} 328}
141 329
diff --git a/arch/arm/mach-s3c64xx/setup-fb-24bpp.c b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c
index 000736877df2..8f3091182f9c 100644
--- a/arch/arm/mach-s3c64xx/setup-fb-24bpp.c
+++ b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c
@@ -23,15 +23,6 @@
23 23
24extern void s3c64xx_fb_gpio_setup_24bpp(void) 24extern void s3c64xx_fb_gpio_setup_24bpp(void)
25{ 25{
26 unsigned int gpio; 26 s3c_gpio_cfgrange_nopull(S3C64XX_GPI(0), 16, S3C_GPIO_SFN(2));
27 27 s3c_gpio_cfgrange_nopull(S3C64XX_GPJ(0), 12, S3C_GPIO_SFN(2));
28 for (gpio = S3C64XX_GPI(0); gpio <= S3C64XX_GPI(15); gpio++) {
29 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
30 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
31 }
32
33 for (gpio = S3C64XX_GPJ(0); gpio <= S3C64XX_GPJ(11); gpio++) {
34 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
35 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
36 }
37} 28}
diff --git a/arch/arm/mach-s3c64xx/setup-ide.c b/arch/arm/mach-s3c64xx/setup-ide.c
index c12c315f33bc..41b425602d88 100644
--- a/arch/arm/mach-s3c64xx/setup-ide.c
+++ b/arch/arm/mach-s3c64xx/setup-ide.c
@@ -17,11 +17,11 @@
17#include <mach/map.h> 17#include <mach/map.h>
18#include <mach/regs-clock.h> 18#include <mach/regs-clock.h>
19#include <plat/gpio-cfg.h> 19#include <plat/gpio-cfg.h>
20#include <plat/ata.h>
20 21
21void s3c64xx_ide_setup_gpio(void) 22void s3c64xx_ide_setup_gpio(void)
22{ 23{
23 u32 reg; 24 u32 reg;
24 u32 gpio = 0;
25 25
26 reg = readl(S3C_MEM_SYS_CFG) & (~0x3f); 26 reg = readl(S3C_MEM_SYS_CFG) & (~0x3f);
27 27
@@ -32,15 +32,12 @@ void s3c64xx_ide_setup_gpio(void)
32 s3c_gpio_cfgpin(S3C64XX_GPB(4), S3C_GPIO_SFN(4)); 32 s3c_gpio_cfgpin(S3C64XX_GPB(4), S3C_GPIO_SFN(4));
33 33
34 /* Set XhiDATA[15:0] pins as CF Data[15:0] */ 34 /* Set XhiDATA[15:0] pins as CF Data[15:0] */
35 for (gpio = S3C64XX_GPK(0); gpio <= S3C64XX_GPK(15); gpio++) 35 s3c_gpio_cfgpin_range(S3C64XX_GPK(0), 16, S3C_GPIO_SFN(5));
36 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(5));
37 36
38 /* Set XhiADDR[2:0] pins as CF ADDR[2:0] */ 37 /* Set XhiADDR[2:0] pins as CF ADDR[2:0] */
39 for (gpio = S3C64XX_GPL(0); gpio <= S3C64XX_GPL(2); gpio++) 38 s3c_gpio_cfgpin_range(S3C64XX_GPL(0), 3, S3C_GPIO_SFN(6));
40 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6));
41 39
42 /* Set Xhi ctrl pins as CF ctrl pins(IORDY, IOWR, IORD, CE[0:1]) */ 40 /* Set Xhi ctrl pins as CF ctrl pins(IORDY, IOWR, IORD, CE[0:1]) */
43 s3c_gpio_cfgpin(S3C64XX_GPM(5), S3C_GPIO_SFN(1)); 41 s3c_gpio_cfgpin(S3C64XX_GPM(5), S3C_GPIO_SFN(1));
44 for (gpio = S3C64XX_GPM(0); gpio <= S3C64XX_GPM(4); gpio++) 42 s3c_gpio_cfgpin_range(S3C64XX_GPM(0), 5, S3C_GPIO_SFN(6));
45 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6));
46} 43}
diff --git a/arch/arm/mach-s3c64xx/setup-keypad.c b/arch/arm/mach-s3c64xx/setup-keypad.c
index abc34e4e1a93..f8ed0d22db70 100644
--- a/arch/arm/mach-s3c64xx/setup-keypad.c
+++ b/arch/arm/mach-s3c64xx/setup-keypad.c
@@ -12,23 +12,13 @@
12 12
13#include <linux/gpio.h> 13#include <linux/gpio.h>
14#include <plat/gpio-cfg.h> 14#include <plat/gpio-cfg.h>
15#include <plat/keypad.h>
15 16
16void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) 17void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
17{ 18{
18 unsigned int gpio;
19 unsigned int end;
20
21 /* Set all the necessary GPK pins to special-function 3: KP_ROW[x] */ 19 /* Set all the necessary GPK pins to special-function 3: KP_ROW[x] */
22 end = S3C64XX_GPK(8 + rows); 20 s3c_gpio_cfgrange_nopull(S3C64XX_GPK(8), 8 + rows, S3C_GPIO_SFN(3));
23 for (gpio = S3C64XX_GPK(8); gpio < end; gpio++) {
24 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
25 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
26 }
27 21
28 /* Set all the necessary GPL pins to special-function 3: KP_COL[x] */ 22 /* Set all the necessary GPL pins to special-function 3: KP_COL[x] */
29 end = S3C64XX_GPL(0 + cols); 23 s3c_gpio_cfgrange_nopull(S3C64XX_GPL(0), cols, S3C_GPIO_SFN(3));
30 for (gpio = S3C64XX_GPL(0); gpio < end; gpio++) {
31 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
32 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
33 }
34} 24}
diff --git a/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c b/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c
index 322359591374..6eac071afae2 100644
--- a/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c
+++ b/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c
@@ -24,16 +24,9 @@
24void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) 24void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
25{ 25{
26 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; 26 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
27 unsigned int gpio;
28 unsigned int end;
29 27
30 end = S3C64XX_GPG(2 + width); 28 /* Set all the necessary GPG pins to special-function 2 */
31 29 s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width, S3C_GPIO_SFN(2));
32 /* Set all the necessary GPG pins to special-function 0 */
33 for (gpio = S3C64XX_GPG(0); gpio < end; gpio++) {
34 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
35 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
36 }
37 30
38 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { 31 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
39 s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP); 32 s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
@@ -44,16 +37,9 @@ void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
44void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) 37void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
45{ 38{
46 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; 39 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
47 unsigned int gpio;
48 unsigned int end;
49 40
50 end = S3C64XX_GPH(2 + width); 41 /* Set all the necessary GPH pins to special-function 2 */
51 42 s3c_gpio_cfgrange_nopull(S3C64XX_GPH(0), 2 + width, S3C_GPIO_SFN(2));
52 /* Set all the necessary GPG pins to special-function 0 */
53 for (gpio = S3C64XX_GPH(0); gpio < end; gpio++) {
54 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
55 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
56 }
57 43
58 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { 44 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
59 s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP); 45 s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
@@ -63,20 +49,9 @@ void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
63 49
64void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) 50void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
65{ 51{
66 unsigned int gpio; 52 /* Set all the necessary GPH pins to special-function 3 */
67 unsigned int end; 53 s3c_gpio_cfgrange_nopull(S3C64XX_GPH(6), width, S3C_GPIO_SFN(3));
68 54
69 end = S3C64XX_GPH(6 + width); 55 /* Set all the necessary GPC pins to special-function 3 */
70 56 s3c_gpio_cfgrange_nopull(S3C64XX_GPC(4), 2, S3C_GPIO_SFN(3));
71 /* Set all the necessary GPH pins to special-function 1 */
72 for (gpio = S3C64XX_GPH(6); gpio < end; gpio++) {
73 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
74 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
75 }
76
77 /* Set all the necessary GPC pins to special-function 1 */
78 for (gpio = S3C64XX_GPC(4); gpio < S3C64XX_GPC(6); gpio++) {
79 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
80 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
81 }
82} 57}
diff --git a/arch/arm/mach-s5p6442/Kconfig b/arch/arm/mach-s5p6442/Kconfig
index 0fda0a5df968..33569e4007c4 100644
--- a/arch/arm/mach-s5p6442/Kconfig
+++ b/arch/arm/mach-s5p6442/Kconfig
@@ -11,7 +11,6 @@ if ARCH_S5P6442
11 11
12config CPU_S5P6442 12config CPU_S5P6442
13 bool 13 bool
14 select PLAT_S5P
15 select S3C_PL330_DMA 14 select S3C_PL330_DMA
16 help 15 help
17 Enable S5P6442 CPU support 16 Enable S5P6442 CPU support
diff --git a/arch/arm/mach-s5p6442/clock.c b/arch/arm/mach-s5p6442/clock.c
index dcd20f17212a..16d6e7e61b50 100644
--- a/arch/arm/mach-s5p6442/clock.c
+++ b/arch/arm/mach-s5p6442/clock.c
@@ -192,6 +192,11 @@ static struct clk clk_pclkd1 = {
192 .parent = &clk_hclkd1, 192 .parent = &clk_hclkd1,
193}; 193};
194 194
195int s5p6442_clk_ip0_ctrl(struct clk *clk, int enable)
196{
197 return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable);
198}
199
195int s5p6442_clk_ip3_ctrl(struct clk *clk, int enable) 200int s5p6442_clk_ip3_ctrl(struct clk *clk, int enable)
196{ 201{
197 return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable); 202 return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
@@ -335,6 +340,16 @@ void __init_or_cpufreq s5p6442_setup_clocks(void)
335 clk_pclkd1.rate = pclkd1; 340 clk_pclkd1.rate = pclkd1;
336} 341}
337 342
343static struct clk init_clocks_disable[] = {
344 {
345 .name = "pdma",
346 .id = -1,
347 .parent = &clk_pclkd1,
348 .enable = s5p6442_clk_ip0_ctrl,
349 .ctrlbit = (1 << 3),
350 },
351};
352
338static struct clk init_clocks[] = { 353static struct clk init_clocks[] = {
339 { 354 {
340 .name = "systimer", 355 .name = "systimer",
@@ -393,10 +408,23 @@ static struct clk *clks[] __initdata = {
393 408
394void __init s5p6442_register_clocks(void) 409void __init s5p6442_register_clocks(void)
395{ 410{
411 struct clk *clkptr;
412 int i, ret;
413
396 s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); 414 s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
397 415
398 s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); 416 s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
399 s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); 417 s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
400 418
419 clkptr = init_clocks_disable;
420 for (i = 0; i < ARRAY_SIZE(init_clocks_disable); i++, clkptr++) {
421 ret = s3c24xx_register_clock(clkptr);
422 if (ret < 0) {
423 printk(KERN_ERR "Fail to register clock %s (%d)\n",
424 clkptr->name, ret);
425 } else
426 (clkptr->enable)(clkptr, 0);
427 }
428
401 s3c_pwmclk_init(); 429 s3c_pwmclk_init();
402} 430}
diff --git a/arch/arm/mach-s5p6442/dev-audio.c b/arch/arm/mach-s5p6442/dev-audio.c
index 7a4e34720b7b..3462197ff352 100644
--- a/arch/arm/mach-s5p6442/dev-audio.c
+++ b/arch/arm/mach-s5p6442/dev-audio.c
@@ -21,22 +21,16 @@
21 21
22static int s5p6442_cfg_i2s(struct platform_device *pdev) 22static int s5p6442_cfg_i2s(struct platform_device *pdev)
23{ 23{
24 unsigned int base;
25
24 /* configure GPIO for i2s port */ 26 /* configure GPIO for i2s port */
25 switch (pdev->id) { 27 switch (pdev->id) {
26 case 1: 28 case 1:
27 s3c_gpio_cfgpin(S5P6442_GPC1(0), S3C_GPIO_SFN(2)); 29 base = S5P6442_GPC1(0);
28 s3c_gpio_cfgpin(S5P6442_GPC1(1), S3C_GPIO_SFN(2));
29 s3c_gpio_cfgpin(S5P6442_GPC1(2), S3C_GPIO_SFN(2));
30 s3c_gpio_cfgpin(S5P6442_GPC1(3), S3C_GPIO_SFN(2));
31 s3c_gpio_cfgpin(S5P6442_GPC1(4), S3C_GPIO_SFN(2));
32 break; 30 break;
33 31
34 case -1: 32 case -1:
35 s3c_gpio_cfgpin(S5P6442_GPC0(0), S3C_GPIO_SFN(2)); 33 base = S5P6442_GPC0(0);
36 s3c_gpio_cfgpin(S5P6442_GPC0(1), S3C_GPIO_SFN(2));
37 s3c_gpio_cfgpin(S5P6442_GPC0(2), S3C_GPIO_SFN(2));
38 s3c_gpio_cfgpin(S5P6442_GPC0(3), S3C_GPIO_SFN(2));
39 s3c_gpio_cfgpin(S5P6442_GPC0(4), S3C_GPIO_SFN(2));
40 break; 34 break;
41 35
42 default: 36 default:
@@ -44,6 +38,7 @@ static int s5p6442_cfg_i2s(struct platform_device *pdev)
44 return -EINVAL; 38 return -EINVAL;
45 } 39 }
46 40
41 s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(2));
47 return 0; 42 return 0;
48} 43}
49 44
@@ -111,21 +106,15 @@ struct platform_device s5p6442_device_iis1 = {
111 106
112static int s5p6442_pcm_cfg_gpio(struct platform_device *pdev) 107static int s5p6442_pcm_cfg_gpio(struct platform_device *pdev)
113{ 108{
109 unsigned int base;
110
114 switch (pdev->id) { 111 switch (pdev->id) {
115 case 0: 112 case 0:
116 s3c_gpio_cfgpin(S5P6442_GPC0(0), S3C_GPIO_SFN(3)); 113 base = S5P6442_GPC0(0);
117 s3c_gpio_cfgpin(S5P6442_GPC0(1), S3C_GPIO_SFN(3));
118 s3c_gpio_cfgpin(S5P6442_GPC0(2), S3C_GPIO_SFN(3));
119 s3c_gpio_cfgpin(S5P6442_GPC0(3), S3C_GPIO_SFN(3));
120 s3c_gpio_cfgpin(S5P6442_GPC0(4), S3C_GPIO_SFN(3));
121 break; 114 break;
122 115
123 case 1: 116 case 1:
124 s3c_gpio_cfgpin(S5P6442_GPC1(0), S3C_GPIO_SFN(3)); 117 base = S5P6442_GPC1(0);
125 s3c_gpio_cfgpin(S5P6442_GPC1(1), S3C_GPIO_SFN(3));
126 s3c_gpio_cfgpin(S5P6442_GPC1(2), S3C_GPIO_SFN(3));
127 s3c_gpio_cfgpin(S5P6442_GPC1(3), S3C_GPIO_SFN(3));
128 s3c_gpio_cfgpin(S5P6442_GPC1(4), S3C_GPIO_SFN(3));
129 break; 118 break;
130 119
131 default: 120 default:
@@ -133,6 +122,7 @@ static int s5p6442_pcm_cfg_gpio(struct platform_device *pdev)
133 return -EINVAL; 122 return -EINVAL;
134 } 123 }
135 124
125 s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(3));
136 return 0; 126 return 0;
137} 127}
138 128
diff --git a/arch/arm/mach-s5p6442/dev-spi.c b/arch/arm/mach-s5p6442/dev-spi.c
index e894651a88bd..cce8c2470709 100644
--- a/arch/arm/mach-s5p6442/dev-spi.c
+++ b/arch/arm/mach-s5p6442/dev-spi.c
@@ -38,11 +38,9 @@ static int s5p6442_spi_cfg_gpio(struct platform_device *pdev)
38 switch (pdev->id) { 38 switch (pdev->id) {
39 case 0: 39 case 0:
40 s3c_gpio_cfgpin(S5P6442_GPB(0), S3C_GPIO_SFN(2)); 40 s3c_gpio_cfgpin(S5P6442_GPB(0), S3C_GPIO_SFN(2));
41 s3c_gpio_cfgpin(S5P6442_GPB(2), S3C_GPIO_SFN(2));
42 s3c_gpio_cfgpin(S5P6442_GPB(3), S3C_GPIO_SFN(2));
43 s3c_gpio_setpull(S5P6442_GPB(0), S3C_GPIO_PULL_UP); 41 s3c_gpio_setpull(S5P6442_GPB(0), S3C_GPIO_PULL_UP);
44 s3c_gpio_setpull(S5P6442_GPB(2), S3C_GPIO_PULL_UP); 42 s3c_gpio_cfgall_range(S5P6442_GPB(2), 2,
45 s3c_gpio_setpull(S5P6442_GPB(3), S3C_GPIO_PULL_UP); 43 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
46 break; 44 break;
47 45
48 default: 46 default:
diff --git a/arch/arm/mach-s5p6442/dma.c b/arch/arm/mach-s5p6442/dma.c
index ad4f8704b93d..7dfb13654f8a 100644
--- a/arch/arm/mach-s5p6442/dma.c
+++ b/arch/arm/mach-s5p6442/dma.c
@@ -82,7 +82,7 @@ static struct s3c_pl330_platdata s5p6442_pdma_pdata = {
82 82
83static struct platform_device s5p6442_device_pdma = { 83static struct platform_device s5p6442_device_pdma = {
84 .name = "s3c-pl330", 84 .name = "s3c-pl330",
85 .id = 1, 85 .id = -1,
86 .num_resources = ARRAY_SIZE(s5p6442_pdma_resource), 86 .num_resources = ARRAY_SIZE(s5p6442_pdma_resource),
87 .resource = s5p6442_pdma_resource, 87 .resource = s5p6442_pdma_resource,
88 .dev = { 88 .dev = {
diff --git a/arch/arm/mach-s5p6442/include/mach/regs-clock.h b/arch/arm/mach-s5p6442/include/mach/regs-clock.h
index d8360b5d4ece..00828a336991 100644
--- a/arch/arm/mach-s5p6442/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5p6442/include/mach/regs-clock.h
@@ -46,6 +46,7 @@
46#define S5P_CLK_DIV5 S5P_CLKREG(0x314) 46#define S5P_CLK_DIV5 S5P_CLKREG(0x314)
47#define S5P_CLK_DIV6 S5P_CLKREG(0x318) 47#define S5P_CLK_DIV6 S5P_CLKREG(0x318)
48 48
49#define S5P_CLKGATE_IP0 S5P_CLKREG(0x460)
49#define S5P_CLKGATE_IP3 S5P_CLKREG(0x46C) 50#define S5P_CLKGATE_IP3 S5P_CLKREG(0x46C)
50 51
51/* CLK_OUT */ 52/* CLK_OUT */
diff --git a/arch/arm/mach-s5p6442/include/mach/vmalloc.h b/arch/arm/mach-s5p6442/include/mach/vmalloc.h
index f5c83f02c18e..4aa55e55ac47 100644
--- a/arch/arm/mach-s5p6442/include/mach/vmalloc.h
+++ b/arch/arm/mach-s5p6442/include/mach/vmalloc.h
@@ -12,6 +12,6 @@
12#ifndef __ASM_ARCH_VMALLOC_H 12#ifndef __ASM_ARCH_VMALLOC_H
13#define __ASM_ARCH_VMALLOC_H 13#define __ASM_ARCH_VMALLOC_H
14 14
15#define VMALLOC_END 0xE0000000UL 15#define VMALLOC_END 0xF6000000UL
16 16
17#endif /* __ASM_ARCH_VMALLOC_H */ 17#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
index fbcae9352022..164d2783d381 100644
--- a/arch/arm/mach-s5p64x0/Kconfig
+++ b/arch/arm/mach-s5p64x0/Kconfig
@@ -9,14 +9,12 @@ if ARCH_S5P64X0
9 9
10config CPU_S5P6440 10config CPU_S5P6440
11 bool 11 bool
12 select PLAT_S5P
13 select S3C_PL330_DMA 12 select S3C_PL330_DMA
14 help 13 help
15 Enable S5P6440 CPU support 14 Enable S5P6440 CPU support
16 15
17config CPU_S5P6450 16config CPU_S5P6450
18 bool 17 bool
19 select PLAT_S5P
20 select S3C_PL330_DMA 18 select S3C_PL330_DMA
21 help 19 help
22 Enable S5P6450 CPU support 20 Enable S5P6450 CPU support
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
index f93dcd8b4d6a..e4883dc1c8d7 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6440.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c
@@ -79,13 +79,16 @@ static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate)
79 __raw_writel(epll_con, S5P64X0_EPLL_CON); 79 __raw_writel(epll_con, S5P64X0_EPLL_CON);
80 __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K); 80 __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
81 81
82 printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
83 clk->rate, rate);
84
82 clk->rate = rate; 85 clk->rate = rate;
83 86
84 return 0; 87 return 0;
85} 88}
86 89
87static struct clk_ops s5p6440_epll_ops = { 90static struct clk_ops s5p6440_epll_ops = {
88 .get_rate = s5p64x0_epll_get_rate, 91 .get_rate = s5p_epll_get_rate,
89 .set_rate = s5p6440_epll_set_rate, 92 .set_rate = s5p6440_epll_set_rate,
90}; 93};
91 94
@@ -150,6 +153,12 @@ static struct clk init_clocks_disable[] = {
150 .enable = s5p64x0_hclk0_ctrl, 153 .enable = s5p64x0_hclk0_ctrl,
151 .ctrlbit = (1 << 8), 154 .ctrlbit = (1 << 8),
152 }, { 155 }, {
156 .name = "pdma",
157 .id = -1,
158 .parent = &clk_hclk_low.clk,
159 .enable = s5p64x0_hclk0_ctrl,
160 .ctrlbit = (1 << 12),
161 }, {
153 .name = "hsmmc", 162 .name = "hsmmc",
154 .id = 0, 163 .id = 0,
155 .parent = &clk_hclk_low.clk, 164 .parent = &clk_hclk_low.clk,
@@ -331,12 +340,6 @@ static struct clk init_clocks[] = {
331 .enable = s5p64x0_hclk0_ctrl, 340 .enable = s5p64x0_hclk0_ctrl,
332 .ctrlbit = (1 << 21), 341 .ctrlbit = (1 << 21),
333 }, { 342 }, {
334 .name = "dma",
335 .id = -1,
336 .parent = &clk_hclk_low.clk,
337 .enable = s5p64x0_hclk0_ctrl,
338 .ctrlbit = (1 << 12),
339 }, {
340 .name = "uart", 343 .name = "uart",
341 .id = 0, 344 .id = 0,
342 .parent = &clk_pclk_low.clk, 345 .parent = &clk_pclk_low.clk,
@@ -548,7 +551,7 @@ void __init_or_cpufreq s5p6440_setup_clocks(void)
548 551
549 /* Set S5P6440 functions for clk_fout_epll */ 552 /* Set S5P6440 functions for clk_fout_epll */
550 553
551 clk_fout_epll.enable = s5p64x0_epll_enable; 554 clk_fout_epll.enable = s5p_epll_enable;
552 clk_fout_epll.ops = &s5p6440_epll_ops; 555 clk_fout_epll.ops = &s5p6440_epll_ops;
553 556
554 clk_48m.enable = s5p64x0_clk48m_ctrl; 557 clk_48m.enable = s5p64x0_clk48m_ctrl;
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
index f9afb05b217c..7dbf3c968f53 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6450.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c
@@ -80,13 +80,16 @@ static int s5p6450_epll_set_rate(struct clk *clk, unsigned long rate)
80 __raw_writel(epll_con, S5P64X0_EPLL_CON); 80 __raw_writel(epll_con, S5P64X0_EPLL_CON);
81 __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K); 81 __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
82 82
83 printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
84 clk->rate, rate);
85
83 clk->rate = rate; 86 clk->rate = rate;
84 87
85 return 0; 88 return 0;
86} 89}
87 90
88static struct clk_ops s5p6450_epll_ops = { 91static struct clk_ops s5p6450_epll_ops = {
89 .get_rate = s5p64x0_epll_get_rate, 92 .get_rate = s5p_epll_get_rate,
90 .set_rate = s5p6450_epll_set_rate, 93 .set_rate = s5p6450_epll_set_rate,
91}; 94};
92 95
@@ -186,6 +189,12 @@ static struct clk init_clocks_disable[] = {
186 .enable = s5p64x0_hclk0_ctrl, 189 .enable = s5p64x0_hclk0_ctrl,
187 .ctrlbit = (1 << 3), 190 .ctrlbit = (1 << 3),
188 }, { 191 }, {
192 .name = "pdma",
193 .id = -1,
194 .parent = &clk_hclk_low.clk,
195 .enable = s5p64x0_hclk0_ctrl,
196 .ctrlbit = (1 << 12),
197 }, {
189 .name = "hsmmc", 198 .name = "hsmmc",
190 .id = 0, 199 .id = 0,
191 .parent = &clk_hclk_low.clk, 200 .parent = &clk_hclk_low.clk,
@@ -283,12 +292,6 @@ static struct clk init_clocks[] = {
283 .enable = s5p64x0_hclk0_ctrl, 292 .enable = s5p64x0_hclk0_ctrl,
284 .ctrlbit = (1 << 21), 293 .ctrlbit = (1 << 21),
285 }, { 294 }, {
286 .name = "dma",
287 .id = -1,
288 .parent = &clk_hclk_low.clk,
289 .enable = s5p64x0_hclk0_ctrl,
290 .ctrlbit = (1 << 12),
291 }, {
292 .name = "uart", 295 .name = "uart",
293 .id = 0, 296 .id = 0,
294 .parent = &clk_pclk_low.clk, 297 .parent = &clk_pclk_low.clk,
@@ -581,7 +584,7 @@ void __init_or_cpufreq s5p6450_setup_clocks(void)
581 584
582 /* Set S5P6450 functions for clk_fout_epll */ 585 /* Set S5P6450 functions for clk_fout_epll */
583 586
584 clk_fout_epll.enable = s5p64x0_epll_enable; 587 clk_fout_epll.enable = s5p_epll_enable;
585 clk_fout_epll.ops = &s5p6450_epll_ops; 588 clk_fout_epll.ops = &s5p6450_epll_ops;
586 589
587 clk_48m.enable = s5p64x0_clk48m_ctrl; 590 clk_48m.enable = s5p64x0_clk48m_ctrl;
diff --git a/arch/arm/mach-s5p64x0/clock.c b/arch/arm/mach-s5p64x0/clock.c
index 523ba8039ac2..b52c6e2f37a6 100644
--- a/arch/arm/mach-s5p64x0/clock.c
+++ b/arch/arm/mach-s5p64x0/clock.c
@@ -73,24 +73,6 @@ static const u32 clock_table[][3] = {
73 {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P64X0_CLKDIV0_HCLK_SHIFT)}, 73 {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
74}; 74};
75 75
76int s5p64x0_epll_enable(struct clk *clk, int enable)
77{
78 unsigned int ctrlbit = clk->ctrlbit;
79 unsigned int epll_con = __raw_readl(S5P64X0_EPLL_CON) & ~ctrlbit;
80
81 if (enable)
82 __raw_writel(epll_con | ctrlbit, S5P64X0_EPLL_CON);
83 else
84 __raw_writel(epll_con, S5P64X0_EPLL_CON);
85
86 return 0;
87}
88
89unsigned long s5p64x0_epll_get_rate(struct clk *clk)
90{
91 return clk->rate;
92}
93
94unsigned long s5p64x0_armclk_get_rate(struct clk *clk) 76unsigned long s5p64x0_armclk_get_rate(struct clk *clk)
95{ 77{
96 unsigned long rate = clk_get_rate(clk->parent); 78 unsigned long rate = clk_get_rate(clk->parent);
diff --git a/arch/arm/mach-s5p64x0/dev-audio.c b/arch/arm/mach-s5p64x0/dev-audio.c
index fa097bd68ca4..396bacc0a39a 100644
--- a/arch/arm/mach-s5p64x0/dev-audio.c
+++ b/arch/arm/mach-s5p64x0/dev-audio.c
@@ -24,13 +24,8 @@ static int s5p6440_cfg_i2s(struct platform_device *pdev)
24 /* configure GPIO for i2s port */ 24 /* configure GPIO for i2s port */
25 switch (pdev->id) { 25 switch (pdev->id) {
26 case -1: 26 case -1:
27 s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5)); 27 s3c_gpio_cfgpin_range(S5P6440_GPR(4), 5, S3C_GPIO_SFN(5));
28 s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5)); 28 s3c_gpio_cfgpin_range(S5P6440_GPR(13), 2, S3C_GPIO_SFN(5));
29 s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5));
30 s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5));
31 s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5));
32 s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5));
33 s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5));
34 break; 29 break;
35 30
36 default: 31 default:
@@ -47,13 +42,9 @@ static int s5p6450_cfg_i2s(struct platform_device *pdev)
47 switch (pdev->id) { 42 switch (pdev->id) {
48 case -1: 43 case -1:
49 s3c_gpio_cfgpin(S5P6450_GPB(4), S3C_GPIO_SFN(5)); 44 s3c_gpio_cfgpin(S5P6450_GPB(4), S3C_GPIO_SFN(5));
50 s3c_gpio_cfgpin(S5P6450_GPR(4), S3C_GPIO_SFN(5)); 45 s3c_gpio_cfgpin_range(S5P6450_GPR(4), 5, S3C_GPIO_SFN(5));
51 s3c_gpio_cfgpin(S5P6450_GPR(5), S3C_GPIO_SFN(5)); 46 s3c_gpio_cfgpin_range(S5P6450_GPR(13), 2, S3C_GPIO_SFN(5));
52 s3c_gpio_cfgpin(S5P6450_GPR(6), S3C_GPIO_SFN(5)); 47
53 s3c_gpio_cfgpin(S5P6450_GPR(7), S3C_GPIO_SFN(5));
54 s3c_gpio_cfgpin(S5P6450_GPR(8), S3C_GPIO_SFN(5));
55 s3c_gpio_cfgpin(S5P6450_GPR(13), S3C_GPIO_SFN(5));
56 s3c_gpio_cfgpin(S5P6450_GPR(14), S3C_GPIO_SFN(5));
57 break; 48 break;
58 49
59 default: 50 default:
@@ -116,11 +107,8 @@ static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev)
116{ 107{
117 switch (pdev->id) { 108 switch (pdev->id) {
118 case 0: 109 case 0:
119 s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2)); 110 s3c_gpio_cfgpin_range(S5P6440_GPR(6), 3, S3C_GPIO_SFN(2));
120 s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2)); 111 s3c_gpio_cfgpin_range(S5P6440_GPR(13), 2, S3C_GPIO_SFN(2));
121 s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2));
122 s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2));
123 s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2));
124 break; 112 break;
125 113
126 default: 114 default:
diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c
index 5b69ec4c8af3..e78ee18c76e3 100644
--- a/arch/arm/mach-s5p64x0/dev-spi.c
+++ b/arch/arm/mach-s5p64x0/dev-spi.c
@@ -39,23 +39,15 @@ static char *s5p64x0_spi_src_clks[] = {
39 */ 39 */
40static int s5p6440_spi_cfg_gpio(struct platform_device *pdev) 40static int s5p6440_spi_cfg_gpio(struct platform_device *pdev)
41{ 41{
42 unsigned int base;
43
42 switch (pdev->id) { 44 switch (pdev->id) {
43 case 0: 45 case 0:
44 s3c_gpio_cfgpin(S5P6440_GPC(0), S3C_GPIO_SFN(2)); 46 base = S5P6440_GPC(0);
45 s3c_gpio_cfgpin(S5P6440_GPC(1), S3C_GPIO_SFN(2));
46 s3c_gpio_cfgpin(S5P6440_GPC(2), S3C_GPIO_SFN(2));
47 s3c_gpio_setpull(S5P6440_GPC(0), S3C_GPIO_PULL_UP);
48 s3c_gpio_setpull(S5P6440_GPC(1), S3C_GPIO_PULL_UP);
49 s3c_gpio_setpull(S5P6440_GPC(2), S3C_GPIO_PULL_UP);
50 break; 47 break;
51 48
52 case 1: 49 case 1:
53 s3c_gpio_cfgpin(S5P6440_GPC(4), S3C_GPIO_SFN(2)); 50 base = S5P6440_GPC(4);
54 s3c_gpio_cfgpin(S5P6440_GPC(5), S3C_GPIO_SFN(2));
55 s3c_gpio_cfgpin(S5P6440_GPC(6), S3C_GPIO_SFN(2));
56 s3c_gpio_setpull(S5P6440_GPC(4), S3C_GPIO_PULL_UP);
57 s3c_gpio_setpull(S5P6440_GPC(5), S3C_GPIO_PULL_UP);
58 s3c_gpio_setpull(S5P6440_GPC(6), S3C_GPIO_PULL_UP);
59 break; 51 break;
60 52
61 default: 53 default:
@@ -63,28 +55,23 @@ static int s5p6440_spi_cfg_gpio(struct platform_device *pdev)
63 return -EINVAL; 55 return -EINVAL;
64 } 56 }
65 57
58 s3c_gpio_cfgall_range(base, 3,
59 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
60
66 return 0; 61 return 0;
67} 62}
68 63
69static int s5p6450_spi_cfg_gpio(struct platform_device *pdev) 64static int s5p6450_spi_cfg_gpio(struct platform_device *pdev)
70{ 65{
66 unsigned int base;
67
71 switch (pdev->id) { 68 switch (pdev->id) {
72 case 0: 69 case 0:
73 s3c_gpio_cfgpin(S5P6450_GPC(0), S3C_GPIO_SFN(2)); 70 base = S5P6450_GPC(0);
74 s3c_gpio_cfgpin(S5P6450_GPC(1), S3C_GPIO_SFN(2));
75 s3c_gpio_cfgpin(S5P6450_GPC(2), S3C_GPIO_SFN(2));
76 s3c_gpio_setpull(S5P6450_GPC(0), S3C_GPIO_PULL_UP);
77 s3c_gpio_setpull(S5P6450_GPC(1), S3C_GPIO_PULL_UP);
78 s3c_gpio_setpull(S5P6450_GPC(2), S3C_GPIO_PULL_UP);
79 break; 71 break;
80 72
81 case 1: 73 case 1:
82 s3c_gpio_cfgpin(S5P6450_GPC(4), S3C_GPIO_SFN(2)); 74 base = S5P6450_GPC(4);
83 s3c_gpio_cfgpin(S5P6450_GPC(5), S3C_GPIO_SFN(2));
84 s3c_gpio_cfgpin(S5P6450_GPC(6), S3C_GPIO_SFN(2));
85 s3c_gpio_setpull(S5P6450_GPC(4), S3C_GPIO_PULL_UP);
86 s3c_gpio_setpull(S5P6450_GPC(5), S3C_GPIO_PULL_UP);
87 s3c_gpio_setpull(S5P6450_GPC(6), S3C_GPIO_PULL_UP);
88 break; 75 break;
89 76
90 default: 77 default:
@@ -92,6 +79,9 @@ static int s5p6450_spi_cfg_gpio(struct platform_device *pdev)
92 return -EINVAL; 79 return -EINVAL;
93 } 80 }
94 81
82 s3c_gpio_cfgall_range(base, 3,
83 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
84
95 return 0; 85 return 0;
96} 86}
97 87
diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c
index 29a8c2410049..d7ad944b3475 100644
--- a/arch/arm/mach-s5p64x0/dma.c
+++ b/arch/arm/mach-s5p64x0/dma.c
@@ -122,7 +122,7 @@ static struct s3c_pl330_platdata s5p6450_pdma_pdata = {
122 122
123static struct platform_device s5p64x0_device_pdma = { 123static struct platform_device s5p64x0_device_pdma = {
124 .name = "s3c-pl330", 124 .name = "s3c-pl330",
125 .id = 0, 125 .id = -1,
126 .num_resources = ARRAY_SIZE(s5p64x0_pdma_resource), 126 .num_resources = ARRAY_SIZE(s5p64x0_pdma_resource),
127 .resource = s5p64x0_pdma_resource, 127 .resource = s5p64x0_pdma_resource,
128 .dev = { 128 .dev = {
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
index 58e1bc813804..a133f22fa155 100644
--- a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
@@ -60,4 +60,6 @@
60#define ARM_DIV_RATIO_SHIFT 0 60#define ARM_DIV_RATIO_SHIFT 0
61#define ARM_DIV_MASK (0xF << ARM_DIV_RATIO_SHIFT) 61#define ARM_DIV_MASK (0xF << ARM_DIV_RATIO_SHIFT)
62 62
63#define S5P_EPLL_CON S5P64X0_EPLL_CON
64
63#endif /* __ASM_ARCH_REGS_CLOCK_H */ 65#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/vmalloc.h b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h
index 97a9df38f1cf..38dcc71a03cc 100644
--- a/arch/arm/mach-s5p64x0/include/mach/vmalloc.h
+++ b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h
@@ -15,6 +15,6 @@
15#ifndef __ASM_ARCH_VMALLOC_H 15#ifndef __ASM_ARCH_VMALLOC_H
16#define __ASM_ARCH_VMALLOC_H 16#define __ASM_ARCH_VMALLOC_H
17 17
18#define VMALLOC_END 0xE0000000UL 18#define VMALLOC_END 0xF6000000UL
19 19
20#endif /* __ASM_ARCH_VMALLOC_H */ 20#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5p64x0/setup-i2c0.c b/arch/arm/mach-s5p64x0/setup-i2c0.c
index dc4cc65a5019..46b463917c54 100644
--- a/arch/arm/mach-s5p64x0/setup-i2c0.c
+++ b/arch/arm/mach-s5p64x0/setup-i2c0.c
@@ -25,18 +25,14 @@ struct platform_device; /* don't need the contents */
25 25
26void s5p6440_i2c0_cfg_gpio(struct platform_device *dev) 26void s5p6440_i2c0_cfg_gpio(struct platform_device *dev)
27{ 27{
28 s3c_gpio_cfgpin(S5P6440_GPB(5), S3C_GPIO_SFN(2)); 28 s3c_gpio_cfgall_range(S5P6440_GPB(5), 2,
29 s3c_gpio_setpull(S5P6440_GPB(5), S3C_GPIO_PULL_UP); 29 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
30 s3c_gpio_cfgpin(S5P6440_GPB(6), S3C_GPIO_SFN(2));
31 s3c_gpio_setpull(S5P6440_GPB(6), S3C_GPIO_PULL_UP);
32} 30}
33 31
34void s5p6450_i2c0_cfg_gpio(struct platform_device *dev) 32void s5p6450_i2c0_cfg_gpio(struct platform_device *dev)
35{ 33{
36 s3c_gpio_cfgpin(S5P6450_GPB(5), S3C_GPIO_SFN(2)); 34 s3c_gpio_cfgall_range(S5P6450_GPB(5), 2,
37 s3c_gpio_setpull(S5P6450_GPB(5), S3C_GPIO_PULL_UP); 35 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
38 s3c_gpio_cfgpin(S5P6450_GPB(6), S3C_GPIO_SFN(2));
39 s3c_gpio_setpull(S5P6450_GPB(6), S3C_GPIO_PULL_UP);
40} 36}
41 37
42void s3c_i2c0_cfg_gpio(struct platform_device *dev) { } 38void s3c_i2c0_cfg_gpio(struct platform_device *dev) { }
diff --git a/arch/arm/mach-s5p64x0/setup-i2c1.c b/arch/arm/mach-s5p64x0/setup-i2c1.c
index 2edd7912f8e4..6ad3b986021c 100644
--- a/arch/arm/mach-s5p64x0/setup-i2c1.c
+++ b/arch/arm/mach-s5p64x0/setup-i2c1.c
@@ -25,18 +25,14 @@ struct platform_device; /* don't need the contents */
25 25
26void s5p6440_i2c1_cfg_gpio(struct platform_device *dev) 26void s5p6440_i2c1_cfg_gpio(struct platform_device *dev)
27{ 27{
28 s3c_gpio_cfgpin(S5P6440_GPR(9), S3C_GPIO_SFN(6)); 28 s3c_gpio_cfgall_range(S5P6440_GPR(9), 2,
29 s3c_gpio_setpull(S5P6440_GPR(9), S3C_GPIO_PULL_UP); 29 S3C_GPIO_SFN(6), S3C_GPIO_PULL_UP);
30 s3c_gpio_cfgpin(S5P6440_GPR(10), S3C_GPIO_SFN(6));
31 s3c_gpio_setpull(S5P6440_GPR(10), S3C_GPIO_PULL_UP);
32} 30}
33 31
34void s5p6450_i2c1_cfg_gpio(struct platform_device *dev) 32void s5p6450_i2c1_cfg_gpio(struct platform_device *dev)
35{ 33{
36 s3c_gpio_cfgpin(S5P6450_GPR(9), S3C_GPIO_SFN(6)); 34 s3c_gpio_cfgall_range(S5P6450_GPR(9), 2,
37 s3c_gpio_setpull(S5P6450_GPR(9), S3C_GPIO_PULL_UP); 35 S3C_GPIO_SFN(6), S3C_GPIO_PULL_UP);
38 s3c_gpio_cfgpin(S5P6450_GPR(10), S3C_GPIO_SFN(6));
39 s3c_gpio_setpull(S5P6450_GPR(10), S3C_GPIO_PULL_UP);
40} 36}
41 37
42void s3c_i2c1_cfg_gpio(struct platform_device *dev) { } 38void s3c_i2c1_cfg_gpio(struct platform_device *dev) { }
diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index 77ae4bfb74ba..b8fbf2fcba6f 100644
--- a/arch/arm/mach-s5pc100/Kconfig
+++ b/arch/arm/mach-s5pc100/Kconfig
@@ -9,7 +9,6 @@ if ARCH_S5PC100
9 9
10config CPU_S5PC100 10config CPU_S5PC100
11 bool 11 bool
12 select PLAT_S5P
13 select S5P_EXT_INT 12 select S5P_EXT_INT
14 select S3C_PL330_DMA 13 select S3C_PL330_DMA
15 help 14 help
diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile
index a021ed1fb4b6..eecab57d2e5d 100644
--- a/arch/arm/mach-s5pc100/Makefile
+++ b/arch/arm/mach-s5pc100/Makefile
@@ -11,7 +11,7 @@ obj- :=
11 11
12# Core support for S5PC100 system 12# Core support for S5PC100 system
13 13
14obj-$(CONFIG_CPU_S5PC100) += cpu.o init.o clock.o gpiolib.o irq-gpio.o 14obj-$(CONFIG_CPU_S5PC100) += cpu.o init.o clock.o gpiolib.o
15obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o 15obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o
16obj-$(CONFIG_CPU_S5PC100) += dma.o 16obj-$(CONFIG_CPU_S5PC100) += dma.o
17 17
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c
index 084abd13b0a5..2d4a761a5163 100644
--- a/arch/arm/mach-s5pc100/clock.c
+++ b/arch/arm/mach-s5pc100/clock.c
@@ -273,24 +273,6 @@ static struct clksrc_clk clk_div_hdmi = {
273 .reg_div = { .reg = S5P_CLK_DIV3, .shift = 28, .size = 4 }, 273 .reg_div = { .reg = S5P_CLK_DIV3, .shift = 28, .size = 4 },
274}; 274};
275 275
276static int s5pc100_epll_enable(struct clk *clk, int enable)
277{
278 unsigned int ctrlbit = clk->ctrlbit;
279 unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit;
280
281 if (enable)
282 __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON);
283 else
284 __raw_writel(epll_con, S5P_EPLL_CON);
285
286 return 0;
287}
288
289static unsigned long s5pc100_epll_get_rate(struct clk *clk)
290{
291 return clk->rate;
292}
293
294static u32 epll_div[][4] = { 276static u32 epll_div[][4] = {
295 { 32750000, 131, 3, 4 }, 277 { 32750000, 131, 3, 4 },
296 { 32768000, 131, 3, 4 }, 278 { 32768000, 131, 3, 4 },
@@ -341,13 +323,16 @@ static int s5pc100_epll_set_rate(struct clk *clk, unsigned long rate)
341 323
342 __raw_writel(epll_con, S5P_EPLL_CON); 324 __raw_writel(epll_con, S5P_EPLL_CON);
343 325
326 printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
327 clk->rate, rate);
328
344 clk->rate = rate; 329 clk->rate = rate;
345 330
346 return 0; 331 return 0;
347} 332}
348 333
349static struct clk_ops s5pc100_epll_ops = { 334static struct clk_ops s5pc100_epll_ops = {
350 .get_rate = s5pc100_epll_get_rate, 335 .get_rate = s5p_epll_get_rate,
351 .set_rate = s5pc100_epll_set_rate, 336 .set_rate = s5pc100_epll_set_rate,
352}; 337};
353 338
@@ -691,55 +676,55 @@ static struct clk init_clocks_disable[] = {
691 }, { 676 }, {
692 .name = "iis", 677 .name = "iis",
693 .id = 0, 678 .id = 0,
694 .parent = &clk_div_d1_bus.clk, 679 .parent = &clk_div_pclkd1.clk,
695 .enable = s5pc100_d1_5_ctrl, 680 .enable = s5pc100_d1_5_ctrl,
696 .ctrlbit = (1 << 0), 681 .ctrlbit = (1 << 0),
697 }, { 682 }, {
698 .name = "iis", 683 .name = "iis",
699 .id = 1, 684 .id = 1,
700 .parent = &clk_div_d1_bus.clk, 685 .parent = &clk_div_pclkd1.clk,
701 .enable = s5pc100_d1_5_ctrl, 686 .enable = s5pc100_d1_5_ctrl,
702 .ctrlbit = (1 << 1), 687 .ctrlbit = (1 << 1),
703 }, { 688 }, {
704 .name = "iis", 689 .name = "iis",
705 .id = 2, 690 .id = 2,
706 .parent = &clk_div_d1_bus.clk, 691 .parent = &clk_div_pclkd1.clk,
707 .enable = s5pc100_d1_5_ctrl, 692 .enable = s5pc100_d1_5_ctrl,
708 .ctrlbit = (1 << 2), 693 .ctrlbit = (1 << 2),
709 }, { 694 }, {
710 .name = "ac97", 695 .name = "ac97",
711 .id = -1, 696 .id = -1,
712 .parent = &clk_div_d1_bus.clk, 697 .parent = &clk_div_pclkd1.clk,
713 .enable = s5pc100_d1_5_ctrl, 698 .enable = s5pc100_d1_5_ctrl,
714 .ctrlbit = (1 << 3), 699 .ctrlbit = (1 << 3),
715 }, { 700 }, {
716 .name = "pcm", 701 .name = "pcm",
717 .id = 0, 702 .id = 0,
718 .parent = &clk_div_d1_bus.clk, 703 .parent = &clk_div_pclkd1.clk,
719 .enable = s5pc100_d1_5_ctrl, 704 .enable = s5pc100_d1_5_ctrl,
720 .ctrlbit = (1 << 4), 705 .ctrlbit = (1 << 4),
721 }, { 706 }, {
722 .name = "pcm", 707 .name = "pcm",
723 .id = 1, 708 .id = 1,
724 .parent = &clk_div_d1_bus.clk, 709 .parent = &clk_div_pclkd1.clk,
725 .enable = s5pc100_d1_5_ctrl, 710 .enable = s5pc100_d1_5_ctrl,
726 .ctrlbit = (1 << 5), 711 .ctrlbit = (1 << 5),
727 }, { 712 }, {
728 .name = "spdif", 713 .name = "spdif",
729 .id = -1, 714 .id = -1,
730 .parent = &clk_div_d1_bus.clk, 715 .parent = &clk_div_pclkd1.clk,
731 .enable = s5pc100_d1_5_ctrl, 716 .enable = s5pc100_d1_5_ctrl,
732 .ctrlbit = (1 << 6), 717 .ctrlbit = (1 << 6),
733 }, { 718 }, {
734 .name = "adc", 719 .name = "adc",
735 .id = -1, 720 .id = -1,
736 .parent = &clk_div_d1_bus.clk, 721 .parent = &clk_div_pclkd1.clk,
737 .enable = s5pc100_d1_5_ctrl, 722 .enable = s5pc100_d1_5_ctrl,
738 .ctrlbit = (1 << 7), 723 .ctrlbit = (1 << 7),
739 }, { 724 }, {
740 .name = "keypad", 725 .name = "keypad",
741 .id = -1, 726 .id = -1,
742 .parent = &clk_div_d1_bus.clk, 727 .parent = &clk_div_pclkd1.clk,
743 .enable = s5pc100_d1_5_ctrl, 728 .enable = s5pc100_d1_5_ctrl,
744 .ctrlbit = (1 << 8), 729 .ctrlbit = (1 << 8),
745 }, { 730 }, {
@@ -848,6 +833,18 @@ struct clksrc_sources clk_src_group3 = {
848 .nr_sources = ARRAY_SIZE(clk_src_group3_list), 833 .nr_sources = ARRAY_SIZE(clk_src_group3_list),
849}; 834};
850 835
836static struct clksrc_clk clk_sclk_audio0 = {
837 .clk = {
838 .name = "sclk_audio",
839 .id = 0,
840 .ctrlbit = (1 << 8),
841 .enable = s5pc100_sclk1_ctrl,
842 },
843 .sources = &clk_src_group3,
844 .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 },
845 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
846};
847
851static struct clk *clk_src_group4_list[] = { 848static struct clk *clk_src_group4_list[] = {
852 [0] = &clk_mout_epll.clk, 849 [0] = &clk_mout_epll.clk,
853 [1] = &clk_div_mpll.clk, 850 [1] = &clk_div_mpll.clk,
@@ -862,6 +859,18 @@ struct clksrc_sources clk_src_group4 = {
862 .nr_sources = ARRAY_SIZE(clk_src_group4_list), 859 .nr_sources = ARRAY_SIZE(clk_src_group4_list),
863}; 860};
864 861
862static struct clksrc_clk clk_sclk_audio1 = {
863 .clk = {
864 .name = "sclk_audio",
865 .id = 1,
866 .ctrlbit = (1 << 9),
867 .enable = s5pc100_sclk1_ctrl,
868 },
869 .sources = &clk_src_group4,
870 .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 },
871 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
872};
873
865static struct clk *clk_src_group5_list[] = { 874static struct clk *clk_src_group5_list[] = {
866 [0] = &clk_mout_epll.clk, 875 [0] = &clk_mout_epll.clk,
867 [1] = &clk_div_mpll.clk, 876 [1] = &clk_div_mpll.clk,
@@ -875,6 +884,18 @@ struct clksrc_sources clk_src_group5 = {
875 .nr_sources = ARRAY_SIZE(clk_src_group5_list), 884 .nr_sources = ARRAY_SIZE(clk_src_group5_list),
876}; 885};
877 886
887static struct clksrc_clk clk_sclk_audio2 = {
888 .clk = {
889 .name = "sclk_audio",
890 .id = 2,
891 .ctrlbit = (1 << 10),
892 .enable = s5pc100_sclk1_ctrl,
893 },
894 .sources = &clk_src_group5,
895 .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 },
896 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
897};
898
878static struct clk *clk_src_group6_list[] = { 899static struct clk *clk_src_group6_list[] = {
879 [0] = &s5p_clk_27m, 900 [0] = &s5p_clk_27m,
880 [1] = &clk_vclk54m, 901 [1] = &clk_vclk54m,
@@ -944,6 +965,64 @@ struct clksrc_sources clk_src_pwi = {
944 .nr_sources = ARRAY_SIZE(clk_src_pwi_list), 965 .nr_sources = ARRAY_SIZE(clk_src_pwi_list),
945}; 966};
946 967
968static struct clk *clk_sclk_spdif_list[] = {
969 [0] = &clk_sclk_audio0.clk,
970 [1] = &clk_sclk_audio1.clk,
971 [2] = &clk_sclk_audio2.clk,
972};
973
974struct clksrc_sources clk_src_sclk_spdif = {
975 .sources = clk_sclk_spdif_list,
976 .nr_sources = ARRAY_SIZE(clk_sclk_spdif_list),
977};
978
979static int s5pc100_spdif_set_rate(struct clk *clk, unsigned long rate)
980{
981 struct clk *pclk;
982 int ret;
983
984 pclk = clk_get_parent(clk);
985 if (IS_ERR(pclk))
986 return -EINVAL;
987
988 ret = pclk->ops->set_rate(pclk, rate);
989 clk_put(pclk);
990
991 return ret;
992}
993
994static unsigned long s5pc100_spdif_get_rate(struct clk *clk)
995{
996 struct clk *pclk;
997 int rate;
998
999 pclk = clk_get_parent(clk);
1000 if (IS_ERR(pclk))
1001 return -EINVAL;
1002
1003 rate = pclk->ops->get_rate(clk);
1004 clk_put(pclk);
1005
1006 return rate;
1007}
1008
1009static struct clk_ops s5pc100_sclk_spdif_ops = {
1010 .set_rate = s5pc100_spdif_set_rate,
1011 .get_rate = s5pc100_spdif_get_rate,
1012};
1013
1014static struct clksrc_clk clk_sclk_spdif = {
1015 .clk = {
1016 .name = "sclk_spdif",
1017 .id = -1,
1018 .ctrlbit = (1 << 11),
1019 .enable = s5pc100_sclk1_ctrl,
1020 .ops = &s5pc100_sclk_spdif_ops,
1021 },
1022 .sources = &clk_src_sclk_spdif,
1023 .reg_src = { .reg = S5P_CLK_SRC3, .shift = 24, .size = 2 },
1024};
1025
947static struct clksrc_clk clksrcs[] = { 1026static struct clksrc_clk clksrcs[] = {
948 { 1027 {
949 .clk = { 1028 .clk = {
@@ -1001,39 +1080,6 @@ static struct clksrc_clk clksrcs[] = {
1001 .reg_src = { .reg = S5P_CLK_SRC2, .shift = 28, .size = 2 }, 1080 .reg_src = { .reg = S5P_CLK_SRC2, .shift = 28, .size = 2 },
1002 }, { 1081 }, {
1003 .clk = { 1082 .clk = {
1004 .name = "sclk_audio",
1005 .id = 0,
1006 .ctrlbit = (1 << 8),
1007 .enable = s5pc100_sclk1_ctrl,
1008
1009 },
1010 .sources = &clk_src_group3,
1011 .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 },
1012 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
1013 }, {
1014 .clk = {
1015 .name = "sclk_audio",
1016 .id = 1,
1017 .ctrlbit = (1 << 9),
1018 .enable = s5pc100_sclk1_ctrl,
1019
1020 },
1021 .sources = &clk_src_group4,
1022 .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 },
1023 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
1024 }, {
1025 .clk = {
1026 .name = "sclk_audio",
1027 .id = 2,
1028 .ctrlbit = (1 << 10),
1029 .enable = s5pc100_sclk1_ctrl,
1030
1031 },
1032 .sources = &clk_src_group5,
1033 .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 },
1034 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
1035 }, {
1036 .clk = {
1037 .name = "sclk_lcd", 1083 .name = "sclk_lcd",
1038 .id = -1, 1084 .id = -1,
1039 .ctrlbit = (1 << 0), 1085 .ctrlbit = (1 << 0),
@@ -1179,6 +1225,10 @@ static struct clksrc_clk *sysclks[] = {
1179 &clk_div_pclkd1, 1225 &clk_div_pclkd1,
1180 &clk_div_cam, 1226 &clk_div_cam,
1181 &clk_div_hdmi, 1227 &clk_div_hdmi,
1228 &clk_sclk_audio0,
1229 &clk_sclk_audio1,
1230 &clk_sclk_audio2,
1231 &clk_sclk_spdif,
1182}; 1232};
1183 1233
1184void __init_or_cpufreq s5pc100_setup_clocks(void) 1234void __init_or_cpufreq s5pc100_setup_clocks(void)
@@ -1196,7 +1246,7 @@ void __init_or_cpufreq s5pc100_setup_clocks(void)
1196 unsigned int ptr; 1246 unsigned int ptr;
1197 1247
1198 /* Set S5PC100 functions for clk_fout_epll */ 1248 /* Set S5PC100 functions for clk_fout_epll */
1199 clk_fout_epll.enable = s5pc100_epll_enable; 1249 clk_fout_epll.enable = s5p_epll_enable;
1200 clk_fout_epll.ops = &s5pc100_epll_ops; 1250 clk_fout_epll.ops = &s5pc100_epll_ops;
1201 1251
1202 printk(KERN_DEBUG "%s: registering clocks\n", __func__); 1252 printk(KERN_DEBUG "%s: registering clocks\n", __func__);
diff --git a/arch/arm/mach-s5pc100/dev-audio.c b/arch/arm/mach-s5pc100/dev-audio.c
index a699ed6acc23..564e195ec493 100644
--- a/arch/arm/mach-s5pc100/dev-audio.c
+++ b/arch/arm/mach-s5pc100/dev-audio.c
@@ -24,19 +24,11 @@ static int s5pc100_cfg_i2s(struct platform_device *pdev)
24 /* configure GPIO for i2s port */ 24 /* configure GPIO for i2s port */
25 switch (pdev->id) { 25 switch (pdev->id) {
26 case 1: 26 case 1:
27 s3c_gpio_cfgpin(S5PC100_GPC(0), S3C_GPIO_SFN(2)); 27 s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(2));
28 s3c_gpio_cfgpin(S5PC100_GPC(1), S3C_GPIO_SFN(2));
29 s3c_gpio_cfgpin(S5PC100_GPC(2), S3C_GPIO_SFN(2));
30 s3c_gpio_cfgpin(S5PC100_GPC(3), S3C_GPIO_SFN(2));
31 s3c_gpio_cfgpin(S5PC100_GPC(4), S3C_GPIO_SFN(2));
32 break; 28 break;
33 29
34 case 2: 30 case 2:
35 s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(4)); 31 s3c_gpio_cfgpin_range(S5PC100_GPG3(0), 5, S3C_GPIO_SFN(4));
36 s3c_gpio_cfgpin(S5PC100_GPG3(1), S3C_GPIO_SFN(4));
37 s3c_gpio_cfgpin(S5PC100_GPG3(2), S3C_GPIO_SFN(4));
38 s3c_gpio_cfgpin(S5PC100_GPG3(3), S3C_GPIO_SFN(4));
39 s3c_gpio_cfgpin(S5PC100_GPG3(4), S3C_GPIO_SFN(4));
40 break; 32 break;
41 33
42 case -1: /* Dedicated pins */ 34 case -1: /* Dedicated pins */
@@ -144,19 +136,11 @@ static int s5pc100_pcm_cfg_gpio(struct platform_device *pdev)
144{ 136{
145 switch (pdev->id) { 137 switch (pdev->id) {
146 case 0: 138 case 0:
147 s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(5)); 139 s3c_gpio_cfgpin_range(S5PC100_GPG3(0), 5, S3C_GPIO_SFN(5));
148 s3c_gpio_cfgpin(S5PC100_GPG3(1), S3C_GPIO_SFN(5));
149 s3c_gpio_cfgpin(S5PC100_GPG3(2), S3C_GPIO_SFN(5));
150 s3c_gpio_cfgpin(S5PC100_GPG3(3), S3C_GPIO_SFN(5));
151 s3c_gpio_cfgpin(S5PC100_GPG3(4), S3C_GPIO_SFN(5));
152 break; 140 break;
153 141
154 case 1: 142 case 1:
155 s3c_gpio_cfgpin(S5PC100_GPC(0), S3C_GPIO_SFN(3)); 143 s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(3));
156 s3c_gpio_cfgpin(S5PC100_GPC(1), S3C_GPIO_SFN(3));
157 s3c_gpio_cfgpin(S5PC100_GPC(2), S3C_GPIO_SFN(3));
158 s3c_gpio_cfgpin(S5PC100_GPC(3), S3C_GPIO_SFN(3));
159 s3c_gpio_cfgpin(S5PC100_GPC(4), S3C_GPIO_SFN(3));
160 break; 144 break;
161 145
162 default: 146 default:
@@ -231,13 +215,7 @@ struct platform_device s5pc100_device_pcm1 = {
231 215
232static int s5pc100_ac97_cfg_gpio(struct platform_device *pdev) 216static int s5pc100_ac97_cfg_gpio(struct platform_device *pdev)
233{ 217{
234 s3c_gpio_cfgpin(S5PC100_GPC(0), S3C_GPIO_SFN(4)); 218 return s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(4));
235 s3c_gpio_cfgpin(S5PC100_GPC(1), S3C_GPIO_SFN(4));
236 s3c_gpio_cfgpin(S5PC100_GPC(2), S3C_GPIO_SFN(4));
237 s3c_gpio_cfgpin(S5PC100_GPC(3), S3C_GPIO_SFN(4));
238 s3c_gpio_cfgpin(S5PC100_GPC(4), S3C_GPIO_SFN(4));
239
240 return 0;
241} 219}
242 220
243static struct resource s5pc100_ac97_resource[] = { 221static struct resource s5pc100_ac97_resource[] = {
@@ -285,3 +263,57 @@ struct platform_device s5pc100_device_ac97 = {
285 .coherent_dma_mask = DMA_BIT_MASK(32), 263 .coherent_dma_mask = DMA_BIT_MASK(32),
286 }, 264 },
287}; 265};
266
267/* S/PDIF Controller platform_device */
268static int s5pc100_spdif_cfg_gpd(struct platform_device *pdev)
269{
270 s3c_gpio_cfgpin_range(S5PC100_GPD(5), 2, S3C_GPIO_SFN(3));
271
272 return 0;
273}
274
275static int s5pc100_spdif_cfg_gpg3(struct platform_device *pdev)
276{
277 s3c_gpio_cfgpin_range(S5PC100_GPG3(5), 2, S3C_GPIO_SFN(3));
278
279 return 0;
280}
281
282static struct resource s5pc100_spdif_resource[] = {
283 [0] = {
284 .start = S5PC100_PA_SPDIF,
285 .end = S5PC100_PA_SPDIF + 0x100 - 1,
286 .flags = IORESOURCE_MEM,
287 },
288 [1] = {
289 .start = DMACH_SPDIF,
290 .end = DMACH_SPDIF,
291 .flags = IORESOURCE_DMA,
292 },
293};
294
295static struct s3c_audio_pdata s5p_spdif_pdata = {
296 .cfg_gpio = s5pc100_spdif_cfg_gpd,
297};
298
299static u64 s5pc100_spdif_dmamask = DMA_BIT_MASK(32);
300
301struct platform_device s5pc100_device_spdif = {
302 .name = "samsung-spdif",
303 .id = -1,
304 .num_resources = ARRAY_SIZE(s5pc100_spdif_resource),
305 .resource = s5pc100_spdif_resource,
306 .dev = {
307 .platform_data = &s5p_spdif_pdata,
308 .dma_mask = &s5pc100_spdif_dmamask,
309 .coherent_dma_mask = DMA_BIT_MASK(32),
310 },
311};
312
313void __init s5pc100_spdif_setup_gpio(int gpio)
314{
315 if (gpio == S5PC100_SPDIF_GPD)
316 s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpd;
317 else
318 s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpg3;
319}
diff --git a/arch/arm/mach-s5pc100/dev-spi.c b/arch/arm/mach-s5pc100/dev-spi.c
index a0ef7c302c16..57b19794d9bb 100644
--- a/arch/arm/mach-s5pc100/dev-spi.c
+++ b/arch/arm/mach-s5pc100/dev-spi.c
@@ -38,30 +38,20 @@ static int s5pc100_spi_cfg_gpio(struct platform_device *pdev)
38{ 38{
39 switch (pdev->id) { 39 switch (pdev->id) {
40 case 0: 40 case 0:
41 s3c_gpio_cfgpin(S5PC100_GPB(0), S3C_GPIO_SFN(2)); 41 s3c_gpio_cfgall_range(S5PC100_GPB(0), 3,
42 s3c_gpio_cfgpin(S5PC100_GPB(1), S3C_GPIO_SFN(2)); 42 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
43 s3c_gpio_cfgpin(S5PC100_GPB(2), S3C_GPIO_SFN(2));
44 s3c_gpio_setpull(S5PC100_GPB(0), S3C_GPIO_PULL_UP);
45 s3c_gpio_setpull(S5PC100_GPB(1), S3C_GPIO_PULL_UP);
46 s3c_gpio_setpull(S5PC100_GPB(2), S3C_GPIO_PULL_UP);
47 break; 43 break;
48 44
49 case 1: 45 case 1:
50 s3c_gpio_cfgpin(S5PC100_GPB(4), S3C_GPIO_SFN(2)); 46 s3c_gpio_cfgall_range(S5PC100_GPB(4), 3,
51 s3c_gpio_cfgpin(S5PC100_GPB(5), S3C_GPIO_SFN(2)); 47 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
52 s3c_gpio_cfgpin(S5PC100_GPB(6), S3C_GPIO_SFN(2));
53 s3c_gpio_setpull(S5PC100_GPB(4), S3C_GPIO_PULL_UP);
54 s3c_gpio_setpull(S5PC100_GPB(5), S3C_GPIO_PULL_UP);
55 s3c_gpio_setpull(S5PC100_GPB(6), S3C_GPIO_PULL_UP);
56 break; 48 break;
57 49
58 case 2: 50 case 2:
59 s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3)); 51 s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3));
60 s3c_gpio_cfgpin(S5PC100_GPG3(2), S3C_GPIO_SFN(3));
61 s3c_gpio_cfgpin(S5PC100_GPG3(3), S3C_GPIO_SFN(3));
62 s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP); 52 s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP);
63 s3c_gpio_setpull(S5PC100_GPG3(2), S3C_GPIO_PULL_UP); 53 s3c_gpio_cfgall_range(S5PC100_GPB(2), 2,
64 s3c_gpio_setpull(S5PC100_GPG3(3), S3C_GPIO_PULL_UP); 54 S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
65 break; 55 break;
66 56
67 default: 57 default:
diff --git a/arch/arm/mach-s5pc100/dma.c b/arch/arm/mach-s5pc100/dma.c
index 0f5517571e2c..bf4cd0fb97c6 100644
--- a/arch/arm/mach-s5pc100/dma.c
+++ b/arch/arm/mach-s5pc100/dma.c
@@ -81,7 +81,7 @@ static struct s3c_pl330_platdata s5pc100_pdma0_pdata = {
81 81
82static struct platform_device s5pc100_device_pdma0 = { 82static struct platform_device s5pc100_device_pdma0 = {
83 .name = "s3c-pl330", 83 .name = "s3c-pl330",
84 .id = 1, 84 .id = 0,
85 .num_resources = ARRAY_SIZE(s5pc100_pdma0_resource), 85 .num_resources = ARRAY_SIZE(s5pc100_pdma0_resource),
86 .resource = s5pc100_pdma0_resource, 86 .resource = s5pc100_pdma0_resource,
87 .dev = { 87 .dev = {
@@ -143,7 +143,7 @@ static struct s3c_pl330_platdata s5pc100_pdma1_pdata = {
143 143
144static struct platform_device s5pc100_device_pdma1 = { 144static struct platform_device s5pc100_device_pdma1 = {
145 .name = "s3c-pl330", 145 .name = "s3c-pl330",
146 .id = 2, 146 .id = 1,
147 .num_resources = ARRAY_SIZE(s5pc100_pdma1_resource), 147 .num_resources = ARRAY_SIZE(s5pc100_pdma1_resource),
148 .resource = s5pc100_pdma1_resource, 148 .resource = s5pc100_pdma1_resource,
149 .dev = { 149 .dev = {
diff --git a/arch/arm/mach-s5pc100/gpiolib.c b/arch/arm/mach-s5pc100/gpiolib.c
index 0fab7f2cd8bf..20856eb7dd51 100644
--- a/arch/arm/mach-s5pc100/gpiolib.c
+++ b/arch/arm/mach-s5pc100/gpiolib.c
@@ -1,5 +1,7 @@
1/* 1/* linux/arch/arm/mach-s5pc100/gpiolib.c
2 * arch/arm/plat-s5pc100/gpiolib.c 2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
3 * 5 *
4 * Copyright 2009 Samsung Electronics Co 6 * Copyright 2009 Samsung Electronics Co
5 * Kyungmin Park <kyungmin.park@samsung.com> 7 * Kyungmin Park <kyungmin.park@samsung.com>
@@ -61,30 +63,6 @@
61 * L3 8 4Bit None 63 * L3 8 4Bit None
62 */ 64 */
63 65
64static int s5pc100_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
65{
66 return S3C_IRQ_GPIO(chip->base + offset);
67}
68
69static int s5pc100_gpiolib_to_eint(struct gpio_chip *chip, unsigned int offset)
70{
71 int base;
72
73 base = chip->base - S5PC100_GPH0(0);
74 if (base == 0)
75 return IRQ_EINT(offset);
76 base = chip->base - S5PC100_GPH1(0);
77 if (base == 0)
78 return IRQ_EINT(8 + offset);
79 base = chip->base - S5PC100_GPH2(0);
80 if (base == 0)
81 return IRQ_EINT(16 + offset);
82 base = chip->base - S5PC100_GPH3(0);
83 if (base == 0)
84 return IRQ_EINT(24 + offset);
85 return -EINVAL;
86}
87
88static struct s3c_gpio_cfg gpio_cfg = { 66static struct s3c_gpio_cfg gpio_cfg = {
89 .set_config = s3c_gpio_setcfg_s3c64xx_4bit, 67 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
90 .set_pull = s3c_gpio_setpull_updown, 68 .set_pull = s3c_gpio_setpull_updown,
@@ -104,209 +82,150 @@ static struct s3c_gpio_cfg gpio_cfg_noint = {
104 .get_pull = s3c_gpio_getpull_updown, 82 .get_pull = s3c_gpio_getpull_updown,
105}; 83};
106 84
85/*
86 * GPIO bank's base address given the index of the bank in the
87 * list of all gpio banks.
88 */
89#define S5PC100_BANK_BASE(bank_nr) (S5P_VA_GPIO + ((bank_nr) * 0x20))
90
91/*
92 * Following are the gpio banks in S5PC100.
93 *
94 * The 'config' member when left to NULL, is initialized to the default
95 * structure gpio_cfg in the init function below.
96 *
97 * The 'base' member is also initialized in the init function below.
98 * Note: The initialization of 'base' member of s3c_gpio_chip structure
99 * uses the above macro and depends on the banks being listed in order here.
100 */
107static struct s3c_gpio_chip s5pc100_gpio_chips[] = { 101static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
108 { 102 {
109 .base = S5PC100_GPA0_BASE,
110 .config = &gpio_cfg,
111 .chip = { 103 .chip = {
112 .base = S5PC100_GPA0(0), 104 .base = S5PC100_GPA0(0),
113 .ngpio = S5PC100_GPIO_A0_NR, 105 .ngpio = S5PC100_GPIO_A0_NR,
114 .label = "GPA0", 106 .label = "GPA0",
115 }, 107 },
116 }, { 108 }, {
117 .base = S5PC100_GPA1_BASE,
118 .config = &gpio_cfg,
119 .chip = { 109 .chip = {
120 .base = S5PC100_GPA1(0), 110 .base = S5PC100_GPA1(0),
121 .ngpio = S5PC100_GPIO_A1_NR, 111 .ngpio = S5PC100_GPIO_A1_NR,
122 .label = "GPA1", 112 .label = "GPA1",
123 }, 113 },
124 }, { 114 }, {
125 .base = S5PC100_GPB_BASE,
126 .config = &gpio_cfg,
127 .chip = { 115 .chip = {
128 .base = S5PC100_GPB(0), 116 .base = S5PC100_GPB(0),
129 .ngpio = S5PC100_GPIO_B_NR, 117 .ngpio = S5PC100_GPIO_B_NR,
130 .label = "GPB", 118 .label = "GPB",
131 }, 119 },
132 }, { 120 }, {
133 .base = S5PC100_GPC_BASE,
134 .config = &gpio_cfg,
135 .chip = { 121 .chip = {
136 .base = S5PC100_GPC(0), 122 .base = S5PC100_GPC(0),
137 .ngpio = S5PC100_GPIO_C_NR, 123 .ngpio = S5PC100_GPIO_C_NR,
138 .label = "GPC", 124 .label = "GPC",
139 }, 125 },
140 }, { 126 }, {
141 .base = S5PC100_GPD_BASE,
142 .config = &gpio_cfg,
143 .chip = { 127 .chip = {
144 .base = S5PC100_GPD(0), 128 .base = S5PC100_GPD(0),
145 .ngpio = S5PC100_GPIO_D_NR, 129 .ngpio = S5PC100_GPIO_D_NR,
146 .label = "GPD", 130 .label = "GPD",
147 }, 131 },
148 }, { 132 }, {
149 .base = S5PC100_GPE0_BASE,
150 .config = &gpio_cfg,
151 .chip = { 133 .chip = {
152 .base = S5PC100_GPE0(0), 134 .base = S5PC100_GPE0(0),
153 .ngpio = S5PC100_GPIO_E0_NR, 135 .ngpio = S5PC100_GPIO_E0_NR,
154 .label = "GPE0", 136 .label = "GPE0",
155 }, 137 },
156 }, { 138 }, {
157 .base = S5PC100_GPE1_BASE,
158 .config = &gpio_cfg,
159 .chip = { 139 .chip = {
160 .base = S5PC100_GPE1(0), 140 .base = S5PC100_GPE1(0),
161 .ngpio = S5PC100_GPIO_E1_NR, 141 .ngpio = S5PC100_GPIO_E1_NR,
162 .label = "GPE1", 142 .label = "GPE1",
163 }, 143 },
164 }, { 144 }, {
165 .base = S5PC100_GPF0_BASE,
166 .config = &gpio_cfg,
167 .chip = { 145 .chip = {
168 .base = S5PC100_GPF0(0), 146 .base = S5PC100_GPF0(0),
169 .ngpio = S5PC100_GPIO_F0_NR, 147 .ngpio = S5PC100_GPIO_F0_NR,
170 .label = "GPF0", 148 .label = "GPF0",
171 }, 149 },
172 }, { 150 }, {
173 .base = S5PC100_GPF1_BASE,
174 .config = &gpio_cfg,
175 .chip = { 151 .chip = {
176 .base = S5PC100_GPF1(0), 152 .base = S5PC100_GPF1(0),
177 .ngpio = S5PC100_GPIO_F1_NR, 153 .ngpio = S5PC100_GPIO_F1_NR,
178 .label = "GPF1", 154 .label = "GPF1",
179 }, 155 },
180 }, { 156 }, {
181 .base = S5PC100_GPF2_BASE,
182 .config = &gpio_cfg,
183 .chip = { 157 .chip = {
184 .base = S5PC100_GPF2(0), 158 .base = S5PC100_GPF2(0),
185 .ngpio = S5PC100_GPIO_F2_NR, 159 .ngpio = S5PC100_GPIO_F2_NR,
186 .label = "GPF2", 160 .label = "GPF2",
187 }, 161 },
188 }, { 162 }, {
189 .base = S5PC100_GPF3_BASE,
190 .config = &gpio_cfg,
191 .chip = { 163 .chip = {
192 .base = S5PC100_GPF3(0), 164 .base = S5PC100_GPF3(0),
193 .ngpio = S5PC100_GPIO_F3_NR, 165 .ngpio = S5PC100_GPIO_F3_NR,
194 .label = "GPF3", 166 .label = "GPF3",
195 }, 167 },
196 }, { 168 }, {
197 .base = S5PC100_GPG0_BASE,
198 .config = &gpio_cfg,
199 .chip = { 169 .chip = {
200 .base = S5PC100_GPG0(0), 170 .base = S5PC100_GPG0(0),
201 .ngpio = S5PC100_GPIO_G0_NR, 171 .ngpio = S5PC100_GPIO_G0_NR,
202 .label = "GPG0", 172 .label = "GPG0",
203 }, 173 },
204 }, { 174 }, {
205 .base = S5PC100_GPG1_BASE,
206 .config = &gpio_cfg,
207 .chip = { 175 .chip = {
208 .base = S5PC100_GPG1(0), 176 .base = S5PC100_GPG1(0),
209 .ngpio = S5PC100_GPIO_G1_NR, 177 .ngpio = S5PC100_GPIO_G1_NR,
210 .label = "GPG1", 178 .label = "GPG1",
211 }, 179 },
212 }, { 180 }, {
213 .base = S5PC100_GPG2_BASE,
214 .config = &gpio_cfg,
215 .chip = { 181 .chip = {
216 .base = S5PC100_GPG2(0), 182 .base = S5PC100_GPG2(0),
217 .ngpio = S5PC100_GPIO_G2_NR, 183 .ngpio = S5PC100_GPIO_G2_NR,
218 .label = "GPG2", 184 .label = "GPG2",
219 }, 185 },
220 }, { 186 }, {
221 .base = S5PC100_GPG3_BASE,
222 .config = &gpio_cfg,
223 .chip = { 187 .chip = {
224 .base = S5PC100_GPG3(0), 188 .base = S5PC100_GPG3(0),
225 .ngpio = S5PC100_GPIO_G3_NR, 189 .ngpio = S5PC100_GPIO_G3_NR,
226 .label = "GPG3", 190 .label = "GPG3",
227 }, 191 },
228 }, { 192 }, {
229 .base = S5PC100_GPH0_BASE,
230 .config = &gpio_cfg_eint,
231 .chip = {
232 .base = S5PC100_GPH0(0),
233 .ngpio = S5PC100_GPIO_H0_NR,
234 .label = "GPH0",
235 },
236 }, {
237 .base = S5PC100_GPH1_BASE,
238 .config = &gpio_cfg_eint,
239 .chip = {
240 .base = S5PC100_GPH1(0),
241 .ngpio = S5PC100_GPIO_H1_NR,
242 .label = "GPH1",
243 },
244 }, {
245 .base = S5PC100_GPH2_BASE,
246 .config = &gpio_cfg_eint,
247 .chip = {
248 .base = S5PC100_GPH2(0),
249 .ngpio = S5PC100_GPIO_H2_NR,
250 .label = "GPH2",
251 },
252 }, {
253 .base = S5PC100_GPH3_BASE,
254 .config = &gpio_cfg_eint,
255 .chip = {
256 .base = S5PC100_GPH3(0),
257 .ngpio = S5PC100_GPIO_H3_NR,
258 .label = "GPH3",
259 },
260 }, {
261 .base = S5PC100_GPI_BASE,
262 .config = &gpio_cfg,
263 .chip = { 193 .chip = {
264 .base = S5PC100_GPI(0), 194 .base = S5PC100_GPI(0),
265 .ngpio = S5PC100_GPIO_I_NR, 195 .ngpio = S5PC100_GPIO_I_NR,
266 .label = "GPI", 196 .label = "GPI",
267 }, 197 },
268 }, { 198 }, {
269 .base = S5PC100_GPJ0_BASE,
270 .config = &gpio_cfg,
271 .chip = { 199 .chip = {
272 .base = S5PC100_GPJ0(0), 200 .base = S5PC100_GPJ0(0),
273 .ngpio = S5PC100_GPIO_J0_NR, 201 .ngpio = S5PC100_GPIO_J0_NR,
274 .label = "GPJ0", 202 .label = "GPJ0",
275 }, 203 },
276 }, { 204 }, {
277 .base = S5PC100_GPJ1_BASE,
278 .config = &gpio_cfg,
279 .chip = { 205 .chip = {
280 .base = S5PC100_GPJ1(0), 206 .base = S5PC100_GPJ1(0),
281 .ngpio = S5PC100_GPIO_J1_NR, 207 .ngpio = S5PC100_GPIO_J1_NR,
282 .label = "GPJ1", 208 .label = "GPJ1",
283 }, 209 },
284 }, { 210 }, {
285 .base = S5PC100_GPJ2_BASE,
286 .config = &gpio_cfg,
287 .chip = { 211 .chip = {
288 .base = S5PC100_GPJ2(0), 212 .base = S5PC100_GPJ2(0),
289 .ngpio = S5PC100_GPIO_J2_NR, 213 .ngpio = S5PC100_GPIO_J2_NR,
290 .label = "GPJ2", 214 .label = "GPJ2",
291 }, 215 },
292 }, { 216 }, {
293 .base = S5PC100_GPJ3_BASE,
294 .config = &gpio_cfg,
295 .chip = { 217 .chip = {
296 .base = S5PC100_GPJ3(0), 218 .base = S5PC100_GPJ3(0),
297 .ngpio = S5PC100_GPIO_J3_NR, 219 .ngpio = S5PC100_GPIO_J3_NR,
298 .label = "GPJ3", 220 .label = "GPJ3",
299 }, 221 },
300 }, { 222 }, {
301 .base = S5PC100_GPJ4_BASE,
302 .config = &gpio_cfg,
303 .chip = { 223 .chip = {
304 .base = S5PC100_GPJ4(0), 224 .base = S5PC100_GPJ4(0),
305 .ngpio = S5PC100_GPIO_J4_NR, 225 .ngpio = S5PC100_GPIO_J4_NR,
306 .label = "GPJ4", 226 .label = "GPJ4",
307 }, 227 },
308 }, { 228 }, {
309 .base = S5PC100_GPK0_BASE,
310 .config = &gpio_cfg_noint, 229 .config = &gpio_cfg_noint,
311 .chip = { 230 .chip = {
312 .base = S5PC100_GPK0(0), 231 .base = S5PC100_GPK0(0),
@@ -314,7 +233,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
314 .label = "GPK0", 233 .label = "GPK0",
315 }, 234 },
316 }, { 235 }, {
317 .base = S5PC100_GPK1_BASE,
318 .config = &gpio_cfg_noint, 236 .config = &gpio_cfg_noint,
319 .chip = { 237 .chip = {
320 .base = S5PC100_GPK1(0), 238 .base = S5PC100_GPK1(0),
@@ -322,7 +240,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
322 .label = "GPK1", 240 .label = "GPK1",
323 }, 241 },
324 }, { 242 }, {
325 .base = S5PC100_GPK2_BASE,
326 .config = &gpio_cfg_noint, 243 .config = &gpio_cfg_noint,
327 .chip = { 244 .chip = {
328 .base = S5PC100_GPK2(0), 245 .base = S5PC100_GPK2(0),
@@ -330,7 +247,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
330 .label = "GPK2", 247 .label = "GPK2",
331 }, 248 },
332 }, { 249 }, {
333 .base = S5PC100_GPK3_BASE,
334 .config = &gpio_cfg_noint, 250 .config = &gpio_cfg_noint,
335 .chip = { 251 .chip = {
336 .base = S5PC100_GPK3(0), 252 .base = S5PC100_GPK3(0),
@@ -338,7 +254,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
338 .label = "GPK3", 254 .label = "GPK3",
339 }, 255 },
340 }, { 256 }, {
341 .base = S5PC100_GPL0_BASE,
342 .config = &gpio_cfg_noint, 257 .config = &gpio_cfg_noint,
343 .chip = { 258 .chip = {
344 .base = S5PC100_GPL0(0), 259 .base = S5PC100_GPL0(0),
@@ -346,7 +261,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
346 .label = "GPL0", 261 .label = "GPL0",
347 }, 262 },
348 }, { 263 }, {
349 .base = S5PC100_GPL1_BASE,
350 .config = &gpio_cfg_noint, 264 .config = &gpio_cfg_noint,
351 .chip = { 265 .chip = {
352 .base = S5PC100_GPL1(0), 266 .base = S5PC100_GPL1(0),
@@ -354,7 +268,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
354 .label = "GPL1", 268 .label = "GPL1",
355 }, 269 },
356 }, { 270 }, {
357 .base = S5PC100_GPL2_BASE,
358 .config = &gpio_cfg_noint, 271 .config = &gpio_cfg_noint,
359 .chip = { 272 .chip = {
360 .base = S5PC100_GPL2(0), 273 .base = S5PC100_GPL2(0),
@@ -362,7 +275,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
362 .label = "GPL2", 275 .label = "GPL2",
363 }, 276 },
364 }, { 277 }, {
365 .base = S5PC100_GPL3_BASE,
366 .config = &gpio_cfg_noint, 278 .config = &gpio_cfg_noint,
367 .chip = { 279 .chip = {
368 .base = S5PC100_GPL3(0), 280 .base = S5PC100_GPL3(0),
@@ -370,56 +282,72 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
370 .label = "GPL3", 282 .label = "GPL3",
371 }, 283 },
372 }, { 284 }, {
373 .base = S5PC100_GPL4_BASE,
374 .config = &gpio_cfg_noint, 285 .config = &gpio_cfg_noint,
375 .chip = { 286 .chip = {
376 .base = S5PC100_GPL4(0), 287 .base = S5PC100_GPL4(0),
377 .ngpio = S5PC100_GPIO_L4_NR, 288 .ngpio = S5PC100_GPIO_L4_NR,
378 .label = "GPL4", 289 .label = "GPL4",
379 }, 290 },
291 }, {
292 .base = (S5P_VA_GPIO + 0xC00),
293 .config = &gpio_cfg_eint,
294 .irq_base = IRQ_EINT(0),
295 .chip = {
296 .base = S5PC100_GPH0(0),
297 .ngpio = S5PC100_GPIO_H0_NR,
298 .label = "GPH0",
299 .to_irq = samsung_gpiolib_to_irq,
300 },
301 }, {
302 .base = (S5P_VA_GPIO + 0xC20),
303 .config = &gpio_cfg_eint,
304 .irq_base = IRQ_EINT(8),
305 .chip = {
306 .base = S5PC100_GPH1(0),
307 .ngpio = S5PC100_GPIO_H1_NR,
308 .label = "GPH1",
309 .to_irq = samsung_gpiolib_to_irq,
310 },
311 }, {
312 .base = (S5P_VA_GPIO + 0xC40),
313 .config = &gpio_cfg_eint,
314 .irq_base = IRQ_EINT(16),
315 .chip = {
316 .base = S5PC100_GPH2(0),
317 .ngpio = S5PC100_GPIO_H2_NR,
318 .label = "GPH2",
319 .to_irq = samsung_gpiolib_to_irq,
320 },
321 }, {
322 .base = (S5P_VA_GPIO + 0xC60),
323 .config = &gpio_cfg_eint,
324 .irq_base = IRQ_EINT(24),
325 .chip = {
326 .base = S5PC100_GPH3(0),
327 .ngpio = S5PC100_GPIO_H3_NR,
328 .label = "GPH3",
329 .to_irq = samsung_gpiolib_to_irq,
330 },
380 }, 331 },
381}; 332};
382 333
383/* FIXME move from irq-gpio.c */ 334static __init int s5pc100_gpiolib_init(void)
384extern struct irq_chip s5pc100_gpioint;
385extern void s5pc100_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc);
386
387static __init void s5pc100_gpiolib_link(struct s3c_gpio_chip *chip)
388{ 335{
389 /* Interrupt */ 336 struct s3c_gpio_chip *chip = s5pc100_gpio_chips;
390 if (chip->config == &gpio_cfg) { 337 int nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
391 int i, irq; 338 int gpioint_group = 0;
392 339 int i;
393 chip->chip.to_irq = s5pc100_gpiolib_to_irq;
394 340
395 for (i = 0; i < chip->chip.ngpio; i++) { 341 for (i = 0; i < nr_chips; i++, chip++) {
396 irq = S3C_IRQ_GPIO_BASE + chip->chip.base + i; 342 if (chip->config == NULL) {
397 set_irq_chip(irq, &s5pc100_gpioint); 343 chip->config = &gpio_cfg;
398 set_irq_data(irq, &chip->chip); 344 chip->group = gpioint_group++;
399 set_irq_handler(irq, handle_level_irq);
400 set_irq_flags(irq, IRQF_VALID);
401 } 345 }
402 } else if (chip->config == &gpio_cfg_eint) { 346 if (chip->base == NULL)
403 chip->chip.to_irq = s5pc100_gpiolib_to_eint; 347 chip->base = S5PC100_BANK_BASE(i);
404 } 348 }
405}
406
407static __init int s5pc100_gpiolib_init(void)
408{
409 struct s3c_gpio_chip *chip;
410 int nr_chips;
411
412 chip = s5pc100_gpio_chips;
413 nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
414
415 for (; nr_chips > 0; nr_chips--, chip++)
416 s5pc100_gpiolib_link(chip);
417
418 samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips,
419 ARRAY_SIZE(s5pc100_gpio_chips));
420 349
421 /* Interrupt */ 350 samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips);
422 set_irq_chained_handler(IRQ_GPIOINT, s5pc100_irq_gpioint_handler);
423 351
424 return 0; 352 return 0;
425} 353}
diff --git a/arch/arm/mach-s5pc100/include/mach/gpio.h b/arch/arm/mach-s5pc100/include/mach/gpio.h
index 71ae1f52df1d..29a8a12d9b4f 100644
--- a/arch/arm/mach-s5pc100/include/mach/gpio.h
+++ b/arch/arm/mach-s5pc100/include/mach/gpio.h
@@ -146,13 +146,6 @@ enum s5p_gpio_number {
146/* define the number of gpios we need to the one after the MP04() range */ 146/* define the number of gpios we need to the one after the MP04() range */
147#define ARCH_NR_GPIOS (S5PC100_GPIO_END + 1) 147#define ARCH_NR_GPIOS (S5PC100_GPIO_END + 1)
148 148
149#define EINT_MODE S3C_GPIO_SFN(0x2)
150
151#define EINT_GPIO_0(x) S5PC100_GPH0(x)
152#define EINT_GPIO_1(x) S5PC100_GPH1(x)
153#define EINT_GPIO_2(x) S5PC100_GPH2(x)
154#define EINT_GPIO_3(x) S5PC100_GPH3(x)
155
156#include <asm-generic/gpio.h> 149#include <asm-generic/gpio.h>
157 150
158#endif /* __ASM_ARCH_GPIO_H */ 151#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h
index 06513e647242..d2eb4757381f 100644
--- a/arch/arm/mach-s5pc100/include/mach/irqs.h
+++ b/arch/arm/mach-s5pc100/include/mach/irqs.h
@@ -48,8 +48,8 @@
48#define IRQ_SPI1 S5P_IRQ_VIC1(16) 48#define IRQ_SPI1 S5P_IRQ_VIC1(16)
49#define IRQ_SPI2 S5P_IRQ_VIC1(17) 49#define IRQ_SPI2 S5P_IRQ_VIC1(17)
50#define IRQ_IRDA S5P_IRQ_VIC1(18) 50#define IRQ_IRDA S5P_IRQ_VIC1(18)
51#define IRQ_CAN0 S5P_IRQ_VIC1(19) 51#define IRQ_IIC2 S5P_IRQ_VIC1(19)
52#define IRQ_CAN1 S5P_IRQ_VIC1(20) 52#define IRQ_IIC3 S5P_IRQ_VIC1(20)
53#define IRQ_HSIRX S5P_IRQ_VIC1(21) 53#define IRQ_HSIRX S5P_IRQ_VIC1(21)
54#define IRQ_HSITX S5P_IRQ_VIC1(22) 54#define IRQ_HSITX S5P_IRQ_VIC1(22)
55#define IRQ_UHOST S5P_IRQ_VIC1(23) 55#define IRQ_UHOST S5P_IRQ_VIC1(23)
@@ -100,11 +100,12 @@
100#define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0)) 100#define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0))
101#define S5P_EINT_BASE2 (IRQ_VIC_END + 1) 101#define S5P_EINT_BASE2 (IRQ_VIC_END + 1)
102 102
103#define S3C_IRQ_GPIO_BASE (IRQ_EINT(31) + 1) 103/* GPIO interrupt */
104#define S3C_IRQ_GPIO(x) (S3C_IRQ_GPIO_BASE + (x)) 104#define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1)
105#define S5P_GPIOINT_GROUP_MAXNR 21
105 106
106/* Until MP04 Groups -> 40 (exactly 39) Groups * 8 ~= 320 GPIOs */ 107/* Set the default NR_IRQS */
107#define NR_IRQS (S3C_IRQ_GPIO(320) + 1) 108#define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
108 109
109/* Compatibility */ 110/* Compatibility */
110#define IRQ_LCD_FIFO IRQ_LCD0 111#define IRQ_LCD_FIFO IRQ_LCD0
diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h
index 8751ef4a6804..32e9cab5c864 100644
--- a/arch/arm/mach-s5pc100/include/mach/map.h
+++ b/arch/arm/mach-s5pc100/include/mach/map.h
@@ -110,6 +110,8 @@
110#define S5PC100_PA_PCM0 0xF2400000 110#define S5PC100_PA_PCM0 0xF2400000
111#define S5PC100_PA_PCM1 0xF2500000 111#define S5PC100_PA_PCM1 0xF2500000
112 112
113#define S5PC100_PA_SPDIF 0xF2600000
114
113#define S5PC100_PA_TSADC (0xF3000000) 115#define S5PC100_PA_TSADC (0xF3000000)
114 116
115/* KEYPAD */ 117/* KEYPAD */
diff --git a/arch/arm/mach-s5pc100/include/mach/regs-gpio.h b/arch/arm/mach-s5pc100/include/mach/regs-gpio.h
index dd6295e1251d..0bf73209ec7b 100644
--- a/arch/arm/mach-s5pc100/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s5pc100/include/mach/regs-gpio.h
@@ -11,43 +11,6 @@
11 11
12#include <mach/map.h> 12#include <mach/map.h>
13 13
14/* S5PC100 */
15#define S5PC100_GPIO_BASE S5P_VA_GPIO
16#define S5PC100_GPA0_BASE (S5PC100_GPIO_BASE + 0x0000)
17#define S5PC100_GPA1_BASE (S5PC100_GPIO_BASE + 0x0020)
18#define S5PC100_GPB_BASE (S5PC100_GPIO_BASE + 0x0040)
19#define S5PC100_GPC_BASE (S5PC100_GPIO_BASE + 0x0060)
20#define S5PC100_GPD_BASE (S5PC100_GPIO_BASE + 0x0080)
21#define S5PC100_GPE0_BASE (S5PC100_GPIO_BASE + 0x00A0)
22#define S5PC100_GPE1_BASE (S5PC100_GPIO_BASE + 0x00C0)
23#define S5PC100_GPF0_BASE (S5PC100_GPIO_BASE + 0x00E0)
24#define S5PC100_GPF1_BASE (S5PC100_GPIO_BASE + 0x0100)
25#define S5PC100_GPF2_BASE (S5PC100_GPIO_BASE + 0x0120)
26#define S5PC100_GPF3_BASE (S5PC100_GPIO_BASE + 0x0140)
27#define S5PC100_GPG0_BASE (S5PC100_GPIO_BASE + 0x0160)
28#define S5PC100_GPG1_BASE (S5PC100_GPIO_BASE + 0x0180)
29#define S5PC100_GPG2_BASE (S5PC100_GPIO_BASE + 0x01A0)
30#define S5PC100_GPG3_BASE (S5PC100_GPIO_BASE + 0x01C0)
31#define S5PC100_GPH0_BASE (S5PC100_GPIO_BASE + 0x0C00)
32#define S5PC100_GPH1_BASE (S5PC100_GPIO_BASE + 0x0C20)
33#define S5PC100_GPH2_BASE (S5PC100_GPIO_BASE + 0x0C40)
34#define S5PC100_GPH3_BASE (S5PC100_GPIO_BASE + 0x0C60)
35#define S5PC100_GPI_BASE (S5PC100_GPIO_BASE + 0x01E0)
36#define S5PC100_GPJ0_BASE (S5PC100_GPIO_BASE + 0x0200)
37#define S5PC100_GPJ1_BASE (S5PC100_GPIO_BASE + 0x0220)
38#define S5PC100_GPJ2_BASE (S5PC100_GPIO_BASE + 0x0240)
39#define S5PC100_GPJ3_BASE (S5PC100_GPIO_BASE + 0x0260)
40#define S5PC100_GPJ4_BASE (S5PC100_GPIO_BASE + 0x0280)
41#define S5PC100_GPK0_BASE (S5PC100_GPIO_BASE + 0x02A0)
42#define S5PC100_GPK1_BASE (S5PC100_GPIO_BASE + 0x02C0)
43#define S5PC100_GPK2_BASE (S5PC100_GPIO_BASE + 0x02E0)
44#define S5PC100_GPK3_BASE (S5PC100_GPIO_BASE + 0x0300)
45#define S5PC100_GPL0_BASE (S5PC100_GPIO_BASE + 0x0320)
46#define S5PC100_GPL1_BASE (S5PC100_GPIO_BASE + 0x0340)
47#define S5PC100_GPL2_BASE (S5PC100_GPIO_BASE + 0x0360)
48#define S5PC100_GPL3_BASE (S5PC100_GPIO_BASE + 0x0380)
49#define S5PC100_GPL4_BASE (S5PC100_GPIO_BASE + 0x03A0)
50
51#define S5PC100EINT30CON (S5P_VA_GPIO + 0xE00) 14#define S5PC100EINT30CON (S5P_VA_GPIO + 0xE00)
52#define S5P_EINT_CON(x) (S5PC100EINT30CON + ((x) * 0x4)) 15#define S5P_EINT_CON(x) (S5PC100EINT30CON + ((x) * 0x4))
53 16
@@ -64,12 +27,12 @@
64 27
65#define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7)) 28#define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7))
66 29
67/* values for S5P_EXTINT0 */ 30#define EINT_MODE S3C_GPIO_SFN(0x2)
68#define S5P_EXTINT_LOWLEV (0x00) 31
69#define S5P_EXTINT_HILEV (0x01) 32#define EINT_GPIO_0(x) S5PC100_GPH0(x)
70#define S5P_EXTINT_FALLEDGE (0x02) 33#define EINT_GPIO_1(x) S5PC100_GPH1(x)
71#define S5P_EXTINT_RISEEDGE (0x03) 34#define EINT_GPIO_2(x) S5PC100_GPH2(x)
72#define S5P_EXTINT_BOTHEDGE (0x04) 35#define EINT_GPIO_3(x) S5PC100_GPH3(x)
73 36
74#endif /* __ASM_MACH_S5PC100_REGS_GPIO_H */ 37#endif /* __ASM_MACH_S5PC100_REGS_GPIO_H */
75 38
diff --git a/arch/arm/mach-s5pc100/include/mach/vmalloc.h b/arch/arm/mach-s5pc100/include/mach/vmalloc.h
index be9df79903ed..44c8e5726d9d 100644
--- a/arch/arm/mach-s5pc100/include/mach/vmalloc.h
+++ b/arch/arm/mach-s5pc100/include/mach/vmalloc.h
@@ -12,6 +12,6 @@
12#ifndef __ASM_ARCH_VMALLOC_H 12#ifndef __ASM_ARCH_VMALLOC_H
13#define __ASM_ARCH_VMALLOC_H 13#define __ASM_ARCH_VMALLOC_H
14 14
15#define VMALLOC_END (0xe0000000UL) 15#define VMALLOC_END 0xF6000000UL
16 16
17#endif /* __ASM_ARCH_VMALLOC_H */ 17#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5pc100/irq-gpio.c b/arch/arm/mach-s5pc100/irq-gpio.c
deleted file mode 100644
index 2bf86c18bc73..000000000000
--- a/arch/arm/mach-s5pc100/irq-gpio.c
+++ /dev/null
@@ -1,266 +0,0 @@
1/*
2 * arch/arm/mach-s5pc100/irq-gpio.c
3 *
4 * Copyright (C) 2009 Samsung Electronics
5 *
6 * S5PC100 - Interrupt handling for IRQ_GPIO${group}(x)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/irq.h>
16#include <linux/io.h>
17#include <linux/gpio.h>
18
19#include <mach/map.h>
20#include <plat/gpio-cfg.h>
21
22#define S5P_GPIOREG(x) (S5P_VA_GPIO + (x))
23
24#define CON_OFFSET 0x700
25#define MASK_OFFSET 0x900
26#define PEND_OFFSET 0xA00
27#define CON_OFFSET_2 0xE00
28#define MASK_OFFSET_2 0xF00
29#define PEND_OFFSET_2 0xF40
30
31#define GPIOINT_LEVEL_LOW 0x0
32#define GPIOINT_LEVEL_HIGH 0x1
33#define GPIOINT_EDGE_FALLING 0x2
34#define GPIOINT_EDGE_RISING 0x3
35#define GPIOINT_EDGE_BOTH 0x4
36
37static int group_to_con_offset(int group)
38{
39 return group << 2;
40}
41
42static int group_to_mask_offset(int group)
43{
44 return group << 2;
45}
46
47static int group_to_pend_offset(int group)
48{
49 return group << 2;
50}
51
52static int s5pc100_get_start(unsigned int group)
53{
54 switch (group) {
55 case 0: return S5PC100_GPIO_A0_START;
56 case 1: return S5PC100_GPIO_A1_START;
57 case 2: return S5PC100_GPIO_B_START;
58 case 3: return S5PC100_GPIO_C_START;
59 case 4: return S5PC100_GPIO_D_START;
60 case 5: return S5PC100_GPIO_E0_START;
61 case 6: return S5PC100_GPIO_E1_START;
62 case 7: return S5PC100_GPIO_F0_START;
63 case 8: return S5PC100_GPIO_F1_START;
64 case 9: return S5PC100_GPIO_F2_START;
65 case 10: return S5PC100_GPIO_F3_START;
66 case 11: return S5PC100_GPIO_G0_START;
67 case 12: return S5PC100_GPIO_G1_START;
68 case 13: return S5PC100_GPIO_G2_START;
69 case 14: return S5PC100_GPIO_G3_START;
70 case 15: return S5PC100_GPIO_I_START;
71 case 16: return S5PC100_GPIO_J0_START;
72 case 17: return S5PC100_GPIO_J1_START;
73 case 18: return S5PC100_GPIO_J2_START;
74 case 19: return S5PC100_GPIO_J3_START;
75 case 20: return S5PC100_GPIO_J4_START;
76 default:
77 BUG();
78 }
79
80 return -EINVAL;
81}
82
83static int s5pc100_get_group(unsigned int irq)
84{
85 irq -= S3C_IRQ_GPIO(0);
86
87 switch (irq) {
88 case S5PC100_GPIO_A0_START ... S5PC100_GPIO_A1_START - 1:
89 return 0;
90 case S5PC100_GPIO_A1_START ... S5PC100_GPIO_B_START - 1:
91 return 1;
92 case S5PC100_GPIO_B_START ... S5PC100_GPIO_C_START - 1:
93 return 2;
94 case S5PC100_GPIO_C_START ... S5PC100_GPIO_D_START - 1:
95 return 3;
96 case S5PC100_GPIO_D_START ... S5PC100_GPIO_E0_START - 1:
97 return 4;
98 case S5PC100_GPIO_E0_START ... S5PC100_GPIO_E1_START - 1:
99 return 5;
100 case S5PC100_GPIO_E1_START ... S5PC100_GPIO_F0_START - 1:
101 return 6;
102 case S5PC100_GPIO_F0_START ... S5PC100_GPIO_F1_START - 1:
103 return 7;
104 case S5PC100_GPIO_F1_START ... S5PC100_GPIO_F2_START - 1:
105 return 8;
106 case S5PC100_GPIO_F2_START ... S5PC100_GPIO_F3_START - 1:
107 return 9;
108 case S5PC100_GPIO_F3_START ... S5PC100_GPIO_G0_START - 1:
109 return 10;
110 case S5PC100_GPIO_G0_START ... S5PC100_GPIO_G1_START - 1:
111 return 11;
112 case S5PC100_GPIO_G1_START ... S5PC100_GPIO_G2_START - 1:
113 return 12;
114 case S5PC100_GPIO_G2_START ... S5PC100_GPIO_G3_START - 1:
115 return 13;
116 case S5PC100_GPIO_G3_START ... S5PC100_GPIO_H0_START - 1:
117 return 14;
118 case S5PC100_GPIO_I_START ... S5PC100_GPIO_J0_START - 1:
119 return 15;
120 case S5PC100_GPIO_J0_START ... S5PC100_GPIO_J1_START - 1:
121 return 16;
122 case S5PC100_GPIO_J1_START ... S5PC100_GPIO_J2_START - 1:
123 return 17;
124 case S5PC100_GPIO_J2_START ... S5PC100_GPIO_J3_START - 1:
125 return 18;
126 case S5PC100_GPIO_J3_START ... S5PC100_GPIO_J4_START - 1:
127 return 19;
128 case S5PC100_GPIO_J4_START ... S5PC100_GPIO_K0_START - 1:
129 return 20;
130 default:
131 BUG();
132 }
133
134 return -EINVAL;
135}
136
137static int s5pc100_get_offset(unsigned int irq)
138{
139 struct gpio_chip *chip = get_irq_data(irq);
140 return irq - S3C_IRQ_GPIO(chip->base);
141}
142
143static void s5pc100_gpioint_ack(unsigned int irq)
144{
145 int group, offset, pend_offset;
146 unsigned int value;
147
148 group = s5pc100_get_group(irq);
149 offset = s5pc100_get_offset(irq);
150 pend_offset = group_to_pend_offset(group);
151
152 value = __raw_readl(S5P_GPIOREG(PEND_OFFSET) + pend_offset);
153 value |= 1 << offset;
154 __raw_writel(value, S5P_GPIOREG(PEND_OFFSET) + pend_offset);
155}
156
157static void s5pc100_gpioint_mask(unsigned int irq)
158{
159 int group, offset, mask_offset;
160 unsigned int value;
161
162 group = s5pc100_get_group(irq);
163 offset = s5pc100_get_offset(irq);
164 mask_offset = group_to_mask_offset(group);
165
166 value = __raw_readl(S5P_GPIOREG(MASK_OFFSET) + mask_offset);
167 value |= 1 << offset;
168 __raw_writel(value, S5P_GPIOREG(MASK_OFFSET) + mask_offset);
169}
170
171static void s5pc100_gpioint_unmask(unsigned int irq)
172{
173 int group, offset, mask_offset;
174 unsigned int value;
175
176 group = s5pc100_get_group(irq);
177 offset = s5pc100_get_offset(irq);
178 mask_offset = group_to_mask_offset(group);
179
180 value = __raw_readl(S5P_GPIOREG(MASK_OFFSET) + mask_offset);
181 value &= ~(1 << offset);
182 __raw_writel(value, S5P_GPIOREG(MASK_OFFSET) + mask_offset);
183}
184
185static void s5pc100_gpioint_mask_ack(unsigned int irq)
186{
187 s5pc100_gpioint_mask(irq);
188 s5pc100_gpioint_ack(irq);
189}
190
191static int s5pc100_gpioint_set_type(unsigned int irq, unsigned int type)
192{
193 int group, offset, con_offset;
194 unsigned int value;
195
196 group = s5pc100_get_group(irq);
197 offset = s5pc100_get_offset(irq);
198 con_offset = group_to_con_offset(group);
199
200 switch (type) {
201 case IRQ_TYPE_NONE:
202 printk(KERN_WARNING "No irq type\n");
203 return -EINVAL;
204 case IRQ_TYPE_EDGE_RISING:
205 type = GPIOINT_EDGE_RISING;
206 break;
207 case IRQ_TYPE_EDGE_FALLING:
208 type = GPIOINT_EDGE_FALLING;
209 break;
210 case IRQ_TYPE_EDGE_BOTH:
211 type = GPIOINT_EDGE_BOTH;
212 break;
213 case IRQ_TYPE_LEVEL_HIGH:
214 type = GPIOINT_LEVEL_HIGH;
215 break;
216 case IRQ_TYPE_LEVEL_LOW:
217 type = GPIOINT_LEVEL_LOW;
218 break;
219 default:
220 BUG();
221 }
222
223
224 value = __raw_readl(S5P_GPIOREG(CON_OFFSET) + con_offset);
225 value &= ~(0xf << (offset * 0x4));
226 value |= (type << (offset * 0x4));
227 __raw_writel(value, S5P_GPIOREG(CON_OFFSET) + con_offset);
228
229 return 0;
230}
231
232struct irq_chip s5pc100_gpioint = {
233 .name = "GPIO",
234 .ack = s5pc100_gpioint_ack,
235 .mask = s5pc100_gpioint_mask,
236 .mask_ack = s5pc100_gpioint_mask_ack,
237 .unmask = s5pc100_gpioint_unmask,
238 .set_type = s5pc100_gpioint_set_type,
239};
240
241void s5pc100_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc)
242{
243 int group, offset, pend_offset, mask_offset;
244 int real_irq, group_end;
245 unsigned int pend, mask;
246
247 group_end = 21;
248
249 for (group = 0; group < group_end; group++) {
250 pend_offset = group_to_pend_offset(group);
251 pend = __raw_readl(S5P_GPIOREG(PEND_OFFSET) + pend_offset);
252 if (!pend)
253 continue;
254
255 mask_offset = group_to_mask_offset(group);
256 mask = __raw_readl(S5P_GPIOREG(MASK_OFFSET) + mask_offset);
257 pend &= ~mask;
258
259 for (offset = 0; offset < 8; offset++) {
260 if (pend & (1 << offset)) {
261 real_irq = s5pc100_get_start(group) + offset;
262 generic_handle_irq(S3C_IRQ_GPIO(real_irq));
263 }
264 }
265 }
266}
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 880fb075092c..18b405d514d6 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -47,6 +47,7 @@
47#include <plat/adc.h> 47#include <plat/adc.h>
48#include <plat/keypad.h> 48#include <plat/keypad.h>
49#include <plat/ts.h> 49#include <plat/ts.h>
50#include <plat/audio.h>
50 51
51/* Following are default values for UCON, ULCON and UFCON UART registers */ 52/* Following are default values for UCON, ULCON and UFCON UART registers */
52#define SMDKC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ 53#define SMDKC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -196,6 +197,7 @@ static struct platform_device *smdkc100_devices[] __initdata = {
196 &s5p_device_fimc0, 197 &s5p_device_fimc0,
197 &s5p_device_fimc1, 198 &s5p_device_fimc1,
198 &s5p_device_fimc2, 199 &s5p_device_fimc2,
200 &s5pc100_device_spdif,
199}; 201};
200 202
201static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { 203static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
@@ -226,6 +228,8 @@ static void __init smdkc100_machine_init(void)
226 228
227 samsung_keypad_set_platdata(&smdkc100_keypad_data); 229 samsung_keypad_set_platdata(&smdkc100_keypad_data);
228 230
231 s5pc100_spdif_setup_gpio(S5PC100_SPDIF_GPD);
232
229 /* LCD init */ 233 /* LCD init */
230 gpio_request(S5PC100_GPD(0), "GPD"); 234 gpio_request(S5PC100_GPD(0), "GPD");
231 gpio_request(S5PC100_GPH0(6), "GPH0"); 235 gpio_request(S5PC100_GPH0(6), "GPH0");
diff --git a/arch/arm/mach-s5pc100/setup-fb-24bpp.c b/arch/arm/mach-s5pc100/setup-fb-24bpp.c
index 6eba6cb8e2f4..d31c0f3fe222 100644
--- a/arch/arm/mach-s5pc100/setup-fb-24bpp.c
+++ b/arch/arm/mach-s5pc100/setup-fb-24bpp.c
@@ -22,27 +22,15 @@
22 22
23#define DISR_OFFSET 0x7008 23#define DISR_OFFSET 0x7008
24 24
25void s5pc100_fb_gpio_setup_24bpp(void) 25static void s5pc100_fb_setgpios(unsigned int base, unsigned int nr)
26{ 26{
27 unsigned int gpio = 0; 27 s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(2));
28 28}
29 for (gpio = S5PC100_GPF0(0); gpio <= S5PC100_GPF0(7); gpio++) {
30 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
31 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
32 }
33
34 for (gpio = S5PC100_GPF1(0); gpio <= S5PC100_GPF1(7); gpio++) {
35 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
36 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
37 }
38
39 for (gpio = S5PC100_GPF2(0); gpio <= S5PC100_GPF2(7); gpio++) {
40 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
41 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
42 }
43 29
44 for (gpio = S5PC100_GPF3(0); gpio <= S5PC100_GPF3(3); gpio++) { 30void s5pc100_fb_gpio_setup_24bpp(void)
45 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); 31{
46 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); 32 s5pc100_fb_setgpios(S5PC100_GPF0(0), 8);
47 } 33 s5pc100_fb_setgpios(S5PC100_GPF1(0), 8);
34 s5pc100_fb_setgpios(S5PC100_GPF2(0), 8);
35 s5pc100_fb_setgpios(S5PC100_GPF3(0), 4);
48} 36}
diff --git a/arch/arm/mach-s5pc100/setup-i2c0.c b/arch/arm/mach-s5pc100/setup-i2c0.c
index dd3174e6ecc5..eaef7a3bda49 100644
--- a/arch/arm/mach-s5pc100/setup-i2c0.c
+++ b/arch/arm/mach-s5pc100/setup-i2c0.c
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */
23 23
24void s3c_i2c0_cfg_gpio(struct platform_device *dev) 24void s3c_i2c0_cfg_gpio(struct platform_device *dev)
25{ 25{
26 s3c_gpio_cfgpin(S5PC100_GPD(3), S3C_GPIO_SFN(2)); 26 s3c_gpio_cfgall_range(S5PC100_GPD(3), 2,
27 s3c_gpio_setpull(S5PC100_GPD(3), S3C_GPIO_PULL_UP); 27 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
28 s3c_gpio_cfgpin(S5PC100_GPD(4), S3C_GPIO_SFN(2));
29 s3c_gpio_setpull(S5PC100_GPD(4), S3C_GPIO_PULL_UP);
30} 28}
diff --git a/arch/arm/mach-s5pc100/setup-i2c1.c b/arch/arm/mach-s5pc100/setup-i2c1.c
index d1fec26b69ee..aaff74a90dee 100644
--- a/arch/arm/mach-s5pc100/setup-i2c1.c
+++ b/arch/arm/mach-s5pc100/setup-i2c1.c
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */
23 23
24void s3c_i2c1_cfg_gpio(struct platform_device *dev) 24void s3c_i2c1_cfg_gpio(struct platform_device *dev)
25{ 25{
26 s3c_gpio_cfgpin(S5PC100_GPD(5), S3C_GPIO_SFN(2)); 26 s3c_gpio_cfgall_range(S5PC100_GPD(5), 2,
27 s3c_gpio_setpull(S5PC100_GPD(5), S3C_GPIO_PULL_UP); 27 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
28 s3c_gpio_cfgpin(S5PC100_GPD(6), S3C_GPIO_SFN(2));
29 s3c_gpio_setpull(S5PC100_GPD(6), S3C_GPIO_PULL_UP);
30} 28}
diff --git a/arch/arm/mach-s5pc100/setup-ide.c b/arch/arm/mach-s5pc100/setup-ide.c
index 83575671fb59..223aae044466 100644
--- a/arch/arm/mach-s5pc100/setup-ide.c
+++ b/arch/arm/mach-s5pc100/setup-ide.c
@@ -17,52 +17,39 @@
17#include <mach/regs-clock.h> 17#include <mach/regs-clock.h>
18#include <plat/gpio-cfg.h> 18#include <plat/gpio-cfg.h>
19 19
20static void s5pc100_ide_cfg_gpios(unsigned int base, unsigned int nr)
21{
22 s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(4));
23
24 for (; nr > 0; nr--, base++)
25 s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4);
26}
27
20void s5pc100_ide_setup_gpio(void) 28void s5pc100_ide_setup_gpio(void)
21{ 29{
22 u32 reg; 30 u32 reg;
23 u32 gpio = 0;
24 31
25 /* Independent CF interface, CF chip select configuration */ 32 /* Independent CF interface, CF chip select configuration */
26 reg = readl(S5PC100_MEM_SYS_CFG) & (~0x3f); 33 reg = readl(S5PC100_MEM_SYS_CFG) & (~0x3f);
27 writel(reg | MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S5PC100_MEM_SYS_CFG); 34 writel(reg | MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S5PC100_MEM_SYS_CFG);
28 35
29 /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */ 36 /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */
30 for (gpio = S5PC100_GPJ0(0); gpio <= S5PC100_GPJ0(7); gpio++) { 37 s5pc100_ide_cfg_gpios(S5PC100_GPJ0(0), 8);
31 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
32 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
33 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
34 }
35 38
36 /*CF_Data[0 - 7] */ 39 /*CF_Data[0 - 7] */
37 for (gpio = S5PC100_GPJ2(0); gpio <= S5PC100_GPJ2(7); gpio++) { 40 s5pc100_ide_cfg_gpios(S5PC100_GPJ2(0), 8);
38 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
39 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
40 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
41 }
42 41
43 /* CF_Data[8 - 15] */ 42 /* CF_Data[8 - 15] */
44 for (gpio = S5PC100_GPJ3(0); gpio <= S5PC100_GPJ3(7); gpio++) { 43 s5pc100_ide_cfg_gpios(S5PC100_GPJ3(0), 8);
45 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
46 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
47 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
48 }
49 44
50 /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */ 45 /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */
51 for (gpio = S5PC100_GPJ4(0); gpio <= S5PC100_GPJ4(3); gpio++) { 46 s5pc100_ide_cfg_gpios(S5PC100_GPJ4(0), 4);
52 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
53 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
54 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
55 }
56 47
57 /* EBI_OE, EBI_WE */ 48 /* EBI_OE, EBI_WE */
58 for (gpio = S5PC100_GPK0(6); gpio <= S5PC100_GPK0(7); gpio++) 49 s3c_gpio_cfgpin_range(S5PC100_GPK0(6), 2, S3C_GPIO_SFN(0));
59 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0));
60 50
61 /* CF_OE, CF_WE */ 51 /* CF_OE, CF_WE */
62 for (gpio = S5PC100_GPK1(6); gpio <= S5PC100_GPK1(7); gpio++) { 52 s3c_gpio_cfgrange_nopull(S5PC100_GPK1(6), 8, S3C_GPIO_SFN(2));
63 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
64 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
65 }
66 53
67 /* CF_CD */ 54 /* CF_CD */
68 s3c_gpio_cfgpin(S5PC100_GPK3(5), S3C_GPIO_SFN(2)); 55 s3c_gpio_cfgpin(S5PC100_GPK3(5), S3C_GPIO_SFN(2));
diff --git a/arch/arm/mach-s5pc100/setup-keypad.c b/arch/arm/mach-s5pc100/setup-keypad.c
index d0837a72a58e..ada377f0c206 100644
--- a/arch/arm/mach-s5pc100/setup-keypad.c
+++ b/arch/arm/mach-s5pc100/setup-keypad.c
@@ -15,20 +15,9 @@
15 15
16void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) 16void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
17{ 17{
18 unsigned int gpio;
19 unsigned int end;
20
21 /* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */ 18 /* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */
22 end = S5PC100_GPH3(rows); 19 s3c_gpio_cfgrange_nopull(S5PC100_GPH3(0), rows, S3C_GPIO_SFN(3));
23 for (gpio = S5PC100_GPH3(0); gpio < end; gpio++) {
24 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
25 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
26 }
27 20
28 /* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */ 21 /* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */
29 end = S5PC100_GPH2(cols); 22 s3c_gpio_cfgrange_nopull(S5PC100_GPH2(0), cols, S3C_GPIO_SFN(3));
30 for (gpio = S5PC100_GPH2(0); gpio < end; gpio++) {
31 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
32 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
33 }
34} 23}
diff --git a/arch/arm/mach-s5pc100/setup-sdhci-gpio.c b/arch/arm/mach-s5pc100/setup-sdhci-gpio.c
index dc7208c639ea..03c02d04c68c 100644
--- a/arch/arm/mach-s5pc100/setup-sdhci-gpio.c
+++ b/arch/arm/mach-s5pc100/setup-sdhci-gpio.c
@@ -25,8 +25,6 @@
25void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) 25void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
26{ 26{
27 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; 27 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
28 unsigned int gpio;
29 unsigned int end;
30 unsigned int num; 28 unsigned int num;
31 29
32 num = width; 30 num = width;
@@ -34,20 +32,11 @@ void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
34 if (width == 8) 32 if (width == 8)
35 num = width - 2; 33 num = width - 2;
36 34
37 end = S5PC100_GPG0(2 + num);
38
39 /* Set all the necessary GPG0/GPG1 pins to special-function 0 */ 35 /* Set all the necessary GPG0/GPG1 pins to special-function 0 */
40 for (gpio = S5PC100_GPG0(0); gpio < end; gpio++) { 36 s3c_gpio_cfgrange_nopull(S5PC100_GPG0(0), 2 + num, S3C_GPIO_SFN(2));
41 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
42 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
43 }
44 37
45 if (width == 8) { 38 if (width == 8)
46 for (gpio = S5PC100_GPG1(0); gpio <= S5PC100_GPG1(1); gpio++) { 39 s3c_gpio_cfgrange_nopull(S5PC100_GPG1(0), 2, S3C_GPIO_SFN(2));
47 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
48 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
49 }
50 }
51 40
52 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { 41 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
53 s3c_gpio_setpull(S5PC100_GPG1(2), S3C_GPIO_PULL_UP); 42 s3c_gpio_setpull(S5PC100_GPG1(2), S3C_GPIO_PULL_UP);
@@ -58,16 +47,9 @@ void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
58void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) 47void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
59{ 48{
60 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; 49 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
61 unsigned int gpio;
62 unsigned int end;
63
64 end = S5PC100_GPG2(2 + width);
65 50
66 /* Set all the necessary GPG2 pins to special-function 2 */ 51 /* Set all the necessary GPG2 pins to special-function 2 */
67 for (gpio = S5PC100_GPG2(0); gpio < end; gpio++) { 52 s3c_gpio_cfgrange_nopull(S5PC100_GPG2(0), 2 + width, S3C_GPIO_SFN(2));
68 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
69 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
70 }
71 53
72 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { 54 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
73 s3c_gpio_setpull(S5PC100_GPG2(6), S3C_GPIO_PULL_UP); 55 s3c_gpio_setpull(S5PC100_GPG2(6), S3C_GPIO_PULL_UP);
@@ -78,16 +60,9 @@ void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
78void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) 60void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
79{ 61{
80 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; 62 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
81 unsigned int gpio;
82 unsigned int end;
83
84 end = S5PC100_GPG3(2 + width);
85 63
86 /* Set all the necessary GPG3 pins to special-function 2 */ 64 /* Set all the necessary GPG3 pins to special-function 2 */
87 for (gpio = S5PC100_GPG3(0); gpio < end; gpio++) { 65 s3c_gpio_cfgrange_nopull(S5PC100_GPG3(0), 2 + width, S3C_GPIO_SFN(2));
88 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
89 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
90 }
91 66
92 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { 67 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
93 s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP); 68 s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP);
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 5315fec3db86..862f239a0fdb 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -11,9 +11,9 @@ if ARCH_S5PV210
11 11
12config CPU_S5PV210 12config CPU_S5PV210
13 bool 13 bool
14 select PLAT_S5P
15 select S3C_PL330_DMA 14 select S3C_PL330_DMA
16 select S5P_EXT_INT 15 select S5P_EXT_INT
16 select S5PV210_PM if PM
17 help 17 help
18 Enable S5PV210 CPU support 18 Enable S5PV210 CPU support
19 19
@@ -58,7 +58,6 @@ menu "S5PC110 Machines"
58config MACH_AQUILA 58config MACH_AQUILA
59 bool "Aquila" 59 bool "Aquila"
60 select CPU_S5PV210 60 select CPU_S5PV210
61 select ARCH_SPARSEMEM_ENABLE
62 select S3C_DEV_FB 61 select S3C_DEV_FB
63 select S5P_DEV_FIMC0 62 select S5P_DEV_FIMC0
64 select S5P_DEV_FIMC1 63 select S5P_DEV_FIMC1
@@ -75,7 +74,7 @@ config MACH_AQUILA
75config MACH_GONI 74config MACH_GONI
76 bool "GONI" 75 bool "GONI"
77 select CPU_S5PV210 76 select CPU_S5PV210
78 select ARCH_SPARSEMEM_ENABLE 77 select S5P_GPIO_INT
79 select S3C_DEV_FB 78 select S3C_DEV_FB
80 select S5P_DEV_FIMC0 79 select S5P_DEV_FIMC0
81 select S5P_DEV_FIMC1 80 select S5P_DEV_FIMC1
@@ -83,8 +82,15 @@ config MACH_GONI
83 select S3C_DEV_HSMMC 82 select S3C_DEV_HSMMC
84 select S3C_DEV_HSMMC1 83 select S3C_DEV_HSMMC1
85 select S3C_DEV_HSMMC2 84 select S3C_DEV_HSMMC2
85 select S3C_DEV_I2C1
86 select S3C_DEV_I2C2
87 select S3C_DEV_USB_HSOTG
86 select S5P_DEV_ONENAND 88 select S5P_DEV_ONENAND
89 select SAMSUNG_DEV_KEYPAD
87 select S5PV210_SETUP_FB_24BPP 90 select S5PV210_SETUP_FB_24BPP
91 select S5PV210_SETUP_I2C1
92 select S5PV210_SETUP_I2C2
93 select S5PV210_SETUP_KEYPAD
88 select S5PV210_SETUP_SDHCI 94 select S5PV210_SETUP_SDHCI
89 help 95 help
90 Machine support for Samsung GONI board 96 Machine support for Samsung GONI board
@@ -93,7 +99,6 @@ config MACH_GONI
93config MACH_SMDKC110 99config MACH_SMDKC110
94 bool "SMDKC110" 100 bool "SMDKC110"
95 select CPU_S5PV210 101 select CPU_S5PV210
96 select ARCH_SPARSEMEM_ENABLE
97 select S3C_DEV_I2C1 102 select S3C_DEV_I2C1
98 select S3C_DEV_I2C2 103 select S3C_DEV_I2C2
99 select S3C_DEV_RTC 104 select S3C_DEV_RTC
@@ -113,7 +118,6 @@ menu "S5PV210 Machines"
113config MACH_SMDKV210 118config MACH_SMDKV210
114 bool "SMDKV210" 119 bool "SMDKV210"
115 select CPU_S5PV210 120 select CPU_S5PV210
116 select ARCH_SPARSEMEM_ENABLE
117 select S3C_DEV_HSMMC 121 select S3C_DEV_HSMMC
118 select S3C_DEV_HSMMC1 122 select S3C_DEV_HSMMC1
119 select S3C_DEV_HSMMC2 123 select S3C_DEV_HSMMC2
@@ -134,6 +138,29 @@ config MACH_SMDKV210
134 help 138 help
135 Machine support for Samsung SMDKV210 139 Machine support for Samsung SMDKV210
136 140
141config MACH_TORBRECK
142 bool "Torbreck"
143 select CPU_S5PV210
144 select ARCH_SPARSEMEM_ENABLE
145 select S3C_DEV_HSMMC
146 select S3C_DEV_HSMMC1
147 select S3C_DEV_HSMMC2
148 select S3C_DEV_HSMMC3
149 select S3C_DEV_I2C1
150 select S3C_DEV_I2C2
151 select S3C_DEV_RTC
152 select S3C_DEV_WDT
153 select S5PV210_SETUP_I2C1
154 select S5PV210_SETUP_I2C2
155 select S5PV210_SETUP_SDHCI
156 help
157 Machine support for aESOP Torbreck
158
137endmenu 159endmenu
138 160
161config S5PV210_PM
162 bool
163 help
164 Power Management code common to S5PV210
165
139endif 166endif
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 704548912408..ff1a0db57a2f 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -14,6 +14,8 @@ obj- :=
14 14
15obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o gpiolib.o 15obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o gpiolib.o
16obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o 16obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o
17obj-$(CONFIG_S5PV210_PM) += pm.o sleep.o
18obj-$(CONFIG_CPU_FREQ) += cpufreq.o
17 19
18# machine support 20# machine support
19 21
@@ -21,6 +23,7 @@ obj-$(CONFIG_MACH_AQUILA) += mach-aquila.o
21obj-$(CONFIG_MACH_SMDKV210) += mach-smdkv210.o 23obj-$(CONFIG_MACH_SMDKV210) += mach-smdkv210.o
22obj-$(CONFIG_MACH_SMDKC110) += mach-smdkc110.o 24obj-$(CONFIG_MACH_SMDKC110) += mach-smdkc110.o
23obj-$(CONFIG_MACH_GONI) += mach-goni.o 25obj-$(CONFIG_MACH_GONI) += mach-goni.o
26obj-$(CONFIG_MACH_TORBRECK) += mach-torbreck.o
24 27
25# device support 28# device support
26 29
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index d562670e1b0b..019c3a69b0e4 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -31,6 +31,8 @@
31#include <plat/clock-clksrc.h> 31#include <plat/clock-clksrc.h>
32#include <plat/s5pv210.h> 32#include <plat/s5pv210.h>
33 33
34static unsigned long xtal;
35
34static struct clksrc_clk clk_mout_apll = { 36static struct clksrc_clk clk_mout_apll = {
35 .clk = { 37 .clk = {
36 .name = "mout_apll", 38 .name = "mout_apll",
@@ -259,6 +261,36 @@ static struct clksrc_clk clk_sclk_vpll = {
259 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 }, 261 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
260}; 262};
261 263
264static struct clk *clkset_moutdmc0src_list[] = {
265 [0] = &clk_sclk_a2m.clk,
266 [1] = &clk_mout_mpll.clk,
267 [2] = NULL,
268 [3] = NULL,
269};
270
271static struct clksrc_sources clkset_moutdmc0src = {
272 .sources = clkset_moutdmc0src_list,
273 .nr_sources = ARRAY_SIZE(clkset_moutdmc0src_list),
274};
275
276static struct clksrc_clk clk_mout_dmc0 = {
277 .clk = {
278 .name = "mout_dmc0",
279 .id = -1,
280 },
281 .sources = &clkset_moutdmc0src,
282 .reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
283};
284
285static struct clksrc_clk clk_sclk_dmc0 = {
286 .clk = {
287 .name = "sclk_dmc0",
288 .id = -1,
289 .parent = &clk_mout_dmc0.clk,
290 },
291 .reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
292};
293
262static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk) 294static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk)
263{ 295{
264 return clk_get_rate(clk->parent) / 2; 296 return clk_get_rate(clk->parent) / 2;
@@ -268,8 +300,29 @@ static struct clk_ops clk_hclk_imem_ops = {
268 .get_rate = s5pv210_clk_imem_get_rate, 300 .get_rate = s5pv210_clk_imem_get_rate,
269}; 301};
270 302
303static unsigned long s5pv210_clk_fout_apll_get_rate(struct clk *clk)
304{
305 return s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
306}
307
308static struct clk_ops clk_fout_apll_ops = {
309 .get_rate = s5pv210_clk_fout_apll_get_rate,
310};
311
271static struct clk init_clocks_disable[] = { 312static struct clk init_clocks_disable[] = {
272 { 313 {
314 .name = "pdma",
315 .id = 0,
316 .parent = &clk_hclk_psys.clk,
317 .enable = s5pv210_clk_ip0_ctrl,
318 .ctrlbit = (1 << 3),
319 }, {
320 .name = "pdma",
321 .id = 1,
322 .parent = &clk_hclk_psys.clk,
323 .enable = s5pv210_clk_ip0_ctrl,
324 .ctrlbit = (1 << 4),
325 }, {
273 .name = "rot", 326 .name = "rot",
274 .id = -1, 327 .id = -1,
275 .parent = &clk_hclk_dsys.clk, 328 .parent = &clk_hclk_dsys.clk,
@@ -431,6 +484,12 @@ static struct clk init_clocks_disable[] = {
431 .parent = &clk_p, 484 .parent = &clk_p,
432 .enable = s5pv210_clk_ip3_ctrl, 485 .enable = s5pv210_clk_ip3_ctrl,
433 .ctrlbit = (1 << 6), 486 .ctrlbit = (1 << 6),
487 }, {
488 .name = "spdif",
489 .id = -1,
490 .parent = &clk_p,
491 .enable = s5pv210_clk_ip3_ctrl,
492 .ctrlbit = (1 << 0),
434 }, 493 },
435}; 494};
436 495
@@ -660,6 +719,53 @@ static struct clksrc_sources clkset_sclk_spdif = {
660 .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list), 719 .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list),
661}; 720};
662 721
722static int s5pv210_spdif_set_rate(struct clk *clk, unsigned long rate)
723{
724 struct clk *pclk;
725 int ret;
726
727 pclk = clk_get_parent(clk);
728 if (IS_ERR(pclk))
729 return -EINVAL;
730
731 ret = pclk->ops->set_rate(pclk, rate);
732 clk_put(pclk);
733
734 return ret;
735}
736
737static unsigned long s5pv210_spdif_get_rate(struct clk *clk)
738{
739 struct clk *pclk;
740 int rate;
741
742 pclk = clk_get_parent(clk);
743 if (IS_ERR(pclk))
744 return -EINVAL;
745
746 rate = pclk->ops->get_rate(clk);
747 clk_put(pclk);
748
749 return rate;
750}
751
752static struct clk_ops s5pv210_sclk_spdif_ops = {
753 .set_rate = s5pv210_spdif_set_rate,
754 .get_rate = s5pv210_spdif_get_rate,
755};
756
757static struct clksrc_clk clk_sclk_spdif = {
758 .clk = {
759 .name = "sclk_spdif",
760 .id = -1,
761 .enable = s5pv210_clk_mask0_ctrl,
762 .ctrlbit = (1 << 27),
763 .ops = &s5pv210_sclk_spdif_ops,
764 },
765 .sources = &clkset_sclk_spdif,
766 .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
767};
768
663static struct clk *clkset_group2_list[] = { 769static struct clk *clkset_group2_list[] = {
664 [0] = &clk_ext_xtal_mux, 770 [0] = &clk_ext_xtal_mux,
665 [1] = &clk_xusbxti, 771 [1] = &clk_xusbxti,
@@ -744,15 +850,6 @@ static struct clksrc_clk clksrcs[] = {
744 .sources = &clkset_sclk_mixer, 850 .sources = &clkset_sclk_mixer,
745 .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 }, 851 .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
746 }, { 852 }, {
747 .clk = {
748 .name = "sclk_spdif",
749 .id = -1,
750 .enable = s5pv210_clk_mask0_ctrl,
751 .ctrlbit = (1 << 27),
752 },
753 .sources = &clkset_sclk_spdif,
754 .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
755 }, {
756 .clk = { 853 .clk = {
757 .name = "sclk_fimc", 854 .name = "sclk_fimc",
758 .id = 0, 855 .id = 0,
@@ -953,12 +1050,93 @@ static struct clksrc_clk *sysclks[] = {
953 &clk_sclk_dac, 1050 &clk_sclk_dac,
954 &clk_sclk_pixel, 1051 &clk_sclk_pixel,
955 &clk_sclk_hdmi, 1052 &clk_sclk_hdmi,
1053 &clk_mout_dmc0,
1054 &clk_sclk_dmc0,
1055 &clk_sclk_audio0,
1056 &clk_sclk_audio1,
1057 &clk_sclk_audio2,
1058 &clk_sclk_spdif,
1059};
1060
1061static u32 epll_div[][6] = {
1062 { 48000000, 0, 48, 3, 3, 0 },
1063 { 96000000, 0, 48, 3, 2, 0 },
1064 { 144000000, 1, 72, 3, 2, 0 },
1065 { 192000000, 0, 48, 3, 1, 0 },
1066 { 288000000, 1, 72, 3, 1, 0 },
1067 { 32750000, 1, 65, 3, 4, 35127 },
1068 { 32768000, 1, 65, 3, 4, 35127 },
1069 { 45158400, 0, 45, 3, 3, 10355 },
1070 { 45000000, 0, 45, 3, 3, 10355 },
1071 { 45158000, 0, 45, 3, 3, 10355 },
1072 { 49125000, 0, 49, 3, 3, 9961 },
1073 { 49152000, 0, 49, 3, 3, 9961 },
1074 { 67737600, 1, 67, 3, 3, 48366 },
1075 { 67738000, 1, 67, 3, 3, 48366 },
1076 { 73800000, 1, 73, 3, 3, 47710 },
1077 { 73728000, 1, 73, 3, 3, 47710 },
1078 { 36000000, 1, 32, 3, 4, 0 },
1079 { 60000000, 1, 60, 3, 3, 0 },
1080 { 72000000, 1, 72, 3, 3, 0 },
1081 { 80000000, 1, 80, 3, 3, 0 },
1082 { 84000000, 0, 42, 3, 2, 0 },
1083 { 50000000, 0, 50, 3, 3, 0 },
1084};
1085
1086static int s5pv210_epll_set_rate(struct clk *clk, unsigned long rate)
1087{
1088 unsigned int epll_con, epll_con_k;
1089 unsigned int i;
1090
1091 /* Return if nothing changed */
1092 if (clk->rate == rate)
1093 return 0;
1094
1095 epll_con = __raw_readl(S5P_EPLL_CON);
1096 epll_con_k = __raw_readl(S5P_EPLL_CON1);
1097
1098 epll_con_k &= ~PLL46XX_KDIV_MASK;
1099 epll_con &= ~(1 << 27 |
1100 PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |
1101 PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |
1102 PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
1103
1104 for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
1105 if (epll_div[i][0] == rate) {
1106 epll_con_k |= epll_div[i][5] << 0;
1107 epll_con |= (epll_div[i][1] << 27 |
1108 epll_div[i][2] << PLL46XX_MDIV_SHIFT |
1109 epll_div[i][3] << PLL46XX_PDIV_SHIFT |
1110 epll_div[i][4] << PLL46XX_SDIV_SHIFT);
1111 break;
1112 }
1113 }
1114
1115 if (i == ARRAY_SIZE(epll_div)) {
1116 printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
1117 __func__);
1118 return -EINVAL;
1119 }
1120
1121 __raw_writel(epll_con, S5P_EPLL_CON);
1122 __raw_writel(epll_con_k, S5P_EPLL_CON1);
1123
1124 printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
1125 clk->rate, rate);
1126
1127 clk->rate = rate;
1128
1129 return 0;
1130}
1131
1132static struct clk_ops s5pv210_epll_ops = {
1133 .set_rate = s5pv210_epll_set_rate,
1134 .get_rate = s5p_epll_get_rate,
956}; 1135};
957 1136
958void __init_or_cpufreq s5pv210_setup_clocks(void) 1137void __init_or_cpufreq s5pv210_setup_clocks(void)
959{ 1138{
960 struct clk *xtal_clk; 1139 struct clk *xtal_clk;
961 unsigned long xtal;
962 unsigned long vpllsrc; 1140 unsigned long vpllsrc;
963 unsigned long armclk; 1141 unsigned long armclk;
964 unsigned long hclk_msys; 1142 unsigned long hclk_msys;
@@ -974,6 +1152,10 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
974 unsigned int ptr; 1152 unsigned int ptr;
975 u32 clkdiv0, clkdiv1; 1153 u32 clkdiv0, clkdiv1;
976 1154
1155 /* Set functions for clk_fout_epll */
1156 clk_fout_epll.enable = s5p_epll_enable;
1157 clk_fout_epll.ops = &s5pv210_epll_ops;
1158
977 printk(KERN_DEBUG "%s: registering clocks\n", __func__); 1159 printk(KERN_DEBUG "%s: registering clocks\n", __func__);
978 1160
979 clkdiv0 = __raw_readl(S5P_CLK_DIV0); 1161 clkdiv0 = __raw_readl(S5P_CLK_DIV0);
@@ -992,11 +1174,12 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
992 1174
993 apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); 1175 apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
994 mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502); 1176 mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
995 epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500); 1177 epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON),
1178 __raw_readl(S5P_EPLL_CON1), pll_4600);
996 vpllsrc = clk_get_rate(&clk_vpllsrc.clk); 1179 vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
997 vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502); 1180 vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502);
998 1181
999 clk_fout_apll.rate = apll; 1182 clk_fout_apll.ops = &clk_fout_apll_ops;
1000 clk_fout_mpll.rate = mpll; 1183 clk_fout_mpll.rate = mpll;
1001 clk_fout_epll.rate = epll; 1184 clk_fout_epll.rate = epll;
1002 clk_fout_vpll.rate = vpll; 1185 clk_fout_vpll.rate = vpll;
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index 2f16bfc0a116..8eb480e201b0 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -85,6 +85,21 @@ static struct map_desc s5pv210_iodesc[] __initdata = {
85 .pfn = __phys_to_pfn(S5PV210_PA_SROMC), 85 .pfn = __phys_to_pfn(S5PV210_PA_SROMC),
86 .length = SZ_4K, 86 .length = SZ_4K,
87 .type = MT_DEVICE, 87 .type = MT_DEVICE,
88 }, {
89 .virtual = (unsigned long)S5P_VA_DMC0,
90 .pfn = __phys_to_pfn(S5PV210_PA_DMC0),
91 .length = SZ_4K,
92 .type = MT_DEVICE,
93 }, {
94 .virtual = (unsigned long)S5P_VA_DMC1,
95 .pfn = __phys_to_pfn(S5PV210_PA_DMC1),
96 .length = SZ_4K,
97 .type = MT_DEVICE,
98 }, {
99 .virtual = (unsigned long)S3C_VA_USB_HSPHY,
100 .pfn =__phys_to_pfn(S5PV210_PA_HSPHY),
101 .length = SZ_4K,
102 .type = MT_DEVICE,
88 } 103 }
89}; 104};
90 105
diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/arch/arm/mach-s5pv210/cpufreq.c
new file mode 100644
index 000000000000..a6f22920a2c2
--- /dev/null
+++ b/arch/arm/mach-s5pv210/cpufreq.c
@@ -0,0 +1,484 @@
1/* linux/arch/arm/mach-s5pv210/cpufreq.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * CPU frequency scaling for S5PC110/S5PV210
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/types.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/err.h>
17#include <linux/clk.h>
18#include <linux/io.h>
19#include <linux/cpufreq.h>
20
21#include <mach/map.h>
22#include <mach/regs-clock.h>
23
24static struct clk *cpu_clk;
25static struct clk *dmc0_clk;
26static struct clk *dmc1_clk;
27static struct cpufreq_freqs freqs;
28
29/* APLL M,P,S values for 1G/800Mhz */
30#define APLL_VAL_1000 ((1 << 31) | (125 << 16) | (3 << 8) | 1)
31#define APLL_VAL_800 ((1 << 31) | (100 << 16) | (3 << 8) | 1)
32
33/*
34 * DRAM configurations to calculate refresh counter for changing
35 * frequency of memory.
36 */
37struct dram_conf {
38 unsigned long freq; /* HZ */
39 unsigned long refresh; /* DRAM refresh counter * 1000 */
40};
41
42/* DRAM configuration (DMC0 and DMC1) */
43static struct dram_conf s5pv210_dram_conf[2];
44
45enum perf_level {
46 L0, L1, L2, L3, L4,
47};
48
49enum s5pv210_mem_type {
50 LPDDR = 0x1,
51 LPDDR2 = 0x2,
52 DDR2 = 0x4,
53};
54
55enum s5pv210_dmc_port {
56 DMC0 = 0,
57 DMC1,
58};
59
60static struct cpufreq_frequency_table s5pv210_freq_table[] = {
61 {L0, 1000*1000},
62 {L1, 800*1000},
63 {L2, 400*1000},
64 {L3, 200*1000},
65 {L4, 100*1000},
66 {0, CPUFREQ_TABLE_END},
67};
68
69static u32 clkdiv_val[5][11] = {
70 /*
71 * Clock divider value for following
72 * { APLL, A2M, HCLK_MSYS, PCLK_MSYS,
73 * HCLK_DSYS, PCLK_DSYS, HCLK_PSYS, PCLK_PSYS,
74 * ONEDRAM, MFC, G3D }
75 */
76
77 /* L0 : [1000/200/100][166/83][133/66][200/200] */
78 {0, 4, 4, 1, 3, 1, 4, 1, 3, 0, 0},
79
80 /* L1 : [800/200/100][166/83][133/66][200/200] */
81 {0, 3, 3, 1, 3, 1, 4, 1, 3, 0, 0},
82
83 /* L2 : [400/200/100][166/83][133/66][200/200] */
84 {1, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0},
85
86 /* L3 : [200/200/100][166/83][133/66][200/200] */
87 {3, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0},
88
89 /* L4 : [100/100/100][83/83][66/66][100/100] */
90 {7, 7, 0, 0, 7, 0, 9, 0, 7, 0, 0},
91};
92
93/*
94 * This function set DRAM refresh counter
95 * accoriding to operating frequency of DRAM
96 * ch: DMC port number 0 or 1
97 * freq: Operating frequency of DRAM(KHz)
98 */
99static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
100{
101 unsigned long tmp, tmp1;
102 void __iomem *reg = NULL;
103
104 if (ch == DMC0)
105 reg = (S5P_VA_DMC0 + 0x30);
106 else if (ch == DMC1)
107 reg = (S5P_VA_DMC1 + 0x30);
108 else
109 printk(KERN_ERR "Cannot find DMC port\n");
110
111 /* Find current DRAM frequency */
112 tmp = s5pv210_dram_conf[ch].freq;
113
114 do_div(tmp, freq);
115
116 tmp1 = s5pv210_dram_conf[ch].refresh;
117
118 do_div(tmp1, tmp);
119
120 __raw_writel(tmp1, reg);
121}
122
123int s5pv210_verify_speed(struct cpufreq_policy *policy)
124{
125 if (policy->cpu)
126 return -EINVAL;
127
128 return cpufreq_frequency_table_verify(policy, s5pv210_freq_table);
129}
130
131unsigned int s5pv210_getspeed(unsigned int cpu)
132{
133 if (cpu)
134 return 0;
135
136 return clk_get_rate(cpu_clk) / 1000;
137}
138
139static int s5pv210_target(struct cpufreq_policy *policy,
140 unsigned int target_freq,
141 unsigned int relation)
142{
143 unsigned long reg;
144 unsigned int index, priv_index;
145 unsigned int pll_changing = 0;
146 unsigned int bus_speed_changing = 0;
147
148 freqs.old = s5pv210_getspeed(0);
149
150 if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
151 target_freq, relation, &index))
152 return -EINVAL;
153
154 freqs.new = s5pv210_freq_table[index].frequency;
155 freqs.cpu = 0;
156
157 if (freqs.new == freqs.old)
158 return 0;
159
160 /* Finding current running level index */
161 if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
162 freqs.old, relation, &priv_index))
163 return -EINVAL;
164
165 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
166
167 if (freqs.new > freqs.old) {
168 /* Voltage up: will be implemented */
169 }
170
171 /* Check if there need to change PLL */
172 if ((index == L0) || (priv_index == L0))
173 pll_changing = 1;
174
175 /* Check if there need to change System bus clock */
176 if ((index == L4) || (priv_index == L4))
177 bus_speed_changing = 1;
178
179 if (bus_speed_changing) {
180 /*
181 * Reconfigure DRAM refresh counter value for minimum
182 * temporary clock while changing divider.
183 * expected clock is 83Mhz : 7.8usec/(1/83Mhz) = 0x287
184 */
185 if (pll_changing)
186 s5pv210_set_refresh(DMC1, 83000);
187 else
188 s5pv210_set_refresh(DMC1, 100000);
189
190 s5pv210_set_refresh(DMC0, 83000);
191 }
192
193 /*
194 * APLL should be changed in this level
195 * APLL -> MPLL(for stable transition) -> APLL
196 * Some clock source's clock API are not prepared.
197 * Do not use clock API in below code.
198 */
199 if (pll_changing) {
200 /*
201 * 1. Temporary Change divider for MFC and G3D
202 * SCLKA2M(200/1=200)->(200/4=50)Mhz
203 */
204 reg = __raw_readl(S5P_CLK_DIV2);
205 reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK);
206 reg |= (3 << S5P_CLKDIV2_G3D_SHIFT) |
207 (3 << S5P_CLKDIV2_MFC_SHIFT);
208 __raw_writel(reg, S5P_CLK_DIV2);
209
210 /* For MFC, G3D dividing */
211 do {
212 reg = __raw_readl(S5P_CLKDIV_STAT0);
213 } while (reg & ((1 << 16) | (1 << 17)));
214
215 /*
216 * 2. Change SCLKA2M(200Mhz)to SCLKMPLL in MFC_MUX, G3D MUX
217 * (200/4=50)->(667/4=166)Mhz
218 */
219 reg = __raw_readl(S5P_CLK_SRC2);
220 reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK);
221 reg |= (1 << S5P_CLKSRC2_G3D_SHIFT) |
222 (1 << S5P_CLKSRC2_MFC_SHIFT);
223 __raw_writel(reg, S5P_CLK_SRC2);
224
225 do {
226 reg = __raw_readl(S5P_CLKMUX_STAT1);
227 } while (reg & ((1 << 7) | (1 << 3)));
228
229 /*
230 * 3. DMC1 refresh count for 133Mhz if (index == L4) is
231 * true refresh counter is already programed in upper
232 * code. 0x287@83Mhz
233 */
234 if (!bus_speed_changing)
235 s5pv210_set_refresh(DMC1, 133000);
236
237 /* 4. SCLKAPLL -> SCLKMPLL */
238 reg = __raw_readl(S5P_CLK_SRC0);
239 reg &= ~(S5P_CLKSRC0_MUX200_MASK);
240 reg |= (0x1 << S5P_CLKSRC0_MUX200_SHIFT);
241 __raw_writel(reg, S5P_CLK_SRC0);
242
243 do {
244 reg = __raw_readl(S5P_CLKMUX_STAT0);
245 } while (reg & (0x1 << 18));
246
247 }
248
249 /* Change divider */
250 reg = __raw_readl(S5P_CLK_DIV0);
251
252 reg &= ~(S5P_CLKDIV0_APLL_MASK | S5P_CLKDIV0_A2M_MASK |
253 S5P_CLKDIV0_HCLK200_MASK | S5P_CLKDIV0_PCLK100_MASK |
254 S5P_CLKDIV0_HCLK166_MASK | S5P_CLKDIV0_PCLK83_MASK |
255 S5P_CLKDIV0_HCLK133_MASK | S5P_CLKDIV0_PCLK66_MASK);
256
257 reg |= ((clkdiv_val[index][0] << S5P_CLKDIV0_APLL_SHIFT) |
258 (clkdiv_val[index][1] << S5P_CLKDIV0_A2M_SHIFT) |
259 (clkdiv_val[index][2] << S5P_CLKDIV0_HCLK200_SHIFT) |
260 (clkdiv_val[index][3] << S5P_CLKDIV0_PCLK100_SHIFT) |
261 (clkdiv_val[index][4] << S5P_CLKDIV0_HCLK166_SHIFT) |
262 (clkdiv_val[index][5] << S5P_CLKDIV0_PCLK83_SHIFT) |
263 (clkdiv_val[index][6] << S5P_CLKDIV0_HCLK133_SHIFT) |
264 (clkdiv_val[index][7] << S5P_CLKDIV0_PCLK66_SHIFT));
265
266 __raw_writel(reg, S5P_CLK_DIV0);
267
268 do {
269 reg = __raw_readl(S5P_CLKDIV_STAT0);
270 } while (reg & 0xff);
271
272 /* ARM MCS value changed */
273 reg = __raw_readl(S5P_ARM_MCS_CON);
274 reg &= ~0x3;
275 if (index >= L3)
276 reg |= 0x3;
277 else
278 reg |= 0x1;
279
280 __raw_writel(reg, S5P_ARM_MCS_CON);
281
282 if (pll_changing) {
283 /* 5. Set Lock time = 30us*24Mhz = 0x2cf */
284 __raw_writel(0x2cf, S5P_APLL_LOCK);
285
286 /*
287 * 6. Turn on APLL
288 * 6-1. Set PMS values
289 * 6-2. Wait untile the PLL is locked
290 */
291 if (index == L0)
292 __raw_writel(APLL_VAL_1000, S5P_APLL_CON);
293 else
294 __raw_writel(APLL_VAL_800, S5P_APLL_CON);
295
296 do {
297 reg = __raw_readl(S5P_APLL_CON);
298 } while (!(reg & (0x1 << 29)));
299
300 /*
301 * 7. Change souce clock from SCLKMPLL(667Mhz)
302 * to SCLKA2M(200Mhz) in MFC_MUX and G3D MUX
303 * (667/4=166)->(200/4=50)Mhz
304 */
305 reg = __raw_readl(S5P_CLK_SRC2);
306 reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK);
307 reg |= (0 << S5P_CLKSRC2_G3D_SHIFT) |
308 (0 << S5P_CLKSRC2_MFC_SHIFT);
309 __raw_writel(reg, S5P_CLK_SRC2);
310
311 do {
312 reg = __raw_readl(S5P_CLKMUX_STAT1);
313 } while (reg & ((1 << 7) | (1 << 3)));
314
315 /*
316 * 8. Change divider for MFC and G3D
317 * (200/4=50)->(200/1=200)Mhz
318 */
319 reg = __raw_readl(S5P_CLK_DIV2);
320 reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK);
321 reg |= (clkdiv_val[index][10] << S5P_CLKDIV2_G3D_SHIFT) |
322 (clkdiv_val[index][9] << S5P_CLKDIV2_MFC_SHIFT);
323 __raw_writel(reg, S5P_CLK_DIV2);
324
325 /* For MFC, G3D dividing */
326 do {
327 reg = __raw_readl(S5P_CLKDIV_STAT0);
328 } while (reg & ((1 << 16) | (1 << 17)));
329
330 /* 9. Change MPLL to APLL in MSYS_MUX */
331 reg = __raw_readl(S5P_CLK_SRC0);
332 reg &= ~(S5P_CLKSRC0_MUX200_MASK);
333 reg |= (0x0 << S5P_CLKSRC0_MUX200_SHIFT);
334 __raw_writel(reg, S5P_CLK_SRC0);
335
336 do {
337 reg = __raw_readl(S5P_CLKMUX_STAT0);
338 } while (reg & (0x1 << 18));
339
340 /*
341 * 10. DMC1 refresh counter
342 * L4 : DMC1 = 100Mhz 7.8us/(1/100) = 0x30c
343 * Others : DMC1 = 200Mhz 7.8us/(1/200) = 0x618
344 */
345 if (!bus_speed_changing)
346 s5pv210_set_refresh(DMC1, 200000);
347 }
348
349 /*
350 * L4 level need to change memory bus speed, hence onedram clock divier
351 * and memory refresh parameter should be changed
352 */
353 if (bus_speed_changing) {
354 reg = __raw_readl(S5P_CLK_DIV6);
355 reg &= ~S5P_CLKDIV6_ONEDRAM_MASK;
356 reg |= (clkdiv_val[index][8] << S5P_CLKDIV6_ONEDRAM_SHIFT);
357 __raw_writel(reg, S5P_CLK_DIV6);
358
359 do {
360 reg = __raw_readl(S5P_CLKDIV_STAT1);
361 } while (reg & (1 << 15));
362
363 /* Reconfigure DRAM refresh counter value */
364 if (index != L4) {
365 /*
366 * DMC0 : 166Mhz
367 * DMC1 : 200Mhz
368 */
369 s5pv210_set_refresh(DMC0, 166000);
370 s5pv210_set_refresh(DMC1, 200000);
371 } else {
372 /*
373 * DMC0 : 83Mhz
374 * DMC1 : 100Mhz
375 */
376 s5pv210_set_refresh(DMC0, 83000);
377 s5pv210_set_refresh(DMC1, 100000);
378 }
379 }
380
381 if (freqs.new < freqs.old) {
382 /* Voltage down: will be implemented */
383 }
384
385 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
386
387 printk(KERN_DEBUG "Perf changed[L%d]\n", index);
388
389 return 0;
390}
391
392#ifdef CONFIG_PM
393static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy,
394 pm_message_t pmsg)
395{
396 return 0;
397}
398
399static int s5pv210_cpufreq_resume(struct cpufreq_policy *policy)
400{
401 return 0;
402}
403#endif
404
405static int check_mem_type(void __iomem *dmc_reg)
406{
407 unsigned long val;
408
409 val = __raw_readl(dmc_reg + 0x4);
410 val = (val & (0xf << 8));
411
412 return val >> 8;
413}
414
415static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
416{
417 unsigned long mem_type;
418
419 cpu_clk = clk_get(NULL, "armclk");
420 if (IS_ERR(cpu_clk))
421 return PTR_ERR(cpu_clk);
422
423 dmc0_clk = clk_get(NULL, "sclk_dmc0");
424 if (IS_ERR(dmc0_clk)) {
425 clk_put(cpu_clk);
426 return PTR_ERR(dmc0_clk);
427 }
428
429 dmc1_clk = clk_get(NULL, "hclk_msys");
430 if (IS_ERR(dmc1_clk)) {
431 clk_put(dmc0_clk);
432 clk_put(cpu_clk);
433 return PTR_ERR(dmc1_clk);
434 }
435
436 if (policy->cpu != 0)
437 return -EINVAL;
438
439 /*
440 * check_mem_type : This driver only support LPDDR & LPDDR2.
441 * other memory type is not supported.
442 */
443 mem_type = check_mem_type(S5P_VA_DMC0);
444
445 if ((mem_type != LPDDR) && (mem_type != LPDDR2)) {
446 printk(KERN_ERR "CPUFreq doesn't support this memory type\n");
447 return -EINVAL;
448 }
449
450 /* Find current refresh counter and frequency each DMC */
451 s5pv210_dram_conf[0].refresh = (__raw_readl(S5P_VA_DMC0 + 0x30) * 1000);
452 s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk);
453
454 s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
455 s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
456
457 policy->cur = policy->min = policy->max = s5pv210_getspeed(0);
458
459 cpufreq_frequency_table_get_attr(s5pv210_freq_table, policy->cpu);
460
461 policy->cpuinfo.transition_latency = 40000;
462
463 return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table);
464}
465
466static struct cpufreq_driver s5pv210_driver = {
467 .flags = CPUFREQ_STICKY,
468 .verify = s5pv210_verify_speed,
469 .target = s5pv210_target,
470 .get = s5pv210_getspeed,
471 .init = s5pv210_cpu_init,
472 .name = "s5pv210",
473#ifdef CONFIG_PM
474 .suspend = s5pv210_cpufreq_suspend,
475 .resume = s5pv210_cpufreq_resume,
476#endif
477};
478
479static int __init s5pv210_cpufreq_init(void)
480{
481 return cpufreq_register_driver(&s5pv210_driver);
482}
483
484late_initcall(s5pv210_cpufreq_init);
diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c
index 21dc6cf955c3..1303fcb12b51 100644
--- a/arch/arm/mach-s5pv210/dev-audio.c
+++ b/arch/arm/mach-s5pv210/dev-audio.c
@@ -24,29 +24,15 @@ static int s5pv210_cfg_i2s(struct platform_device *pdev)
24 /* configure GPIO for i2s port */ 24 /* configure GPIO for i2s port */
25 switch (pdev->id) { 25 switch (pdev->id) {
26 case 1: 26 case 1:
27 s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(2)); 27 s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(2));
28 s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(2));
29 s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(2));
30 s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(2));
31 s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(2));
32 break; 28 break;
33 29
34 case 2: 30 case 2:
35 s3c_gpio_cfgpin(S5PV210_GPC1(0), S3C_GPIO_SFN(4)); 31 s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(4));
36 s3c_gpio_cfgpin(S5PV210_GPC1(1), S3C_GPIO_SFN(4));
37 s3c_gpio_cfgpin(S5PV210_GPC1(2), S3C_GPIO_SFN(4));
38 s3c_gpio_cfgpin(S5PV210_GPC1(3), S3C_GPIO_SFN(4));
39 s3c_gpio_cfgpin(S5PV210_GPC1(4), S3C_GPIO_SFN(4));
40 break; 32 break;
41 33
42 case -1: 34 case -1:
43 s3c_gpio_cfgpin(S5PV210_GPI(0), S3C_GPIO_SFN(2)); 35 s3c_gpio_cfgpin_range(S5PV210_GPI(0), 7, S3C_GPIO_SFN(2));
44 s3c_gpio_cfgpin(S5PV210_GPI(1), S3C_GPIO_SFN(2));
45 s3c_gpio_cfgpin(S5PV210_GPI(2), S3C_GPIO_SFN(2));
46 s3c_gpio_cfgpin(S5PV210_GPI(3), S3C_GPIO_SFN(2));
47 s3c_gpio_cfgpin(S5PV210_GPI(4), S3C_GPIO_SFN(2));
48 s3c_gpio_cfgpin(S5PV210_GPI(5), S3C_GPIO_SFN(2));
49 s3c_gpio_cfgpin(S5PV210_GPI(6), S3C_GPIO_SFN(2));
50 break; 36 break;
51 37
52 default: 38 default:
@@ -151,25 +137,13 @@ static int s5pv210_pcm_cfg_gpio(struct platform_device *pdev)
151{ 137{
152 switch (pdev->id) { 138 switch (pdev->id) {
153 case 0: 139 case 0:
154 s3c_gpio_cfgpin(S5PV210_GPI(0), S3C_GPIO_SFN(3)); 140 s3c_gpio_cfgpin_range(S5PV210_GPI(0), 5, S3C_GPIO_SFN(3));
155 s3c_gpio_cfgpin(S5PV210_GPI(1), S3C_GPIO_SFN(3));
156 s3c_gpio_cfgpin(S5PV210_GPI(2), S3C_GPIO_SFN(3));
157 s3c_gpio_cfgpin(S5PV210_GPI(3), S3C_GPIO_SFN(3));
158 s3c_gpio_cfgpin(S5PV210_GPI(4), S3C_GPIO_SFN(3));
159 break; 141 break;
160 case 1: 142 case 1:
161 s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(3)); 143 s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(3));
162 s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(3));
163 s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(3));
164 s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(3));
165 s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(3));
166 break; 144 break;
167 case 2: 145 case 2:
168 s3c_gpio_cfgpin(S5PV210_GPC1(0), S3C_GPIO_SFN(2)); 146 s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(2));
169 s3c_gpio_cfgpin(S5PV210_GPC1(1), S3C_GPIO_SFN(2));
170 s3c_gpio_cfgpin(S5PV210_GPC1(2), S3C_GPIO_SFN(2));
171 s3c_gpio_cfgpin(S5PV210_GPC1(3), S3C_GPIO_SFN(2));
172 s3c_gpio_cfgpin(S5PV210_GPC1(4), S3C_GPIO_SFN(2));
173 break; 147 break;
174 default: 148 default:
175 printk(KERN_DEBUG "Invalid PCM Controller number!"); 149 printk(KERN_DEBUG "Invalid PCM Controller number!");
@@ -271,13 +245,7 @@ struct platform_device s5pv210_device_pcm2 = {
271 245
272static int s5pv210_ac97_cfg_gpio(struct platform_device *pdev) 246static int s5pv210_ac97_cfg_gpio(struct platform_device *pdev)
273{ 247{
274 s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(4)); 248 return s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(4));
275 s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(4));
276 s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(4));
277 s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(4));
278 s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(4));
279
280 return 0;
281} 249}
282 250
283static struct resource s5pv210_ac97_resource[] = { 251static struct resource s5pv210_ac97_resource[] = {
@@ -325,3 +293,43 @@ struct platform_device s5pv210_device_ac97 = {
325 .coherent_dma_mask = DMA_BIT_MASK(32), 293 .coherent_dma_mask = DMA_BIT_MASK(32),
326 }, 294 },
327}; 295};
296
297/* S/PDIF Controller platform_device */
298
299static int s5pv210_spdif_cfg_gpio(struct platform_device *pdev)
300{
301 s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 2, S3C_GPIO_SFN(3));
302
303 return 0;
304}
305
306static struct resource s5pv210_spdif_resource[] = {
307 [0] = {
308 .start = S5PV210_PA_SPDIF,
309 .end = S5PV210_PA_SPDIF + 0x100 - 1,
310 .flags = IORESOURCE_MEM,
311 },
312 [1] = {
313 .start = DMACH_SPDIF,
314 .end = DMACH_SPDIF,
315 .flags = IORESOURCE_DMA,
316 },
317};
318
319static struct s3c_audio_pdata samsung_spdif_pdata = {
320 .cfg_gpio = s5pv210_spdif_cfg_gpio,
321};
322
323static u64 s5pv210_spdif_dmamask = DMA_BIT_MASK(32);
324
325struct platform_device s5pv210_device_spdif = {
326 .name = "samsung-spdif",
327 .id = -1,
328 .num_resources = ARRAY_SIZE(s5pv210_spdif_resource),
329 .resource = s5pv210_spdif_resource,
330 .dev = {
331 .platform_data = &samsung_spdif_pdata,
332 .dma_mask = &s5pv210_spdif_dmamask,
333 .coherent_dma_mask = DMA_BIT_MASK(32),
334 },
335};
diff --git a/arch/arm/mach-s5pv210/dev-spi.c b/arch/arm/mach-s5pv210/dev-spi.c
index 826cdbc43e20..e3249a47e3b1 100644
--- a/arch/arm/mach-s5pv210/dev-spi.c
+++ b/arch/arm/mach-s5pv210/dev-spi.c
@@ -35,23 +35,15 @@ static char *spi_src_clks[] = {
35 */ 35 */
36static int s5pv210_spi_cfg_gpio(struct platform_device *pdev) 36static int s5pv210_spi_cfg_gpio(struct platform_device *pdev)
37{ 37{
38 unsigned int base;
39
38 switch (pdev->id) { 40 switch (pdev->id) {
39 case 0: 41 case 0:
40 s3c_gpio_cfgpin(S5PV210_GPB(0), S3C_GPIO_SFN(2)); 42 base = S5PV210_GPB(0);
41 s3c_gpio_cfgpin(S5PV210_GPB(1), S3C_GPIO_SFN(2));
42 s3c_gpio_cfgpin(S5PV210_GPB(2), S3C_GPIO_SFN(2));
43 s3c_gpio_setpull(S5PV210_GPB(0), S3C_GPIO_PULL_UP);
44 s3c_gpio_setpull(S5PV210_GPB(1), S3C_GPIO_PULL_UP);
45 s3c_gpio_setpull(S5PV210_GPB(2), S3C_GPIO_PULL_UP);
46 break; 43 break;
47 44
48 case 1: 45 case 1:
49 s3c_gpio_cfgpin(S5PV210_GPB(4), S3C_GPIO_SFN(2)); 46 base = S5PV210_GPB(4);
50 s3c_gpio_cfgpin(S5PV210_GPB(5), S3C_GPIO_SFN(2));
51 s3c_gpio_cfgpin(S5PV210_GPB(6), S3C_GPIO_SFN(2));
52 s3c_gpio_setpull(S5PV210_GPB(4), S3C_GPIO_PULL_UP);
53 s3c_gpio_setpull(S5PV210_GPB(5), S3C_GPIO_PULL_UP);
54 s3c_gpio_setpull(S5PV210_GPB(6), S3C_GPIO_PULL_UP);
55 break; 47 break;
56 48
57 default: 49 default:
@@ -59,6 +51,9 @@ static int s5pv210_spi_cfg_gpio(struct platform_device *pdev)
59 return -EINVAL; 51 return -EINVAL;
60 } 52 }
61 53
54 s3c_gpio_cfgall_range(base, 3,
55 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
56
62 return 0; 57 return 0;
63} 58}
64 59
diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c
index 778ad5fe231a..497d3439a142 100644
--- a/arch/arm/mach-s5pv210/dma.c
+++ b/arch/arm/mach-s5pv210/dma.c
@@ -82,7 +82,7 @@ static struct s3c_pl330_platdata s5pv210_pdma0_pdata = {
82 82
83static struct platform_device s5pv210_device_pdma0 = { 83static struct platform_device s5pv210_device_pdma0 = {
84 .name = "s3c-pl330", 84 .name = "s3c-pl330",
85 .id = 1, 85 .id = 0,
86 .num_resources = ARRAY_SIZE(s5pv210_pdma0_resource), 86 .num_resources = ARRAY_SIZE(s5pv210_pdma0_resource),
87 .resource = s5pv210_pdma0_resource, 87 .resource = s5pv210_pdma0_resource,
88 .dev = { 88 .dev = {
@@ -144,7 +144,7 @@ static struct s3c_pl330_platdata s5pv210_pdma1_pdata = {
144 144
145static struct platform_device s5pv210_device_pdma1 = { 145static struct platform_device s5pv210_device_pdma1 = {
146 .name = "s3c-pl330", 146 .name = "s3c-pl330",
147 .id = 2, 147 .id = 1,
148 .num_resources = ARRAY_SIZE(s5pv210_pdma1_resource), 148 .num_resources = ARRAY_SIZE(s5pv210_pdma1_resource),
149 .resource = s5pv210_pdma1_resource, 149 .resource = s5pv210_pdma1_resource,
150 .dev = { 150 .dev = {
diff --git a/arch/arm/mach-s5pv210/gpiolib.c b/arch/arm/mach-s5pv210/gpiolib.c
index 0d459112d039..ab673effd767 100644
--- a/arch/arm/mach-s5pv210/gpiolib.c
+++ b/arch/arm/mach-s5pv210/gpiolib.c
@@ -150,6 +150,7 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
150 .label = "GPG3", 150 .label = "GPG3",
151 }, 151 },
152 }, { 152 }, {
153 .config = &gpio_cfg_noint,
153 .chip = { 154 .chip = {
154 .base = S5PV210_GPI(0), 155 .base = S5PV210_GPI(0),
155 .ngpio = S5PV210_GPIO_I_NR, 156 .ngpio = S5PV210_GPIO_I_NR,
@@ -223,34 +224,42 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
223 }, { 224 }, {
224 .base = (S5P_VA_GPIO + 0xC00), 225 .base = (S5P_VA_GPIO + 0xC00),
225 .config = &gpio_cfg_noint, 226 .config = &gpio_cfg_noint,
227 .irq_base = IRQ_EINT(0),
226 .chip = { 228 .chip = {
227 .base = S5PV210_GPH0(0), 229 .base = S5PV210_GPH0(0),
228 .ngpio = S5PV210_GPIO_H0_NR, 230 .ngpio = S5PV210_GPIO_H0_NR,
229 .label = "GPH0", 231 .label = "GPH0",
232 .to_irq = samsung_gpiolib_to_irq,
230 }, 233 },
231 }, { 234 }, {
232 .base = (S5P_VA_GPIO + 0xC20), 235 .base = (S5P_VA_GPIO + 0xC20),
233 .config = &gpio_cfg_noint, 236 .config = &gpio_cfg_noint,
237 .irq_base = IRQ_EINT(8),
234 .chip = { 238 .chip = {
235 .base = S5PV210_GPH1(0), 239 .base = S5PV210_GPH1(0),
236 .ngpio = S5PV210_GPIO_H1_NR, 240 .ngpio = S5PV210_GPIO_H1_NR,
237 .label = "GPH1", 241 .label = "GPH1",
242 .to_irq = samsung_gpiolib_to_irq,
238 }, 243 },
239 }, { 244 }, {
240 .base = (S5P_VA_GPIO + 0xC40), 245 .base = (S5P_VA_GPIO + 0xC40),
241 .config = &gpio_cfg_noint, 246 .config = &gpio_cfg_noint,
247 .irq_base = IRQ_EINT(16),
242 .chip = { 248 .chip = {
243 .base = S5PV210_GPH2(0), 249 .base = S5PV210_GPH2(0),
244 .ngpio = S5PV210_GPIO_H2_NR, 250 .ngpio = S5PV210_GPIO_H2_NR,
245 .label = "GPH2", 251 .label = "GPH2",
252 .to_irq = samsung_gpiolib_to_irq,
246 }, 253 },
247 }, { 254 }, {
248 .base = (S5P_VA_GPIO + 0xC60), 255 .base = (S5P_VA_GPIO + 0xC60),
249 .config = &gpio_cfg_noint, 256 .config = &gpio_cfg_noint,
257 .irq_base = IRQ_EINT(24),
250 .chip = { 258 .chip = {
251 .base = S5PV210_GPH3(0), 259 .base = S5PV210_GPH3(0),
252 .ngpio = S5PV210_GPIO_H3_NR, 260 .ngpio = S5PV210_GPIO_H3_NR,
253 .label = "GPH3", 261 .label = "GPH3",
262 .to_irq = samsung_gpiolib_to_irq,
254 }, 263 },
255 }, 264 },
256}; 265};
@@ -259,11 +268,14 @@ static __init int s5pv210_gpiolib_init(void)
259{ 268{
260 struct s3c_gpio_chip *chip = s5pv210_gpio_4bit; 269 struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
261 int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit); 270 int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
271 int gpioint_group = 0;
262 int i = 0; 272 int i = 0;
263 273
264 for (i = 0; i < nr_chips; i++, chip++) { 274 for (i = 0; i < nr_chips; i++, chip++) {
265 if (chip->config == NULL) 275 if (chip->config == NULL) {
266 chip->config = &gpio_cfg; 276 chip->config = &gpio_cfg;
277 chip->group = gpioint_group++;
278 }
267 if (chip->base == NULL) 279 if (chip->base == NULL)
268 chip->base = S5PV210_BANK_BASE(i); 280 chip->base = S5PV210_BANK_BASE(i);
269 } 281 }
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
index e1c020e5a49b..119b95fdc3ce 100644
--- a/arch/arm/mach-s5pv210/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
@@ -55,8 +55,8 @@
55#define IRQ_SPI1 S5P_IRQ_VIC1(16) 55#define IRQ_SPI1 S5P_IRQ_VIC1(16)
56#define IRQ_SPI2 S5P_IRQ_VIC1(17) 56#define IRQ_SPI2 S5P_IRQ_VIC1(17)
57#define IRQ_IRDA S5P_IRQ_VIC1(18) 57#define IRQ_IRDA S5P_IRQ_VIC1(18)
58#define IRQ_CAN0 S5P_IRQ_VIC1(19) 58#define IRQ_IIC2 S5P_IRQ_VIC1(19)
59#define IRQ_CAN1 S5P_IRQ_VIC1(20) 59#define IRQ_IIC3 S5P_IRQ_VIC1(20)
60#define IRQ_HSIRX S5P_IRQ_VIC1(21) 60#define IRQ_HSIRX S5P_IRQ_VIC1(21)
61#define IRQ_HSITX S5P_IRQ_VIC1(22) 61#define IRQ_HSITX S5P_IRQ_VIC1(22)
62#define IRQ_UHOST S5P_IRQ_VIC1(23) 62#define IRQ_UHOST S5P_IRQ_VIC1(23)
@@ -109,7 +109,7 @@
109 109
110#define IRQ_IPC S5P_IRQ_VIC3(0) 110#define IRQ_IPC S5P_IRQ_VIC3(0)
111#define IRQ_HOSTIF S5P_IRQ_VIC3(1) 111#define IRQ_HOSTIF S5P_IRQ_VIC3(1)
112#define IRQ_MMC3 S5P_IRQ_VIC3(2) 112#define IRQ_HSMMC3 S5P_IRQ_VIC3(2)
113#define IRQ_CEC S5P_IRQ_VIC3(3) 113#define IRQ_CEC S5P_IRQ_VIC3(3)
114#define IRQ_TSI S5P_IRQ_VIC3(4) 114#define IRQ_TSI S5P_IRQ_VIC3(4)
115#define IRQ_MDNIE0 S5P_IRQ_VIC3(5) 115#define IRQ_MDNIE0 S5P_IRQ_VIC3(5)
@@ -121,8 +121,12 @@
121#define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0)) 121#define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0))
122#define S5P_EINT_BASE2 (IRQ_VIC_END + 1) 122#define S5P_EINT_BASE2 (IRQ_VIC_END + 1)
123 123
124/* GPIO interrupt */
125#define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1)
126#define S5P_GPIOINT_GROUP_MAXNR 22
127
124/* Set the default NR_IRQS */ 128/* Set the default NR_IRQS */
125#define NR_IRQS (IRQ_EINT(31) + 1) 129#define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
126 130
127/* Compatibility */ 131/* Compatibility */
128#define IRQ_LCD_FIFO IRQ_LCD0 132#define IRQ_LCD_FIFO IRQ_LCD0
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
index bd9afd52466a..861d7fe11fc9 100644
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -57,6 +57,8 @@
57 57
58#define S5P_SZ_UART SZ_256 58#define S5P_SZ_UART SZ_256
59 59
60#define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
61
60#define S5PV210_PA_SROMC (0xE8000000) 62#define S5PV210_PA_SROMC (0xE8000000)
61 63
62#define S5PV210_PA_CFCON (0xE8200000) 64#define S5PV210_PA_CFCON (0xE8200000)
@@ -73,6 +75,9 @@
73 75
74#define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000)) 76#define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000))
75 77
78#define S5PV210_PA_HSOTG (0xEC000000)
79#define S5PV210_PA_HSPHY (0xEC100000)
80
76#define S5PV210_PA_VIC0 (0xF2000000) 81#define S5PV210_PA_VIC0 (0xF2000000)
77#define S5PV210_PA_VIC1 (0xF2100000) 82#define S5PV210_PA_VIC1 (0xF2100000)
78#define S5PV210_PA_VIC2 (0xF2200000) 83#define S5PV210_PA_VIC2 (0xF2200000)
@@ -81,6 +86,9 @@
81#define S5PV210_PA_SDRAM (0x20000000) 86#define S5PV210_PA_SDRAM (0x20000000)
82#define S5P_PA_SDRAM S5PV210_PA_SDRAM 87#define S5P_PA_SDRAM S5PV210_PA_SDRAM
83 88
89/* S/PDIF */
90#define S5PV210_PA_SPDIF 0xE1100000
91
84/* I2S */ 92/* I2S */
85#define S5PV210_PA_IIS0 0xEEE30000 93#define S5PV210_PA_IIS0 0xEEE30000
86#define S5PV210_PA_IIS1 0xE2100000 94#define S5PV210_PA_IIS1 0xE2100000
@@ -96,6 +104,9 @@
96 104
97#define S5PV210_PA_ADC (0xE1700000) 105#define S5PV210_PA_ADC (0xE1700000)
98 106
107#define S5PV210_PA_DMC0 (0xF0000000)
108#define S5PV210_PA_DMC1 (0xF1400000)
109
99/* compatibiltiy defines. */ 110/* compatibiltiy defines. */
100#define S3C_PA_UART S5PV210_PA_UART 111#define S3C_PA_UART S5PV210_PA_UART
101#define S3C_PA_HSMMC0 S5PV210_PA_HSMMC(0) 112#define S3C_PA_HSMMC0 S5PV210_PA_HSMMC(0)
@@ -108,6 +119,7 @@
108#define S3C_PA_FB S5PV210_PA_FB 119#define S3C_PA_FB S5PV210_PA_FB
109#define S3C_PA_RTC S5PV210_PA_RTC 120#define S3C_PA_RTC S5PV210_PA_RTC
110#define S3C_PA_WDT S5PV210_PA_WATCHDOG 121#define S3C_PA_WDT S5PV210_PA_WATCHDOG
122#define S3C_PA_USB_HSOTG S5PV210_PA_HSOTG
111#define S5P_PA_FIMC0 S5PV210_PA_FIMC0 123#define S5P_PA_FIMC0 S5PV210_PA_FIMC0
112#define S5P_PA_FIMC1 S5PV210_PA_FIMC1 124#define S5P_PA_FIMC1 S5PV210_PA_FIMC1
113#define S5P_PA_FIMC2 S5PV210_PA_FIMC2 125#define S5P_PA_FIMC2 S5PV210_PA_FIMC2
diff --git a/arch/arm/mach-s5pv210/include/mach/pm-core.h b/arch/arm/mach-s5pv210/include/mach/pm-core.h
new file mode 100644
index 000000000000..e8d394f8b057
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/pm-core.h
@@ -0,0 +1,43 @@
1/* linux/arch/arm/mach-s5pv210/include/mach/pm-core.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * Based on arch/arm/mach-s3c2410/include/mach/pm-core.h,
7 * Copyright 2008 Simtec Electronics
8 * Ben Dooks <ben@simtec.co.uk>
9 * http://armlinux.simtec.co.uk/
10 *
11 * S5PV210 - PM core support for arch/arm/plat-s5p/pm.c
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16*/
17
18static inline void s3c_pm_debug_init_uart(void)
19{
20 /* nothing here yet */
21}
22
23static inline void s3c_pm_arch_prepare_irqs(void)
24{
25 __raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK);
26 __raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK);
27}
28
29static inline void s3c_pm_arch_stop_clocks(void)
30{
31 /* nothing here yet */
32}
33
34static inline void s3c_pm_arch_show_resume_irqs(void)
35{
36 /* nothing here yet */
37}
38
39static inline void s3c_pm_arch_update_uart(void __iomem *regs,
40 struct pm_uart_save *save)
41{
42 /* nothing here yet */
43}
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
index 499aef737476..ebaabe021af9 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
@@ -25,6 +25,7 @@
25#define S5P_APLL_CON S5P_CLKREG(0x100) 25#define S5P_APLL_CON S5P_CLKREG(0x100)
26#define S5P_MPLL_CON S5P_CLKREG(0x108) 26#define S5P_MPLL_CON S5P_CLKREG(0x108)
27#define S5P_EPLL_CON S5P_CLKREG(0x110) 27#define S5P_EPLL_CON S5P_CLKREG(0x110)
28#define S5P_EPLL_CON1 S5P_CLKREG(0x114)
28#define S5P_VPLL_CON S5P_CLKREG(0x120) 29#define S5P_VPLL_CON S5P_CLKREG(0x120)
29 30
30#define S5P_CLK_SRC0 S5P_CLKREG(0x200) 31#define S5P_CLK_SRC0 S5P_CLKREG(0x200)
@@ -67,11 +68,28 @@
67#define S5P_CLKGATE_BUS1 S5P_CLKREG(0x488) 68#define S5P_CLKGATE_BUS1 S5P_CLKREG(0x488)
68#define S5P_CLK_OUT S5P_CLKREG(0x500) 69#define S5P_CLK_OUT S5P_CLKREG(0x500)
69 70
71/* DIV/MUX STATUS */
72#define S5P_CLKDIV_STAT0 S5P_CLKREG(0x1000)
73#define S5P_CLKDIV_STAT1 S5P_CLKREG(0x1004)
74#define S5P_CLKMUX_STAT0 S5P_CLKREG(0x1100)
75#define S5P_CLKMUX_STAT1 S5P_CLKREG(0x1104)
76
70/* CLKSRC0 */ 77/* CLKSRC0 */
71#define S5P_CLKSRC0_MUX200_MASK (0x1<<16) 78#define S5P_CLKSRC0_MUX200_SHIFT (16)
79#define S5P_CLKSRC0_MUX200_MASK (0x1 << S5P_CLKSRC0_MUX200_SHIFT)
72#define S5P_CLKSRC0_MUX166_MASK (0x1<<20) 80#define S5P_CLKSRC0_MUX166_MASK (0x1<<20)
73#define S5P_CLKSRC0_MUX133_MASK (0x1<<24) 81#define S5P_CLKSRC0_MUX133_MASK (0x1<<24)
74 82
83/* CLKSRC2 */
84#define S5P_CLKSRC2_G3D_SHIFT (0)
85#define S5P_CLKSRC2_G3D_MASK (0x3 << S5P_CLKSRC2_G3D_SHIFT)
86#define S5P_CLKSRC2_MFC_SHIFT (4)
87#define S5P_CLKSRC2_MFC_MASK (0x3 << S5P_CLKSRC2_MFC_SHIFT)
88
89/* CLKSRC6*/
90#define S5P_CLKSRC6_ONEDRAM_SHIFT (24)
91#define S5P_CLKSRC6_ONEDRAM_MASK (0x3 << S5P_CLKSRC6_ONEDRAM_SHIFT)
92
75/* CLKDIV0 */ 93/* CLKDIV0 */
76#define S5P_CLKDIV0_APLL_SHIFT (0) 94#define S5P_CLKDIV0_APLL_SHIFT (0)
77#define S5P_CLKDIV0_APLL_MASK (0x7 << S5P_CLKDIV0_APLL_SHIFT) 95#define S5P_CLKDIV0_APLL_MASK (0x7 << S5P_CLKDIV0_APLL_SHIFT)
@@ -90,12 +108,24 @@
90#define S5P_CLKDIV0_PCLK66_SHIFT (28) 108#define S5P_CLKDIV0_PCLK66_SHIFT (28)
91#define S5P_CLKDIV0_PCLK66_MASK (0x7 << S5P_CLKDIV0_PCLK66_SHIFT) 109#define S5P_CLKDIV0_PCLK66_MASK (0x7 << S5P_CLKDIV0_PCLK66_SHIFT)
92 110
111/* CLKDIV2 */
112#define S5P_CLKDIV2_G3D_SHIFT (0)
113#define S5P_CLKDIV2_G3D_MASK (0xF << S5P_CLKDIV2_G3D_SHIFT)
114#define S5P_CLKDIV2_MFC_SHIFT (4)
115#define S5P_CLKDIV2_MFC_MASK (0xF << S5P_CLKDIV2_MFC_SHIFT)
116
117/* CLKDIV6 */
118#define S5P_CLKDIV6_ONEDRAM_SHIFT (28)
119#define S5P_CLKDIV6_ONEDRAM_MASK (0xF << S5P_CLKDIV6_ONEDRAM_SHIFT)
120
93#define S5P_SWRESET S5P_CLKREG(0x2000) 121#define S5P_SWRESET S5P_CLKREG(0x2000)
94 122
123#define S5P_ARM_MCS_CON S5P_CLKREG(0x6100)
124
95/* Registers related to power management */ 125/* Registers related to power management */
96#define S5P_PWR_CFG S5P_CLKREG(0xC000) 126#define S5P_PWR_CFG S5P_CLKREG(0xC000)
97#define S5P_EINT_WAKEUP_MASK S5P_CLKREG(0xC004) 127#define S5P_EINT_WAKEUP_MASK S5P_CLKREG(0xC004)
98#define S5P_WAKEUP_MASK S5P_CLKREG(0xC008) 128#define S5P_WAKEUP_MASK S5P_CLKREG(0xC008)
99#define S5P_PWR_MODE S5P_CLKREG(0xC00C) 129#define S5P_PWR_MODE S5P_CLKREG(0xC00C)
100#define S5P_NORMAL_CFG S5P_CLKREG(0xC010) 130#define S5P_NORMAL_CFG S5P_CLKREG(0xC010)
101#define S5P_IDLE_CFG S5P_CLKREG(0xC020) 131#define S5P_IDLE_CFG S5P_CLKREG(0xC020)
@@ -159,8 +189,11 @@
159#define S5P_SLEEP_CFG_USBOSC_EN (1 << 1) 189#define S5P_SLEEP_CFG_USBOSC_EN (1 << 1)
160 190
161/* OTHERS Resgister */ 191/* OTHERS Resgister */
192#define S5P_OTHERS_RET_IO (1 << 31)
193#define S5P_OTHERS_RET_CF (1 << 30)
194#define S5P_OTHERS_RET_MMC (1 << 29)
195#define S5P_OTHERS_RET_UART (1 << 28)
162#define S5P_OTHERS_USB_SIG_MASK (1 << 16) 196#define S5P_OTHERS_USB_SIG_MASK (1 << 16)
163#define S5P_OTHERS_MIPI_DPHY_EN (1 << 28)
164 197
165/* MIPI */ 198/* MIPI */
166#define S5P_MIPI_DPHY_EN (3) 199#define S5P_MIPI_DPHY_EN (3)
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-gpio.h b/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
index 49e029b4978a..de0c89976078 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
@@ -31,13 +31,6 @@
31 31
32#define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7)) 32#define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7))
33 33
34/* values for S5P_EXTINT0 */
35#define S5P_EXTINT_LOWLEV (0x00)
36#define S5P_EXTINT_HILEV (0x01)
37#define S5P_EXTINT_FALLEDGE (0x02)
38#define S5P_EXTINT_RISEEDGE (0x03)
39#define S5P_EXTINT_BOTHEDGE (0x04)
40
41#define EINT_MODE S3C_GPIO_SFN(0xf) 34#define EINT_MODE S3C_GPIO_SFN(0xf)
42 35
43#define EINT_GPIO_0(x) S5PV210_GPH0(x) 36#define EINT_GPIO_0(x) S5PV210_GPH0(x)
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-sys.h b/arch/arm/mach-s5pv210/include/mach/regs-sys.h
new file mode 100644
index 000000000000..26691d39d0f4
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/regs-sys.h
@@ -0,0 +1,19 @@
1/* arch/arm/mach-s5pv210/include/mach/regs-sys.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV210 - System registers definitions
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#define S5PV210_USB_PHY_CON (S3C_VA_SYS + 0xE80C)
14#define S5PV210_USB_PHY0_EN (1 << 0)
15#define S5PV210_USB_PHY1_EN (1 << 1)
16
17/* compatibility defines for s3c-hsotg driver */
18#define S3C64XX_OTHERS S5PV210_USB_PHY_CON
19#define S3C64XX_OTHERS_USBMASK S5PV210_USB_PHY0_EN
diff --git a/arch/arm/mach-s5pv210/include/mach/vmalloc.h b/arch/arm/mach-s5pv210/include/mach/vmalloc.h
index df9a28808323..a6c659d68a5d 100644
--- a/arch/arm/mach-s5pv210/include/mach/vmalloc.h
+++ b/arch/arm/mach-s5pv210/include/mach/vmalloc.h
@@ -17,6 +17,6 @@
17#ifndef __ASM_ARCH_VMALLOC_H 17#ifndef __ASM_ARCH_VMALLOC_H
18#define __ASM_ARCH_VMALLOC_H __FILE__ 18#define __ASM_ARCH_VMALLOC_H __FILE__
19 19
20#define VMALLOC_END (0xE0000000UL) 20#define VMALLOC_END 0xF6000000UL
21 21
22#endif /* __ASM_ARCH_VMALLOC_H */ 22#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 00883087363c..28677caf3613 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -16,6 +16,8 @@
16#include <linux/i2c.h> 16#include <linux/i2c.h>
17#include <linux/i2c-gpio.h> 17#include <linux/i2c-gpio.h>
18#include <linux/mfd/max8998.h> 18#include <linux/mfd/max8998.h>
19#include <linux/mfd/wm8994/pdata.h>
20#include <linux/regulator/fixed.h>
19#include <linux/gpio_keys.h> 21#include <linux/gpio_keys.h>
20#include <linux/input.h> 22#include <linux/input.h>
21#include <linux/gpio.h> 23#include <linux/gpio.h>
@@ -379,6 +381,119 @@ static struct max8998_platform_data aquila_max8998_pdata = {
379}; 381};
380#endif 382#endif
381 383
384static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
385 {
386 .dev_name = "5-001a",
387 .supply = "DBVDD",
388 }, {
389 .dev_name = "5-001a",
390 .supply = "AVDD2",
391 }, {
392 .dev_name = "5-001a",
393 .supply = "CPVDD",
394 },
395};
396
397static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
398 {
399 .dev_name = "5-001a",
400 .supply = "SPKVDD1",
401 }, {
402 .dev_name = "5-001a",
403 .supply = "SPKVDD2",
404 },
405};
406
407static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
408 .constraints = {
409 .always_on = 1,
410 },
411 .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage0_supplies),
412 .consumer_supplies = wm8994_fixed_voltage0_supplies,
413};
414
415static struct regulator_init_data wm8994_fixed_voltage1_init_data = {
416 .constraints = {
417 .always_on = 1,
418 },
419 .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage1_supplies),
420 .consumer_supplies = wm8994_fixed_voltage1_supplies,
421};
422
423static struct fixed_voltage_config wm8994_fixed_voltage0_config = {
424 .supply_name = "VCC_1.8V_PDA",
425 .microvolts = 1800000,
426 .gpio = -EINVAL,
427 .init_data = &wm8994_fixed_voltage0_init_data,
428};
429
430static struct fixed_voltage_config wm8994_fixed_voltage1_config = {
431 .supply_name = "V_BAT",
432 .microvolts = 3700000,
433 .gpio = -EINVAL,
434 .init_data = &wm8994_fixed_voltage1_init_data,
435};
436
437static struct platform_device wm8994_fixed_voltage0 = {
438 .name = "reg-fixed-voltage",
439 .id = 0,
440 .dev = {
441 .platform_data = &wm8994_fixed_voltage0_config,
442 },
443};
444
445static struct platform_device wm8994_fixed_voltage1 = {
446 .name = "reg-fixed-voltage",
447 .id = 1,
448 .dev = {
449 .platform_data = &wm8994_fixed_voltage1_config,
450 },
451};
452
453static struct regulator_consumer_supply wm8994_avdd1_supply = {
454 .dev_name = "5-001a",
455 .supply = "AVDD1",
456};
457
458static struct regulator_consumer_supply wm8994_dcvdd_supply = {
459 .dev_name = "5-001a",
460 .supply = "DCVDD",
461};
462
463static struct regulator_init_data wm8994_ldo1_data = {
464 .constraints = {
465 .name = "AVDD1_3.0V",
466 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
467 },
468 .num_consumer_supplies = 1,
469 .consumer_supplies = &wm8994_avdd1_supply,
470};
471
472static struct regulator_init_data wm8994_ldo2_data = {
473 .constraints = {
474 .name = "DCVDD_1.0V",
475 },
476 .num_consumer_supplies = 1,
477 .consumer_supplies = &wm8994_dcvdd_supply,
478};
479
480static struct wm8994_pdata wm8994_platform_data = {
481 /* configure gpio1 function: 0x0001(Logic level input/output) */
482 .gpio_defaults[0] = 0x0001,
483 /* configure gpio3/4/5/7 function for AIF2 voice */
484 .gpio_defaults[2] = 0x8100,
485 .gpio_defaults[3] = 0x8100,
486 .gpio_defaults[4] = 0x8100,
487 .gpio_defaults[6] = 0x0100,
488 /* configure gpio8/9/10/11 function for AIF3 BT */
489 .gpio_defaults[7] = 0x8100,
490 .gpio_defaults[8] = 0x0100,
491 .gpio_defaults[9] = 0x0100,
492 .gpio_defaults[10] = 0x0100,
493 .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */
494 .ldo[1] = { 0, NULL, &wm8994_ldo2_data },
495};
496
382/* GPIO I2C PMIC */ 497/* GPIO I2C PMIC */
383#define AP_I2C_GPIO_PMIC_BUS_4 4 498#define AP_I2C_GPIO_PMIC_BUS_4 4
384static struct i2c_gpio_platform_data aquila_i2c_gpio_pmic_data = { 499static struct i2c_gpio_platform_data aquila_i2c_gpio_pmic_data = {
@@ -404,6 +519,29 @@ static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = {
404#endif 519#endif
405}; 520};
406 521
522/* GPIO I2C AP 1.8V */
523#define AP_I2C_GPIO_BUS_5 5
524static struct i2c_gpio_platform_data aquila_i2c_gpio5_data = {
525 .sda_pin = S5PV210_MP05(3), /* XM0ADDR_11 */
526 .scl_pin = S5PV210_MP05(2), /* XM0ADDR_10 */
527};
528
529static struct platform_device aquila_i2c_gpio5 = {
530 .name = "i2c-gpio",
531 .id = AP_I2C_GPIO_BUS_5,
532 .dev = {
533 .platform_data = &aquila_i2c_gpio5_data,
534 },
535};
536
537static struct i2c_board_info i2c_gpio5_devs[] __initdata = {
538 {
539 /* CS/ADDR = low 0x34 (FYI: high = 0x36) */
540 I2C_BOARD_INFO("wm8994", 0x1a),
541 .platform_data = &wm8994_platform_data,
542 },
543};
544
407/* PMIC Power button */ 545/* PMIC Power button */
408static struct gpio_keys_button aquila_gpio_keys_table[] = { 546static struct gpio_keys_button aquila_gpio_keys_table[] = {
409 { 547 {
@@ -475,6 +613,7 @@ static void aquila_setup_sdhci(void)
475 613
476static struct platform_device *aquila_devices[] __initdata = { 614static struct platform_device *aquila_devices[] __initdata = {
477 &aquila_i2c_gpio_pmic, 615 &aquila_i2c_gpio_pmic,
616 &aquila_i2c_gpio5,
478 &aquila_device_gpiokeys, 617 &aquila_device_gpiokeys,
479 &s3c_device_fb, 618 &s3c_device_fb,
480 &s5p_device_onenand, 619 &s5p_device_onenand,
@@ -484,8 +623,33 @@ static struct platform_device *aquila_devices[] __initdata = {
484 &s5p_device_fimc0, 623 &s5p_device_fimc0,
485 &s5p_device_fimc1, 624 &s5p_device_fimc1,
486 &s5p_device_fimc2, 625 &s5p_device_fimc2,
626 &s5pv210_device_iis0,
627 &wm8994_fixed_voltage0,
628 &wm8994_fixed_voltage1,
487}; 629};
488 630
631static void __init aquila_sound_init(void)
632{
633 unsigned int gpio;
634
635 /* CODEC_XTAL_EN
636 *
637 * The Aquila board have a oscillator which provide main clock
638 * to WM8994 codec. The oscillator provide 24MHz clock to WM8994
639 * clock. Set gpio setting of "CODEC_XTAL_EN" to enable a oscillator.
640 * */
641 gpio = S5PV210_GPH3(2); /* XEINT_26 */
642 gpio_request(gpio, "CODEC_XTAL_EN");
643 s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT);
644 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
645
646 /* Ths main clock of WM8994 codec uses the output of CLKOUT pin.
647 * The CLKOUT[9:8] set to 0x3(XUSBXTI) of 0xE010E000(OTHERS)
648 * because it needs 24MHz clock to operate WM8994 codec.
649 */
650 __raw_writel(__raw_readl(S5P_OTHERS) | (0x3 << 8), S5P_OTHERS);
651}
652
489static void __init aquila_map_io(void) 653static void __init aquila_map_io(void)
490{ 654{
491 s5p_init_io(NULL, 0, S5P_VA_CHIPID); 655 s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -506,6 +670,11 @@ static void __init aquila_machine_init(void)
506 s3c_fimc_setname(1, "s5p-fimc"); 670 s3c_fimc_setname(1, "s5p-fimc");
507 s3c_fimc_setname(2, "s5p-fimc"); 671 s3c_fimc_setname(2, "s5p-fimc");
508 672
673 /* SOUND */
674 aquila_sound_init();
675 i2c_register_board_info(AP_I2C_GPIO_BUS_5, i2c_gpio5_devs,
676 ARRAY_SIZE(i2c_gpio5_devs));
677
509 /* FB */ 678 /* FB */
510 s3c_fb_set_platdata(&aquila_lcd_pdata); 679 s3c_fb_set_platdata(&aquila_lcd_pdata);
511 680
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index d9ecf57fc2a5..b1dcf964a768 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -15,7 +15,13 @@
15#include <linux/fb.h> 15#include <linux/fb.h>
16#include <linux/i2c.h> 16#include <linux/i2c.h>
17#include <linux/i2c-gpio.h> 17#include <linux/i2c-gpio.h>
18#include <linux/i2c/qt602240_ts.h>
18#include <linux/mfd/max8998.h> 19#include <linux/mfd/max8998.h>
20#include <linux/mfd/wm8994/pdata.h>
21#include <linux/regulator/fixed.h>
22#include <linux/spi/spi.h>
23#include <linux/spi/spi_gpio.h>
24#include <linux/lcd.h>
19#include <linux/gpio_keys.h> 25#include <linux/gpio_keys.h>
20#include <linux/input.h> 26#include <linux/input.h>
21#include <linux/gpio.h> 27#include <linux/gpio.h>
@@ -35,7 +41,10 @@
35#include <plat/devs.h> 41#include <plat/devs.h>
36#include <plat/cpu.h> 42#include <plat/cpu.h>
37#include <plat/fb.h> 43#include <plat/fb.h>
44#include <plat/iic.h>
45#include <plat/keypad.h>
38#include <plat/sdhci.h> 46#include <plat/sdhci.h>
47#include <plat/clock.h>
39 48
40/* Following are default values for UCON, ULCON and UFCON UART registers */ 49/* Following are default values for UCON, ULCON and UFCON UART registers */
41#define GONI_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ 50#define GONI_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -87,13 +96,12 @@ static struct s3c2410_uartcfg goni_uartcfgs[] __initdata = {
87/* Frame Buffer */ 96/* Frame Buffer */
88static struct s3c_fb_pd_win goni_fb_win0 = { 97static struct s3c_fb_pd_win goni_fb_win0 = {
89 .win_mode = { 98 .win_mode = {
90 .pixclock = 1000000000000ULL / ((16+16+2+480)*(28+3+2+800)*55),
91 .left_margin = 16, 99 .left_margin = 16,
92 .right_margin = 16, 100 .right_margin = 16,
93 .upper_margin = 3, 101 .upper_margin = 2,
94 .lower_margin = 28, 102 .lower_margin = 28,
95 .hsync_len = 2, 103 .hsync_len = 2,
96 .vsync_len = 2, 104 .vsync_len = 1,
97 .xres = 480, 105 .xres = 480,
98 .yres = 800, 106 .yres = 800,
99 .refresh = 55, 107 .refresh = 55,
@@ -111,9 +119,160 @@ static struct s3c_fb_platdata goni_lcd_pdata __initdata = {
111 .setup_gpio = s5pv210_fb_gpio_setup_24bpp, 119 .setup_gpio = s5pv210_fb_gpio_setup_24bpp,
112}; 120};
113 121
122static int lcd_power_on(struct lcd_device *ld, int enable)
123{
124 return 1;
125}
126
127static int reset_lcd(struct lcd_device *ld)
128{
129 static unsigned int first = 1;
130 int reset_gpio = -1;
131
132 reset_gpio = S5PV210_MP05(5);
133
134 if (first) {
135 gpio_request(reset_gpio, "MLCD_RST");
136 first = 0;
137 }
138
139 gpio_direction_output(reset_gpio, 1);
140 return 1;
141}
142
143static struct lcd_platform_data goni_lcd_platform_data = {
144 .reset = reset_lcd,
145 .power_on = lcd_power_on,
146 .lcd_enabled = 0,
147 .reset_delay = 120, /* 120ms */
148 .power_on_delay = 25, /* 25ms */
149 .power_off_delay = 200, /* 200ms */
150};
151
152#define LCD_BUS_NUM 3
153static struct spi_board_info spi_board_info[] __initdata = {
154 {
155 .modalias = "s6e63m0",
156 .platform_data = &goni_lcd_platform_data,
157 .max_speed_hz = 1200000,
158 .bus_num = LCD_BUS_NUM,
159 .chip_select = 0,
160 .mode = SPI_MODE_3,
161 .controller_data = (void *)S5PV210_MP01(1), /* DISPLAY_CS */
162 },
163};
164
165static struct spi_gpio_platform_data lcd_spi_gpio_data = {
166 .sck = S5PV210_MP04(1), /* DISPLAY_CLK */
167 .mosi = S5PV210_MP04(3), /* DISPLAY_SI */
168 .miso = SPI_GPIO_NO_MISO,
169 .num_chipselect = 1,
170};
171
172static struct platform_device goni_spi_gpio = {
173 .name = "spi_gpio",
174 .id = LCD_BUS_NUM,
175 .dev = {
176 .parent = &s3c_device_fb.dev,
177 .platform_data = &lcd_spi_gpio_data,
178 },
179};
180
181/* KEYPAD */
182static uint32_t keymap[] __initdata = {
183 /* KEY(row, col, keycode) */
184 KEY(0, 1, KEY_MENU), /* Send */
185 KEY(0, 2, KEY_BACK), /* End */
186 KEY(1, 1, KEY_CONFIG), /* Half shot */
187 KEY(1, 2, KEY_VOLUMEUP),
188 KEY(2, 1, KEY_CAMERA), /* Full shot */
189 KEY(2, 2, KEY_VOLUMEDOWN),
190};
191
192static struct matrix_keymap_data keymap_data __initdata = {
193 .keymap = keymap,
194 .keymap_size = ARRAY_SIZE(keymap),
195};
196
197static struct samsung_keypad_platdata keypad_data __initdata = {
198 .keymap_data = &keymap_data,
199 .rows = 3,
200 .cols = 3,
201};
202
203/* Radio */
204static struct i2c_board_info i2c1_devs[] __initdata = {
205 {
206 I2C_BOARD_INFO("si470x", 0x10),
207 },
208};
209
210static void __init goni_radio_init(void)
211{
212 int gpio;
213
214 gpio = S5PV210_GPJ2(4); /* XMSMDATA_4 */
215 gpio_request(gpio, "FM_INT");
216 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
217 i2c1_devs[0].irq = gpio_to_irq(gpio);
218
219 gpio = S5PV210_GPJ2(5); /* XMSMDATA_5 */
220 gpio_request(gpio, "FM_RST");
221 gpio_direction_output(gpio, 1);
222}
223
224/* TSP */
225static struct qt602240_platform_data qt602240_platform_data = {
226 .x_line = 17,
227 .y_line = 11,
228 .x_size = 800,
229 .y_size = 480,
230 .blen = 0x21,
231 .threshold = 0x28,
232 .voltage = 2800000, /* 2.8V */
233 .orient = QT602240_DIAGONAL,
234};
235
236static struct s3c2410_platform_i2c i2c2_data __initdata = {
237 .flags = 0,
238 .bus_num = 2,
239 .slave_addr = 0x10,
240 .frequency = 400 * 1000,
241 .sda_delay = 100,
242};
243
244static struct i2c_board_info i2c2_devs[] __initdata = {
245 {
246 I2C_BOARD_INFO("qt602240_ts", 0x4a),
247 .platform_data = &qt602240_platform_data,
248 },
249};
250
251static void __init goni_tsp_init(void)
252{
253 int gpio;
254
255 gpio = S5PV210_GPJ1(3); /* XMSMADDR_11 */
256 gpio_request(gpio, "TSP_LDO_ON");
257 gpio_direction_output(gpio, 1);
258 gpio_export(gpio, 0);
259
260 gpio = S5PV210_GPJ0(5); /* XMSMADDR_5 */
261 gpio_request(gpio, "TSP_INT");
262
263 s5p_register_gpio_interrupt(gpio);
264 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
265 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
266 i2c2_devs[0].irq = gpio_to_irq(gpio);
267}
268
114/* MAX8998 regulators */ 269/* MAX8998 regulators */
115#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE) 270#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
116 271
272static struct regulator_consumer_supply goni_ldo5_consumers[] = {
273 REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
274};
275
117static struct regulator_init_data goni_ldo2_data = { 276static struct regulator_init_data goni_ldo2_data = {
118 .constraints = { 277 .constraints = {
119 .name = "VALIVE_1.1V", 278 .name = "VALIVE_1.1V",
@@ -153,6 +312,8 @@ static struct regulator_init_data goni_ldo5_data = {
153 .max_uV = 2800000, 312 .max_uV = 2800000,
154 .apply_uV = 1, 313 .apply_uV = 1,
155 }, 314 },
315 .num_consumer_supplies = ARRAY_SIZE(goni_ldo5_consumers),
316 .consumer_supplies = goni_ldo5_consumers,
156}; 317};
157 318
158static struct regulator_init_data goni_ldo6_data = { 319static struct regulator_init_data goni_ldo6_data = {
@@ -360,6 +521,119 @@ static struct max8998_platform_data goni_max8998_pdata = {
360}; 521};
361#endif 522#endif
362 523
524static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
525 {
526 .dev_name = "5-001a",
527 .supply = "DBVDD",
528 }, {
529 .dev_name = "5-001a",
530 .supply = "AVDD2",
531 }, {
532 .dev_name = "5-001a",
533 .supply = "CPVDD",
534 },
535};
536
537static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
538 {
539 .dev_name = "5-001a",
540 .supply = "SPKVDD1",
541 }, {
542 .dev_name = "5-001a",
543 .supply = "SPKVDD2",
544 },
545};
546
547static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
548 .constraints = {
549 .always_on = 1,
550 },
551 .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage0_supplies),
552 .consumer_supplies = wm8994_fixed_voltage0_supplies,
553};
554
555static struct regulator_init_data wm8994_fixed_voltage1_init_data = {
556 .constraints = {
557 .always_on = 1,
558 },
559 .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage1_supplies),
560 .consumer_supplies = wm8994_fixed_voltage1_supplies,
561};
562
563static struct fixed_voltage_config wm8994_fixed_voltage0_config = {
564 .supply_name = "VCC_1.8V_PDA",
565 .microvolts = 1800000,
566 .gpio = -EINVAL,
567 .init_data = &wm8994_fixed_voltage0_init_data,
568};
569
570static struct fixed_voltage_config wm8994_fixed_voltage1_config = {
571 .supply_name = "V_BAT",
572 .microvolts = 3700000,
573 .gpio = -EINVAL,
574 .init_data = &wm8994_fixed_voltage1_init_data,
575};
576
577static struct platform_device wm8994_fixed_voltage0 = {
578 .name = "reg-fixed-voltage",
579 .id = 0,
580 .dev = {
581 .platform_data = &wm8994_fixed_voltage0_config,
582 },
583};
584
585static struct platform_device wm8994_fixed_voltage1 = {
586 .name = "reg-fixed-voltage",
587 .id = 1,
588 .dev = {
589 .platform_data = &wm8994_fixed_voltage1_config,
590 },
591};
592
593static struct regulator_consumer_supply wm8994_avdd1_supply = {
594 .dev_name = "5-001a",
595 .supply = "AVDD1",
596};
597
598static struct regulator_consumer_supply wm8994_dcvdd_supply = {
599 .dev_name = "5-001a",
600 .supply = "DCVDD",
601};
602
603static struct regulator_init_data wm8994_ldo1_data = {
604 .constraints = {
605 .name = "AVDD1_3.0V",
606 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
607 },
608 .num_consumer_supplies = 1,
609 .consumer_supplies = &wm8994_avdd1_supply,
610};
611
612static struct regulator_init_data wm8994_ldo2_data = {
613 .constraints = {
614 .name = "DCVDD_1.0V",
615 },
616 .num_consumer_supplies = 1,
617 .consumer_supplies = &wm8994_dcvdd_supply,
618};
619
620static struct wm8994_pdata wm8994_platform_data = {
621 /* configure gpio1 function: 0x0001(Logic level input/output) */
622 .gpio_defaults[0] = 0x0001,
623 /* configure gpio3/4/5/7 function for AIF2 voice */
624 .gpio_defaults[2] = 0x8100,
625 .gpio_defaults[3] = 0x8100,
626 .gpio_defaults[4] = 0x8100,
627 .gpio_defaults[6] = 0x0100,
628 /* configure gpio8/9/10/11 function for AIF3 BT */
629 .gpio_defaults[7] = 0x8100,
630 .gpio_defaults[8] = 0x0100,
631 .gpio_defaults[9] = 0x0100,
632 .gpio_defaults[10] = 0x0100,
633 .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */
634 .ldo[1] = { 0, NULL, &wm8994_ldo2_data },
635};
636
363/* GPIO I2C PMIC */ 637/* GPIO I2C PMIC */
364#define AP_I2C_GPIO_PMIC_BUS_4 4 638#define AP_I2C_GPIO_PMIC_BUS_4 4
365static struct i2c_gpio_platform_data goni_i2c_gpio_pmic_data = { 639static struct i2c_gpio_platform_data goni_i2c_gpio_pmic_data = {
@@ -385,6 +659,29 @@ static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = {
385#endif 659#endif
386}; 660};
387 661
662/* GPIO I2C AP 1.8V */
663#define AP_I2C_GPIO_BUS_5 5
664static struct i2c_gpio_platform_data goni_i2c_gpio5_data = {
665 .sda_pin = S5PV210_MP05(3), /* XM0ADDR_11 */
666 .scl_pin = S5PV210_MP05(2), /* XM0ADDR_10 */
667};
668
669static struct platform_device goni_i2c_gpio5 = {
670 .name = "i2c-gpio",
671 .id = AP_I2C_GPIO_BUS_5,
672 .dev = {
673 .platform_data = &goni_i2c_gpio5_data,
674 },
675};
676
677static struct i2c_board_info i2c_gpio5_devs[] __initdata = {
678 {
679 /* CS/ADDR = low 0x34 (FYI: high = 0x36) */
680 I2C_BOARD_INFO("wm8994", 0x1a),
681 .platform_data = &wm8994_platform_data,
682 },
683};
684
388/* PMIC Power button */ 685/* PMIC Power button */
389static struct gpio_keys_button goni_gpio_keys_table[] = { 686static struct gpio_keys_button goni_gpio_keys_table[] = {
390 { 687 {
@@ -444,11 +741,37 @@ static struct s3c_sdhci_platdata goni_hsmmc2_data __initdata = {
444 .ext_cd_gpio_invert = 1, 741 .ext_cd_gpio_invert = 1,
445}; 742};
446 743
744static struct regulator_consumer_supply mmc2_supplies[] = {
745 REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
746};
747
748static struct regulator_init_data mmc2_fixed_voltage_init_data = {
749 .constraints = {
750 .name = "V_TF_2.8V",
751 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
752 },
753 .num_consumer_supplies = ARRAY_SIZE(mmc2_supplies),
754 .consumer_supplies = mmc2_supplies,
755};
756
757static struct fixed_voltage_config mmc2_fixed_voltage_config = {
758 .supply_name = "EXT_FLASH_EN",
759 .microvolts = 2800000,
760 .gpio = GONI_EXT_FLASH_EN,
761 .enable_high = true,
762 .init_data = &mmc2_fixed_voltage_init_data,
763};
764
765static struct platform_device mmc2_fixed_voltage = {
766 .name = "reg-fixed-voltage",
767 .id = 2,
768 .dev = {
769 .platform_data = &mmc2_fixed_voltage_config,
770 },
771};
772
447static void goni_setup_sdhci(void) 773static void goni_setup_sdhci(void)
448{ 774{
449 gpio_request(GONI_EXT_FLASH_EN, "FLASH_EN");
450 gpio_direction_output(GONI_EXT_FLASH_EN, 1);
451
452 s3c_sdhci0_set_platdata(&goni_hsmmc0_data); 775 s3c_sdhci0_set_platdata(&goni_hsmmc0_data);
453 s3c_sdhci1_set_platdata(&goni_hsmmc1_data); 776 s3c_sdhci1_set_platdata(&goni_hsmmc1_data);
454 s3c_sdhci2_set_platdata(&goni_hsmmc2_data); 777 s3c_sdhci2_set_platdata(&goni_hsmmc2_data);
@@ -457,7 +780,10 @@ static void goni_setup_sdhci(void)
457static struct platform_device *goni_devices[] __initdata = { 780static struct platform_device *goni_devices[] __initdata = {
458 &s3c_device_fb, 781 &s3c_device_fb,
459 &s5p_device_onenand, 782 &s5p_device_onenand,
783 &goni_spi_gpio,
460 &goni_i2c_gpio_pmic, 784 &goni_i2c_gpio_pmic,
785 &goni_i2c_gpio5,
786 &mmc2_fixed_voltage,
461 &goni_device_gpiokeys, 787 &goni_device_gpiokeys,
462 &s5p_device_fimc0, 788 &s5p_device_fimc0,
463 &s5p_device_fimc1, 789 &s5p_device_fimc1,
@@ -465,8 +791,24 @@ static struct platform_device *goni_devices[] __initdata = {
465 &s3c_device_hsmmc0, 791 &s3c_device_hsmmc0,
466 &s3c_device_hsmmc1, 792 &s3c_device_hsmmc1,
467 &s3c_device_hsmmc2, 793 &s3c_device_hsmmc2,
794 &s5pv210_device_iis0,
795 &s3c_device_usb_hsotg,
796 &samsung_device_keypad,
797 &s3c_device_i2c1,
798 &s3c_device_i2c2,
799 &wm8994_fixed_voltage0,
800 &wm8994_fixed_voltage1,
468}; 801};
469 802
803static void __init goni_sound_init(void)
804{
805 /* Ths main clock of WM8994 codec uses the output of CLKOUT pin.
806 * The CLKOUT[9:8] set to 0x3(XUSBXTI) of 0xE010E000(OTHERS)
807 * because it needs 24MHz clock to operate WM8994 codec.
808 */
809 __raw_writel(__raw_readl(S5P_OTHERS) | (0x3 << 8), S5P_OTHERS);
810}
811
470static void __init goni_map_io(void) 812static void __init goni_map_io(void)
471{ 813{
472 s5p_init_io(NULL, 0, S5P_VA_CHIPID); 814 s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -476,6 +818,20 @@ static void __init goni_map_io(void)
476 818
477static void __init goni_machine_init(void) 819static void __init goni_machine_init(void)
478{ 820{
821 /* Radio: call before I2C 1 registeration */
822 goni_radio_init();
823
824 /* I2C1 */
825 s3c_i2c1_set_platdata(NULL);
826 i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
827
828 /* TSP: call before I2C 2 registeration */
829 goni_tsp_init();
830
831 /* I2C2 */
832 s3c_i2c2_set_platdata(&i2c2_data);
833 i2c_register_board_info(2, i2c2_devs, ARRAY_SIZE(i2c2_devs));
834
479 /* PMIC */ 835 /* PMIC */
480 goni_pmic_init(); 836 goni_pmic_init();
481 i2c_register_board_info(AP_I2C_GPIO_PMIC_BUS_4, i2c_gpio_pmic_devs, 837 i2c_register_board_info(AP_I2C_GPIO_PMIC_BUS_4, i2c_gpio_pmic_devs,
@@ -483,9 +839,22 @@ static void __init goni_machine_init(void)
483 /* SDHCI */ 839 /* SDHCI */
484 goni_setup_sdhci(); 840 goni_setup_sdhci();
485 841
842 /* SOUND */
843 goni_sound_init();
844 i2c_register_board_info(AP_I2C_GPIO_BUS_5, i2c_gpio5_devs,
845 ARRAY_SIZE(i2c_gpio5_devs));
846
486 /* FB */ 847 /* FB */
487 s3c_fb_set_platdata(&goni_lcd_pdata); 848 s3c_fb_set_platdata(&goni_lcd_pdata);
488 849
850 /* SPI */
851 spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
852
853 /* KEYPAD */
854 samsung_keypad_set_platdata(&keypad_data);
855
856 clk_xusbxti.rate = 24000000;
857
489 platform_add_devices(goni_devices, ARRAY_SIZE(goni_devices)); 858 platform_add_devices(goni_devices, ARRAY_SIZE(goni_devices));
490} 859}
491 860
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index cea9bca79d88..0ad7924fe62e 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -28,6 +28,7 @@
28#include <plat/cpu.h> 28#include <plat/cpu.h>
29#include <plat/ata.h> 29#include <plat/ata.h>
30#include <plat/iic.h> 30#include <plat/iic.h>
31#include <plat/pm.h>
31 32
32/* Following are default values for UCON, ULCON and UFCON UART registers */ 33/* Following are default values for UCON, ULCON and UFCON UART registers */
33#define SMDKC110_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ 34#define SMDKC110_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -81,6 +82,7 @@ static struct s3c_ide_platdata smdkc110_ide_pdata __initdata = {
81static struct platform_device *smdkc110_devices[] __initdata = { 82static struct platform_device *smdkc110_devices[] __initdata = {
82 &s5pv210_device_iis0, 83 &s5pv210_device_iis0,
83 &s5pv210_device_ac97, 84 &s5pv210_device_ac97,
85 &s5pv210_device_spdif,
84 &s3c_device_cfcon, 86 &s3c_device_cfcon,
85 &s3c_device_i2c0, 87 &s3c_device_i2c0,
86 &s3c_device_i2c1, 88 &s3c_device_i2c1,
@@ -110,6 +112,8 @@ static void __init smdkc110_map_io(void)
110 112
111static void __init smdkc110_machine_init(void) 113static void __init smdkc110_machine_init(void)
112{ 114{
115 s3c_pm_init();
116
113 s3c_i2c0_set_platdata(NULL); 117 s3c_i2c0_set_platdata(NULL);
114 s3c_i2c1_set_platdata(NULL); 118 s3c_i2c1_set_platdata(NULL);
115 s3c_i2c2_set_platdata(NULL); 119 s3c_i2c2_set_platdata(NULL);
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index 83189ae9da9a..bcd7a5d53401 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -31,6 +31,7 @@
31#include <plat/ata.h> 31#include <plat/ata.h>
32#include <plat/iic.h> 32#include <plat/iic.h>
33#include <plat/keypad.h> 33#include <plat/keypad.h>
34#include <plat/pm.h>
34 35
35/* Following are default values for UCON, ULCON and UFCON UART registers */ 36/* Following are default values for UCON, ULCON and UFCON UART registers */
36#define SMDKV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ 37#define SMDKV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -103,6 +104,7 @@ static struct samsung_keypad_platdata smdkv210_keypad_data __initdata = {
103static struct platform_device *smdkv210_devices[] __initdata = { 104static struct platform_device *smdkv210_devices[] __initdata = {
104 &s5pv210_device_iis0, 105 &s5pv210_device_iis0,
105 &s5pv210_device_ac97, 106 &s5pv210_device_ac97,
107 &s5pv210_device_spdif,
106 &s3c_device_adc, 108 &s3c_device_adc,
107 &s3c_device_cfcon, 109 &s3c_device_cfcon,
108 &s3c_device_hsmmc0, 110 &s3c_device_hsmmc0,
@@ -145,6 +147,8 @@ static void __init smdkv210_map_io(void)
145 147
146static void __init smdkv210_machine_init(void) 148static void __init smdkv210_machine_init(void)
147{ 149{
150 s3c_pm_init();
151
148 samsung_keypad_set_platdata(&smdkv210_keypad_data); 152 samsung_keypad_set_platdata(&smdkv210_keypad_data);
149 s3c24xx_ts_set_platdata(&s3c_ts_platform); 153 s3c24xx_ts_set_platdata(&s3c_ts_platform);
150 154
diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c
new file mode 100644
index 000000000000..043c938806b0
--- /dev/null
+++ b/arch/arm/mach-s5pv210/mach-torbreck.c
@@ -0,0 +1,131 @@
1/* linux/arch/arm/mach-s5pv210/mach-torbreck.c
2 *
3 * Copyright (c) 2010 aESOP Community
4 * http://www.aesop.or.kr/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9*/
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <linux/i2c.h>
14#include <linux/init.h>
15#include <linux/serial_core.h>
16
17#include <asm/mach/arch.h>
18#include <asm/mach/map.h>
19#include <asm/setup.h>
20#include <asm/mach-types.h>
21
22#include <mach/map.h>
23#include <mach/regs-clock.h>
24
25#include <plat/regs-serial.h>
26#include <plat/s5pv210.h>
27#include <plat/devs.h>
28#include <plat/cpu.h>
29#include <plat/iic.h>
30
31/* Following are default values for UCON, ULCON and UFCON UART registers */
32#define TORBRECK_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
33 S3C2410_UCON_RXILEVEL | \
34 S3C2410_UCON_TXIRQMODE | \
35 S3C2410_UCON_RXIRQMODE | \
36 S3C2410_UCON_RXFIFO_TOI | \
37 S3C2443_UCON_RXERR_IRQEN)
38
39#define TORBRECK_ULCON_DEFAULT S3C2410_LCON_CS8
40
41#define TORBRECK_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
42 S5PV210_UFCON_TXTRIG4 | \
43 S5PV210_UFCON_RXTRIG4)
44
45static struct s3c2410_uartcfg torbreck_uartcfgs[] __initdata = {
46 [0] = {
47 .hwport = 0,
48 .flags = 0,
49 .ucon = TORBRECK_UCON_DEFAULT,
50 .ulcon = TORBRECK_ULCON_DEFAULT,
51 .ufcon = TORBRECK_UFCON_DEFAULT,
52 },
53 [1] = {
54 .hwport = 1,
55 .flags = 0,
56 .ucon = TORBRECK_UCON_DEFAULT,
57 .ulcon = TORBRECK_ULCON_DEFAULT,
58 .ufcon = TORBRECK_UFCON_DEFAULT,
59 },
60 [2] = {
61 .hwport = 2,
62 .flags = 0,
63 .ucon = TORBRECK_UCON_DEFAULT,
64 .ulcon = TORBRECK_ULCON_DEFAULT,
65 .ufcon = TORBRECK_UFCON_DEFAULT,
66 },
67 [3] = {
68 .hwport = 3,
69 .flags = 0,
70 .ucon = TORBRECK_UCON_DEFAULT,
71 .ulcon = TORBRECK_ULCON_DEFAULT,
72 .ufcon = TORBRECK_UFCON_DEFAULT,
73 },
74};
75
76static struct platform_device *torbreck_devices[] __initdata = {
77 &s5pv210_device_iis0,
78 &s3c_device_cfcon,
79 &s3c_device_hsmmc0,
80 &s3c_device_hsmmc1,
81 &s3c_device_hsmmc2,
82 &s3c_device_hsmmc3,
83 &s3c_device_i2c0,
84 &s3c_device_i2c1,
85 &s3c_device_i2c2,
86 &s3c_device_rtc,
87 &s3c_device_wdt,
88};
89
90static struct i2c_board_info torbreck_i2c_devs0[] __initdata = {
91 /* To Be Updated */
92};
93
94static struct i2c_board_info torbreck_i2c_devs1[] __initdata = {
95 /* To Be Updated */
96};
97
98static struct i2c_board_info torbreck_i2c_devs2[] __initdata = {
99 /* To Be Updated */
100};
101
102static void __init torbreck_map_io(void)
103{
104 s5p_init_io(NULL, 0, S5P_VA_CHIPID);
105 s3c24xx_init_clocks(24000000);
106 s3c24xx_init_uarts(torbreck_uartcfgs, ARRAY_SIZE(torbreck_uartcfgs));
107}
108
109static void __init torbreck_machine_init(void)
110{
111 s3c_i2c0_set_platdata(NULL);
112 s3c_i2c1_set_platdata(NULL);
113 s3c_i2c2_set_platdata(NULL);
114 i2c_register_board_info(0, torbreck_i2c_devs0,
115 ARRAY_SIZE(torbreck_i2c_devs0));
116 i2c_register_board_info(1, torbreck_i2c_devs1,
117 ARRAY_SIZE(torbreck_i2c_devs1));
118 i2c_register_board_info(2, torbreck_i2c_devs2,
119 ARRAY_SIZE(torbreck_i2c_devs2));
120
121 platform_add_devices(torbreck_devices, ARRAY_SIZE(torbreck_devices));
122}
123
124MACHINE_START(TORBRECK, "TORBRECK")
125 /* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */
126 .boot_params = S5P_PA_SDRAM + 0x100,
127 .init_irq = s5pv210_init_irq,
128 .map_io = torbreck_map_io,
129 .init_machine = torbreck_machine_init,
130 .timer = &s3c24xx_timer,
131MACHINE_END
diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c
new file mode 100644
index 000000000000..549d7924fd4c
--- /dev/null
+++ b/arch/arm/mach-s5pv210/pm.c
@@ -0,0 +1,166 @@
1/* linux/arch/arm/mach-s5pv210/pm.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * S5PV210 - Power Management support
7 *
8 * Based on arch/arm/mach-s3c2410/pm.c
9 * Copyright (c) 2006 Simtec Electronics
10 * Ben Dooks <ben@simtec.co.uk>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15*/
16
17#include <linux/init.h>
18#include <linux/suspend.h>
19#include <linux/io.h>
20
21#include <plat/cpu.h>
22#include <plat/pm.h>
23#include <plat/regs-timer.h>
24
25#include <mach/regs-irq.h>
26#include <mach/regs-clock.h>
27
28static struct sleep_save s5pv210_core_save[] = {
29 /* Clock source */
30 SAVE_ITEM(S5P_CLK_SRC0),
31 SAVE_ITEM(S5P_CLK_SRC1),
32 SAVE_ITEM(S5P_CLK_SRC2),
33 SAVE_ITEM(S5P_CLK_SRC3),
34 SAVE_ITEM(S5P_CLK_SRC4),
35 SAVE_ITEM(S5P_CLK_SRC5),
36 SAVE_ITEM(S5P_CLK_SRC6),
37
38 /* Clock source Mask */
39 SAVE_ITEM(S5P_CLK_SRC_MASK0),
40 SAVE_ITEM(S5P_CLK_SRC_MASK1),
41
42 /* Clock Divider */
43 SAVE_ITEM(S5P_CLK_DIV0),
44 SAVE_ITEM(S5P_CLK_DIV1),
45 SAVE_ITEM(S5P_CLK_DIV2),
46 SAVE_ITEM(S5P_CLK_DIV3),
47 SAVE_ITEM(S5P_CLK_DIV4),
48 SAVE_ITEM(S5P_CLK_DIV5),
49 SAVE_ITEM(S5P_CLK_DIV6),
50 SAVE_ITEM(S5P_CLK_DIV7),
51
52 /* Clock Main Gate */
53 SAVE_ITEM(S5P_CLKGATE_MAIN0),
54 SAVE_ITEM(S5P_CLKGATE_MAIN1),
55 SAVE_ITEM(S5P_CLKGATE_MAIN2),
56
57 /* Clock source Peri Gate */
58 SAVE_ITEM(S5P_CLKGATE_PERI0),
59 SAVE_ITEM(S5P_CLKGATE_PERI1),
60
61 /* Clock source SCLK Gate */
62 SAVE_ITEM(S5P_CLKGATE_SCLK0),
63 SAVE_ITEM(S5P_CLKGATE_SCLK1),
64
65 /* Clock IP Clock gate */
66 SAVE_ITEM(S5P_CLKGATE_IP0),
67 SAVE_ITEM(S5P_CLKGATE_IP1),
68 SAVE_ITEM(S5P_CLKGATE_IP2),
69 SAVE_ITEM(S5P_CLKGATE_IP3),
70 SAVE_ITEM(S5P_CLKGATE_IP4),
71
72 /* Clock Blcok and Bus gate */
73 SAVE_ITEM(S5P_CLKGATE_BLOCK),
74 SAVE_ITEM(S5P_CLKGATE_BUS0),
75
76 /* Clock ETC */
77 SAVE_ITEM(S5P_CLK_OUT),
78 SAVE_ITEM(S5P_MDNIE_SEL),
79
80 /* PWM Register */
81 SAVE_ITEM(S3C2410_TCFG0),
82 SAVE_ITEM(S3C2410_TCFG1),
83 SAVE_ITEM(S3C64XX_TINT_CSTAT),
84 SAVE_ITEM(S3C2410_TCON),
85 SAVE_ITEM(S3C2410_TCNTB(0)),
86 SAVE_ITEM(S3C2410_TCMPB(0)),
87 SAVE_ITEM(S3C2410_TCNTO(0)),
88};
89
90void s5pv210_cpu_suspend(void)
91{
92 unsigned long tmp;
93
94 /* issue the standby signal into the pm unit. Note, we
95 * issue a write-buffer drain just in case */
96
97 tmp = 0;
98
99 asm("b 1f\n\t"
100 ".align 5\n\t"
101 "1:\n\t"
102 "mcr p15, 0, %0, c7, c10, 5\n\t"
103 "mcr p15, 0, %0, c7, c10, 4\n\t"
104 "wfi" : : "r" (tmp));
105
106 /* we should never get past here */
107 panic("sleep resumed to originator?");
108}
109
110static void s5pv210_pm_prepare(void)
111{
112 unsigned int tmp;
113
114 /* ensure at least INFORM0 has the resume address */
115 __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
116
117 tmp = __raw_readl(S5P_SLEEP_CFG);
118 tmp &= ~(S5P_SLEEP_CFG_OSC_EN | S5P_SLEEP_CFG_USBOSC_EN);
119 __raw_writel(tmp, S5P_SLEEP_CFG);
120
121 /* WFI for SLEEP mode configuration by SYSCON */
122 tmp = __raw_readl(S5P_PWR_CFG);
123 tmp &= S5P_CFG_WFI_CLEAN;
124 tmp |= S5P_CFG_WFI_SLEEP;
125 __raw_writel(tmp, S5P_PWR_CFG);
126
127 /* SYSCON interrupt handling disable */
128 tmp = __raw_readl(S5P_OTHERS);
129 tmp |= S5P_OTHER_SYSC_INTOFF;
130 __raw_writel(tmp, S5P_OTHERS);
131
132 s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
133}
134
135static int s5pv210_pm_add(struct sys_device *sysdev)
136{
137 pm_cpu_prep = s5pv210_pm_prepare;
138 pm_cpu_sleep = s5pv210_cpu_suspend;
139
140 return 0;
141}
142
143static int s5pv210_pm_resume(struct sys_device *dev)
144{
145 u32 tmp;
146
147 tmp = __raw_readl(S5P_OTHERS);
148 tmp |= (S5P_OTHERS_RET_IO | S5P_OTHERS_RET_CF |\
149 S5P_OTHERS_RET_MMC | S5P_OTHERS_RET_UART);
150 __raw_writel(tmp , S5P_OTHERS);
151
152 s3c_pm_do_restore_core(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
153
154 return 0;
155}
156
157static struct sysdev_driver s5pv210_pm_driver = {
158 .add = s5pv210_pm_add,
159 .resume = s5pv210_pm_resume,
160};
161
162static __init int s5pv210_pm_drvinit(void)
163{
164 return sysdev_driver_register(&s5pv210_sysclass, &s5pv210_pm_driver);
165}
166arch_initcall(s5pv210_pm_drvinit);
diff --git a/arch/arm/mach-s5pv210/setup-fb-24bpp.c b/arch/arm/mach-s5pv210/setup-fb-24bpp.c
index 928cf1f125fa..e932ebfac56d 100644
--- a/arch/arm/mach-s5pv210/setup-fb-24bpp.c
+++ b/arch/arm/mach-s5pv210/setup-fb-24bpp.c
@@ -21,33 +21,21 @@
21#include <mach/regs-clock.h> 21#include <mach/regs-clock.h>
22#include <plat/gpio-cfg.h> 22#include <plat/gpio-cfg.h>
23 23
24void s5pv210_fb_gpio_setup_24bpp(void) 24static void s5pv210_fb_cfg_gpios(unsigned int base, unsigned int nr)
25{ 25{
26 unsigned int gpio = 0; 26 s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(2));
27
28 for (gpio = S5PV210_GPF0(0); gpio <= S5PV210_GPF0(7); gpio++) {
29 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
30 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
31 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
32 }
33 27
34 for (gpio = S5PV210_GPF1(0); gpio <= S5PV210_GPF1(7); gpio++) { 28 for (; nr > 0; nr--, base++)
35 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); 29 s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4);
36 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); 30}
37 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
38 }
39 31
40 for (gpio = S5PV210_GPF2(0); gpio <= S5PV210_GPF2(7); gpio++) {
41 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
42 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
43 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
44 }
45 32
46 for (gpio = S5PV210_GPF3(0); gpio <= S5PV210_GPF3(3); gpio++) { 33void s5pv210_fb_gpio_setup_24bpp(void)
47 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); 34{
48 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); 35 s5pv210_fb_cfg_gpios(S5PV210_GPF0(0), 8);
49 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); 36 s5pv210_fb_cfg_gpios(S5PV210_GPF1(0), 8);
50 } 37 s5pv210_fb_cfg_gpios(S5PV210_GPF2(0), 8);
38 s5pv210_fb_cfg_gpios(S5PV210_GPF3(0), 4);
51 39
52 /* Set DISPLAY_CONTROL register for Display path selection. 40 /* Set DISPLAY_CONTROL register for Display path selection.
53 * 41 *
diff --git a/arch/arm/mach-s5pv210/setup-i2c0.c b/arch/arm/mach-s5pv210/setup-i2c0.c
index d38f7cb7e662..0f1cc3a1c1e8 100644
--- a/arch/arm/mach-s5pv210/setup-i2c0.c
+++ b/arch/arm/mach-s5pv210/setup-i2c0.c
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */
23 23
24void s3c_i2c0_cfg_gpio(struct platform_device *dev) 24void s3c_i2c0_cfg_gpio(struct platform_device *dev)
25{ 25{
26 s3c_gpio_cfgpin(S5PV210_GPD1(0), S3C_GPIO_SFN(2)); 26 s3c_gpio_cfgall_range(S5PV210_GPD1(0), 2,
27 s3c_gpio_setpull(S5PV210_GPD1(0), S3C_GPIO_PULL_UP); 27 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
28 s3c_gpio_cfgpin(S5PV210_GPD1(1), S3C_GPIO_SFN(2));
29 s3c_gpio_setpull(S5PV210_GPD1(1), S3C_GPIO_PULL_UP);
30} 28}
diff --git a/arch/arm/mach-s5pv210/setup-i2c1.c b/arch/arm/mach-s5pv210/setup-i2c1.c
index 148bb7857d89..f61365a34c56 100644
--- a/arch/arm/mach-s5pv210/setup-i2c1.c
+++ b/arch/arm/mach-s5pv210/setup-i2c1.c
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */
23 23
24void s3c_i2c1_cfg_gpio(struct platform_device *dev) 24void s3c_i2c1_cfg_gpio(struct platform_device *dev)
25{ 25{
26 s3c_gpio_cfgpin(S5PV210_GPD1(2), S3C_GPIO_SFN(2)); 26 s3c_gpio_cfgall_range(S5PV210_GPD1(2), 2,
27 s3c_gpio_setpull(S5PV210_GPD1(2), S3C_GPIO_PULL_UP); 27 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
28 s3c_gpio_cfgpin(S5PV210_GPD1(3), S3C_GPIO_SFN(2));
29 s3c_gpio_setpull(S5PV210_GPD1(3), S3C_GPIO_PULL_UP);
30} 28}
diff --git a/arch/arm/mach-s5pv210/setup-i2c2.c b/arch/arm/mach-s5pv210/setup-i2c2.c
index 2396cb8c373e..2f91b5cefbc6 100644
--- a/arch/arm/mach-s5pv210/setup-i2c2.c
+++ b/arch/arm/mach-s5pv210/setup-i2c2.c
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */
23 23
24void s3c_i2c2_cfg_gpio(struct platform_device *dev) 24void s3c_i2c2_cfg_gpio(struct platform_device *dev)
25{ 25{
26 s3c_gpio_cfgpin(S5PV210_GPD1(4), S3C_GPIO_SFN(2)); 26 s3c_gpio_cfgall_range(S5PV210_GPD1(4), 2,
27 s3c_gpio_setpull(S5PV210_GPD1(4), S3C_GPIO_PULL_UP); 27 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
28 s3c_gpio_cfgpin(S5PV210_GPD1(5), S3C_GPIO_SFN(2));
29 s3c_gpio_setpull(S5PV210_GPD1(5), S3C_GPIO_PULL_UP);
30} 28}
diff --git a/arch/arm/mach-s5pv210/setup-ide.c b/arch/arm/mach-s5pv210/setup-ide.c
index b558b1cc8d60..ea123d546bd2 100644
--- a/arch/arm/mach-s5pv210/setup-ide.c
+++ b/arch/arm/mach-s5pv210/setup-ide.c
@@ -15,36 +15,25 @@
15 15
16#include <plat/gpio-cfg.h> 16#include <plat/gpio-cfg.h>
17 17
18static void s5pv210_ide_cfg_gpios(unsigned int base, unsigned int nr)
19{
20 s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(4));
21
22 for (; nr > 0; nr--, base++)
23 s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4);
24}
25
18void s5pv210_ide_setup_gpio(void) 26void s5pv210_ide_setup_gpio(void)
19{ 27{
20 unsigned int gpio = 0; 28 /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */
21 29 s5pv210_ide_cfg_gpios(S5PV210_GPJ0(0), 8);
22 for (gpio = S5PV210_GPJ0(0); gpio <= S5PV210_GPJ0(7); gpio++) { 30
23 /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, 31 /* CF_Data[0 - 7] */
24 CF_DMACK */ 32 s5pv210_ide_cfg_gpios(S5PV210_GPJ2(0), 8);
25 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); 33
26 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); 34 /* CF_Data[8 - 15] */
27 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); 35 s5pv210_ide_cfg_gpios(S5PV210_GPJ3(0), 8);
28 } 36
29 37 /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */
30 for (gpio = S5PV210_GPJ2(0); gpio <= S5PV210_GPJ2(7); gpio++) { 38 s5pv210_ide_cfg_gpios(S5PV210_GPJ4(0), 4);
31 /*CF_Data[0 - 7] */
32 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
33 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
34 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
35 }
36
37 for (gpio = S5PV210_GPJ3(0); gpio <= S5PV210_GPJ3(7); gpio++) {
38 /* CF_Data[8 - 15] */
39 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
40 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
41 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
42 }
43
44 for (gpio = S5PV210_GPJ4(0); gpio <= S5PV210_GPJ4(3); gpio++) {
45 /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */
46 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
47 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
48 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
49 }
50} 39}
diff --git a/arch/arm/mach-s5pv210/setup-keypad.c b/arch/arm/mach-s5pv210/setup-keypad.c
index 37b2790aafc3..c56420a52f48 100644
--- a/arch/arm/mach-s5pv210/setup-keypad.c
+++ b/arch/arm/mach-s5pv210/setup-keypad.c
@@ -16,19 +16,9 @@
16 16
17void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) 17void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
18{ 18{
19 unsigned int gpio, end;
20
21 /* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */ 19 /* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */
22 end = S5PV210_GPH3(rows); 20 s3c_gpio_cfgrange_nopull(S5PV210_GPH3(0), rows, S3C_GPIO_SFN(3));
23 for (gpio = S5PV210_GPH3(0); gpio < end; gpio++) {
24 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
25 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
26 }
27 21
28 /* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */ 22 /* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */
29 end = S5PV210_GPH2(cols); 23 s3c_gpio_cfgrange_nopull(S5PV210_GPH2(0), cols, S3C_GPIO_SFN(3));
30 for (gpio = S5PV210_GPH2(0); gpio < end; gpio++) {
31 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
32 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
33 }
34} 24}
diff --git a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
index b18587b1ec58..746777d56df9 100644
--- a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
+++ b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
@@ -26,26 +26,17 @@
26void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) 26void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
27{ 27{
28 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; 28 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
29 unsigned int gpio;
30 29
31 /* Set all the necessary GPG0/GPG1 pins to special-function 2 */ 30 /* Set all the necessary GPG0/GPG1 pins to special-function 2 */
32 for (gpio = S5PV210_GPG0(0); gpio < S5PV210_GPG0(2); gpio++) { 31 s3c_gpio_cfgrange_nopull(S5PV210_GPG0(0), 2, S3C_GPIO_SFN(2));
33 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); 32
34 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
35 }
36 switch (width) { 33 switch (width) {
37 case 8: 34 case 8:
38 /* GPG1[3:6] special-funtion 3 */ 35 /* GPG1[3:6] special-funtion 3 */
39 for (gpio = S5PV210_GPG1(3); gpio <= S5PV210_GPG1(6); gpio++) { 36 s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(3));
40 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
41 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
42 }
43 case 4: 37 case 4:
44 /* GPG0[3:6] special-funtion 2 */ 38 /* GPG0[3:6] special-funtion 2 */
45 for (gpio = S5PV210_GPG0(3); gpio <= S5PV210_GPG0(6); gpio++) { 39 s3c_gpio_cfgrange_nopull(S5PV210_GPG0(3), 4, S3C_GPIO_SFN(2));
46 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
47 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
48 }
49 default: 40 default:
50 break; 41 break;
51 } 42 }
@@ -59,19 +50,12 @@ void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
59void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) 50void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
60{ 51{
61 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; 52 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
62 unsigned int gpio;
63 53
64 /* Set all the necessary GPG1[0:1] pins to special-function 2 */ 54 /* Set all the necessary GPG1[0:1] pins to special-function 2 */
65 for (gpio = S5PV210_GPG1(0); gpio < S5PV210_GPG1(2); gpio++) { 55 s3c_gpio_cfgrange_nopull(S5PV210_GPG1(0), 2, S3C_GPIO_SFN(2));
66 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
67 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
68 }
69 56
70 /* Data pin GPG1[3:6] to special-function 2 */ 57 /* Data pin GPG1[3:6] to special-function 2 */
71 for (gpio = S5PV210_GPG1(3); gpio <= S5PV210_GPG1(6); gpio++) { 58 s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(2));
72 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
73 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
74 }
75 59
76 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { 60 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
77 s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP); 61 s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP);
@@ -82,27 +66,17 @@ void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
82void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) 66void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
83{ 67{
84 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; 68 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
85 unsigned int gpio;
86 69
87 /* Set all the necessary GPG2[0:1] pins to special-function 2 */ 70 /* Set all the necessary GPG2[0:1] pins to special-function 2 */
88 for (gpio = S5PV210_GPG2(0); gpio < S5PV210_GPG2(2); gpio++) { 71 s3c_gpio_cfgrange_nopull(S5PV210_GPG2(0), 2, S3C_GPIO_SFN(2));
89 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
90 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
91 }
92 72
93 switch (width) { 73 switch (width) {
94 case 8: 74 case 8:
95 /* Data pin GPG3[3:6] to special-function 3 */ 75 /* Data pin GPG3[3:6] to special-function 3 */
96 for (gpio = S5PV210_GPG3(3); gpio <= S5PV210_GPG3(6); gpio++) { 76 s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(3));
97 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
98 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
99 }
100 case 4: 77 case 4:
101 /* Data pin GPG2[3:6] to special-function 2 */ 78 /* Data pin GPG2[3:6] to special-function 2 */
102 for (gpio = S5PV210_GPG2(3); gpio <= S5PV210_GPG2(6); gpio++) { 79 s3c_gpio_cfgrange_nopull(S5PV210_GPG2(3), 4, S3C_GPIO_SFN(2));
103 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
104 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
105 }
106 default: 80 default:
107 break; 81 break;
108 } 82 }
@@ -116,19 +90,12 @@ void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
116void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width) 90void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
117{ 91{
118 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; 92 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
119 unsigned int gpio;
120 93
121 /* Set all the necessary GPG3[0:2] pins to special-function 2 */ 94 /* Set all the necessary GPG3[0:1] pins to special-function 2 */
122 for (gpio = S5PV210_GPG3(0); gpio < S5PV210_GPG3(2); gpio++) { 95 s3c_gpio_cfgrange_nopull(S5PV210_GPG3(0), 2, S3C_GPIO_SFN(2));
123 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
124 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
125 }
126 96
127 /* Data pin GPG3[3:6] to special-function 2 */ 97 /* Data pin GPG3[3:6] to special-function 2 */
128 for (gpio = S5PV210_GPG3(3); gpio <= S5PV210_GPG3(6); gpio++) { 98 s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(2));
129 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
130 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
131 }
132 99
133 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { 100 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
134 s3c_gpio_setpull(S5PV210_GPG3(2), S3C_GPIO_PULL_UP); 101 s3c_gpio_setpull(S5PV210_GPG3(2), S3C_GPIO_PULL_UP);
diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S
new file mode 100644
index 000000000000..d4d222b716b4
--- /dev/null
+++ b/arch/arm/mach-s5pv210/sleep.S
@@ -0,0 +1,170 @@
1/* linux/arch/arm/plat-s5p/sleep.S
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * S5PV210 power Manager (Suspend-To-RAM) support
7 * Based on S3C2410 sleep code by:
8 * Ben Dooks, (c) 2004 Simtec Electronics
9 *
10 * Based on PXA/SA1100 sleep code by:
11 * Nicolas Pitre, (c) 2002 Monta Vista Software Inc
12 * Cliff Brake, (c) 2001
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27*/
28
29#include <linux/linkage.h>
30#include <asm/assembler.h>
31#include <asm/memory.h>
32
33 .text
34
35 /* s3c_cpu_save
36 *
37 * entry:
38 * r0 = save address (virtual addr of s3c_sleep_save_phys)
39 */
40
41ENTRY(s3c_cpu_save)
42
43 stmfd sp!, { r3 - r12, lr }
44
45 mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
46 mrc p15, 0, r5, c3, c0, 0 @ Domain ID
47 mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
48 mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
49 mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control
50 mrc p15, 0, r9, c1, c0, 0 @ Control register
51 mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register
52 mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls
53 mrc p15, 0, r12, c10, c2, 0 @ Read PRRR
54 mrc p15, 0, r3, c10, c2, 1 @ READ NMRR
55
56 stmia r0, { r3 - r13 }
57
58 bl s3c_pm_cb_flushcache
59
60 ldr r0, =pm_cpu_sleep
61 ldr r0, [ r0 ]
62 mov pc, r0
63
64resume_with_mmu:
65 /*
66 * After MMU is turned on, restore the previous MMU table.
67 */
68 ldr r9 , =(PAGE_OFFSET - PHYS_OFFSET)
69 add r4, r4, r9
70 str r12, [r4]
71
72 ldmfd sp!, { r3 - r12, pc }
73
74 .ltorg
75
76 .data
77
78 .global s3c_sleep_save_phys
79s3c_sleep_save_phys:
80 .word 0
81
82 /* sleep magic, to allow the bootloader to check for an valid
83 * image to resume to. Must be the first word before the
84 * s3c_cpu_resume entry.
85 */
86
87 .word 0x2bedf00d
88
89 /* s3c_cpu_resume
90 *
91 * resume code entry for bootloader to call
92 *
93 * we must put this code here in the data segment as we have no
94 * other way of restoring the stack pointer after sleep, and we
95 * must not write to the code segment (code is read-only)
96 */
97
98ENTRY(s3c_cpu_resume)
99 mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
100 msr cpsr_c, r0
101
102 mov r1, #0
103 mcr p15, 0, r1, c8, c7, 0 @ invalidate TLBs
104 mcr p15, 0, r1, c7, c5, 0 @ invalidate I Cache
105
106 ldr r0, s3c_sleep_save_phys @ address of restore block
107 ldmia r0, { r3 - r13 }
108
109 mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
110 mcr p15, 0, r5, c3, c0, 0 @ Domain ID
111
112 mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control
113 mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
114 mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
115
116 mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register
117
118 mov r0, #0
119 mcr p15, 0, r0, c8, c7, 0 @ Invalidate I & D TLB
120
121 mov r0, #0 @ restore copro access
122 mcr p15, 0, r11, c1, c0, 2 @ Co-processor access
123 mcr p15, 0, r0, c7, c5, 4
124
125 mcr p15, 0, r12, c10, c2, 0 @ write PRRR
126 mcr p15, 0, r3, c10, c2, 1 @ write NMRR
127
128 /*
129 * In Cortex-A8, when MMU is turned on, the pipeline is flushed.
130 * And there are no valid entries in the MMU table at this point.
131 * So before turning on the MMU, the MMU entry for the DRAM address
132 * range is added. After the MMU is turned on, the other entries
133 * in the MMU table will be restored.
134 */
135
136 /* r6 = Translation Table BASE0 */
137 mov r4, r6
138 mov r4, r4, LSR #14
139 mov r4, r4, LSL #14
140
141 /* Load address for adding to MMU table list */
142 ldr r11, =0xE010F000 @ INFORM0 reg.
143 ldr r10, [r11, #0]
144 mov r10, r10, LSR #18
145 bic r10, r10, #0x3
146 orr r4, r4, r10
147
148 /* Calculate MMU table entry */
149 mov r10, r10, LSL #18
150 ldr r5, =0x40E
151 orr r10, r10, r5
152
153 /* Back up originally data */
154 ldr r12, [r4]
155
156 /* Add calculated MMU table entry into MMU table list */
157 str r10, [r4]
158
159 ldr r2, =resume_with_mmu
160 mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc
161
162 nop
163 nop
164 nop
165 nop
166 nop @ second-to-last before mmu
167
168 mov pc, r2 @ go back to virtual address
169
170 .ltorg
diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig
index 331b5bd97aba..1150b360f38c 100644
--- a/arch/arm/mach-s5pv310/Kconfig
+++ b/arch/arm/mach-s5pv310/Kconfig
@@ -11,7 +11,6 @@ if ARCH_S5PV310
11 11
12config CPU_S5PV310 12config CPU_S5PV310
13 bool 13 bool
14 select PLAT_S5P
15 help 14 help
16 Enable S5PV310 CPU support 15 Enable S5PV310 CPU support
17 16
@@ -25,21 +24,105 @@ config S5PV310_SETUP_I2C2
25 help 24 help
26 Common setup code for i2c bus 2. 25 Common setup code for i2c bus 2.
27 26
27config S5PV310_SETUP_I2C3
28 bool
29 help
30 Common setup code for i2c bus 3.
31
32config S5PV310_SETUP_I2C4
33 bool
34 help
35 Common setup code for i2c bus 4.
36
37config S5PV310_SETUP_I2C5
38 bool
39 help
40 Common setup code for i2c bus 5.
41
42config S5PV310_SETUP_I2C6
43 bool
44 help
45 Common setup code for i2c bus 6.
46
47config S5PV310_SETUP_I2C7
48 bool
49 help
50 Common setup code for i2c bus 7.
51
52config S5PV310_SETUP_SDHCI
53 bool
54 select S5PV310_SETUP_SDHCI_GPIO
55 help
56 Internal helper functions for S5PV310 based SDHCI systems.
57
58config S5PV310_SETUP_SDHCI_GPIO
59 bool
60 help
61 Common setup code for SDHCI gpio.
62
28# machine support 63# machine support
29 64
30config MACH_SMDKV310 65menu "S5PC210 Machines"
31 bool "SMDKV310" 66
67config MACH_SMDKC210
68 bool "SMDKC210"
32 select CPU_S5PV310 69 select CPU_S5PV310
33 select ARCH_SPARSEMEM_ENABLE 70 select S3C_DEV_RTC
71 select S3C_DEV_WDT
72 select S3C_DEV_HSMMC
73 select S3C_DEV_HSMMC1
74 select S3C_DEV_HSMMC2
75 select S3C_DEV_HSMMC3
76 select S5PV310_SETUP_SDHCI
34 help 77 help
35 Machine support for Samsung SMDKV310 78 Machine support for Samsung SMDKC210
79 S5PC210(MCP) is one of package option of S5PV310
36 80
37config MACH_UNIVERSAL_C210 81config MACH_UNIVERSAL_C210
38 bool "Mobile UNIVERSAL_C210 Board" 82 bool "Mobile UNIVERSAL_C210 Board"
39 select CPU_S5PV310 83 select CPU_S5PV310
40 select ARCH_SPARSEMEM_ENABLE 84 select S5P_DEV_ONENAND
85 select S3C_DEV_I2C1
86 select S5PV310_SETUP_I2C1
41 help 87 help
42 Machine support for Samsung Mobile Universal S5PC210 Reference 88 Machine support for Samsung Mobile Universal S5PC210 Reference
43 Board. S5PC210(MCP) is one of package option of S5PV310 89 Board. S5PC210(MCP) is one of package option of S5PV310
44 90
91endmenu
92
93menu "S5PV310 Machines"
94
95config MACH_SMDKV310
96 bool "SMDKV310"
97 select CPU_S5PV310
98 select S3C_DEV_RTC
99 select S3C_DEV_WDT
100 select S3C_DEV_HSMMC
101 select S3C_DEV_HSMMC1
102 select S3C_DEV_HSMMC2
103 select S3C_DEV_HSMMC3
104 select S5PV310_SETUP_SDHCI
105 help
106 Machine support for Samsung SMDKV310
107
108endmenu
109
110comment "Configuration for HSMMC bus width"
111
112menu "Use 8-bit bus width"
113
114config S5PV310_SDHCI_CH0_8BIT
115 bool "Channel 0 with 8-bit bus"
116 help
117 Support HSMMC Channel 0 8-bit bus.
118 If selected, Channel 1 is disabled.
119
120config S5PV310_SDHCI_CH2_8BIT
121 bool "Channel 2 with 8-bit bus"
122 help
123 Support HSMMC Channel 2 8-bit bus.
124 If selected, Channel 3 is disabled.
125
126endmenu
127
45endif 128endif
diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile
index d5b51c72340f..84afc64e7c01 100644
--- a/arch/arm/mach-s5pv310/Makefile
+++ b/arch/arm/mach-s5pv310/Makefile
@@ -13,7 +13,7 @@ obj- :=
13# Core support for S5PV310 system 13# Core support for S5PV310 system
14 14
15obj-$(CONFIG_CPU_S5PV310) += cpu.o init.o clock.o irq-combiner.o 15obj-$(CONFIG_CPU_S5PV310) += cpu.o init.o clock.o irq-combiner.o
16obj-$(CONFIG_CPU_S5PV310) += setup-i2c0.o time.o 16obj-$(CONFIG_CPU_S5PV310) += setup-i2c0.o time.o gpiolib.o irq-eint.o
17 17
18obj-$(CONFIG_SMP) += platsmp.o headsmp.o 18obj-$(CONFIG_SMP) += platsmp.o headsmp.o
19obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o 19obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
@@ -21,6 +21,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
21 21
22# machine support 22# machine support
23 23
24obj-$(CONFIG_MACH_SMDKC210) += mach-smdkc210.o
24obj-$(CONFIG_MACH_SMDKV310) += mach-smdkv310.o 25obj-$(CONFIG_MACH_SMDKV310) += mach-smdkv310.o
25obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o 26obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o
26 27
@@ -28,3 +29,10 @@ obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o
28 29
29obj-$(CONFIG_S5PV310_SETUP_I2C1) += setup-i2c1.o 30obj-$(CONFIG_S5PV310_SETUP_I2C1) += setup-i2c1.o
30obj-$(CONFIG_S5PV310_SETUP_I2C2) += setup-i2c2.o 31obj-$(CONFIG_S5PV310_SETUP_I2C2) += setup-i2c2.o
32obj-$(CONFIG_S5PV310_SETUP_I2C3) += setup-i2c3.o
33obj-$(CONFIG_S5PV310_SETUP_I2C4) += setup-i2c4.o
34obj-$(CONFIG_S5PV310_SETUP_I2C5) += setup-i2c5.o
35obj-$(CONFIG_S5PV310_SETUP_I2C6) += setup-i2c6.o
36obj-$(CONFIG_S5PV310_SETUP_I2C7) += setup-i2c7.o
37obj-$(CONFIG_S5PV310_SETUP_SDHCI) += setup-sdhci.o
38obj-$(CONFIG_S5PV310_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
index 26a0f03df8ea..58c9d33f36fe 100644
--- a/arch/arm/mach-s5pv310/clock.c
+++ b/arch/arm/mach-s5pv310/clock.c
@@ -30,16 +30,92 @@ static struct clk clk_sclk_hdmi27m = {
30 .rate = 27000000, 30 .rate = 27000000,
31}; 31};
32 32
33static struct clk clk_sclk_hdmiphy = {
34 .name = "sclk_hdmiphy",
35 .id = -1,
36};
37
38static struct clk clk_sclk_usbphy0 = {
39 .name = "sclk_usbphy0",
40 .id = -1,
41 .rate = 27000000,
42};
43
44static struct clk clk_sclk_usbphy1 = {
45 .name = "sclk_usbphy1",
46 .id = -1,
47};
48
49static int s5pv310_clksrc_mask_top_ctrl(struct clk *clk, int enable)
50{
51 return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
52}
53
54static int s5pv310_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
55{
56 return s5p_gatectrl(S5P_CLKSRC_MASK_CAM, clk, enable);
57}
58
59static int s5pv310_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
60{
61 return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable);
62}
63
64static int s5pv310_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
65{
66 return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable);
67}
68
69static int s5pv310_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
70{
71 return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable);
72}
73
33static int s5pv310_clksrc_mask_peril0_ctrl(struct clk *clk, int enable) 74static int s5pv310_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
34{ 75{
35 return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable); 76 return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable);
36} 77}
37 78
79static int s5pv310_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
80{
81 return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable);
82}
83
84static int s5pv310_clk_ip_cam_ctrl(struct clk *clk, int enable)
85{
86 return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
87}
88
89static int s5pv310_clk_ip_image_ctrl(struct clk *clk, int enable)
90{
91 return s5p_gatectrl(S5P_CLKGATE_IP_IMAGE, clk, enable);
92}
93
94static int s5pv310_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
95{
96 return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable);
97}
98
99static int s5pv310_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
100{
101 return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable);
102}
103
104static int s5pv310_clk_ip_fsys_ctrl(struct clk *clk, int enable)
105{
106 return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable);
107}
108
38static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable) 109static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable)
39{ 110{
40 return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable); 111 return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
41} 112}
42 113
114static int s5pv310_clk_ip_perir_ctrl(struct clk *clk, int enable)
115{
116 return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
117}
118
43/* Core list of CMU_CPU side */ 119/* Core list of CMU_CPU side */
44 120
45static struct clksrc_clk clk_mout_apll = { 121static struct clksrc_clk clk_mout_apll = {
@@ -79,7 +155,7 @@ static struct clksrc_clk clk_mout_mpll = {
79}; 155};
80 156
81static struct clk *clkset_moutcore_list[] = { 157static struct clk *clkset_moutcore_list[] = {
82 [0] = &clk_sclk_apll.clk, 158 [0] = &clk_mout_apll.clk,
83 [1] = &clk_mout_mpll.clk, 159 [1] = &clk_mout_mpll.clk,
84}; 160};
85 161
@@ -150,24 +226,6 @@ static struct clksrc_clk clk_periphclk = {
150 .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 }, 226 .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
151}; 227};
152 228
153static struct clksrc_clk clk_atclk = {
154 .clk = {
155 .name = "atclk",
156 .id = -1,
157 .parent = &clk_moutcore.clk,
158 },
159 .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 16, .size = 3 },
160};
161
162static struct clksrc_clk clk_pclk_dbg = {
163 .clk = {
164 .name = "pclk_dbg",
165 .id = -1,
166 .parent = &clk_atclk.clk,
167 },
168 .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 20, .size = 3 },
169};
170
171/* Core list of CMU_CORE side */ 229/* Core list of CMU_CORE side */
172 230
173static struct clk *clkset_corebus_list[] = { 231static struct clk *clkset_corebus_list[] = {
@@ -241,7 +299,7 @@ static struct clk *clkset_aclk_top_list[] = {
241 [1] = &clk_sclk_apll.clk, 299 [1] = &clk_sclk_apll.clk,
242}; 300};
243 301
244static struct clksrc_sources clkset_aclk_200 = { 302static struct clksrc_sources clkset_aclk = {
245 .sources = clkset_aclk_top_list, 303 .sources = clkset_aclk_top_list,
246 .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), 304 .nr_sources = ARRAY_SIZE(clkset_aclk_top_list),
247}; 305};
@@ -251,52 +309,37 @@ static struct clksrc_clk clk_aclk_200 = {
251 .name = "aclk_200", 309 .name = "aclk_200",
252 .id = -1, 310 .id = -1,
253 }, 311 },
254 .sources = &clkset_aclk_200, 312 .sources = &clkset_aclk,
255 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 }, 313 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
256 .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 }, 314 .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 },
257}; 315};
258 316
259static struct clksrc_sources clkset_aclk_100 = {
260 .sources = clkset_aclk_top_list,
261 .nr_sources = ARRAY_SIZE(clkset_aclk_top_list),
262};
263
264static struct clksrc_clk clk_aclk_100 = { 317static struct clksrc_clk clk_aclk_100 = {
265 .clk = { 318 .clk = {
266 .name = "aclk_100", 319 .name = "aclk_100",
267 .id = -1, 320 .id = -1,
268 }, 321 },
269 .sources = &clkset_aclk_100, 322 .sources = &clkset_aclk,
270 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 }, 323 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
271 .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 }, 324 .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 },
272}; 325};
273 326
274static struct clksrc_sources clkset_aclk_160 = {
275 .sources = clkset_aclk_top_list,
276 .nr_sources = ARRAY_SIZE(clkset_aclk_top_list),
277};
278
279static struct clksrc_clk clk_aclk_160 = { 327static struct clksrc_clk clk_aclk_160 = {
280 .clk = { 328 .clk = {
281 .name = "aclk_160", 329 .name = "aclk_160",
282 .id = -1, 330 .id = -1,
283 }, 331 },
284 .sources = &clkset_aclk_160, 332 .sources = &clkset_aclk,
285 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 }, 333 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
286 .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 }, 334 .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
287}; 335};
288 336
289static struct clksrc_sources clkset_aclk_133 = {
290 .sources = clkset_aclk_top_list,
291 .nr_sources = ARRAY_SIZE(clkset_aclk_top_list),
292};
293
294static struct clksrc_clk clk_aclk_133 = { 337static struct clksrc_clk clk_aclk_133 = {
295 .clk = { 338 .clk = {
296 .name = "aclk_133", 339 .name = "aclk_133",
297 .id = -1, 340 .id = -1,
298 }, 341 },
299 .sources = &clkset_aclk_133, 342 .sources = &clkset_aclk,
300 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 }, 343 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
301 .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 }, 344 .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 },
302}; 345};
@@ -315,6 +358,8 @@ static struct clksrc_clk clk_vpllsrc = {
315 .clk = { 358 .clk = {
316 .name = "vpll_src", 359 .name = "vpll_src",
317 .id = -1, 360 .id = -1,
361 .enable = s5pv310_clksrc_mask_top_ctrl,
362 .ctrlbit = (1 << 0),
318 }, 363 },
319 .sources = &clkset_vpllsrc, 364 .sources = &clkset_vpllsrc,
320 .reg_src = { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 }, 365 .reg_src = { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 },
@@ -346,7 +391,175 @@ static struct clk init_clocks_disable[] = {
346 .parent = &clk_aclk_100.clk, 391 .parent = &clk_aclk_100.clk,
347 .enable = s5pv310_clk_ip_peril_ctrl, 392 .enable = s5pv310_clk_ip_peril_ctrl,
348 .ctrlbit = (1<<24), 393 .ctrlbit = (1<<24),
349 } 394 }, {
395 .name = "csis",
396 .id = 0,
397 .enable = s5pv310_clk_ip_cam_ctrl,
398 .ctrlbit = (1 << 4),
399 }, {
400 .name = "csis",
401 .id = 1,
402 .enable = s5pv310_clk_ip_cam_ctrl,
403 .ctrlbit = (1 << 5),
404 }, {
405 .name = "fimc",
406 .id = 0,
407 .enable = s5pv310_clk_ip_cam_ctrl,
408 .ctrlbit = (1 << 0),
409 }, {
410 .name = "fimc",
411 .id = 1,
412 .enable = s5pv310_clk_ip_cam_ctrl,
413 .ctrlbit = (1 << 1),
414 }, {
415 .name = "fimc",
416 .id = 2,
417 .enable = s5pv310_clk_ip_cam_ctrl,
418 .ctrlbit = (1 << 2),
419 }, {
420 .name = "fimc",
421 .id = 3,
422 .enable = s5pv310_clk_ip_cam_ctrl,
423 .ctrlbit = (1 << 3),
424 }, {
425 .name = "fimd",
426 .id = 0,
427 .enable = s5pv310_clk_ip_lcd0_ctrl,
428 .ctrlbit = (1 << 0),
429 }, {
430 .name = "fimd",
431 .id = 1,
432 .enable = s5pv310_clk_ip_lcd1_ctrl,
433 .ctrlbit = (1 << 0),
434 }, {
435 .name = "hsmmc",
436 .id = 0,
437 .parent = &clk_aclk_133.clk,
438 .enable = s5pv310_clk_ip_fsys_ctrl,
439 .ctrlbit = (1 << 5),
440 }, {
441 .name = "hsmmc",
442 .id = 1,
443 .parent = &clk_aclk_133.clk,
444 .enable = s5pv310_clk_ip_fsys_ctrl,
445 .ctrlbit = (1 << 6),
446 }, {
447 .name = "hsmmc",
448 .id = 2,
449 .parent = &clk_aclk_133.clk,
450 .enable = s5pv310_clk_ip_fsys_ctrl,
451 .ctrlbit = (1 << 7),
452 }, {
453 .name = "hsmmc",
454 .id = 3,
455 .parent = &clk_aclk_133.clk,
456 .enable = s5pv310_clk_ip_fsys_ctrl,
457 .ctrlbit = (1 << 8),
458 }, {
459 .name = "hsmmc",
460 .id = 4,
461 .parent = &clk_aclk_133.clk,
462 .enable = s5pv310_clk_ip_fsys_ctrl,
463 .ctrlbit = (1 << 9),
464 }, {
465 .name = "sata",
466 .id = -1,
467 .enable = s5pv310_clk_ip_fsys_ctrl,
468 .ctrlbit = (1 << 10),
469 }, {
470 .name = "adc",
471 .id = -1,
472 .enable = s5pv310_clk_ip_peril_ctrl,
473 .ctrlbit = (1 << 15),
474 }, {
475 .name = "rtc",
476 .id = -1,
477 .enable = s5pv310_clk_ip_perir_ctrl,
478 .ctrlbit = (1 << 15),
479 }, {
480 .name = "watchdog",
481 .id = -1,
482 .enable = s5pv310_clk_ip_perir_ctrl,
483 .ctrlbit = (1 << 14),
484 }, {
485 .name = "usbhost",
486 .id = -1,
487 .enable = s5pv310_clk_ip_fsys_ctrl ,
488 .ctrlbit = (1 << 12),
489 }, {
490 .name = "otg",
491 .id = -1,
492 .enable = s5pv310_clk_ip_fsys_ctrl,
493 .ctrlbit = (1 << 13),
494 }, {
495 .name = "spi",
496 .id = 0,
497 .enable = s5pv310_clk_ip_peril_ctrl,
498 .ctrlbit = (1 << 16),
499 }, {
500 .name = "spi",
501 .id = 1,
502 .enable = s5pv310_clk_ip_peril_ctrl,
503 .ctrlbit = (1 << 17),
504 }, {
505 .name = "spi",
506 .id = 2,
507 .enable = s5pv310_clk_ip_peril_ctrl,
508 .ctrlbit = (1 << 18),
509 }, {
510 .name = "fimg2d",
511 .id = -1,
512 .enable = s5pv310_clk_ip_image_ctrl,
513 .ctrlbit = (1 << 0),
514 }, {
515 .name = "i2c",
516 .id = 0,
517 .parent = &clk_aclk_100.clk,
518 .enable = s5pv310_clk_ip_peril_ctrl,
519 .ctrlbit = (1 << 6),
520 }, {
521 .name = "i2c",
522 .id = 1,
523 .parent = &clk_aclk_100.clk,
524 .enable = s5pv310_clk_ip_peril_ctrl,
525 .ctrlbit = (1 << 7),
526 }, {
527 .name = "i2c",
528 .id = 2,
529 .parent = &clk_aclk_100.clk,
530 .enable = s5pv310_clk_ip_peril_ctrl,
531 .ctrlbit = (1 << 8),
532 }, {
533 .name = "i2c",
534 .id = 3,
535 .parent = &clk_aclk_100.clk,
536 .enable = s5pv310_clk_ip_peril_ctrl,
537 .ctrlbit = (1 << 9),
538 }, {
539 .name = "i2c",
540 .id = 4,
541 .parent = &clk_aclk_100.clk,
542 .enable = s5pv310_clk_ip_peril_ctrl,
543 .ctrlbit = (1 << 10),
544 }, {
545 .name = "i2c",
546 .id = 5,
547 .parent = &clk_aclk_100.clk,
548 .enable = s5pv310_clk_ip_peril_ctrl,
549 .ctrlbit = (1 << 11),
550 }, {
551 .name = "i2c",
552 .id = 6,
553 .parent = &clk_aclk_100.clk,
554 .enable = s5pv310_clk_ip_peril_ctrl,
555 .ctrlbit = (1 << 12),
556 }, {
557 .name = "i2c",
558 .id = 7,
559 .parent = &clk_aclk_100.clk,
560 .enable = s5pv310_clk_ip_peril_ctrl,
561 .ctrlbit = (1 << 13),
562 },
350}; 563};
351 564
352static struct clk init_clocks[] = { 565static struct clk init_clocks[] = {
@@ -387,6 +600,9 @@ static struct clk *clkset_group_list[] = {
387 [0] = &clk_ext_xtal_mux, 600 [0] = &clk_ext_xtal_mux,
388 [1] = &clk_xusbxti, 601 [1] = &clk_xusbxti,
389 [2] = &clk_sclk_hdmi27m, 602 [2] = &clk_sclk_hdmi27m,
603 [3] = &clk_sclk_usbphy0,
604 [4] = &clk_sclk_usbphy1,
605 [5] = &clk_sclk_hdmiphy,
390 [6] = &clk_mout_mpll.clk, 606 [6] = &clk_mout_mpll.clk,
391 [7] = &clk_mout_epll.clk, 607 [7] = &clk_mout_epll.clk,
392 [8] = &clk_sclk_vpll.clk, 608 [8] = &clk_sclk_vpll.clk,
@@ -397,6 +613,104 @@ static struct clksrc_sources clkset_group = {
397 .nr_sources = ARRAY_SIZE(clkset_group_list), 613 .nr_sources = ARRAY_SIZE(clkset_group_list),
398}; 614};
399 615
616static struct clk *clkset_mout_g2d0_list[] = {
617 [0] = &clk_mout_mpll.clk,
618 [1] = &clk_sclk_apll.clk,
619};
620
621static struct clksrc_sources clkset_mout_g2d0 = {
622 .sources = clkset_mout_g2d0_list,
623 .nr_sources = ARRAY_SIZE(clkset_mout_g2d0_list),
624};
625
626static struct clksrc_clk clk_mout_g2d0 = {
627 .clk = {
628 .name = "mout_g2d0",
629 .id = -1,
630 },
631 .sources = &clkset_mout_g2d0,
632 .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 0, .size = 1 },
633};
634
635static struct clk *clkset_mout_g2d1_list[] = {
636 [0] = &clk_mout_epll.clk,
637 [1] = &clk_sclk_vpll.clk,
638};
639
640static struct clksrc_sources clkset_mout_g2d1 = {
641 .sources = clkset_mout_g2d1_list,
642 .nr_sources = ARRAY_SIZE(clkset_mout_g2d1_list),
643};
644
645static struct clksrc_clk clk_mout_g2d1 = {
646 .clk = {
647 .name = "mout_g2d1",
648 .id = -1,
649 },
650 .sources = &clkset_mout_g2d1,
651 .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 4, .size = 1 },
652};
653
654static struct clk *clkset_mout_g2d_list[] = {
655 [0] = &clk_mout_g2d0.clk,
656 [1] = &clk_mout_g2d1.clk,
657};
658
659static struct clksrc_sources clkset_mout_g2d = {
660 .sources = clkset_mout_g2d_list,
661 .nr_sources = ARRAY_SIZE(clkset_mout_g2d_list),
662};
663
664static struct clksrc_clk clk_dout_mmc0 = {
665 .clk = {
666 .name = "dout_mmc0",
667 .id = -1,
668 },
669 .sources = &clkset_group,
670 .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 0, .size = 4 },
671 .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 0, .size = 4 },
672};
673
674static struct clksrc_clk clk_dout_mmc1 = {
675 .clk = {
676 .name = "dout_mmc1",
677 .id = -1,
678 },
679 .sources = &clkset_group,
680 .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 4, .size = 4 },
681 .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 16, .size = 4 },
682};
683
684static struct clksrc_clk clk_dout_mmc2 = {
685 .clk = {
686 .name = "dout_mmc2",
687 .id = -1,
688 },
689 .sources = &clkset_group,
690 .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 8, .size = 4 },
691 .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 0, .size = 4 },
692};
693
694static struct clksrc_clk clk_dout_mmc3 = {
695 .clk = {
696 .name = "dout_mmc3",
697 .id = -1,
698 },
699 .sources = &clkset_group,
700 .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 12, .size = 4 },
701 .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 16, .size = 4 },
702};
703
704static struct clksrc_clk clk_dout_mmc4 = {
705 .clk = {
706 .name = "dout_mmc4",
707 .id = -1,
708 },
709 .sources = &clkset_group,
710 .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 16, .size = 4 },
711 .reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 0, .size = 4 },
712};
713
400static struct clksrc_clk clksrcs[] = { 714static struct clksrc_clk clksrcs[] = {
401 { 715 {
402 .clk = { 716 .clk = {
@@ -448,7 +762,200 @@ static struct clksrc_clk clksrcs[] = {
448 .sources = &clkset_group, 762 .sources = &clkset_group,
449 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 }, 763 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 },
450 .reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 }, 764 .reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 },
451 }, 765 }, {
766 .clk = {
767 .name = "sclk_csis",
768 .id = 0,
769 .enable = s5pv310_clksrc_mask_cam_ctrl,
770 .ctrlbit = (1 << 24),
771 },
772 .sources = &clkset_group,
773 .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 24, .size = 4 },
774 .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 24, .size = 4 },
775 }, {
776 .clk = {
777 .name = "sclk_csis",
778 .id = 1,
779 .enable = s5pv310_clksrc_mask_cam_ctrl,
780 .ctrlbit = (1 << 28),
781 },
782 .sources = &clkset_group,
783 .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 28, .size = 4 },
784 .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 28, .size = 4 },
785 }, {
786 .clk = {
787 .name = "sclk_cam",
788 .id = 0,
789 .enable = s5pv310_clksrc_mask_cam_ctrl,
790 .ctrlbit = (1 << 16),
791 },
792 .sources = &clkset_group,
793 .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 16, .size = 4 },
794 .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 16, .size = 4 },
795 }, {
796 .clk = {
797 .name = "sclk_cam",
798 .id = 1,
799 .enable = s5pv310_clksrc_mask_cam_ctrl,
800 .ctrlbit = (1 << 20),
801 },
802 .sources = &clkset_group,
803 .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 20, .size = 4 },
804 .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 20, .size = 4 },
805 }, {
806 .clk = {
807 .name = "sclk_fimc",
808 .id = 0,
809 .enable = s5pv310_clksrc_mask_cam_ctrl,
810 .ctrlbit = (1 << 0),
811 },
812 .sources = &clkset_group,
813 .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 0, .size = 4 },
814 .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 0, .size = 4 },
815 }, {
816 .clk = {
817 .name = "sclk_fimc",
818 .id = 1,
819 .enable = s5pv310_clksrc_mask_cam_ctrl,
820 .ctrlbit = (1 << 4),
821 },
822 .sources = &clkset_group,
823 .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 4, .size = 4 },
824 .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 4, .size = 4 },
825 }, {
826 .clk = {
827 .name = "sclk_fimc",
828 .id = 2,
829 .enable = s5pv310_clksrc_mask_cam_ctrl,
830 .ctrlbit = (1 << 8),
831 },
832 .sources = &clkset_group,
833 .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 8, .size = 4 },
834 .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 8, .size = 4 },
835 }, {
836 .clk = {
837 .name = "sclk_fimc",
838 .id = 3,
839 .enable = s5pv310_clksrc_mask_cam_ctrl,
840 .ctrlbit = (1 << 12),
841 },
842 .sources = &clkset_group,
843 .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 12, .size = 4 },
844 .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 12, .size = 4 },
845 }, {
846 .clk = {
847 .name = "sclk_fimd",
848 .id = 0,
849 .enable = s5pv310_clksrc_mask_lcd0_ctrl,
850 .ctrlbit = (1 << 0),
851 },
852 .sources = &clkset_group,
853 .reg_src = { .reg = S5P_CLKSRC_LCD0, .shift = 0, .size = 4 },
854 .reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 },
855 }, {
856 .clk = {
857 .name = "sclk_fimd",
858 .id = 1,
859 .enable = s5pv310_clksrc_mask_lcd1_ctrl,
860 .ctrlbit = (1 << 0),
861 },
862 .sources = &clkset_group,
863 .reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 },
864 .reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 },
865 }, {
866 .clk = {
867 .name = "sclk_sata",
868 .id = -1,
869 .enable = s5pv310_clksrc_mask_fsys_ctrl,
870 .ctrlbit = (1 << 24),
871 },
872 .sources = &clkset_mout_corebus,
873 .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 },
874 .reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 },
875 }, {
876 .clk = {
877 .name = "sclk_spi",
878 .id = 0,
879 .enable = s5pv310_clksrc_mask_peril1_ctrl,
880 .ctrlbit = (1 << 16),
881 },
882 .sources = &clkset_group,
883 .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 },
884 .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 },
885 }, {
886 .clk = {
887 .name = "sclk_spi",
888 .id = 1,
889 .enable = s5pv310_clksrc_mask_peril1_ctrl,
890 .ctrlbit = (1 << 20),
891 },
892 .sources = &clkset_group,
893 .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 },
894 .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 },
895 }, {
896 .clk = {
897 .name = "sclk_spi",
898 .id = 2,
899 .enable = s5pv310_clksrc_mask_peril1_ctrl,
900 .ctrlbit = (1 << 24),
901 },
902 .sources = &clkset_group,
903 .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 },
904 .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 },
905 }, {
906 .clk = {
907 .name = "sclk_fimg2d",
908 .id = -1,
909 },
910 .sources = &clkset_mout_g2d,
911 .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 },
912 .reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 },
913 }, {
914 .clk = {
915 .name = "sclk_mmc",
916 .id = 0,
917 .parent = &clk_dout_mmc0.clk,
918 .enable = s5pv310_clksrc_mask_fsys_ctrl,
919 .ctrlbit = (1 << 0),
920 },
921 .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 },
922 }, {
923 .clk = {
924 .name = "sclk_mmc",
925 .id = 1,
926 .parent = &clk_dout_mmc1.clk,
927 .enable = s5pv310_clksrc_mask_fsys_ctrl,
928 .ctrlbit = (1 << 4),
929 },
930 .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 },
931 }, {
932 .clk = {
933 .name = "sclk_mmc",
934 .id = 2,
935 .parent = &clk_dout_mmc2.clk,
936 .enable = s5pv310_clksrc_mask_fsys_ctrl,
937 .ctrlbit = (1 << 8),
938 },
939 .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 },
940 }, {
941 .clk = {
942 .name = "sclk_mmc",
943 .id = 3,
944 .parent = &clk_dout_mmc3.clk,
945 .enable = s5pv310_clksrc_mask_fsys_ctrl,
946 .ctrlbit = (1 << 12),
947 },
948 .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
949 }, {
950 .clk = {
951 .name = "sclk_mmc",
952 .id = 4,
953 .parent = &clk_dout_mmc4.clk,
954 .enable = s5pv310_clksrc_mask_fsys_ctrl,
955 .ctrlbit = (1 << 16),
956 },
957 .reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 8, .size = 8 },
958 }
452}; 959};
453 960
454/* Clock initialization code */ 961/* Clock initialization code */
@@ -464,8 +971,6 @@ static struct clksrc_clk *sysclks[] = {
464 &clk_aclk_cores, 971 &clk_aclk_cores,
465 &clk_aclk_corem1, 972 &clk_aclk_corem1,
466 &clk_periphclk, 973 &clk_periphclk,
467 &clk_atclk,
468 &clk_pclk_dbg,
469 &clk_mout_corebus, 974 &clk_mout_corebus,
470 &clk_sclk_dmc, 975 &clk_sclk_dmc,
471 &clk_aclk_cored, 976 &clk_aclk_cored,
@@ -478,6 +983,11 @@ static struct clksrc_clk *sysclks[] = {
478 &clk_aclk_100, 983 &clk_aclk_100,
479 &clk_aclk_160, 984 &clk_aclk_160,
480 &clk_aclk_133, 985 &clk_aclk_133,
986 &clk_dout_mmc0,
987 &clk_dout_mmc1,
988 &clk_dout_mmc2,
989 &clk_dout_mmc3,
990 &clk_dout_mmc4,
481}; 991};
482 992
483void __init_or_cpufreq s5pv310_setup_clocks(void) 993void __init_or_cpufreq s5pv310_setup_clocks(void)
@@ -490,15 +1000,11 @@ void __init_or_cpufreq s5pv310_setup_clocks(void)
490 unsigned long vpllsrc; 1000 unsigned long vpllsrc;
491 unsigned long xtal; 1001 unsigned long xtal;
492 unsigned long armclk; 1002 unsigned long armclk;
493 unsigned long aclk_corem0;
494 unsigned long aclk_cores;
495 unsigned long aclk_corem1;
496 unsigned long periphclk;
497 unsigned long sclk_dmc; 1003 unsigned long sclk_dmc;
498 unsigned long aclk_cored; 1004 unsigned long aclk_200;
499 unsigned long aclk_corep; 1005 unsigned long aclk_100;
500 unsigned long aclk_acp; 1006 unsigned long aclk_160;
501 unsigned long pclk_acp; 1007 unsigned long aclk_133;
502 unsigned int ptr; 1008 unsigned int ptr;
503 1009
504 printk(KERN_DEBUG "%s: registering clocks\n", __func__); 1010 printk(KERN_DEBUG "%s: registering clocks\n", __func__);
@@ -529,26 +1035,21 @@ void __init_or_cpufreq s5pv310_setup_clocks(void)
529 apll, mpll, epll, vpll); 1035 apll, mpll, epll, vpll);
530 1036
531 armclk = clk_get_rate(&clk_armclk.clk); 1037 armclk = clk_get_rate(&clk_armclk.clk);
532 aclk_corem0 = clk_get_rate(&clk_aclk_corem0.clk);
533 aclk_cores = clk_get_rate(&clk_aclk_cores.clk);
534 aclk_corem1 = clk_get_rate(&clk_aclk_corem1.clk);
535 periphclk = clk_get_rate(&clk_periphclk.clk);
536 sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk); 1038 sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk);
537 aclk_cored = clk_get_rate(&clk_aclk_cored.clk); 1039
538 aclk_corep = clk_get_rate(&clk_aclk_corep.clk); 1040 aclk_200 = clk_get_rate(&clk_aclk_200.clk);
539 aclk_acp = clk_get_rate(&clk_aclk_acp.clk); 1041 aclk_100 = clk_get_rate(&clk_aclk_100.clk);
540 pclk_acp = clk_get_rate(&clk_pclk_acp.clk); 1042 aclk_160 = clk_get_rate(&clk_aclk_160.clk);
541 1043 aclk_133 = clk_get_rate(&clk_aclk_133.clk);
542 printk(KERN_INFO "S5PV310: ARMCLK=%ld, COREM0=%ld, CORES=%ld\n" 1044
543 "COREM1=%ld, PERI=%ld, DMC=%ld, CORED=%ld\n" 1045 printk(KERN_INFO "S5PV310: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n"
544 "COREP=%ld, ACLK_ACP=%ld, PCLK_ACP=%ld", 1046 "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n",
545 armclk, aclk_corem0, aclk_cores, aclk_corem1, 1047 armclk, sclk_dmc, aclk_200,
546 periphclk, sclk_dmc, aclk_cored, aclk_corep, 1048 aclk_100, aclk_160, aclk_133);
547 aclk_acp, pclk_acp);
548 1049
549 clk_f.rate = armclk; 1050 clk_f.rate = armclk;
550 clk_h.rate = sclk_dmc; 1051 clk_h.rate = sclk_dmc;
551 clk_p.rate = periphclk; 1052 clk_p.rate = aclk_100;
552 1053
553 for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) 1054 for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
554 s3c_set_clksrc(&clksrcs[ptr], true); 1055 s3c_set_clksrc(&clksrcs[ptr], true);
diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
index 4add39853ff9..82ce4aa6d61a 100644
--- a/arch/arm/mach-s5pv310/cpu.c
+++ b/arch/arm/mach-s5pv310/cpu.c
@@ -15,10 +15,12 @@
15#include <asm/mach/irq.h> 15#include <asm/mach/irq.h>
16 16
17#include <asm/proc-fns.h> 17#include <asm/proc-fns.h>
18#include <asm/hardware/cache-l2x0.h>
18 19
19#include <plat/cpu.h> 20#include <plat/cpu.h>
20#include <plat/clock.h> 21#include <plat/clock.h>
21#include <plat/s5pv310.h> 22#include <plat/s5pv310.h>
23#include <plat/sdhci.h>
22 24
23#include <mach/regs-irq.h> 25#include <mach/regs-irq.h>
24 26
@@ -56,15 +58,30 @@ static struct map_desc s5pv310_iodesc[] __initdata = {
56 .length = SZ_4K, 58 .length = SZ_4K,
57 .type = MT_DEVICE, 59 .type = MT_DEVICE,
58 }, { 60 }, {
59 .virtual = (unsigned long)S5P_VA_GPIO, 61 .virtual = (unsigned long)S5P_VA_GPIO1,
60 .pfn = __phys_to_pfn(S5PV310_PA_GPIO1), 62 .pfn = __phys_to_pfn(S5PV310_PA_GPIO1),
61 .length = SZ_4K, 63 .length = SZ_4K,
62 .type = MT_DEVICE, 64 .type = MT_DEVICE,
63 }, { 65 }, {
66 .virtual = (unsigned long)S5P_VA_GPIO2,
67 .pfn = __phys_to_pfn(S5PV310_PA_GPIO2),
68 .length = SZ_4K,
69 .type = MT_DEVICE,
70 }, {
71 .virtual = (unsigned long)S5P_VA_GPIO3,
72 .pfn = __phys_to_pfn(S5PV310_PA_GPIO3),
73 .length = SZ_256,
74 .type = MT_DEVICE,
75 }, {
64 .virtual = (unsigned long)S3C_VA_UART, 76 .virtual = (unsigned long)S3C_VA_UART,
65 .pfn = __phys_to_pfn(S3C_PA_UART), 77 .pfn = __phys_to_pfn(S3C_PA_UART),
66 .length = SZ_512K, 78 .length = SZ_512K,
67 .type = MT_DEVICE, 79 .type = MT_DEVICE,
80 }, {
81 .virtual = (unsigned long)S5P_VA_SROMC,
82 .pfn = __phys_to_pfn(S5PV310_PA_SROMC),
83 .length = SZ_4K,
84 .type = MT_DEVICE,
68 }, 85 },
69}; 86};
70 87
@@ -83,6 +100,12 @@ static void s5pv310_idle(void)
83void __init s5pv310_map_io(void) 100void __init s5pv310_map_io(void)
84{ 101{
85 iotable_init(s5pv310_iodesc, ARRAY_SIZE(s5pv310_iodesc)); 102 iotable_init(s5pv310_iodesc, ARRAY_SIZE(s5pv310_iodesc));
103
104 /* initialize device information early */
105 s5pv310_default_sdhci0();
106 s5pv310_default_sdhci1();
107 s5pv310_default_sdhci2();
108 s5pv310_default_sdhci3();
86} 109}
87 110
88void __init s5pv310_init_clocks(int xtal) 111void __init s5pv310_init_clocks(int xtal)
@@ -131,6 +154,28 @@ static int __init s5pv310_core_init(void)
131 154
132core_initcall(s5pv310_core_init); 155core_initcall(s5pv310_core_init);
133 156
157#ifdef CONFIG_CACHE_L2X0
158static int __init s5pv310_l2x0_cache_init(void)
159{
160 /* TAG, Data Latency Control: 2cycle */
161 __raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
162 __raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
163
164 /* L2X0 Prefetch Control */
165 __raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
166
167 /* L2X0 Power Control */
168 __raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
169 S5P_VA_L2CC + L2X0_POWER_CTRL);
170
171 l2x0_init(S5P_VA_L2CC, 0x7C070001, 0xC200ffff);
172
173 return 0;
174}
175
176early_initcall(s5pv310_l2x0_cache_init);
177#endif
178
134int __init s5pv310_init(void) 179int __init s5pv310_init(void)
135{ 180{
136 printk(KERN_INFO "S5PV310: Initializing architecture\n"); 181 printk(KERN_INFO "S5PV310: Initializing architecture\n");
diff --git a/arch/arm/mach-s5pv310/gpiolib.c b/arch/arm/mach-s5pv310/gpiolib.c
new file mode 100644
index 000000000000..55217b8923ec
--- /dev/null
+++ b/arch/arm/mach-s5pv310/gpiolib.c
@@ -0,0 +1,304 @@
1/* linux/arch/arm/mach-s5pv310/gpiolib.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * S5PV310 - GPIOlib support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/kernel.h>
14#include <linux/irq.h>
15#include <linux/io.h>
16#include <linux/gpio.h>
17
18#include <mach/map.h>
19
20#include <plat/gpio-core.h>
21#include <plat/gpio-cfg.h>
22#include <plat/gpio-cfg-helpers.h>
23
24static struct s3c_gpio_cfg gpio_cfg = {
25 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
26 .set_pull = s3c_gpio_setpull_updown,
27 .get_pull = s3c_gpio_getpull_updown,
28};
29
30static struct s3c_gpio_cfg gpio_cfg_noint = {
31 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
32 .set_pull = s3c_gpio_setpull_updown,
33 .get_pull = s3c_gpio_getpull_updown,
34};
35
36/*
37 * Following are the gpio banks in v310.
38 *
39 * The 'config' member when left to NULL, is initialized to the default
40 * structure gpio_cfg in the init function below.
41 *
42 * The 'base' member is also initialized in the init function below.
43 * Note: The initialization of 'base' member of s3c_gpio_chip structure
44 * uses the above macro and depends on the banks being listed in order here.
45 */
46static struct s3c_gpio_chip s5pv310_gpio_part1_4bit[] = {
47 {
48 .chip = {
49 .base = S5PV310_GPA0(0),
50 .ngpio = S5PV310_GPIO_A0_NR,
51 .label = "GPA0",
52 },
53 }, {
54 .chip = {
55 .base = S5PV310_GPA1(0),
56 .ngpio = S5PV310_GPIO_A1_NR,
57 .label = "GPA1",
58 },
59 }, {
60 .chip = {
61 .base = S5PV310_GPB(0),
62 .ngpio = S5PV310_GPIO_B_NR,
63 .label = "GPB",
64 },
65 }, {
66 .chip = {
67 .base = S5PV310_GPC0(0),
68 .ngpio = S5PV310_GPIO_C0_NR,
69 .label = "GPC0",
70 },
71 }, {
72 .chip = {
73 .base = S5PV310_GPC1(0),
74 .ngpio = S5PV310_GPIO_C1_NR,
75 .label = "GPC1",
76 },
77 }, {
78 .chip = {
79 .base = S5PV310_GPD0(0),
80 .ngpio = S5PV310_GPIO_D0_NR,
81 .label = "GPD0",
82 },
83 }, {
84 .chip = {
85 .base = S5PV310_GPD1(0),
86 .ngpio = S5PV310_GPIO_D1_NR,
87 .label = "GPD1",
88 },
89 }, {
90 .chip = {
91 .base = S5PV310_GPE0(0),
92 .ngpio = S5PV310_GPIO_E0_NR,
93 .label = "GPE0",
94 },
95 }, {
96 .chip = {
97 .base = S5PV310_GPE1(0),
98 .ngpio = S5PV310_GPIO_E1_NR,
99 .label = "GPE1",
100 },
101 }, {
102 .chip = {
103 .base = S5PV310_GPE2(0),
104 .ngpio = S5PV310_GPIO_E2_NR,
105 .label = "GPE2",
106 },
107 }, {
108 .chip = {
109 .base = S5PV310_GPE3(0),
110 .ngpio = S5PV310_GPIO_E3_NR,
111 .label = "GPE3",
112 },
113 }, {
114 .chip = {
115 .base = S5PV310_GPE4(0),
116 .ngpio = S5PV310_GPIO_E4_NR,
117 .label = "GPE4",
118 },
119 }, {
120 .chip = {
121 .base = S5PV310_GPF0(0),
122 .ngpio = S5PV310_GPIO_F0_NR,
123 .label = "GPF0",
124 },
125 }, {
126 .chip = {
127 .base = S5PV310_GPF1(0),
128 .ngpio = S5PV310_GPIO_F1_NR,
129 .label = "GPF1",
130 },
131 }, {
132 .chip = {
133 .base = S5PV310_GPF2(0),
134 .ngpio = S5PV310_GPIO_F2_NR,
135 .label = "GPF2",
136 },
137 }, {
138 .chip = {
139 .base = S5PV310_GPF3(0),
140 .ngpio = S5PV310_GPIO_F3_NR,
141 .label = "GPF3",
142 },
143 },
144};
145
146static struct s3c_gpio_chip s5pv310_gpio_part2_4bit[] = {
147 {
148 .chip = {
149 .base = S5PV310_GPJ0(0),
150 .ngpio = S5PV310_GPIO_J0_NR,
151 .label = "GPJ0",
152 },
153 }, {
154 .chip = {
155 .base = S5PV310_GPJ1(0),
156 .ngpio = S5PV310_GPIO_J1_NR,
157 .label = "GPJ1",
158 },
159 }, {
160 .chip = {
161 .base = S5PV310_GPK0(0),
162 .ngpio = S5PV310_GPIO_K0_NR,
163 .label = "GPK0",
164 },
165 }, {
166 .chip = {
167 .base = S5PV310_GPK1(0),
168 .ngpio = S5PV310_GPIO_K1_NR,
169 .label = "GPK1",
170 },
171 }, {
172 .chip = {
173 .base = S5PV310_GPK2(0),
174 .ngpio = S5PV310_GPIO_K2_NR,
175 .label = "GPK2",
176 },
177 }, {
178 .chip = {
179 .base = S5PV310_GPK3(0),
180 .ngpio = S5PV310_GPIO_K3_NR,
181 .label = "GPK3",
182 },
183 }, {
184 .chip = {
185 .base = S5PV310_GPL0(0),
186 .ngpio = S5PV310_GPIO_L0_NR,
187 .label = "GPL0",
188 },
189 }, {
190 .chip = {
191 .base = S5PV310_GPL1(0),
192 .ngpio = S5PV310_GPIO_L1_NR,
193 .label = "GPL1",
194 },
195 }, {
196 .chip = {
197 .base = S5PV310_GPL2(0),
198 .ngpio = S5PV310_GPIO_L2_NR,
199 .label = "GPL2",
200 },
201 }, {
202 .base = (S5P_VA_GPIO2 + 0xC00),
203 .config = &gpio_cfg_noint,
204 .irq_base = IRQ_EINT(0),
205 .chip = {
206 .base = S5PV310_GPX0(0),
207 .ngpio = S5PV310_GPIO_X0_NR,
208 .label = "GPX0",
209 .to_irq = samsung_gpiolib_to_irq,
210 },
211 }, {
212 .base = (S5P_VA_GPIO2 + 0xC20),
213 .config = &gpio_cfg_noint,
214 .irq_base = IRQ_EINT(8),
215 .chip = {
216 .base = S5PV310_GPX1(0),
217 .ngpio = S5PV310_GPIO_X1_NR,
218 .label = "GPX1",
219 .to_irq = samsung_gpiolib_to_irq,
220 },
221 }, {
222 .base = (S5P_VA_GPIO2 + 0xC40),
223 .config = &gpio_cfg_noint,
224 .irq_base = IRQ_EINT(16),
225 .chip = {
226 .base = S5PV310_GPX2(0),
227 .ngpio = S5PV310_GPIO_X2_NR,
228 .label = "GPX2",
229 .to_irq = samsung_gpiolib_to_irq,
230 },
231 }, {
232 .base = (S5P_VA_GPIO2 + 0xC60),
233 .config = &gpio_cfg_noint,
234 .irq_base = IRQ_EINT(24),
235 .chip = {
236 .base = S5PV310_GPX3(0),
237 .ngpio = S5PV310_GPIO_X3_NR,
238 .label = "GPX3",
239 .to_irq = samsung_gpiolib_to_irq,
240 },
241 },
242};
243
244static struct s3c_gpio_chip s5pv310_gpio_part3_4bit[] = {
245 {
246 .chip = {
247 .base = S5PV310_GPZ(0),
248 .ngpio = S5PV310_GPIO_Z_NR,
249 .label = "GPZ",
250 },
251 },
252};
253
254static __init int s5pv310_gpiolib_init(void)
255{
256 struct s3c_gpio_chip *chip;
257 int i;
258 int nr_chips;
259
260 /* GPIO part 1 */
261
262 chip = s5pv310_gpio_part1_4bit;
263 nr_chips = ARRAY_SIZE(s5pv310_gpio_part1_4bit);
264
265 for (i = 0; i < nr_chips; i++, chip++) {
266 if (chip->config == NULL)
267 chip->config = &gpio_cfg;
268 if (chip->base == NULL)
269 chip->base = S5P_VA_GPIO1 + (i) * 0x20;
270 }
271
272 samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part1_4bit, nr_chips);
273
274 /* GPIO part 2 */
275
276 chip = s5pv310_gpio_part2_4bit;
277 nr_chips = ARRAY_SIZE(s5pv310_gpio_part2_4bit);
278
279 for (i = 0; i < nr_chips; i++, chip++) {
280 if (chip->config == NULL)
281 chip->config = &gpio_cfg;
282 if (chip->base == NULL)
283 chip->base = S5P_VA_GPIO2 + (i) * 0x20;
284 }
285
286 samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part2_4bit, nr_chips);
287
288 /* GPIO part 3 */
289
290 chip = s5pv310_gpio_part3_4bit;
291 nr_chips = ARRAY_SIZE(s5pv310_gpio_part3_4bit);
292
293 for (i = 0; i < nr_chips; i++, chip++) {
294 if (chip->config == NULL)
295 chip->config = &gpio_cfg;
296 if (chip->base == NULL)
297 chip->base = S5P_VA_GPIO3 + (i) * 0x20;
298 }
299
300 samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part3_4bit, nr_chips);
301
302 return 0;
303}
304core_initcall(s5pv310_gpiolib_init);
diff --git a/arch/arm/mach-s5pv310/hotplug.c b/arch/arm/mach-s5pv310/hotplug.c
new file mode 100644
index 000000000000..03652c3605f6
--- /dev/null
+++ b/arch/arm/mach-s5pv310/hotplug.c
@@ -0,0 +1,144 @@
1/* linux arch/arm/mach-s5pv310/hotplug.c
2 *
3 * Cloned from linux/arch/arm/mach-realview/hotplug.c
4 *
5 * Copyright (C) 2002 ARM Ltd.
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/kernel.h>
14#include <linux/errno.h>
15#include <linux/smp.h>
16#include <linux/completion.h>
17
18#include <asm/cacheflush.h>
19
20extern volatile int pen_release;
21
22static DECLARE_COMPLETION(cpu_killed);
23
24static inline void cpu_enter_lowpower(void)
25{
26 unsigned int v;
27
28 flush_cache_all();
29 asm volatile(
30 " mcr p15, 0, %1, c7, c5, 0\n"
31 " mcr p15, 0, %1, c7, c10, 4\n"
32 /*
33 * Turn off coherency
34 */
35 " mrc p15, 0, %0, c1, c0, 1\n"
36 " bic %0, %0, #0x20\n"
37 " mcr p15, 0, %0, c1, c0, 1\n"
38 " mrc p15, 0, %0, c1, c0, 0\n"
39 " bic %0, %0, #0x04\n"
40 " mcr p15, 0, %0, c1, c0, 0\n"
41 : "=&r" (v)
42 : "r" (0)
43 : "cc");
44}
45
46static inline void cpu_leave_lowpower(void)
47{
48 unsigned int v;
49
50 asm volatile(
51 "mrc p15, 0, %0, c1, c0, 0\n"
52 " orr %0, %0, #0x04\n"
53 " mcr p15, 0, %0, c1, c0, 0\n"
54 " mrc p15, 0, %0, c1, c0, 1\n"
55 " orr %0, %0, #0x20\n"
56 " mcr p15, 0, %0, c1, c0, 1\n"
57 : "=&r" (v)
58 :
59 : "cc");
60}
61
62static inline void platform_do_lowpower(unsigned int cpu)
63{
64 /*
65 * there is no power-control hardware on this platform, so all
66 * we can do is put the core into WFI; this is safe as the calling
67 * code will have already disabled interrupts
68 */
69 for (;;) {
70 /*
71 * here's the WFI
72 */
73 asm(".word 0xe320f003\n"
74 :
75 :
76 : "memory", "cc");
77
78 if (pen_release == cpu) {
79 /*
80 * OK, proper wakeup, we're done
81 */
82 break;
83 }
84
85 /*
86 * getting here, means that we have come out of WFI without
87 * having been woken up - this shouldn't happen
88 *
89 * The trouble is, letting people know about this is not really
90 * possible, since we are currently running incoherently, and
91 * therefore cannot safely call printk() or anything else
92 */
93#ifdef DEBUG
94 printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
95#endif
96 }
97}
98
99int platform_cpu_kill(unsigned int cpu)
100{
101 return wait_for_completion_timeout(&cpu_killed, 5000);
102}
103
104/*
105 * platform-specific code to shutdown a CPU
106 *
107 * Called with IRQs disabled
108 */
109void platform_cpu_die(unsigned int cpu)
110{
111#ifdef DEBUG
112 unsigned int this_cpu = hard_smp_processor_id();
113
114 if (cpu != this_cpu) {
115 printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
116 this_cpu, cpu);
117 BUG();
118 }
119#endif
120
121 printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
122 complete(&cpu_killed);
123
124 /*
125 * we're ready for shutdown now, so do it
126 */
127 cpu_enter_lowpower();
128 platform_do_lowpower(cpu);
129
130 /*
131 * bring this CPU back into the world of cache
132 * coherency, and then restore interrupts
133 */
134 cpu_leave_lowpower();
135}
136
137int platform_cpu_disable(unsigned int cpu)
138{
139 /*
140 * we don't allow CPU 0 to be shutdown (it is still too special
141 * e.g. clock tick interrupts)
142 */
143 return cpu == 0 ? -EPERM : 0;
144}
diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
index 471fc3bb199a..99e7dad8a85a 100644
--- a/arch/arm/mach-s5pv310/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
@@ -3,7 +3,7 @@
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd. 3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/ 4 * http://www.samsung.com/
5 * 5 *
6 * S5PV210 - IRQ definitions 6 * S5PV310 - IRQ definitions
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -60,6 +60,9 @@
60#define IRQ_TIMER3_VIC COMBINER_IRQ(22, 3) 60#define IRQ_TIMER3_VIC COMBINER_IRQ(22, 3)
61#define IRQ_TIMER4_VIC COMBINER_IRQ(22, 4) 61#define IRQ_TIMER4_VIC COMBINER_IRQ(22, 4)
62 62
63#define IRQ_RTC_ALARM COMBINER_IRQ(23, 0)
64#define IRQ_RTC_TIC COMBINER_IRQ(23, 1)
65
63#define IRQ_UART0 COMBINER_IRQ(26, 0) 66#define IRQ_UART0 COMBINER_IRQ(26, 0)
64#define IRQ_UART1 COMBINER_IRQ(26, 1) 67#define IRQ_UART1 COMBINER_IRQ(26, 1)
65#define IRQ_UART2 COMBINER_IRQ(26, 2) 68#define IRQ_UART2 COMBINER_IRQ(26, 2)
@@ -67,13 +70,46 @@
67#define IRQ_UART4 COMBINER_IRQ(26, 4) 70#define IRQ_UART4 COMBINER_IRQ(26, 4)
68 71
69#define IRQ_IIC COMBINER_IRQ(27, 0) 72#define IRQ_IIC COMBINER_IRQ(27, 0)
73#define IRQ_IIC1 COMBINER_IRQ(27, 1)
74#define IRQ_IIC2 COMBINER_IRQ(27, 2)
75#define IRQ_IIC3 COMBINER_IRQ(27, 3)
76#define IRQ_IIC4 COMBINER_IRQ(27, 4)
77#define IRQ_IIC5 COMBINER_IRQ(27, 5)
78#define IRQ_IIC6 COMBINER_IRQ(27, 6)
79#define IRQ_IIC7 COMBINER_IRQ(27, 7)
80
81#define IRQ_HSMMC0 COMBINER_IRQ(29, 0)
82#define IRQ_HSMMC1 COMBINER_IRQ(29, 1)
83#define IRQ_HSMMC2 COMBINER_IRQ(29, 2)
84#define IRQ_HSMMC3 COMBINER_IRQ(29, 3)
70 85
71#define IRQ_ONENAND_AUDI COMBINER_IRQ(34, 0) 86#define IRQ_ONENAND_AUDI COMBINER_IRQ(34, 0)
72 87
73/* Set the default NR_IRQS */ 88#define IRQ_EINT4 COMBINER_IRQ(37, 0)
89#define IRQ_EINT5 COMBINER_IRQ(37, 1)
90#define IRQ_EINT6 COMBINER_IRQ(37, 2)
91#define IRQ_EINT7 COMBINER_IRQ(37, 3)
92#define IRQ_EINT8 COMBINER_IRQ(38, 0)
93
94#define IRQ_EINT9 COMBINER_IRQ(38, 1)
95#define IRQ_EINT10 COMBINER_IRQ(38, 2)
96#define IRQ_EINT11 COMBINER_IRQ(38, 3)
97#define IRQ_EINT12 COMBINER_IRQ(38, 4)
98#define IRQ_EINT13 COMBINER_IRQ(38, 5)
99#define IRQ_EINT14 COMBINER_IRQ(38, 6)
100#define IRQ_EINT15 COMBINER_IRQ(38, 7)
101
102#define IRQ_EINT16_31 COMBINER_IRQ(39, 0)
74 103
75#define NR_IRQS COMBINER_IRQ(MAX_COMBINER_NR, 0) 104#define MAX_COMBINER_NR 40
105
106#define S5P_IRQ_EINT_BASE COMBINER_IRQ(MAX_COMBINER_NR, 0)
107
108#define S5P_EINT_BASE1 (S5P_IRQ_EINT_BASE + 0)
109#define S5P_EINT_BASE2 (S5P_IRQ_EINT_BASE + 16)
110
111/* Set the default NR_IRQS */
76 112
77#define MAX_COMBINER_NR 39 113#define NR_IRQS (S5P_IRQ_EINT_BASE + 32)
78 114
79#endif /* __ASM_ARCH_IRQS_H */ 115#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h
index aff6d23624bb..7acf4e77e92e 100644
--- a/arch/arm/mach-s5pv310/include/mach/map.h
+++ b/arch/arm/mach-s5pv310/include/mach/map.h
@@ -25,6 +25,8 @@
25 25
26#define S5PV310_PA_SYSRAM (0x02025000) 26#define S5PV310_PA_SYSRAM (0x02025000)
27 27
28#define S5PV310_PA_SROM_BANK(x) (0x04000000 + ((x) * 0x01000000))
29
28#define S5PC210_PA_ONENAND (0x0C000000) 30#define S5PC210_PA_ONENAND (0x0C000000)
29#define S5P_PA_ONENAND S5PC210_PA_ONENAND 31#define S5P_PA_ONENAND S5PC210_PA_ONENAND
30 32
@@ -34,12 +36,13 @@
34#define S5PV310_PA_CHIPID (0x10000000) 36#define S5PV310_PA_CHIPID (0x10000000)
35#define S5P_PA_CHIPID S5PV310_PA_CHIPID 37#define S5P_PA_CHIPID S5PV310_PA_CHIPID
36 38
37#define S5PV310_PA_SYSCON (0x10020000) 39#define S5PV310_PA_SYSCON (0x10010000)
38#define S5P_PA_SYSCON S5PV310_PA_SYSCON 40#define S5P_PA_SYSCON S5PV310_PA_SYSCON
39 41
40#define S5PV310_PA_CMU (0x10030000) 42#define S5PV310_PA_CMU (0x10030000)
41 43
42#define S5PV310_PA_WATCHDOG (0x10060000) 44#define S5PV310_PA_WATCHDOG (0x10060000)
45#define S5PV310_PA_RTC (0x10070000)
43 46
44#define S5PV310_PA_COMBINER (0x10448000) 47#define S5PV310_PA_COMBINER (0x10448000)
45 48
@@ -55,6 +58,8 @@
55 58
56#define S5PV310_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000)) 59#define S5PV310_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000))
57 60
61#define S5PV310_PA_SROMC (0x12570000)
62
58#define S5PV310_PA_UART (0x13800000) 63#define S5PV310_PA_UART (0x13800000)
59 64
60#define S5P_PA_UART(x) (S5PV310_PA_UART + ((x) * S3C_UART_OFFSET)) 65#define S5P_PA_UART(x) (S5PV310_PA_UART + ((x) * S3C_UART_OFFSET))
@@ -66,7 +71,7 @@
66 71
67#define S5P_SZ_UART SZ_256 72#define S5P_SZ_UART SZ_256
68 73
69#define S5PV310_PA_IIC0 (0x13860000) 74#define S5PV310_PA_IIC(x) (0x13860000 + ((x) * 0x10000))
70 75
71#define S5PV310_PA_TIMER (0x139D0000) 76#define S5PV310_PA_TIMER (0x139D0000)
72#define S5P_PA_TIMER S5PV310_PA_TIMER 77#define S5P_PA_TIMER S5PV310_PA_TIMER
@@ -80,7 +85,15 @@
80#define S3C_PA_HSMMC1 S5PV310_PA_HSMMC(1) 85#define S3C_PA_HSMMC1 S5PV310_PA_HSMMC(1)
81#define S3C_PA_HSMMC2 S5PV310_PA_HSMMC(2) 86#define S3C_PA_HSMMC2 S5PV310_PA_HSMMC(2)
82#define S3C_PA_HSMMC3 S5PV310_PA_HSMMC(3) 87#define S3C_PA_HSMMC3 S5PV310_PA_HSMMC(3)
83#define S3C_PA_IIC S5PV310_PA_IIC0 88#define S3C_PA_IIC S5PV310_PA_IIC(0)
89#define S3C_PA_IIC1 S5PV310_PA_IIC(1)
90#define S3C_PA_IIC2 S5PV310_PA_IIC(2)
91#define S3C_PA_IIC3 S5PV310_PA_IIC(3)
92#define S3C_PA_IIC4 S5PV310_PA_IIC(4)
93#define S3C_PA_IIC5 S5PV310_PA_IIC(5)
94#define S3C_PA_IIC6 S5PV310_PA_IIC(6)
95#define S3C_PA_IIC7 S5PV310_PA_IIC(7)
96#define S3C_PA_RTC S5PV310_PA_RTC
84#define S3C_PA_WDT S5PV310_PA_WATCHDOG 97#define S3C_PA_WDT S5PV310_PA_WATCHDOG
85 98
86#endif /* __ASM_ARCH_MAP_H */ 99#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
index 4013553cd9be..f1028cad9788 100644
--- a/arch/arm/mach-s5pv310/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
@@ -26,11 +26,23 @@
26 26
27#define S5P_CLKSRC_TOP0 S5P_CLKREG(0x0C210) 27#define S5P_CLKSRC_TOP0 S5P_CLKREG(0x0C210)
28#define S5P_CLKSRC_TOP1 S5P_CLKREG(0x0C214) 28#define S5P_CLKSRC_TOP1 S5P_CLKREG(0x0C214)
29 29#define S5P_CLKSRC_CAM S5P_CLKREG(0x0C220)
30#define S5P_CLKSRC_IMAGE S5P_CLKREG(0x0C230)
31#define S5P_CLKSRC_LCD0 S5P_CLKREG(0x0C234)
32#define S5P_CLKSRC_LCD1 S5P_CLKREG(0x0C238)
33#define S5P_CLKSRC_FSYS S5P_CLKREG(0x0C240)
30#define S5P_CLKSRC_PERIL0 S5P_CLKREG(0x0C250) 34#define S5P_CLKSRC_PERIL0 S5P_CLKREG(0x0C250)
35#define S5P_CLKSRC_PERIL1 S5P_CLKREG(0x0C254)
31 36
32#define S5P_CLKDIV_TOP S5P_CLKREG(0x0C510) 37#define S5P_CLKDIV_TOP S5P_CLKREG(0x0C510)
33 38#define S5P_CLKDIV_CAM S5P_CLKREG(0x0C520)
39#define S5P_CLKDIV_IMAGE S5P_CLKREG(0x0C530)
40#define S5P_CLKDIV_LCD0 S5P_CLKREG(0x0C534)
41#define S5P_CLKDIV_LCD1 S5P_CLKREG(0x0C538)
42#define S5P_CLKDIV_FSYS0 S5P_CLKREG(0x0C540)
43#define S5P_CLKDIV_FSYS1 S5P_CLKREG(0x0C544)
44#define S5P_CLKDIV_FSYS2 S5P_CLKREG(0x0C548)
45#define S5P_CLKDIV_FSYS3 S5P_CLKREG(0x0C54C)
34#define S5P_CLKDIV_PERIL0 S5P_CLKREG(0x0C550) 46#define S5P_CLKDIV_PERIL0 S5P_CLKREG(0x0C550)
35#define S5P_CLKDIV_PERIL1 S5P_CLKREG(0x0C554) 47#define S5P_CLKDIV_PERIL1 S5P_CLKREG(0x0C554)
36#define S5P_CLKDIV_PERIL2 S5P_CLKREG(0x0C558) 48#define S5P_CLKDIV_PERIL2 S5P_CLKREG(0x0C558)
@@ -38,9 +50,21 @@
38#define S5P_CLKDIV_PERIL4 S5P_CLKREG(0x0C560) 50#define S5P_CLKDIV_PERIL4 S5P_CLKREG(0x0C560)
39#define S5P_CLKDIV_PERIL5 S5P_CLKREG(0x0C564) 51#define S5P_CLKDIV_PERIL5 S5P_CLKREG(0x0C564)
40 52
53#define S5P_CLKSRC_MASK_TOP S5P_CLKREG(0x0C310)
54#define S5P_CLKSRC_MASK_CAM S5P_CLKREG(0x0C320)
55#define S5P_CLKSRC_MASK_LCD0 S5P_CLKREG(0x0C334)
56#define S5P_CLKSRC_MASK_LCD1 S5P_CLKREG(0x0C338)
57#define S5P_CLKSRC_MASK_FSYS S5P_CLKREG(0x0C340)
41#define S5P_CLKSRC_MASK_PERIL0 S5P_CLKREG(0x0C350) 58#define S5P_CLKSRC_MASK_PERIL0 S5P_CLKREG(0x0C350)
59#define S5P_CLKSRC_MASK_PERIL1 S5P_CLKREG(0x0C354)
42 60
61#define S5P_CLKGATE_IP_CAM S5P_CLKREG(0x0C920)
62#define S5P_CLKGATE_IP_IMAGE S5P_CLKREG(0x0C930)
63#define S5P_CLKGATE_IP_LCD0 S5P_CLKREG(0x0C934)
64#define S5P_CLKGATE_IP_LCD1 S5P_CLKREG(0x0C938)
65#define S5P_CLKGATE_IP_FSYS S5P_CLKREG(0x0C940)
43#define S5P_CLKGATE_IP_PERIL S5P_CLKREG(0x0C950) 66#define S5P_CLKGATE_IP_PERIL S5P_CLKREG(0x0C950)
67#define S5P_CLKGATE_IP_PERIR S5P_CLKREG(0x0C960)
44 68
45#define S5P_CLKSRC_CORE S5P_CLKREG(0x10200) 69#define S5P_CLKSRC_CORE S5P_CLKREG(0x10200)
46#define S5P_CLKDIV_CORE0 S5P_CLKREG(0x10500) 70#define S5P_CLKDIV_CORE0 S5P_CLKREG(0x10500)
@@ -60,4 +84,8 @@
60 84
61#define S5P_CLKGATE_SCLKCPU S5P_CLKREG(0x14800) 85#define S5P_CLKGATE_SCLKCPU S5P_CLKREG(0x14800)
62 86
87/* Compatibility defines */
88
89#define S5P_EPLL_CON S5P_EPLL_CON0
90
63#endif /* __ASM_ARCH_REGS_CLOCK_H */ 91#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-gpio.h b/arch/arm/mach-s5pv310/include/mach/regs-gpio.h
new file mode 100644
index 000000000000..82e9e0c9d452
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/regs-gpio.h
@@ -0,0 +1,42 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/regs-gpio.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * S5PV310 - GPIO (including EINT) register definitions
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_REGS_GPIO_H
14#define __ASM_ARCH_REGS_GPIO_H __FILE__
15
16#include <mach/map.h>
17#include <mach/irqs.h>
18
19#define S5PV310_EINT40CON (S5P_VA_GPIO2 + 0xE00)
20#define S5P_EINT_CON(x) (S5PV310_EINT40CON + ((x) * 0x4))
21
22#define S5PV310_EINT40FLTCON0 (S5P_VA_GPIO2 + 0xE80)
23#define S5P_EINT_FLTCON(x) (S5PV310_EINT40FLTCON0 + ((x) * 0x4))
24
25#define S5PV310_EINT40MASK (S5P_VA_GPIO2 + 0xF00)
26#define S5P_EINT_MASK(x) (S5PV310_EINT40MASK + ((x) * 0x4))
27
28#define S5PV310_EINT40PEND (S5P_VA_GPIO2 + 0xF40)
29#define S5P_EINT_PEND(x) (S5PV310_EINT40PEND + ((x) * 0x4))
30
31#define EINT_REG_NR(x) (EINT_OFFSET(x) >> 3)
32
33#define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7))
34
35#define EINT_MODE S3C_GPIO_SFN(0xf)
36
37#define EINT_GPIO_0(x) S5PV310_GPX0(x)
38#define EINT_GPIO_1(x) S5PV310_GPX1(x)
39#define EINT_GPIO_2(x) S5PV310_GPX2(x)
40#define EINT_GPIO_3(x) S5PV310_GPX3(x)
41
42#endif /* __ASM_ARCH_REGS_GPIO_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-srom.h b/arch/arm/mach-s5pv310/include/mach/regs-srom.h
new file mode 100644
index 000000000000..1898b3e10550
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/regs-srom.h
@@ -0,0 +1,50 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/regs-srom.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * S5PV310 - SROMC register definitions
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_REGS_SROM_H
14#define __ASM_ARCH_REGS_SROM_H __FILE__
15
16#include <mach/map.h>
17
18#define S5PV310_SROMREG(x) (S5P_VA_SROMC + (x))
19
20#define S5PV310_SROM_BW S5PV310_SROMREG(0x0)
21#define S5PV310_SROM_BC0 S5PV310_SROMREG(0x4)
22#define S5PV310_SROM_BC1 S5PV310_SROMREG(0x8)
23#define S5PV310_SROM_BC2 S5PV310_SROMREG(0xc)
24#define S5PV310_SROM_BC3 S5PV310_SROMREG(0x10)
25
26/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */
27
28#define S5PV310_SROM_BW__DATAWIDTH__SHIFT 0
29#define S5PV310_SROM_BW__ADDRMODE__SHIFT 1
30#define S5PV310_SROM_BW__WAITENABLE__SHIFT 2
31#define S5PV310_SROM_BW__BYTEENABLE__SHIFT 3
32
33#define S5PV310_SROM_BW__CS_MASK 0xf
34
35#define S5PV310_SROM_BW__NCS0__SHIFT 0
36#define S5PV310_SROM_BW__NCS1__SHIFT 4
37#define S5PV310_SROM_BW__NCS2__SHIFT 8
38#define S5PV310_SROM_BW__NCS3__SHIFT 12
39
40/* applies to same to BCS0 - BCS3 */
41
42#define S5PV310_SROM_BCX__PMC__SHIFT 0
43#define S5PV310_SROM_BCX__TACP__SHIFT 4
44#define S5PV310_SROM_BCX__TCAH__SHIFT 8
45#define S5PV310_SROM_BCX__TCOH__SHIFT 12
46#define S5PV310_SROM_BCX__TACC__SHIFT 16
47#define S5PV310_SROM_BCX__TCOS__SHIFT 24
48#define S5PV310_SROM_BCX__TACS__SHIFT 28
49
50#endif /* __ASM_ARCH_REGS_SROM_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/vmalloc.h b/arch/arm/mach-s5pv310/include/mach/vmalloc.h
index 256f221edf3a..65759fb97581 100644
--- a/arch/arm/mach-s5pv310/include/mach/vmalloc.h
+++ b/arch/arm/mach-s5pv310/include/mach/vmalloc.h
@@ -17,6 +17,6 @@
17#ifndef __ASM_ARCH_VMALLOC_H 17#ifndef __ASM_ARCH_VMALLOC_H
18#define __ASM_ARCH_VMALLOC_H __FILE__ 18#define __ASM_ARCH_VMALLOC_H __FILE__
19 19
20#define VMALLOC_END (0xF0000000UL) 20#define VMALLOC_END 0xF6000000UL
21 21
22#endif /* __ASM_ARCH_VMALLOC_H */ 22#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5pv310/irq-combiner.c b/arch/arm/mach-s5pv310/irq-combiner.c
index 0f7052164f23..c3f88c3faf6c 100644
--- a/arch/arm/mach-s5pv310/irq-combiner.c
+++ b/arch/arm/mach-s5pv310/irq-combiner.c
@@ -66,11 +66,7 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
66 if (status == 0) 66 if (status == 0)
67 goto out; 67 goto out;
68 68
69 for (combiner_irq = 0; combiner_irq < 32; combiner_irq++) { 69 combiner_irq = __ffs(status);
70 if (status & 0x1)
71 break;
72 status >>= 1;
73 }
74 70
75 cascade_irq = combiner_irq + (chip_data->irq_offset & ~31); 71 cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
76 if (unlikely(cascade_irq >= NR_IRQS)) 72 if (unlikely(cascade_irq >= NR_IRQS))
diff --git a/arch/arm/mach-s5pv310/irq-eint.c b/arch/arm/mach-s5pv310/irq-eint.c
new file mode 100644
index 000000000000..5877503e92c3
--- /dev/null
+++ b/arch/arm/mach-s5pv310/irq-eint.c
@@ -0,0 +1,228 @@
1/* linux/arch/arm/mach-s5pv310/irq-eint.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * S5PV310 - IRQ EINT support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/irq.h>
16#include <linux/io.h>
17#include <linux/sysdev.h>
18#include <linux/gpio.h>
19
20#include <plat/pm.h>
21#include <plat/cpu.h>
22#include <plat/gpio-cfg.h>
23
24#include <mach/regs-gpio.h>
25
26static DEFINE_SPINLOCK(eint_lock);
27
28static unsigned int eint0_15_data[16];
29
30static unsigned int s5pv310_get_irq_nr(unsigned int number)
31{
32 u32 ret = 0;
33
34 switch (number) {
35 case 0 ... 3:
36 ret = (number + IRQ_EINT0);
37 break;
38 case 4 ... 7:
39 ret = (number + (IRQ_EINT4 - 4));
40 break;
41 case 8 ... 15:
42 ret = (number + (IRQ_EINT8 - 8));
43 break;
44 default:
45 printk(KERN_ERR "number available : %d\n", number);
46 }
47
48 return ret;
49}
50
51static inline void s5pv310_irq_eint_mask(unsigned int irq)
52{
53 u32 mask;
54
55 spin_lock(&eint_lock);
56 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(irq)));
57 mask |= eint_irq_to_bit(irq);
58 __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(irq)));
59 spin_unlock(&eint_lock);
60}
61
62static void s5pv310_irq_eint_unmask(unsigned int irq)
63{
64 u32 mask;
65
66 spin_lock(&eint_lock);
67 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(irq)));
68 mask &= ~(eint_irq_to_bit(irq));
69 __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(irq)));
70 spin_unlock(&eint_lock);
71}
72
73static inline void s5pv310_irq_eint_ack(unsigned int irq)
74{
75 __raw_writel(eint_irq_to_bit(irq), S5P_EINT_PEND(EINT_REG_NR(irq)));
76}
77
78static void s5pv310_irq_eint_maskack(unsigned int irq)
79{
80 s5pv310_irq_eint_mask(irq);
81 s5pv310_irq_eint_ack(irq);
82}
83
84static int s5pv310_irq_eint_set_type(unsigned int irq, unsigned int type)
85{
86 int offs = EINT_OFFSET(irq);
87 int shift;
88 u32 ctrl, mask;
89 u32 newvalue = 0;
90
91 switch (type) {
92 case IRQ_TYPE_EDGE_RISING:
93 newvalue = S5P_IRQ_TYPE_EDGE_RISING;
94 break;
95
96 case IRQ_TYPE_EDGE_FALLING:
97 newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
98 break;
99
100 case IRQ_TYPE_EDGE_BOTH:
101 newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
102 break;
103
104 case IRQ_TYPE_LEVEL_LOW:
105 newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
106 break;
107
108 case IRQ_TYPE_LEVEL_HIGH:
109 newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
110 break;
111
112 default:
113 printk(KERN_ERR "No such irq type %d", type);
114 return -EINVAL;
115 }
116
117 shift = (offs & 0x7) * 4;
118 mask = 0x7 << shift;
119
120 spin_lock(&eint_lock);
121 ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(irq)));
122 ctrl &= ~mask;
123 ctrl |= newvalue << shift;
124 __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(irq)));
125 spin_unlock(&eint_lock);
126
127 switch (offs) {
128 case 0 ... 7:
129 s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
130 break;
131 case 8 ... 15:
132 s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
133 break;
134 case 16 ... 23:
135 s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
136 break;
137 case 24 ... 31:
138 s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
139 break;
140 default:
141 printk(KERN_ERR "No such irq number %d", offs);
142 }
143
144 return 0;
145}
146
147static struct irq_chip s5pv310_irq_eint = {
148 .name = "s5pv310-eint",
149 .mask = s5pv310_irq_eint_mask,
150 .unmask = s5pv310_irq_eint_unmask,
151 .mask_ack = s5pv310_irq_eint_maskack,
152 .ack = s5pv310_irq_eint_ack,
153 .set_type = s5pv310_irq_eint_set_type,
154#ifdef CONFIG_PM
155 .set_wake = s3c_irqext_wake,
156#endif
157};
158
159/* s5pv310_irq_demux_eint
160 *
161 * This function demuxes the IRQ from from EINTs 16 to 31.
162 * It is designed to be inlined into the specific handler
163 * s5p_irq_demux_eintX_Y.
164 *
165 * Each EINT pend/mask registers handle eight of them.
166 */
167static inline void s5pv310_irq_demux_eint(unsigned int start)
168{
169 unsigned int irq;
170
171 u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
172 u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
173
174 status &= ~mask;
175 status &= 0xff;
176
177 while (status) {
178 irq = fls(status) - 1;
179 generic_handle_irq(irq + start);
180 status &= ~(1 << irq);
181 }
182}
183
184static void s5pv310_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
185{
186 s5pv310_irq_demux_eint(IRQ_EINT(16));
187 s5pv310_irq_demux_eint(IRQ_EINT(24));
188}
189
190static void s5pv310_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
191{
192 u32 *irq_data = get_irq_data(irq);
193 struct irq_chip *chip = get_irq_chip(irq);
194
195 chip->mask(irq);
196
197 if (chip->ack)
198 chip->ack(irq);
199
200 generic_handle_irq(*irq_data);
201
202 chip->unmask(irq);
203}
204
205int __init s5pv310_init_irq_eint(void)
206{
207 int irq;
208
209 for (irq = 0 ; irq <= 31 ; irq++) {
210 set_irq_chip(IRQ_EINT(irq), &s5pv310_irq_eint);
211 set_irq_handler(IRQ_EINT(irq), handle_level_irq);
212 set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
213 }
214
215 set_irq_chained_handler(IRQ_EINT16_31, s5pv310_irq_demux_eint16_31);
216
217 for (irq = 0 ; irq <= 15 ; irq++) {
218 eint0_15_data[irq] = IRQ_EINT(irq);
219
220 set_irq_data(s5pv310_get_irq_nr(irq), &eint0_15_data[irq]);
221 set_irq_chained_handler(s5pv310_get_irq_nr(irq),
222 s5pv310_irq_eint0_15);
223 }
224
225 return 0;
226}
227
228arch_initcall(s5pv310_init_irq_eint);
diff --git a/arch/arm/mach-s5pv310/mach-smdkc210.c b/arch/arm/mach-s5pv310/mach-smdkc210.c
new file mode 100644
index 000000000000..2b8d4fc52d7c
--- /dev/null
+++ b/arch/arm/mach-s5pv310/mach-smdkc210.c
@@ -0,0 +1,202 @@
1/* linux/arch/arm/mach-s5pv310/mach-smdkc210.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9*/
10
11#include <linux/serial_core.h>
12#include <linux/gpio.h>
13#include <linux/mmc/host.h>
14#include <linux/platform_device.h>
15#include <linux/smsc911x.h>
16#include <linux/io.h>
17
18#include <asm/mach/arch.h>
19#include <asm/mach-types.h>
20
21#include <plat/regs-serial.h>
22#include <plat/s5pv310.h>
23#include <plat/cpu.h>
24#include <plat/devs.h>
25#include <plat/sdhci.h>
26
27#include <mach/map.h>
28#include <mach/regs-srom.h>
29
30/* Following are default values for UCON, ULCON and UFCON UART registers */
31#define SMDKC210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
32 S3C2410_UCON_RXILEVEL | \
33 S3C2410_UCON_TXIRQMODE | \
34 S3C2410_UCON_RXIRQMODE | \
35 S3C2410_UCON_RXFIFO_TOI | \
36 S3C2443_UCON_RXERR_IRQEN)
37
38#define SMDKC210_ULCON_DEFAULT S3C2410_LCON_CS8
39
40#define SMDKC210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
41 S5PV210_UFCON_TXTRIG4 | \
42 S5PV210_UFCON_RXTRIG4)
43
44static struct s3c2410_uartcfg smdkc210_uartcfgs[] __initdata = {
45 [0] = {
46 .hwport = 0,
47 .flags = 0,
48 .ucon = SMDKC210_UCON_DEFAULT,
49 .ulcon = SMDKC210_ULCON_DEFAULT,
50 .ufcon = SMDKC210_UFCON_DEFAULT,
51 },
52 [1] = {
53 .hwport = 1,
54 .flags = 0,
55 .ucon = SMDKC210_UCON_DEFAULT,
56 .ulcon = SMDKC210_ULCON_DEFAULT,
57 .ufcon = SMDKC210_UFCON_DEFAULT,
58 },
59 [2] = {
60 .hwport = 2,
61 .flags = 0,
62 .ucon = SMDKC210_UCON_DEFAULT,
63 .ulcon = SMDKC210_ULCON_DEFAULT,
64 .ufcon = SMDKC210_UFCON_DEFAULT,
65 },
66 [3] = {
67 .hwport = 3,
68 .flags = 0,
69 .ucon = SMDKC210_UCON_DEFAULT,
70 .ulcon = SMDKC210_ULCON_DEFAULT,
71 .ufcon = SMDKC210_UFCON_DEFAULT,
72 },
73};
74
75static struct s3c_sdhci_platdata smdkc210_hsmmc0_pdata __initdata = {
76 .cd_type = S3C_SDHCI_CD_GPIO,
77 .ext_cd_gpio = S5PV310_GPK0(2),
78 .ext_cd_gpio_invert = 1,
79 .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
80#ifdef CONFIG_S5PV310_SDHCI_CH0_8BIT
81 .max_width = 8,
82 .host_caps = MMC_CAP_8_BIT_DATA,
83#endif
84};
85
86static struct s3c_sdhci_platdata smdkc210_hsmmc1_pdata __initdata = {
87 .cd_type = S3C_SDHCI_CD_GPIO,
88 .ext_cd_gpio = S5PV310_GPK0(2),
89 .ext_cd_gpio_invert = 1,
90 .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
91};
92
93static struct s3c_sdhci_platdata smdkc210_hsmmc2_pdata __initdata = {
94 .cd_type = S3C_SDHCI_CD_GPIO,
95 .ext_cd_gpio = S5PV310_GPK2(2),
96 .ext_cd_gpio_invert = 1,
97 .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
98#ifdef CONFIG_S5PV310_SDHCI_CH2_8BIT
99 .max_width = 8,
100 .host_caps = MMC_CAP_8_BIT_DATA,
101#endif
102};
103
104static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = {
105 .cd_type = S3C_SDHCI_CD_GPIO,
106 .ext_cd_gpio = S5PV310_GPK2(2),
107 .ext_cd_gpio_invert = 1,
108 .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
109};
110
111static struct resource smdkc210_smsc911x_resources[] = {
112 [0] = {
113 .start = S5PV310_PA_SROM_BANK(1),
114 .end = S5PV310_PA_SROM_BANK(1) + SZ_64K - 1,
115 .flags = IORESOURCE_MEM,
116 },
117 [1] = {
118 .start = IRQ_EINT(5),
119 .end = IRQ_EINT(5),
120 .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
121 },
122};
123
124static struct smsc911x_platform_config smsc9215_config = {
125 .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
126 .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
127 .flags = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
128 .phy_interface = PHY_INTERFACE_MODE_MII,
129 .mac = {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
130};
131
132static struct platform_device smdkc210_smsc911x = {
133 .name = "smsc911x",
134 .id = -1,
135 .num_resources = ARRAY_SIZE(smdkc210_smsc911x_resources),
136 .resource = smdkc210_smsc911x_resources,
137 .dev = {
138 .platform_data = &smsc9215_config,
139 },
140};
141
142static struct platform_device *smdkc210_devices[] __initdata = {
143 &s3c_device_hsmmc0,
144 &s3c_device_hsmmc1,
145 &s3c_device_hsmmc2,
146 &s3c_device_hsmmc3,
147 &s3c_device_rtc,
148 &s3c_device_wdt,
149 &smdkc210_smsc911x,
150};
151
152static void __init smdkc210_smsc911x_init(void)
153{
154 u32 cs1;
155
156 /* configure nCS1 width to 16 bits */
157 cs1 = __raw_readl(S5PV310_SROM_BW) &
158 ~(S5PV310_SROM_BW__CS_MASK <<
159 S5PV310_SROM_BW__NCS1__SHIFT);
160 cs1 |= ((1 << S5PV310_SROM_BW__DATAWIDTH__SHIFT) |
161 (1 << S5PV310_SROM_BW__WAITENABLE__SHIFT) |
162 (1 << S5PV310_SROM_BW__BYTEENABLE__SHIFT)) <<
163 S5PV310_SROM_BW__NCS1__SHIFT;
164 __raw_writel(cs1, S5PV310_SROM_BW);
165
166 /* set timing for nCS1 suitable for ethernet chip */
167 __raw_writel((0x1 << S5PV310_SROM_BCX__PMC__SHIFT) |
168 (0x9 << S5PV310_SROM_BCX__TACP__SHIFT) |
169 (0xc << S5PV310_SROM_BCX__TCAH__SHIFT) |
170 (0x1 << S5PV310_SROM_BCX__TCOH__SHIFT) |
171 (0x6 << S5PV310_SROM_BCX__TACC__SHIFT) |
172 (0x1 << S5PV310_SROM_BCX__TCOS__SHIFT) |
173 (0x1 << S5PV310_SROM_BCX__TACS__SHIFT), S5PV310_SROM_BC1);
174}
175
176static void __init smdkc210_map_io(void)
177{
178 s5p_init_io(NULL, 0, S5P_VA_CHIPID);
179 s3c24xx_init_clocks(24000000);
180 s3c24xx_init_uarts(smdkc210_uartcfgs, ARRAY_SIZE(smdkc210_uartcfgs));
181}
182
183static void __init smdkc210_machine_init(void)
184{
185 smdkc210_smsc911x_init();
186
187 s3c_sdhci0_set_platdata(&smdkc210_hsmmc0_pdata);
188 s3c_sdhci1_set_platdata(&smdkc210_hsmmc1_pdata);
189 s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata);
190 s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata);
191
192 platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices));
193}
194
195MACHINE_START(SMDKC210, "SMDKC210")
196 /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
197 .boot_params = S5P_PA_SDRAM + 0x100,
198 .init_irq = s5pv310_init_irq,
199 .map_io = smdkc210_map_io,
200 .init_machine = smdkc210_machine_init,
201 .timer = &s5pv310_timer,
202MACHINE_END
diff --git a/arch/arm/mach-s5pv310/mach-smdkv310.c b/arch/arm/mach-s5pv310/mach-smdkv310.c
index 46215a14b3bb..35826d66632c 100644
--- a/arch/arm/mach-s5pv310/mach-smdkv310.c
+++ b/arch/arm/mach-s5pv310/mach-smdkv310.c
@@ -9,16 +9,23 @@
9*/ 9*/
10 10
11#include <linux/serial_core.h> 11#include <linux/serial_core.h>
12#include <linux/gpio.h>
13#include <linux/mmc/host.h>
14#include <linux/platform_device.h>
15#include <linux/smsc911x.h>
16#include <linux/io.h>
12 17
13#include <asm/mach/arch.h> 18#include <asm/mach/arch.h>
14#include <asm/mach-types.h> 19#include <asm/mach-types.h>
15#include <asm/hardware/cache-l2x0.h>
16 20
17#include <plat/regs-serial.h> 21#include <plat/regs-serial.h>
18#include <plat/s5pv310.h> 22#include <plat/s5pv310.h>
19#include <plat/cpu.h> 23#include <plat/cpu.h>
24#include <plat/devs.h>
25#include <plat/sdhci.h>
20 26
21#include <mach/map.h> 27#include <mach/map.h>
28#include <mach/regs-srom.h>
22 29
23/* Following are default values for UCON, ULCON and UFCON UART registers */ 30/* Following are default values for UCON, ULCON and UFCON UART registers */
24#define SMDKV310_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ 31#define SMDKV310_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -65,6 +72,107 @@ static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
65 }, 72 },
66}; 73};
67 74
75static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = {
76 .cd_type = S3C_SDHCI_CD_GPIO,
77 .ext_cd_gpio = S5PV310_GPK0(2),
78 .ext_cd_gpio_invert = 1,
79 .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
80#ifdef CONFIG_S5PV310_SDHCI_CH0_8BIT
81 .max_width = 8,
82 .host_caps = MMC_CAP_8_BIT_DATA,
83#endif
84};
85
86static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = {
87 .cd_type = S3C_SDHCI_CD_GPIO,
88 .ext_cd_gpio = S5PV310_GPK0(2),
89 .ext_cd_gpio_invert = 1,
90 .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
91};
92
93static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = {
94 .cd_type = S3C_SDHCI_CD_GPIO,
95 .ext_cd_gpio = S5PV310_GPK2(2),
96 .ext_cd_gpio_invert = 1,
97 .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
98#ifdef CONFIG_S5PV310_SDHCI_CH2_8BIT
99 .max_width = 8,
100 .host_caps = MMC_CAP_8_BIT_DATA,
101#endif
102};
103
104static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = {
105 .cd_type = S3C_SDHCI_CD_GPIO,
106 .ext_cd_gpio = S5PV310_GPK2(2),
107 .ext_cd_gpio_invert = 1,
108 .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
109};
110
111static struct resource smdkv310_smsc911x_resources[] = {
112 [0] = {
113 .start = S5PV310_PA_SROM_BANK(1),
114 .end = S5PV310_PA_SROM_BANK(1) + SZ_64K - 1,
115 .flags = IORESOURCE_MEM,
116 },
117 [1] = {
118 .start = IRQ_EINT(5),
119 .end = IRQ_EINT(5),
120 .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
121 },
122};
123
124static struct smsc911x_platform_config smsc9215_config = {
125 .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
126 .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
127 .flags = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
128 .phy_interface = PHY_INTERFACE_MODE_MII,
129 .mac = {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
130};
131
132static struct platform_device smdkv310_smsc911x = {
133 .name = "smsc911x",
134 .id = -1,
135 .num_resources = ARRAY_SIZE(smdkv310_smsc911x_resources),
136 .resource = smdkv310_smsc911x_resources,
137 .dev = {
138 .platform_data = &smsc9215_config,
139 },
140};
141
142static struct platform_device *smdkv310_devices[] __initdata = {
143 &s3c_device_hsmmc0,
144 &s3c_device_hsmmc1,
145 &s3c_device_hsmmc2,
146 &s3c_device_hsmmc3,
147 &s3c_device_rtc,
148 &s3c_device_wdt,
149 &smdkv310_smsc911x,
150};
151
152static void __init smdkv310_smsc911x_init(void)
153{
154 u32 cs1;
155
156 /* configure nCS1 width to 16 bits */
157 cs1 = __raw_readl(S5PV310_SROM_BW) &
158 ~(S5PV310_SROM_BW__CS_MASK <<
159 S5PV310_SROM_BW__NCS1__SHIFT);
160 cs1 |= ((1 << S5PV310_SROM_BW__DATAWIDTH__SHIFT) |
161 (1 << S5PV310_SROM_BW__WAITENABLE__SHIFT) |
162 (1 << S5PV310_SROM_BW__BYTEENABLE__SHIFT)) <<
163 S5PV310_SROM_BW__NCS1__SHIFT;
164 __raw_writel(cs1, S5PV310_SROM_BW);
165
166 /* set timing for nCS1 suitable for ethernet chip */
167 __raw_writel((0x1 << S5PV310_SROM_BCX__PMC__SHIFT) |
168 (0x9 << S5PV310_SROM_BCX__TACP__SHIFT) |
169 (0xc << S5PV310_SROM_BCX__TCAH__SHIFT) |
170 (0x1 << S5PV310_SROM_BCX__TCOH__SHIFT) |
171 (0x6 << S5PV310_SROM_BCX__TACC__SHIFT) |
172 (0x1 << S5PV310_SROM_BCX__TCOS__SHIFT) |
173 (0x1 << S5PV310_SROM_BCX__TACS__SHIFT), S5PV310_SROM_BC1);
174}
175
68static void __init smdkv310_map_io(void) 176static void __init smdkv310_map_io(void)
69{ 177{
70 s5p_init_io(NULL, 0, S5P_VA_CHIPID); 178 s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -74,9 +182,14 @@ static void __init smdkv310_map_io(void)
74 182
75static void __init smdkv310_machine_init(void) 183static void __init smdkv310_machine_init(void)
76{ 184{
77#ifdef CONFIG_CACHE_L2X0 185 smdkv310_smsc911x_init();
78 l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff); 186
79#endif 187 s3c_sdhci0_set_platdata(&smdkv310_hsmmc0_pdata);
188 s3c_sdhci1_set_platdata(&smdkv310_hsmmc1_pdata);
189 s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata);
190 s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata);
191
192 platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
80} 193}
81 194
82MACHINE_START(SMDKV310, "SMDKV310") 195MACHINE_START(SMDKV310, "SMDKV310")
diff --git a/arch/arm/mach-s5pv310/mach-universal_c210.c b/arch/arm/mach-s5pv310/mach-universal_c210.c
index d7c2ec770f88..16d8fc00cafd 100644
--- a/arch/arm/mach-s5pv310/mach-universal_c210.c
+++ b/arch/arm/mach-s5pv310/mach-universal_c210.c
@@ -7,15 +7,20 @@
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8*/ 8*/
9 9
10#include <linux/platform_device.h>
10#include <linux/serial_core.h> 11#include <linux/serial_core.h>
12#include <linux/input.h>
13#include <linux/i2c.h>
14#include <linux/gpio_keys.h>
15#include <linux/gpio.h>
11 16
12#include <asm/mach/arch.h> 17#include <asm/mach/arch.h>
13#include <asm/mach-types.h> 18#include <asm/mach-types.h>
14#include <asm/hardware/cache-l2x0.h>
15 19
16#include <plat/regs-serial.h> 20#include <plat/regs-serial.h>
17#include <plat/s5pv310.h> 21#include <plat/s5pv310.h>
18#include <plat/cpu.h> 22#include <plat/cpu.h>
23#include <plat/devs.h>
19 24
20#include <mach/map.h> 25#include <mach/map.h>
21 26
@@ -60,6 +65,72 @@ static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = {
60 }, 65 },
61}; 66};
62 67
68static struct gpio_keys_button universal_gpio_keys_tables[] = {
69 {
70 .code = KEY_VOLUMEUP,
71 .gpio = S5PV310_GPX2(0), /* XEINT16 */
72 .desc = "gpio-keys: KEY_VOLUMEUP",
73 .type = EV_KEY,
74 .active_low = 1,
75 .debounce_interval = 1,
76 }, {
77 .code = KEY_VOLUMEDOWN,
78 .gpio = S5PV310_GPX2(1), /* XEINT17 */
79 .desc = "gpio-keys: KEY_VOLUMEDOWN",
80 .type = EV_KEY,
81 .active_low = 1,
82 .debounce_interval = 1,
83 }, {
84 .code = KEY_CONFIG,
85 .gpio = S5PV310_GPX2(2), /* XEINT18 */
86 .desc = "gpio-keys: KEY_CONFIG",
87 .type = EV_KEY,
88 .active_low = 1,
89 .debounce_interval = 1,
90 }, {
91 .code = KEY_CAMERA,
92 .gpio = S5PV310_GPX2(3), /* XEINT19 */
93 .desc = "gpio-keys: KEY_CAMERA",
94 .type = EV_KEY,
95 .active_low = 1,
96 .debounce_interval = 1,
97 }, {
98 .code = KEY_OK,
99 .gpio = S5PV310_GPX3(5), /* XEINT29 */
100 .desc = "gpio-keys: KEY_OK",
101 .type = EV_KEY,
102 .active_low = 1,
103 .debounce_interval = 1,
104 },
105};
106
107static struct gpio_keys_platform_data universal_gpio_keys_data = {
108 .buttons = universal_gpio_keys_tables,
109 .nbuttons = ARRAY_SIZE(universal_gpio_keys_tables),
110};
111
112static struct platform_device universal_gpio_keys = {
113 .name = "gpio-keys",
114 .dev = {
115 .platform_data = &universal_gpio_keys_data,
116 },
117};
118
119/* I2C0 */
120static struct i2c_board_info i2c0_devs[] __initdata = {
121 /* Camera, To be updated */
122};
123
124/* I2C1 */
125static struct i2c_board_info i2c1_devs[] __initdata = {
126 /* Gyro, To be updated */
127};
128
129static struct platform_device *universal_devices[] __initdata = {
130 &universal_gpio_keys,
131 &s5p_device_onenand,
132};
133
63static void __init universal_map_io(void) 134static void __init universal_map_io(void)
64{ 135{
65 s5p_init_io(NULL, 0, S5P_VA_CHIPID); 136 s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -69,9 +140,11 @@ static void __init universal_map_io(void)
69 140
70static void __init universal_machine_init(void) 141static void __init universal_machine_init(void)
71{ 142{
72#ifdef CONFIG_CACHE_L2X0 143 i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
73 l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff); 144 i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
74#endif 145
146 /* Last */
147 platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
75} 148}
76 149
77MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210") 150MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
diff --git a/arch/arm/mach-s5pv310/setup-i2c0.c b/arch/arm/mach-s5pv310/setup-i2c0.c
index 436712807383..f47f8f3152ec 100644
--- a/arch/arm/mach-s5pv310/setup-i2c0.c
+++ b/arch/arm/mach-s5pv310/setup-i2c0.c
@@ -21,8 +21,6 @@ struct platform_device; /* don't need the contents */
21 21
22void s3c_i2c0_cfg_gpio(struct platform_device *dev) 22void s3c_i2c0_cfg_gpio(struct platform_device *dev)
23{ 23{
24 s3c_gpio_cfgpin(S5PV310_GPD1(0), S3C_GPIO_SFN(2)); 24 s3c_gpio_cfgall_range(S5PV310_GPD1(0), 2,
25 s3c_gpio_setpull(S5PV310_GPD1(0), S3C_GPIO_PULL_UP); 25 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
26 s3c_gpio_cfgpin(S5PV310_GPD1(1), S3C_GPIO_SFN(2));
27 s3c_gpio_setpull(S5PV310_GPD1(1), S3C_GPIO_PULL_UP);
28} 26}
diff --git a/arch/arm/mach-s5pv310/setup-i2c1.c b/arch/arm/mach-s5pv310/setup-i2c1.c
index 1ecd5bc35b5a..9d07e4e2f14c 100644
--- a/arch/arm/mach-s5pv310/setup-i2c1.c
+++ b/arch/arm/mach-s5pv310/setup-i2c1.c
@@ -18,8 +18,6 @@ struct platform_device; /* don't need the contents */
18 18
19void s3c_i2c1_cfg_gpio(struct platform_device *dev) 19void s3c_i2c1_cfg_gpio(struct platform_device *dev)
20{ 20{
21 s3c_gpio_cfgpin(S5PV310_GPD1(2), S3C_GPIO_SFN(2)); 21 s3c_gpio_cfgall_range(S5PV310_GPD1(2), 2,
22 s3c_gpio_setpull(S5PV310_GPD1(2), S3C_GPIO_PULL_UP); 22 S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
23 s3c_gpio_cfgpin(S5PV310_GPD1(3), S3C_GPIO_SFN(2));
24 s3c_gpio_setpull(S5PV310_GPD1(3), S3C_GPIO_PULL_UP);
25} 23}
diff --git a/arch/arm/mach-s5pv310/setup-i2c2.c b/arch/arm/mach-s5pv310/setup-i2c2.c
index 4c0d8def660a..4163b1233daf 100644
--- a/arch/arm/mach-s5pv310/setup-i2c2.c
+++ b/arch/arm/mach-s5pv310/setup-i2c2.c
@@ -18,8 +18,6 @@ struct platform_device; /* don't need the contents */
18 18
19void s3c_i2c2_cfg_gpio(struct platform_device *dev) 19void s3c_i2c2_cfg_gpio(struct platform_device *dev)
20{ 20{
21 s3c_gpio_cfgpin(S5PV310_GPA0(6), S3C_GPIO_SFN(3)); 21 s3c_gpio_cfgall_range(S5PV310_GPA0(6), 2,
22 s3c_gpio_setpull(S5PV310_GPA0(6), S3C_GPIO_PULL_UP); 22 S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
23 s3c_gpio_cfgpin(S5PV310_GPA0(7), S3C_GPIO_SFN(3));
24 s3c_gpio_setpull(S5PV310_GPA0(7), S3C_GPIO_PULL_UP);
25} 23}
diff --git a/arch/arm/mach-s5pv310/setup-i2c3.c b/arch/arm/mach-s5pv310/setup-i2c3.c
new file mode 100644
index 000000000000..180f153d2a20
--- /dev/null
+++ b/arch/arm/mach-s5pv310/setup-i2c3.c
@@ -0,0 +1,23 @@
1/*
2 * linux/arch/arm/mach-s5pv310/setup-i2c3.c
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 *
6 * I2C3 GPIO configuration.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13struct platform_device; /* don't need the contents */
14
15#include <linux/gpio.h>
16#include <plat/iic.h>
17#include <plat/gpio-cfg.h>
18
19void s3c_i2c3_cfg_gpio(struct platform_device *dev)
20{
21 s3c_gpio_cfgall_range(S5PV310_GPA1(2), 2,
22 S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
23}
diff --git a/arch/arm/mach-s5pv310/setup-i2c4.c b/arch/arm/mach-s5pv310/setup-i2c4.c
new file mode 100644
index 000000000000..909e8dfc5316
--- /dev/null
+++ b/arch/arm/mach-s5pv310/setup-i2c4.c
@@ -0,0 +1,23 @@
1/*
2 * linux/arch/arm/mach-s5pv310/setup-i2c4.c
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 *
6 * I2C4 GPIO configuration.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13struct platform_device; /* don't need the contents */
14
15#include <linux/gpio.h>
16#include <plat/iic.h>
17#include <plat/gpio-cfg.h>
18
19void s3c_i2c4_cfg_gpio(struct platform_device *dev)
20{
21 s3c_gpio_cfgall_range(S5PV310_GPB(2), 2,
22 S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
23}
diff --git a/arch/arm/mach-s5pv310/setup-i2c5.c b/arch/arm/mach-s5pv310/setup-i2c5.c
new file mode 100644
index 000000000000..5d0fa4ac0283
--- /dev/null
+++ b/arch/arm/mach-s5pv310/setup-i2c5.c
@@ -0,0 +1,23 @@
1/*
2 * linux/arch/arm/mach-s5pv310/setup-i2c5.c
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 *
6 * I2C5 GPIO configuration.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13struct platform_device; /* don't need the contents */
14
15#include <linux/gpio.h>
16#include <plat/iic.h>
17#include <plat/gpio-cfg.h>
18
19void s3c_i2c5_cfg_gpio(struct platform_device *dev)
20{
21 s3c_gpio_cfgall_range(S5PV310_GPB(6), 2,
22 S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
23}
diff --git a/arch/arm/mach-s5pv310/setup-i2c6.c b/arch/arm/mach-s5pv310/setup-i2c6.c
new file mode 100644
index 000000000000..34aafab92ac4
--- /dev/null
+++ b/arch/arm/mach-s5pv310/setup-i2c6.c
@@ -0,0 +1,23 @@
1/*
2 * linux/arch/arm/mach-s5pv310/setup-i2c6.c
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 *
6 * I2C6 GPIO configuration.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13struct platform_device; /* don't need the contents */
14
15#include <linux/gpio.h>
16#include <plat/iic.h>
17#include <plat/gpio-cfg.h>
18
19void s3c_i2c6_cfg_gpio(struct platform_device *dev)
20{
21 s3c_gpio_cfgall_range(S5PV310_GPC1(3), 2,
22 S3C_GPIO_SFN(4), S3C_GPIO_PULL_UP);
23}
diff --git a/arch/arm/mach-s5pv310/setup-i2c7.c b/arch/arm/mach-s5pv310/setup-i2c7.c
new file mode 100644
index 000000000000..9b25b8d18920
--- /dev/null
+++ b/arch/arm/mach-s5pv310/setup-i2c7.c
@@ -0,0 +1,23 @@
1/*
2 * linux/arch/arm/mach-s5pv310/setup-i2c7.c
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 *
6 * I2C7 GPIO configuration.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13struct platform_device; /* don't need the contents */
14
15#include <linux/gpio.h>
16#include <plat/iic.h>
17#include <plat/gpio-cfg.h>
18
19void s3c_i2c7_cfg_gpio(struct platform_device *dev)
20{
21 s3c_gpio_cfgall_range(S5PV310_GPD0(2), 2,
22 S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
23}
diff --git a/arch/arm/mach-s5pv310/setup-sdhci-gpio.c b/arch/arm/mach-s5pv310/setup-sdhci-gpio.c
new file mode 100644
index 000000000000..86d38cc49135
--- /dev/null
+++ b/arch/arm/mach-s5pv310/setup-sdhci-gpio.c
@@ -0,0 +1,152 @@
1/* linux/arch/arm/mach-s5pv310/setup-sdhci-gpio.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV310 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/interrupt.h>
16#include <linux/platform_device.h>
17#include <linux/io.h>
18#include <linux/gpio.h>
19#include <linux/mmc/host.h>
20#include <linux/mmc/card.h>
21
22#include <plat/gpio-cfg.h>
23#include <plat/regs-sdhci.h>
24#include <plat/sdhci.h>
25
26void s5pv310_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
27{
28 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
29 unsigned int gpio;
30
31 /* Set all the necessary GPK0[0:1] pins to special-function 2 */
32 for (gpio = S5PV310_GPK0(0); gpio < S5PV310_GPK0(2); gpio++) {
33 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
34 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
35 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
36 }
37
38 switch (width) {
39 case 8:
40 for (gpio = S5PV310_GPK1(3); gpio <= S5PV310_GPK1(6); gpio++) {
41 /* Data pin GPK1[3:6] to special-funtion 3 */
42 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
43 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
44 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
45 }
46 case 4:
47 for (gpio = S5PV310_GPK0(3); gpio <= S5PV310_GPK0(6); gpio++) {
48 /* Data pin GPK0[3:6] to special-funtion 2 */
49 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
50 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
51 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
52 }
53 default:
54 break;
55 }
56
57 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
58 s3c_gpio_cfgpin(S5PV310_GPK0(2), S3C_GPIO_SFN(2));
59 s3c_gpio_setpull(S5PV310_GPK0(2), S3C_GPIO_PULL_UP);
60 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
61 }
62}
63
64void s5pv310_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
65{
66 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
67 unsigned int gpio;
68
69 /* Set all the necessary GPK1[0:1] pins to special-function 2 */
70 for (gpio = S5PV310_GPK1(0); gpio < S5PV310_GPK1(2); gpio++) {
71 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
72 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
73 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
74 }
75
76 for (gpio = S5PV310_GPK1(3); gpio <= S5PV310_GPK1(6); gpio++) {
77 /* Data pin GPK1[3:6] to special-function 2 */
78 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
79 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
80 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
81 }
82
83 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
84 s3c_gpio_cfgpin(S5PV310_GPK1(2), S3C_GPIO_SFN(2));
85 s3c_gpio_setpull(S5PV310_GPK1(2), S3C_GPIO_PULL_UP);
86 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
87 }
88}
89
90void s5pv310_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
91{
92 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
93 unsigned int gpio;
94
95 /* Set all the necessary GPK2[0:1] pins to special-function 2 */
96 for (gpio = S5PV310_GPK2(0); gpio < S5PV310_GPK2(2); gpio++) {
97 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
98 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
99 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
100 }
101
102 switch (width) {
103 case 8:
104 for (gpio = S5PV310_GPK3(3); gpio <= S5PV310_GPK3(6); gpio++) {
105 /* Data pin GPK3[3:6] to special-function 3 */
106 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
107 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
108 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
109 }
110 case 4:
111 for (gpio = S5PV310_GPK2(3); gpio <= S5PV310_GPK2(6); gpio++) {
112 /* Data pin GPK2[3:6] to special-function 2 */
113 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
114 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
115 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
116 }
117 default:
118 break;
119 }
120
121 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
122 s3c_gpio_cfgpin(S5PV310_GPK2(2), S3C_GPIO_SFN(2));
123 s3c_gpio_setpull(S5PV310_GPK2(2), S3C_GPIO_PULL_UP);
124 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
125 }
126}
127
128void s5pv310_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
129{
130 struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
131 unsigned int gpio;
132
133 /* Set all the necessary GPK3[0:1] pins to special-function 2 */
134 for (gpio = S5PV310_GPK3(0); gpio < S5PV310_GPK3(2); gpio++) {
135 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
136 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
137 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
138 }
139
140 for (gpio = S5PV310_GPK3(3); gpio <= S5PV310_GPK3(6); gpio++) {
141 /* Data pin GPK3[3:6] to special-function 2 */
142 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
143 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
144 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
145 }
146
147 if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
148 s3c_gpio_cfgpin(S5PV310_GPK3(2), S3C_GPIO_SFN(2));
149 s3c_gpio_setpull(S5PV310_GPK3(2), S3C_GPIO_PULL_UP);
150 s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
151 }
152}
diff --git a/arch/arm/mach-s5pv310/setup-sdhci.c b/arch/arm/mach-s5pv310/setup-sdhci.c
new file mode 100644
index 000000000000..db8358fc4662
--- /dev/null
+++ b/arch/arm/mach-s5pv310/setup-sdhci.c
@@ -0,0 +1,69 @@
1/* linux/arch/arm/mach-s5pv310/setup-sdhci.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV310 - Helper functions for settign up SDHCI device(s) (HSMMC)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/interrupt.h>
16#include <linux/platform_device.h>
17#include <linux/io.h>
18
19#include <linux/mmc/card.h>
20#include <linux/mmc/host.h>
21
22#include <plat/regs-sdhci.h>
23
24/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
25
26char *s5pv310_hsmmc_clksrcs[4] = {
27 [0] = NULL,
28 [1] = NULL,
29 [2] = "sclk_mmc", /* mmc_bus */
30 [3] = NULL,
31};
32
33void s5pv310_setup_sdhci_cfg_card(struct platform_device *dev, void __iomem *r,
34 struct mmc_ios *ios, struct mmc_card *card)
35{
36 u32 ctrl2, ctrl3;
37
38 /* don't need to alter anything acording to card-type */
39
40 ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
41
42 /* select base clock source to HCLK */
43
44 ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
45
46 /*
47 * clear async mode, enable conflict mask, rx feedback ctrl, SD
48 * clk hold and no use debounce count
49 */
50
51 ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
52 S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
53 S3C_SDHCI_CTRL2_ENFBCLKRX |
54 S3C_SDHCI_CTRL2_DFCNT_NONE |
55 S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
56
57 /* Tx and Rx feedback clock delay control */
58
59 if (ios->clock < 25 * 1000000)
60 ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
61 S3C_SDHCI_CTRL3_FCSEL2 |
62 S3C_SDHCI_CTRL3_FCSEL1 |
63 S3C_SDHCI_CTRL3_FCSEL0);
64 else
65 ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
66
67 writel(ctrl2, r + S3C_SDHCI_CONTROL2);
68 writel(ctrl3, r + S3C_SDHCI_CONTROL3);
69}
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index c0a13ef5436f..96f7dc103b59 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -184,16 +184,15 @@ static int sa1100_target(struct cpufreq_policy *policy,
184{ 184{
185 unsigned int cur = sa11x0_getspeed(0); 185 unsigned int cur = sa11x0_getspeed(0);
186 unsigned int new_ppcr; 186 unsigned int new_ppcr;
187
188 struct cpufreq_freqs freqs; 187 struct cpufreq_freqs freqs;
188
189 new_ppcr = sa11x0_freq_to_ppcr(target_freq);
189 switch(relation){ 190 switch(relation){
190 case CPUFREQ_RELATION_L: 191 case CPUFREQ_RELATION_L:
191 new_ppcr = sa11x0_freq_to_ppcr(target_freq);
192 if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max) 192 if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
193 new_ppcr--; 193 new_ppcr--;
194 break; 194 break;
195 case CPUFREQ_RELATION_H: 195 case CPUFREQ_RELATION_H:
196 new_ppcr = sa11x0_freq_to_ppcr(target_freq);
197 if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) && 196 if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) &&
198 (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min)) 197 (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min))
199 new_ppcr--; 198 new_ppcr--;
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 22a2b44ddb7b..46ca4d4abf91 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -30,7 +30,6 @@
30#include <linux/mtd/mtd.h> 30#include <linux/mtd/mtd.h>
31#include <linux/mtd/partitions.h> 31#include <linux/mtd/partitions.h>
32#include <linux/mtd/physmap.h> 32#include <linux/mtd/physmap.h>
33#include <linux/mmc/host.h>
34#include <linux/mmc/sh_mmcif.h> 33#include <linux/mmc/sh_mmcif.h>
35#include <linux/i2c.h> 34#include <linux/i2c.h>
36#include <linux/i2c/tsc2007.h> 35#include <linux/i2c/tsc2007.h>
@@ -44,6 +43,10 @@
44#include <linux/input/sh_keysc.h> 43#include <linux/input/sh_keysc.h>
45#include <linux/usb/r8a66597.h> 44#include <linux/usb/r8a66597.h>
46 45
46#include <media/sh_mobile_ceu.h>
47#include <media/sh_mobile_csi2.h>
48#include <media/soc_camera.h>
49
47#include <sound/sh_fsi.h> 50#include <sound/sh_fsi.h>
48 51
49#include <video/sh_mobile_hdmi.h> 52#include <video/sh_mobile_hdmi.h>
@@ -250,7 +253,7 @@ static int slot_cn7_get_cd(struct platform_device *pdev)
250/* SH_MMCIF */ 253/* SH_MMCIF */
251static struct resource sh_mmcif_resources[] = { 254static struct resource sh_mmcif_resources[] = {
252 [0] = { 255 [0] = {
253 .name = "SH_MMCIF", 256 .name = "MMCIF",
254 .start = 0xE6BD0000, 257 .start = 0xE6BD0000,
255 .end = 0xE6BD00FF, 258 .end = 0xE6BD00FF,
256 .flags = IORESOURCE_MEM, 259 .flags = IORESOURCE_MEM,
@@ -390,10 +393,40 @@ static struct platform_device usb1_host_device = {
390 .resource = usb1_host_resources, 393 .resource = usb1_host_resources,
391}; 394};
392 395
396const static struct fb_videomode ap4evb_lcdc_modes[] = {
397 {
398#ifdef CONFIG_AP4EVB_QHD
399 .name = "R63302(QHD)",
400 .xres = 544,
401 .yres = 961,
402 .left_margin = 72,
403 .right_margin = 600,
404 .hsync_len = 16,
405 .upper_margin = 8,
406 .lower_margin = 8,
407 .vsync_len = 2,
408 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
409#else
410 .name = "WVGA Panel",
411 .xres = 800,
412 .yres = 480,
413 .left_margin = 220,
414 .right_margin = 110,
415 .hsync_len = 70,
416 .upper_margin = 20,
417 .lower_margin = 5,
418 .vsync_len = 5,
419 .sync = 0,
420#endif
421 },
422};
423
393static struct sh_mobile_lcdc_info lcdc_info = { 424static struct sh_mobile_lcdc_info lcdc_info = {
394 .ch[0] = { 425 .ch[0] = {
395 .chan = LCDC_CHAN_MAINLCD, 426 .chan = LCDC_CHAN_MAINLCD,
396 .bpp = 16, 427 .bpp = 16,
428 .lcd_cfg = ap4evb_lcdc_modes,
429 .num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes),
397 } 430 }
398}; 431};
399 432
@@ -532,27 +565,6 @@ static struct platform_device *qhd_devices[] __initdata = {
532 565
533/* FSI */ 566/* FSI */
534#define IRQ_FSI evt2irq(0x1840) 567#define IRQ_FSI evt2irq(0x1840)
535#define FSIACKCR 0xE6150018
536static void fsiackcr_init(struct clk *clk)
537{
538 u32 status = __raw_readl(clk->enable_reg);
539
540 /* use external clock */
541 status &= ~0x000000ff;
542 status |= 0x00000080;
543 __raw_writel(status, clk->enable_reg);
544}
545
546static struct clk_ops fsiackcr_clk_ops = {
547 .init = fsiackcr_init,
548};
549
550static struct clk fsiackcr_clk = {
551 .ops = &fsiackcr_clk_ops,
552 .enable_reg = (void __iomem *)FSIACKCR,
553 .rate = 0, /* unknown */
554};
555
556static struct sh_fsi_platform_info fsi_info = { 568static struct sh_fsi_platform_info fsi_info = {
557 .porta_flags = SH_FSI_BRS_INV | 569 .porta_flags = SH_FSI_BRS_INV |
558 SH_FSI_OUT_SLAVE_MODE | 570 SH_FSI_OUT_SLAVE_MODE |
@@ -592,26 +604,6 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
592 .interface_type = RGB24, 604 .interface_type = RGB24,
593 .clock_divider = 1, 605 .clock_divider = 1,
594 .flags = LCDC_FLAGS_DWPOL, 606 .flags = LCDC_FLAGS_DWPOL,
595 .lcd_cfg = {
596 .name = "HDMI",
597 /* So far only 720p is supported */
598 .xres = 1280,
599 .yres = 720,
600 /*
601 * If left and right margins are not multiples of 8,
602 * LDHAJR will be adjusted accordingly by the LCDC
603 * driver. Until we start using EDID, these values
604 * might have to be adjusted for different monitors.
605 */
606 .left_margin = 200,
607 .right_margin = 88,
608 .hsync_len = 48,
609 .upper_margin = 20,
610 .lower_margin = 5,
611 .vsync_len = 5,
612 .pixclock = 13468,
613 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
614 },
615 } 607 }
616}; 608};
617 609
@@ -623,7 +615,7 @@ static struct resource lcdc1_resources[] = {
623 .flags = IORESOURCE_MEM, 615 .flags = IORESOURCE_MEM,
624 }, 616 },
625 [1] = { 617 [1] = {
626 .start = intcs_evt2irq(0x17a0), 618 .start = intcs_evt2irq(0x1780),
627 .flags = IORESOURCE_IRQ, 619 .flags = IORESOURCE_IRQ,
628 }, 620 },
629}; 621};
@@ -704,6 +696,95 @@ static struct platform_device leds_device = {
704 }, 696 },
705}; 697};
706 698
699static struct i2c_board_info imx074_info = {
700 I2C_BOARD_INFO("imx074", 0x1a),
701};
702
703struct soc_camera_link imx074_link = {
704 .bus_id = 0,
705 .board_info = &imx074_info,
706 .i2c_adapter_id = 0,
707 .module_name = "imx074",
708};
709
710static struct platform_device ap4evb_camera = {
711 .name = "soc-camera-pdrv",
712 .id = 0,
713 .dev = {
714 .platform_data = &imx074_link,
715 },
716};
717
718static struct sh_csi2_client_config csi2_clients[] = {
719 {
720 .phy = SH_CSI2_PHY_MAIN,
721 .lanes = 3,
722 .channel = 0,
723 .pdev = &ap4evb_camera,
724 },
725};
726
727static struct sh_csi2_pdata csi2_info = {
728 .type = SH_CSI2C,
729 .clients = csi2_clients,
730 .num_clients = ARRAY_SIZE(csi2_clients),
731 .flags = SH_CSI2_ECC | SH_CSI2_CRC,
732};
733
734static struct resource csi2_resources[] = {
735 [0] = {
736 .name = "CSI2",
737 .start = 0xffc90000,
738 .end = 0xffc90fff,
739 .flags = IORESOURCE_MEM,
740 },
741 [1] = {
742 .start = intcs_evt2irq(0x17a0),
743 .flags = IORESOURCE_IRQ,
744 },
745};
746
747static struct platform_device csi2_device = {
748 .name = "sh-mobile-csi2",
749 .id = 0,
750 .num_resources = ARRAY_SIZE(csi2_resources),
751 .resource = csi2_resources,
752 .dev = {
753 .platform_data = &csi2_info,
754 },
755};
756
757static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
758 .flags = SH_CEU_FLAG_USE_8BIT_BUS,
759 .csi2_dev = &csi2_device.dev,
760};
761
762static struct resource ceu_resources[] = {
763 [0] = {
764 .name = "CEU",
765 .start = 0xfe910000,
766 .end = 0xfe91009f,
767 .flags = IORESOURCE_MEM,
768 },
769 [1] = {
770 .start = intcs_evt2irq(0x880),
771 .flags = IORESOURCE_IRQ,
772 },
773 [2] = {
774 /* place holder for contiguous memory */
775 },
776};
777
778static struct platform_device ceu_device = {
779 .name = "sh_mobile_ceu",
780 .id = 0, /* "ceu0" clock */
781 .num_resources = ARRAY_SIZE(ceu_resources),
782 .resource = ceu_resources,
783 .dev = {
784 .platform_data = &sh_mobile_ceu_info,
785 },
786};
787
707static struct platform_device *ap4evb_devices[] __initdata = { 788static struct platform_device *ap4evb_devices[] __initdata = {
708 &leds_device, 789 &leds_device,
709 &nor_flash_device, 790 &nor_flash_device,
@@ -716,6 +797,9 @@ static struct platform_device *ap4evb_devices[] __initdata = {
716 &lcdc1_device, 797 &lcdc1_device,
717 &lcdc_device, 798 &lcdc_device,
718 &hdmi_device, 799 &hdmi_device,
800 &csi2_device,
801 &ceu_device,
802 &ap4evb_camera,
719}; 803};
720 804
721static int __init hdmi_init_pm_clock(void) 805static int __init hdmi_init_pm_clock(void)
@@ -730,22 +814,22 @@ static int __init hdmi_init_pm_clock(void)
730 goto out; 814 goto out;
731 } 815 }
732 816
733 ret = clk_set_parent(&pllc2_clk, &dv_clki_div2_clk); 817 ret = clk_set_parent(&sh7372_pllc2_clk, &sh7372_dv_clki_div2_clk);
734 if (ret < 0) { 818 if (ret < 0) {
735 pr_err("Cannot set PLLC2 parent: %d, %d users\n", ret, pllc2_clk.usecount); 819 pr_err("Cannot set PLLC2 parent: %d, %d users\n", ret, sh7372_pllc2_clk.usecount);
736 goto out; 820 goto out;
737 } 821 }
738 822
739 pr_debug("PLLC2 initial frequency %lu\n", clk_get_rate(&pllc2_clk)); 823 pr_debug("PLLC2 initial frequency %lu\n", clk_get_rate(&sh7372_pllc2_clk));
740 824
741 rate = clk_round_rate(&pllc2_clk, 594000000); 825 rate = clk_round_rate(&sh7372_pllc2_clk, 594000000);
742 if (rate < 0) { 826 if (rate < 0) {
743 pr_err("Cannot get suitable rate: %ld\n", rate); 827 pr_err("Cannot get suitable rate: %ld\n", rate);
744 ret = rate; 828 ret = rate;
745 goto out; 829 goto out;
746 } 830 }
747 831
748 ret = clk_set_rate(&pllc2_clk, rate); 832 ret = clk_set_rate(&sh7372_pllc2_clk, rate);
749 if (ret < 0) { 833 if (ret < 0) {
750 pr_err("Cannot set rate %ld: %d\n", rate, ret); 834 pr_err("Cannot set rate %ld: %d\n", rate, ret);
751 goto out; 835 goto out;
@@ -753,7 +837,7 @@ static int __init hdmi_init_pm_clock(void)
753 837
754 pr_debug("PLLC2 set frequency %lu\n", rate); 838 pr_debug("PLLC2 set frequency %lu\n", rate);
755 839
756 ret = clk_set_parent(hdmi_ick, &pllc2_clk); 840 ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk);
757 if (ret < 0) { 841 if (ret < 0) {
758 pr_err("Cannot set HDMI parent: %d\n", ret); 842 pr_err("Cannot set HDMI parent: %d\n", ret);
759 goto out; 843 goto out;
@@ -767,11 +851,51 @@ out:
767 851
768device_initcall(hdmi_init_pm_clock); 852device_initcall(hdmi_init_pm_clock);
769 853
854#define FSIACK_DUMMY_RATE 48000
855static int __init fsi_init_pm_clock(void)
856{
857 struct clk *fsia_ick;
858 int ret;
859
860 /*
861 * FSIACK is connected to AK4642,
862 * and the rate is depend on playing sound rate.
863 * So, set dummy rate (= 48k) here
864 */
865 ret = clk_set_rate(&sh7372_fsiack_clk, FSIACK_DUMMY_RATE);
866 if (ret < 0) {
867 pr_err("Cannot set FSIACK dummy rate: %d\n", ret);
868 return ret;
869 }
870
871 fsia_ick = clk_get(&fsi_device.dev, "icka");
872 if (IS_ERR(fsia_ick)) {
873 ret = PTR_ERR(fsia_ick);
874 pr_err("Cannot get FSI ICK: %d\n", ret);
875 return ret;
876 }
877
878 ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk);
879 if (ret < 0) {
880 pr_err("Cannot set FSI-A parent: %d\n", ret);
881 goto out;
882 }
883
884 ret = clk_set_rate(fsia_ick, FSIACK_DUMMY_RATE);
885 if (ret < 0)
886 pr_err("Cannot set FSI-A rate: %d\n", ret);
887
888out:
889 clk_put(fsia_ick);
890
891 return ret;
892}
893device_initcall(fsi_init_pm_clock);
894
770/* 895/*
771 * FIXME !! 896 * FIXME !!
772 * 897 *
773 * gpio_no_direction 898 * gpio_no_direction
774 * gpio_pull_up
775 * are quick_hack. 899 * are quick_hack.
776 * 900 *
777 * current gpio frame work doesn't have 901 * current gpio frame work doesn't have
@@ -783,49 +907,37 @@ static void __init gpio_no_direction(u32 addr)
783 __raw_writeb(0x00, addr); 907 __raw_writeb(0x00, addr);
784} 908}
785 909
786static void __init gpio_pull_up(u32 addr)
787{
788 u8 data = __raw_readb(addr);
789
790 data &= 0x0F;
791 data |= 0xC0;
792 __raw_writeb(data, addr);
793}
794
795/* TouchScreen */ 910/* TouchScreen */
911#ifdef CONFIG_AP4EVB_QHD
912# define GPIO_TSC_IRQ GPIO_FN_IRQ28_123
913# define GPIO_TSC_PORT GPIO_PORT123
914#else /* WVGA */
915# define GPIO_TSC_IRQ GPIO_FN_IRQ7_40
916# define GPIO_TSC_PORT GPIO_PORT40
917#endif
918
796#define IRQ28 evt2irq(0x3380) /* IRQ28A */ 919#define IRQ28 evt2irq(0x3380) /* IRQ28A */
797#define IRQ7 evt2irq(0x02e0) /* IRQ7A */ 920#define IRQ7 evt2irq(0x02e0) /* IRQ7A */
798static int ts_get_pendown_state(void) 921static int ts_get_pendown_state(void)
799{ 922{
800 int val1, val2; 923 int val;
801 924
802 gpio_free(GPIO_FN_IRQ28_123); 925 gpio_free(GPIO_TSC_IRQ);
803 gpio_free(GPIO_FN_IRQ7_40);
804 926
805 gpio_request(GPIO_PORT123, NULL); 927 gpio_request(GPIO_TSC_PORT, NULL);
806 gpio_request(GPIO_PORT40, NULL);
807 928
808 gpio_direction_input(GPIO_PORT123); 929 gpio_direction_input(GPIO_TSC_PORT);
809 gpio_direction_input(GPIO_PORT40);
810 930
811 val1 = gpio_get_value(GPIO_PORT123); 931 val = gpio_get_value(GPIO_TSC_PORT);
812 val2 = gpio_get_value(GPIO_PORT40);
813 932
814 gpio_request(GPIO_FN_IRQ28_123, NULL); /* for QHD */ 933 gpio_request(GPIO_TSC_IRQ, NULL);
815 gpio_request(GPIO_FN_IRQ7_40, NULL); /* for WVGA */
816 934
817 return val1 ^ val2; 935 return !val;
818} 936}
819 937
820#define PORT40CR 0xE6051028
821#define PORT123CR 0xE605007B
822static int ts_init(void) 938static int ts_init(void)
823{ 939{
824 gpio_request(GPIO_FN_IRQ28_123, NULL); /* for QHD */ 940 gpio_request(GPIO_TSC_IRQ, NULL);
825 gpio_request(GPIO_FN_IRQ7_40, NULL); /* for WVGA */
826
827 gpio_pull_up(PORT40CR);
828 gpio_pull_up(PORT123CR);
829 941
830 return 0; 942 return 0;
831} 943}
@@ -974,14 +1086,6 @@ static void __init ap4evb_init(void)
974 clk_put(clk); 1086 clk_put(clk);
975 } 1087 }
976 1088
977 /* change parent of FSI A */
978 clk = clk_get(NULL, "fsia_clk");
979 if (!IS_ERR(clk)) {
980 clk_register(&fsiackcr_clk);
981 clk_set_parent(clk, &fsiackcr_clk);
982 clk_put(clk);
983 }
984
985 /* 1089 /*
986 * set irq priority, to avoid sound chopping 1090 * set irq priority, to avoid sound chopping
987 * when NFS rootfs is used 1091 * when NFS rootfs is used
@@ -996,8 +1100,10 @@ static void __init ap4evb_init(void)
996 ARRAY_SIZE(i2c1_devices)); 1100 ARRAY_SIZE(i2c1_devices));
997 1101
998#ifdef CONFIG_AP4EVB_QHD 1102#ifdef CONFIG_AP4EVB_QHD
1103
999 /* 1104 /*
1000 * QHD 1105 * For QHD Panel (MIPI-DSI, CONFIG_AP4EVB_QHD=y) and
1106 * IRQ28 for Touch Panel, set dip switches S3, S43 as OFF, ON.
1001 */ 1107 */
1002 1108
1003 /* enable KEYSC */ 1109 /* enable KEYSC */
@@ -1023,17 +1129,6 @@ static void __init ap4evb_init(void)
1023 lcdc_info.ch[0].interface_type = RGB24; 1129 lcdc_info.ch[0].interface_type = RGB24;
1024 lcdc_info.ch[0].clock_divider = 1; 1130 lcdc_info.ch[0].clock_divider = 1;
1025 lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL; 1131 lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL;
1026 lcdc_info.ch[0].lcd_cfg.name = "R63302(QHD)";
1027 lcdc_info.ch[0].lcd_cfg.xres = 544;
1028 lcdc_info.ch[0].lcd_cfg.yres = 961;
1029 lcdc_info.ch[0].lcd_cfg.left_margin = 72;
1030 lcdc_info.ch[0].lcd_cfg.right_margin = 600;
1031 lcdc_info.ch[0].lcd_cfg.hsync_len = 16;
1032 lcdc_info.ch[0].lcd_cfg.upper_margin = 8;
1033 lcdc_info.ch[0].lcd_cfg.lower_margin = 8;
1034 lcdc_info.ch[0].lcd_cfg.vsync_len = 2;
1035 lcdc_info.ch[0].lcd_cfg.sync = FB_SYNC_VERT_HIGH_ACT |
1036 FB_SYNC_HOR_HIGH_ACT;
1037 lcdc_info.ch[0].lcd_size_cfg.width = 44; 1132 lcdc_info.ch[0].lcd_size_cfg.width = 44;
1038 lcdc_info.ch[0].lcd_size_cfg.height = 79; 1133 lcdc_info.ch[0].lcd_size_cfg.height = 79;
1039 1134
@@ -1041,8 +1136,10 @@ static void __init ap4evb_init(void)
1041 1136
1042#else 1137#else
1043 /* 1138 /*
1044 * WVGA 1139 * For WVGA Panel (18-bit RGB, CONFIG_AP4EVB_WVGA=y) and
1140 * IRQ7 for Touch Panel, set dip switches S3, S43 to ON, OFF.
1045 */ 1141 */
1142
1046 gpio_request(GPIO_FN_LCDD17, NULL); 1143 gpio_request(GPIO_FN_LCDD17, NULL);
1047 gpio_request(GPIO_FN_LCDD16, NULL); 1144 gpio_request(GPIO_FN_LCDD16, NULL);
1048 gpio_request(GPIO_FN_LCDD15, NULL); 1145 gpio_request(GPIO_FN_LCDD15, NULL);
@@ -1074,16 +1171,6 @@ static void __init ap4evb_init(void)
1074 lcdc_info.ch[0].interface_type = RGB18; 1171 lcdc_info.ch[0].interface_type = RGB18;
1075 lcdc_info.ch[0].clock_divider = 2; 1172 lcdc_info.ch[0].clock_divider = 2;
1076 lcdc_info.ch[0].flags = 0; 1173 lcdc_info.ch[0].flags = 0;
1077 lcdc_info.ch[0].lcd_cfg.name = "WVGA Panel";
1078 lcdc_info.ch[0].lcd_cfg.xres = 800;
1079 lcdc_info.ch[0].lcd_cfg.yres = 480;
1080 lcdc_info.ch[0].lcd_cfg.left_margin = 220;
1081 lcdc_info.ch[0].lcd_cfg.right_margin = 110;
1082 lcdc_info.ch[0].lcd_cfg.hsync_len = 70;
1083 lcdc_info.ch[0].lcd_cfg.upper_margin = 20;
1084 lcdc_info.ch[0].lcd_cfg.lower_margin = 5;
1085 lcdc_info.ch[0].lcd_cfg.vsync_len = 5;
1086 lcdc_info.ch[0].lcd_cfg.sync = 0;
1087 lcdc_info.ch[0].lcd_size_cfg.width = 152; 1174 lcdc_info.ch[0].lcd_size_cfg.width = 152;
1088 lcdc_info.ch[0].lcd_size_cfg.height = 91; 1175 lcdc_info.ch[0].lcd_size_cfg.height = 91;
1089 1176
@@ -1094,6 +1181,23 @@ static void __init ap4evb_init(void)
1094 i2c_register_board_info(0, &tsc_device, 1); 1181 i2c_register_board_info(0, &tsc_device, 1);
1095#endif /* CONFIG_AP4EVB_QHD */ 1182#endif /* CONFIG_AP4EVB_QHD */
1096 1183
1184 /* CEU */
1185
1186 /*
1187 * TODO: reserve memory for V4L2 DMA buffers, when a suitable API
1188 * becomes available
1189 */
1190
1191 /* MIPI-CSI stuff */
1192 gpio_request(GPIO_FN_VIO_CKO, NULL);
1193
1194 clk = clk_get(NULL, "vck1_clk");
1195 if (!IS_ERR(clk)) {
1196 clk_set_rate(clk, clk_round_rate(clk, 13000000));
1197 clk_enable(clk);
1198 clk_put(clk);
1199 }
1200
1097 sh7372_add_standard_devices(); 1201 sh7372_add_standard_devices();
1098 1202
1099 /* HDMI */ 1203 /* HDMI */
@@ -1116,7 +1220,7 @@ static void __init ap4evb_timer_init(void)
1116 shmobile_timer.init(); 1220 shmobile_timer.init();
1117 1221
1118 /* External clock source */ 1222 /* External clock source */
1119 clk_set_rate(&dv_clki_clk, 27000000); 1223 clk_set_rate(&sh7372_dv_clki_clk, 27000000);
1120} 1224}
1121 1225
1122static struct sys_timer ap4evb_timer = { 1226static struct sys_timer ap4evb_timer = {
diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c
index b6454c9f2abb..9f78729098f2 100644
--- a/arch/arm/mach-shmobile/clock-sh7367.c
+++ b/arch/arm/mach-shmobile/clock-sh7367.c
@@ -321,7 +321,7 @@ static struct clk_lookup lookups[] = {
321 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]), /* SCIFA3 */ 321 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]), /* SCIFA3 */
322 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]), /* SCIFA4 */ 322 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]), /* SCIFA4 */
323 CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]), /* SIU */ 323 CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]), /* SIU */
324 CLKDEV_CON_ID("cmt1", &mstp_clks[SYMSTP229]), /* CMT10 */ 324 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[SYMSTP229]), /* CMT10 */
325 CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]), /* IRDA */ 325 CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]), /* IRDA */
326 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]), /* IIC1 */ 326 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]), /* IIC1 */
327 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]), /* USBHS */ 327 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]), /* USBHS */
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index 759468992ad2..8565aefa21fd 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -51,7 +51,7 @@
51#define SMSTPCR4 0xe6150140 51#define SMSTPCR4 0xe6150140
52 52
53/* Platforms must set frequency on their DV_CLKI pin */ 53/* Platforms must set frequency on their DV_CLKI pin */
54struct clk dv_clki_clk = { 54struct clk sh7372_dv_clki_clk = {
55}; 55};
56 56
57/* Fixed 32 KHz root clock from EXTALR pin */ 57/* Fixed 32 KHz root clock from EXTALR pin */
@@ -86,9 +86,9 @@ static struct clk_ops div2_clk_ops = {
86}; 86};
87 87
88/* Divide dv_clki by two */ 88/* Divide dv_clki by two */
89struct clk dv_clki_div2_clk = { 89struct clk sh7372_dv_clki_div2_clk = {
90 .ops = &div2_clk_ops, 90 .ops = &div2_clk_ops,
91 .parent = &dv_clki_clk, 91 .parent = &sh7372_dv_clki_clk,
92}; 92};
93 93
94/* Divide extal1 by two */ 94/* Divide extal1 by two */
@@ -150,7 +150,7 @@ static struct clk pllc1_div2_clk = {
150static struct clk *pllc2_parent[] = { 150static struct clk *pllc2_parent[] = {
151 [0] = &extal1_div2_clk, 151 [0] = &extal1_div2_clk,
152 [1] = &extal2_div2_clk, 152 [1] = &extal2_div2_clk,
153 [2] = &dv_clki_div2_clk, 153 [2] = &sh7372_dv_clki_div2_clk,
154}; 154};
155 155
156/* Only multipliers 20 * 2 to 46 * 2 are valid, last entry for CPUFREQ_TABLE_END */ 156/* Only multipliers 20 * 2 to 46 * 2 are valid, last entry for CPUFREQ_TABLE_END */
@@ -284,7 +284,7 @@ static struct clk_ops pllc2_clk_ops = {
284 .set_parent = pllc2_set_parent, 284 .set_parent = pllc2_set_parent,
285}; 285};
286 286
287struct clk pllc2_clk = { 287struct clk sh7372_pllc2_clk = {
288 .ops = &pllc2_clk_ops, 288 .ops = &pllc2_clk_ops,
289 .parent = &extal1_div2_clk, 289 .parent = &extal1_div2_clk,
290 .freq_table = pllc2_freq_table, 290 .freq_table = pllc2_freq_table,
@@ -292,19 +292,28 @@ struct clk pllc2_clk = {
292 .parent_num = ARRAY_SIZE(pllc2_parent), 292 .parent_num = ARRAY_SIZE(pllc2_parent),
293}; 293};
294 294
295/* External input clock (pin name: FSIACK/FSIBCK ) */
296struct clk sh7372_fsiack_clk = {
297};
298
299struct clk sh7372_fsibck_clk = {
300};
301
295static struct clk *main_clks[] = { 302static struct clk *main_clks[] = {
296 &dv_clki_clk, 303 &sh7372_dv_clki_clk,
297 &r_clk, 304 &r_clk,
298 &sh7372_extal1_clk, 305 &sh7372_extal1_clk,
299 &sh7372_extal2_clk, 306 &sh7372_extal2_clk,
300 &dv_clki_div2_clk, 307 &sh7372_dv_clki_div2_clk,
301 &extal1_div2_clk, 308 &extal1_div2_clk,
302 &extal2_div2_clk, 309 &extal2_div2_clk,
303 &extal2_div4_clk, 310 &extal2_div4_clk,
304 &pllc0_clk, 311 &pllc0_clk,
305 &pllc1_clk, 312 &pllc1_clk,
306 &pllc1_div2_clk, 313 &pllc1_div2_clk,
307 &pllc2_clk, 314 &sh7372_pllc2_clk,
315 &sh7372_fsiack_clk,
316 &sh7372_fsibck_clk,
308}; 317};
309 318
310static void div4_kick(struct clk *clk) 319static void div4_kick(struct clk *clk)
@@ -357,7 +366,7 @@ static struct clk div4_clks[DIV4_NR] = {
357}; 366};
358 367
359enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_FMSI, DIV6_FMSO, 368enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_FMSI, DIV6_FMSO,
360 DIV6_FSIA, DIV6_FSIB, DIV6_SUB, DIV6_SPU, 369 DIV6_SUB, DIV6_SPU,
361 DIV6_VOU, DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P, 370 DIV6_VOU, DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P,
362 DIV6_NR }; 371 DIV6_NR };
363 372
@@ -367,8 +376,6 @@ static struct clk div6_clks[DIV6_NR] = {
367 [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0), 376 [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0),
368 [DIV6_FMSI] = SH_CLK_DIV6(&pllc1_div2_clk, FMSICKCR, 0), 377 [DIV6_FMSI] = SH_CLK_DIV6(&pllc1_div2_clk, FMSICKCR, 0),
369 [DIV6_FMSO] = SH_CLK_DIV6(&pllc1_div2_clk, FMSOCKCR, 0), 378 [DIV6_FMSO] = SH_CLK_DIV6(&pllc1_div2_clk, FMSOCKCR, 0),
370 [DIV6_FSIA] = SH_CLK_DIV6(&pllc1_div2_clk, FSIACKCR, 0),
371 [DIV6_FSIB] = SH_CLK_DIV6(&pllc1_div2_clk, FSIBCKCR, 0),
372 [DIV6_SUB] = SH_CLK_DIV6(&sh7372_extal2_clk, SUBCKCR, 0), 379 [DIV6_SUB] = SH_CLK_DIV6(&sh7372_extal2_clk, SUBCKCR, 0),
373 [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0), 380 [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0),
374 [DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0), 381 [DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0),
@@ -377,24 +384,42 @@ static struct clk div6_clks[DIV6_NR] = {
377 [DIV6_DSI1P] = SH_CLK_DIV6(&pllc1_div2_clk, DSI1PCKCR, 0), 384 [DIV6_DSI1P] = SH_CLK_DIV6(&pllc1_div2_clk, DSI1PCKCR, 0),
378}; 385};
379 386
380enum { DIV6_HDMI, DIV6_REPARENT_NR }; 387enum { DIV6_HDMI, DIV6_FSIA, DIV6_FSIB, DIV6_REPARENT_NR };
381 388
382/* Indices are important - they are the actual src selecting values */ 389/* Indices are important - they are the actual src selecting values */
383static struct clk *hdmi_parent[] = { 390static struct clk *hdmi_parent[] = {
384 [0] = &pllc1_div2_clk, 391 [0] = &pllc1_div2_clk,
385 [1] = &pllc2_clk, 392 [1] = &sh7372_pllc2_clk,
386 [2] = &dv_clki_clk, 393 [2] = &sh7372_dv_clki_clk,
387 [3] = NULL, /* pllc2_div4 not implemented yet */ 394 [3] = NULL, /* pllc2_div4 not implemented yet */
388}; 395};
389 396
397static struct clk *fsiackcr_parent[] = {
398 [0] = &pllc1_div2_clk,
399 [1] = &sh7372_pllc2_clk,
400 [2] = &sh7372_fsiack_clk, /* external input for FSI A */
401 [3] = NULL, /* setting prohibited */
402};
403
404static struct clk *fsibckcr_parent[] = {
405 [0] = &pllc1_div2_clk,
406 [1] = &sh7372_pllc2_clk,
407 [2] = &sh7372_fsibck_clk, /* external input for FSI B */
408 [3] = NULL, /* setting prohibited */
409};
410
390static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { 411static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
391 [DIV6_HDMI] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, HDMICKCR, 0, 412 [DIV6_HDMI] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, HDMICKCR, 0,
392 hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), 413 hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
414 [DIV6_FSIA] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, FSIACKCR, 0,
415 fsiackcr_parent, ARRAY_SIZE(fsiackcr_parent), 6, 2),
416 [DIV6_FSIB] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, FSIBCKCR, 0,
417 fsibckcr_parent, ARRAY_SIZE(fsibckcr_parent), 6, 2),
393}; 418};
394 419
395enum { MSTP001, 420enum { MSTP001,
396 MSTP131, MSTP130, 421 MSTP131, MSTP130,
397 MSTP129, MSTP128, MSTP127, MSTP126, 422 MSTP129, MSTP128, MSTP127, MSTP126, MSTP125,
398 MSTP118, MSTP117, MSTP116, 423 MSTP118, MSTP117, MSTP116,
399 MSTP106, MSTP101, MSTP100, 424 MSTP106, MSTP101, MSTP100,
400 MSTP223, 425 MSTP223,
@@ -414,6 +439,7 @@ static struct clk mstp_clks[MSTP_NR] = {
414 [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */ 439 [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */
415 [MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU */ 440 [MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU */
416 [MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2 */ 441 [MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2 */
442 [MSTP125] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */
417 [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */ 443 [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */
418 [MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */ 444 [MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */
419 [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */ 445 [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
@@ -429,7 +455,7 @@ static struct clk mstp_clks[MSTP_NR] = {
429 [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */ 455 [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
430 [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ 456 [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
431 [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ 457 [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
432 [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, 0), /* FSIA */ 458 [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, 0), /* FSI2 */
433 [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ 459 [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
434 [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */ 460 [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */
435 [MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ 461 [MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
@@ -445,10 +471,11 @@ static struct clk mstp_clks[MSTP_NR] = {
445 471
446#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } 472#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
447#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk } 473#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
474#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk }
448 475
449static struct clk_lookup lookups[] = { 476static struct clk_lookup lookups[] = {
450 /* main clocks */ 477 /* main clocks */
451 CLKDEV_CON_ID("dv_clki_div2_clk", &dv_clki_div2_clk), 478 CLKDEV_CON_ID("dv_clki_div2_clk", &sh7372_dv_clki_div2_clk),
452 CLKDEV_CON_ID("r_clk", &r_clk), 479 CLKDEV_CON_ID("r_clk", &r_clk),
453 CLKDEV_CON_ID("extal1", &sh7372_extal1_clk), 480 CLKDEV_CON_ID("extal1", &sh7372_extal1_clk),
454 CLKDEV_CON_ID("extal2", &sh7372_extal2_clk), 481 CLKDEV_CON_ID("extal2", &sh7372_extal2_clk),
@@ -458,7 +485,7 @@ static struct clk_lookup lookups[] = {
458 CLKDEV_CON_ID("pllc0_clk", &pllc0_clk), 485 CLKDEV_CON_ID("pllc0_clk", &pllc0_clk),
459 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), 486 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
460 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), 487 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
461 CLKDEV_CON_ID("pllc2_clk", &pllc2_clk), 488 CLKDEV_CON_ID("pllc2_clk", &sh7372_pllc2_clk),
462 489
463 /* DIV4 clocks */ 490 /* DIV4 clocks */
464 CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), 491 CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
@@ -483,8 +510,8 @@ static struct clk_lookup lookups[] = {
483 CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]), 510 CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
484 CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]), 511 CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]),
485 CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]), 512 CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]),
486 CLKDEV_CON_ID("fsia_clk", &div6_clks[DIV6_FSIA]), 513 CLKDEV_CON_ID("fsia_clk", &div6_reparent_clks[DIV6_FSIA]),
487 CLKDEV_CON_ID("fsib_clk", &div6_clks[DIV6_FSIB]), 514 CLKDEV_CON_ID("fsib_clk", &div6_reparent_clks[DIV6_FSIB]),
488 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]), 515 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
489 CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]), 516 CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
490 CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]), 517 CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
@@ -501,6 +528,8 @@ static struct clk_lookup lookups[] = {
501 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */ 528 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */
502 CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU */ 529 CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU */
503 CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2 */ 530 CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2 */
531 CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), /* TMU00 */
532 CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), /* TMU01 */
504 CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */ 533 CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */
505 CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */ 534 CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */
506 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */ 535 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
@@ -516,7 +545,7 @@ static struct clk_lookup lookups[] = {
516 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */ 545 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
517 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */ 546 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
518 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ 547 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
519 CLKDEV_CON_ID("cmt1", &mstp_clks[MSTP329]), /* CMT10 */ 548 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
520 CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */ 549 CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */
521 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ 550 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
522 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP323]), /* USB0 */ 551 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP323]), /* USB0 */
@@ -531,7 +560,10 @@ static struct clk_lookup lookups[] = {
531 CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */ 560 CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */
532 CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */ 561 CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */
533 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ 562 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
534 {.con_id = "ick", .dev_id = "sh-mobile-hdmi", .clk = &div6_reparent_clks[DIV6_HDMI]}, 563
564 CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
565 CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]),
566 CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]),
535}; 567};
536 568
537void __init sh7372_clock_init(void) 569void __init sh7372_clock_init(void)
@@ -548,7 +580,7 @@ void __init sh7372_clock_init(void)
548 ret = sh_clk_div6_register(div6_clks, DIV6_NR); 580 ret = sh_clk_div6_register(div6_clks, DIV6_NR);
549 581
550 if (!ret) 582 if (!ret)
551 ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_NR); 583 ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_REPARENT_NR);
552 584
553 if (!ret) 585 if (!ret)
554 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); 586 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
diff --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c
index e007c28cf0a8..f91395aeb9ab 100644
--- a/arch/arm/mach-shmobile/clock-sh7377.c
+++ b/arch/arm/mach-shmobile/clock-sh7377.c
@@ -333,7 +333,7 @@ static struct clk_lookup lookups[] = {
333 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */ 333 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
334 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ 334 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
335 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */ 335 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
336 CLKDEV_CON_ID("cmt1", &mstp_clks[MSTP329]), /* CMT10 */ 336 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
337 CLKDEV_DEV_ID("sh_irda", &mstp_clks[MSTP325]), /* IRDA */ 337 CLKDEV_DEV_ID("sh_irda", &mstp_clks[MSTP325]), /* IRDA */
338 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ 338 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
339 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USBHS */ 339 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USBHS */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index 33e9700ded7e..147775a94bce 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -457,8 +457,12 @@ enum {
457 SHDMA_SLAVE_SDHI2_TX, 457 SHDMA_SLAVE_SDHI2_TX,
458}; 458};
459 459
460extern struct clk dv_clki_clk; 460extern struct clk sh7372_extal1_clk;
461extern struct clk dv_clki_div2_clk; 461extern struct clk sh7372_extal2_clk;
462extern struct clk pllc2_clk; 462extern struct clk sh7372_dv_clki_clk;
463extern struct clk sh7372_dv_clki_div2_clk;
464extern struct clk sh7372_pllc2_clk;
465extern struct clk sh7372_fsiack_clk;
466extern struct clk sh7372_fsibck_clk;
463 467
464#endif /* __ASM_SH7372_H__ */ 468#endif /* __ASM_SH7372_H__ */
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c
index e3551b56cd03..4cd3cae38e72 100644
--- a/arch/arm/mach-shmobile/intc-sh7372.c
+++ b/arch/arm/mach-shmobile/intc-sh7372.c
@@ -369,9 +369,13 @@ enum {
369 INTCS, 369 INTCS,
370 370
371 /* interrupt sources INTCS */ 371 /* interrupt sources INTCS */
372
373 /* IRQ0S - IRQ31S */
372 VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3, 374 VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3,
373 RTDMAC_1_DEI0, RTDMAC_1_DEI1, RTDMAC_1_DEI2, RTDMAC_1_DEI3, 375 RTDMAC_1_DEI0, RTDMAC_1_DEI1, RTDMAC_1_DEI2, RTDMAC_1_DEI3,
374 CEU, BEU_BEU0, BEU_BEU1, BEU_BEU2, 376 CEU, BEU_BEU0, BEU_BEU1, BEU_BEU2,
377 /* MFI */
378 /* BBIF2 */
375 VPU, 379 VPU,
376 TSIF1, 380 TSIF1,
377 _3DG_SGX530, 381 _3DG_SGX530,
@@ -379,13 +383,17 @@ enum {
379 IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2, 383 IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2,
380 IPMMU_IPMMUR, IPMMU_IPMMUR2, 384 IPMMU_IPMMUR, IPMMU_IPMMUR2,
381 RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR, 385 RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR,
386 /* KEYSC */
387 /* TTI20 */
382 MSIOF, 388 MSIOF,
383 IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0, 389 IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0,
384 TMU_TUNI0, TMU_TUNI1, TMU_TUNI2, 390 TMU_TUNI0, TMU_TUNI1, TMU_TUNI2,
385 CMT0, 391 CMT0,
386 TSIF0, 392 TSIF0,
393 /* CMT2 */
387 LMB, 394 LMB,
388 CTI, 395 CTI,
396 /* RWDT0 */
389 ICB, 397 ICB,
390 JPU_JPEG, 398 JPU_JPEG,
391 LCDC, 399 LCDC,
@@ -397,11 +405,17 @@ enum {
397 CSIRX, 405 CSIRX,
398 DSITX_DSITX0, 406 DSITX_DSITX0,
399 DSITX_DSITX1, 407 DSITX_DSITX1,
408 /* SPU2 */
409 /* FSI */
410 /* FMSI */
411 /* HDMI */
400 TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2, 412 TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2,
401 CMT4, 413 CMT4,
402 DSITX1_DSITX1_0, 414 DSITX1_DSITX1_0,
403 DSITX1_DSITX1_1, 415 DSITX1_DSITX1_1,
416 /* MFIS2 */
404 CPORTS2R, 417 CPORTS2R,
418 /* CEC */
405 JPU6E, 419 JPU6E,
406 420
407 /* interrupt groups INTCS */ 421 /* interrupt groups INTCS */
@@ -410,12 +424,15 @@ enum {
410}; 424};
411 425
412static struct intc_vect intcs_vectors[] = { 426static struct intc_vect intcs_vectors[] = {
427 /* IRQ0S - IRQ31S */
413 INTCS_VECT(VEU_VEU0, 0x700), INTCS_VECT(VEU_VEU1, 0x720), 428 INTCS_VECT(VEU_VEU0, 0x700), INTCS_VECT(VEU_VEU1, 0x720),
414 INTCS_VECT(VEU_VEU2, 0x740), INTCS_VECT(VEU_VEU3, 0x760), 429 INTCS_VECT(VEU_VEU2, 0x740), INTCS_VECT(VEU_VEU3, 0x760),
415 INTCS_VECT(RTDMAC_1_DEI0, 0x800), INTCS_VECT(RTDMAC_1_DEI1, 0x820), 430 INTCS_VECT(RTDMAC_1_DEI0, 0x800), INTCS_VECT(RTDMAC_1_DEI1, 0x820),
416 INTCS_VECT(RTDMAC_1_DEI2, 0x840), INTCS_VECT(RTDMAC_1_DEI3, 0x860), 431 INTCS_VECT(RTDMAC_1_DEI2, 0x840), INTCS_VECT(RTDMAC_1_DEI3, 0x860),
417 INTCS_VECT(CEU, 0x880), INTCS_VECT(BEU_BEU0, 0x8a0), 432 INTCS_VECT(CEU, 0x880), INTCS_VECT(BEU_BEU0, 0x8a0),
418 INTCS_VECT(BEU_BEU1, 0x8c0), INTCS_VECT(BEU_BEU2, 0x8e0), 433 INTCS_VECT(BEU_BEU1, 0x8c0), INTCS_VECT(BEU_BEU2, 0x8e0),
434 /* MFI */
435 /* BBIF2 */
419 INTCS_VECT(VPU, 0x980), 436 INTCS_VECT(VPU, 0x980),
420 INTCS_VECT(TSIF1, 0x9a0), 437 INTCS_VECT(TSIF1, 0x9a0),
421 INTCS_VECT(_3DG_SGX530, 0x9e0), 438 INTCS_VECT(_3DG_SGX530, 0x9e0),
@@ -425,14 +442,19 @@ static struct intc_vect intcs_vectors[] = {
425 INTCS_VECT(IPMMU_IPMMUR, 0xb00), INTCS_VECT(IPMMU_IPMMUR2, 0xb20), 442 INTCS_VECT(IPMMU_IPMMUR, 0xb00), INTCS_VECT(IPMMU_IPMMUR2, 0xb20),
426 INTCS_VECT(RTDMAC_2_DEI4, 0xb80), INTCS_VECT(RTDMAC_2_DEI5, 0xba0), 443 INTCS_VECT(RTDMAC_2_DEI4, 0xb80), INTCS_VECT(RTDMAC_2_DEI5, 0xba0),
427 INTCS_VECT(RTDMAC_2_DADERR, 0xbc0), 444 INTCS_VECT(RTDMAC_2_DADERR, 0xbc0),
445 /* KEYSC */
446 /* TTI20 */
447 INTCS_VECT(MSIOF, 0x0d20),
428 INTCS_VECT(IIC0_ALI0, 0xe00), INTCS_VECT(IIC0_TACKI0, 0xe20), 448 INTCS_VECT(IIC0_ALI0, 0xe00), INTCS_VECT(IIC0_TACKI0, 0xe20),
429 INTCS_VECT(IIC0_WAITI0, 0xe40), INTCS_VECT(IIC0_DTEI0, 0xe60), 449 INTCS_VECT(IIC0_WAITI0, 0xe40), INTCS_VECT(IIC0_DTEI0, 0xe60),
430 INTCS_VECT(TMU_TUNI0, 0xe80), INTCS_VECT(TMU_TUNI1, 0xea0), 450 INTCS_VECT(TMU_TUNI0, 0xe80), INTCS_VECT(TMU_TUNI1, 0xea0),
431 INTCS_VECT(TMU_TUNI2, 0xec0), 451 INTCS_VECT(TMU_TUNI2, 0xec0),
432 INTCS_VECT(CMT0, 0xf00), 452 INTCS_VECT(CMT0, 0xf00),
433 INTCS_VECT(TSIF0, 0xf20), 453 INTCS_VECT(TSIF0, 0xf20),
454 /* CMT2 */
434 INTCS_VECT(LMB, 0xf60), 455 INTCS_VECT(LMB, 0xf60),
435 INTCS_VECT(CTI, 0x400), 456 INTCS_VECT(CTI, 0x400),
457 /* RWDT0 */
436 INTCS_VECT(ICB, 0x480), 458 INTCS_VECT(ICB, 0x480),
437 INTCS_VECT(JPU_JPEG, 0x560), 459 INTCS_VECT(JPU_JPEG, 0x560),
438 INTCS_VECT(LCDC, 0x580), 460 INTCS_VECT(LCDC, 0x580),
@@ -446,12 +468,18 @@ static struct intc_vect intcs_vectors[] = {
446 INTCS_VECT(CSIRX, 0x17a0), 468 INTCS_VECT(CSIRX, 0x17a0),
447 INTCS_VECT(DSITX_DSITX0, 0x17c0), 469 INTCS_VECT(DSITX_DSITX0, 0x17c0),
448 INTCS_VECT(DSITX_DSITX1, 0x17e0), 470 INTCS_VECT(DSITX_DSITX1, 0x17e0),
471 /* SPU2 */
472 /* FSI */
473 /* FMSI */
474 /* HDMI */
449 INTCS_VECT(TMU1_TUNI0, 0x1900), INTCS_VECT(TMU1_TUNI1, 0x1920), 475 INTCS_VECT(TMU1_TUNI0, 0x1900), INTCS_VECT(TMU1_TUNI1, 0x1920),
450 INTCS_VECT(TMU1_TUNI2, 0x1940), 476 INTCS_VECT(TMU1_TUNI2, 0x1940),
451 INTCS_VECT(CMT4, 0x1980), 477 INTCS_VECT(CMT4, 0x1980),
452 INTCS_VECT(DSITX1_DSITX1_0, 0x19a0), 478 INTCS_VECT(DSITX1_DSITX1_0, 0x19a0),
453 INTCS_VECT(DSITX1_DSITX1_1, 0x19c0), 479 INTCS_VECT(DSITX1_DSITX1_1, 0x19c0),
480 /* MFIS2 */
454 INTCS_VECT(CPORTS2R, 0x1a20), 481 INTCS_VECT(CPORTS2R, 0x1a20),
482 /* CEC */
455 INTCS_VECT(JPU6E, 0x1a80), 483 INTCS_VECT(JPU6E, 0x1a80),
456 484
457 INTC_VECT(INTCS, 0xf80), 485 INTC_VECT(INTCS, 0xf80),
diff --git a/arch/arm/mach-shmobile/pfc-sh7372.c b/arch/arm/mach-shmobile/pfc-sh7372.c
index ec420353f8e3..9c265dae138a 100644
--- a/arch/arm/mach-shmobile/pfc-sh7372.c
+++ b/arch/arm/mach-shmobile/pfc-sh7372.c
@@ -166,12 +166,12 @@ enum {
166 MSIOF2_TSYNC_MARK, MSIOF2_TSCK_MARK, MSIOF2_RXD_MARK, 166 MSIOF2_TSYNC_MARK, MSIOF2_TSCK_MARK, MSIOF2_RXD_MARK,
167 MSIOF2_TXD_MARK, 167 MSIOF2_TXD_MARK,
168 168
169 /* MSIOF3 */ 169 /* BBIF1 */
170 BBIF1_RXD_MARK, BBIF1_TSYNC_MARK, BBIF1_TSCK_MARK, 170 BBIF1_RXD_MARK, BBIF1_TSYNC_MARK, BBIF1_TSCK_MARK,
171 BBIF1_TXD_MARK, BBIF1_RSCK_MARK, BBIF1_RSYNC_MARK, 171 BBIF1_TXD_MARK, BBIF1_RSCK_MARK, BBIF1_RSYNC_MARK,
172 BBIF1_FLOW_MARK, BB_RX_FLOW_N_MARK, 172 BBIF1_FLOW_MARK, BB_RX_FLOW_N_MARK,
173 173
174 /* MSIOF4 */ 174 /* BBIF2 */
175 BBIF2_TSCK1_MARK, BBIF2_TSYNC1_MARK, 175 BBIF2_TSCK1_MARK, BBIF2_TSYNC1_MARK,
176 BBIF2_TXD1_MARK, BBIF2_RXD_MARK, 176 BBIF2_TXD1_MARK, BBIF2_RXD_MARK,
177 177
@@ -976,12 +976,12 @@ static struct pinmux_gpio pinmux_gpios[] = {
976 GPIO_FN(MSIOF2_TSYNC), GPIO_FN(MSIOF2_TSCK), GPIO_FN(MSIOF2_RXD), 976 GPIO_FN(MSIOF2_TSYNC), GPIO_FN(MSIOF2_TSCK), GPIO_FN(MSIOF2_RXD),
977 GPIO_FN(MSIOF2_TXD), 977 GPIO_FN(MSIOF2_TXD),
978 978
979 /* MSIOF3 */ 979 /* BBIF1 */
980 GPIO_FN(BBIF1_RXD), GPIO_FN(BBIF1_TSYNC), GPIO_FN(BBIF1_TSCK), 980 GPIO_FN(BBIF1_RXD), GPIO_FN(BBIF1_TSYNC), GPIO_FN(BBIF1_TSCK),
981 GPIO_FN(BBIF1_TXD), GPIO_FN(BBIF1_RSCK), GPIO_FN(BBIF1_RSYNC), 981 GPIO_FN(BBIF1_TXD), GPIO_FN(BBIF1_RSCK), GPIO_FN(BBIF1_RSYNC),
982 GPIO_FN(BBIF1_FLOW), GPIO_FN(BB_RX_FLOW_N), 982 GPIO_FN(BBIF1_FLOW), GPIO_FN(BB_RX_FLOW_N),
983 983
984 /* MSIOF4 */ 984 /* BBIF2 */
985 GPIO_FN(BBIF2_TSCK1), GPIO_FN(BBIF2_TSYNC1), 985 GPIO_FN(BBIF2_TSCK1), GPIO_FN(BBIF2_TSYNC1),
986 GPIO_FN(BBIF2_TXD1), GPIO_FN(BBIF2_RXD), 986 GPIO_FN(BBIF2_TXD1), GPIO_FN(BBIF2_RXD),
987 987
diff --git a/arch/arm/mach-shmobile/setup-sh7367.c b/arch/arm/mach-shmobile/setup-sh7367.c
index 3148c11a550e..003008c18360 100644
--- a/arch/arm/mach-shmobile/setup-sh7367.c
+++ b/arch/arm/mach-shmobile/setup-sh7367.c
@@ -154,7 +154,6 @@ static struct sh_timer_config cmt10_platform_data = {
154 .name = "CMT10", 154 .name = "CMT10",
155 .channel_offset = 0x10, 155 .channel_offset = 0x10,
156 .timer_bit = 0, 156 .timer_bit = 0,
157 .clk = "r_clk",
158 .clockevent_rating = 125, 157 .clockevent_rating = 125,
159 .clocksource_rating = 125, 158 .clocksource_rating = 125,
160}; 159};
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index e26686c9d0b6..564a6d0be473 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -158,7 +158,6 @@ static struct sh_timer_config cmt10_platform_data = {
158 .name = "CMT10", 158 .name = "CMT10",
159 .channel_offset = 0x10, 159 .channel_offset = 0x10,
160 .timer_bit = 0, 160 .timer_bit = 0,
161 .clk = "cmt1",
162 .clockevent_rating = 125, 161 .clockevent_rating = 125,
163 .clocksource_rating = 125, 162 .clocksource_rating = 125,
164}; 163};
@@ -186,6 +185,67 @@ static struct platform_device cmt10_device = {
186 .num_resources = ARRAY_SIZE(cmt10_resources), 185 .num_resources = ARRAY_SIZE(cmt10_resources),
187}; 186};
188 187
188/* TMU */
189static struct sh_timer_config tmu00_platform_data = {
190 .name = "TMU00",
191 .channel_offset = 0x4,
192 .timer_bit = 0,
193 .clockevent_rating = 200,
194};
195
196static struct resource tmu00_resources[] = {
197 [0] = {
198 .name = "TMU00",
199 .start = 0xfff60008,
200 .end = 0xfff60013,
201 .flags = IORESOURCE_MEM,
202 },
203 [1] = {
204 .start = intcs_evt2irq(0xe80), /* TMU_TUNI0 */
205 .flags = IORESOURCE_IRQ,
206 },
207};
208
209static struct platform_device tmu00_device = {
210 .name = "sh_tmu",
211 .id = 0,
212 .dev = {
213 .platform_data = &tmu00_platform_data,
214 },
215 .resource = tmu00_resources,
216 .num_resources = ARRAY_SIZE(tmu00_resources),
217};
218
219static struct sh_timer_config tmu01_platform_data = {
220 .name = "TMU01",
221 .channel_offset = 0x10,
222 .timer_bit = 1,
223 .clocksource_rating = 200,
224};
225
226static struct resource tmu01_resources[] = {
227 [0] = {
228 .name = "TMU01",
229 .start = 0xfff60014,
230 .end = 0xfff6001f,
231 .flags = IORESOURCE_MEM,
232 },
233 [1] = {
234 .start = intcs_evt2irq(0xea0), /* TMU_TUNI1 */
235 .flags = IORESOURCE_IRQ,
236 },
237};
238
239static struct platform_device tmu01_device = {
240 .name = "sh_tmu",
241 .id = 1,
242 .dev = {
243 .platform_data = &tmu01_platform_data,
244 },
245 .resource = tmu01_resources,
246 .num_resources = ARRAY_SIZE(tmu01_resources),
247};
248
189/* I2C */ 249/* I2C */
190static struct resource iic0_resources[] = { 250static struct resource iic0_resources[] = {
191 [0] = { 251 [0] = {
@@ -419,14 +479,14 @@ static struct resource sh7372_dmae0_resources[] = {
419 }, 479 },
420 { 480 {
421 /* DMA error IRQ */ 481 /* DMA error IRQ */
422 .start = 246, 482 .start = evt2irq(0x20c0),
423 .end = 246, 483 .end = evt2irq(0x20c0),
424 .flags = IORESOURCE_IRQ, 484 .flags = IORESOURCE_IRQ,
425 }, 485 },
426 { 486 {
427 /* IRQ for channels 0-5 */ 487 /* IRQ for channels 0-5 */
428 .start = 240, 488 .start = evt2irq(0x2000),
429 .end = 245, 489 .end = evt2irq(0x20a0),
430 .flags = IORESOURCE_IRQ, 490 .flags = IORESOURCE_IRQ,
431 }, 491 },
432}; 492};
@@ -447,14 +507,14 @@ static struct resource sh7372_dmae1_resources[] = {
447 }, 507 },
448 { 508 {
449 /* DMA error IRQ */ 509 /* DMA error IRQ */
450 .start = 254, 510 .start = evt2irq(0x21c0),
451 .end = 254, 511 .end = evt2irq(0x21c0),
452 .flags = IORESOURCE_IRQ, 512 .flags = IORESOURCE_IRQ,
453 }, 513 },
454 { 514 {
455 /* IRQ for channels 0-5 */ 515 /* IRQ for channels 0-5 */
456 .start = 248, 516 .start = evt2irq(0x2100),
457 .end = 253, 517 .end = evt2irq(0x21a0),
458 .flags = IORESOURCE_IRQ, 518 .flags = IORESOURCE_IRQ,
459 }, 519 },
460}; 520};
@@ -475,14 +535,14 @@ static struct resource sh7372_dmae2_resources[] = {
475 }, 535 },
476 { 536 {
477 /* DMA error IRQ */ 537 /* DMA error IRQ */
478 .start = 262, 538 .start = evt2irq(0x22c0),
479 .end = 262, 539 .end = evt2irq(0x22c0),
480 .flags = IORESOURCE_IRQ, 540 .flags = IORESOURCE_IRQ,
481 }, 541 },
482 { 542 {
483 /* IRQ for channels 0-5 */ 543 /* IRQ for channels 0-5 */
484 .start = 256, 544 .start = evt2irq(0x2200),
485 .end = 261, 545 .end = evt2irq(0x22a0),
486 .flags = IORESOURCE_IRQ, 546 .flags = IORESOURCE_IRQ,
487 }, 547 },
488}; 548};
@@ -526,6 +586,11 @@ static struct platform_device *sh7372_early_devices[] __initdata = {
526 &scif5_device, 586 &scif5_device,
527 &scif6_device, 587 &scif6_device,
528 &cmt10_device, 588 &cmt10_device,
589 &tmu00_device,
590 &tmu01_device,
591};
592
593static struct platform_device *sh7372_late_devices[] __initdata = {
529 &iic0_device, 594 &iic0_device,
530 &iic1_device, 595 &iic1_device,
531 &dma0_device, 596 &dma0_device,
@@ -537,6 +602,9 @@ void __init sh7372_add_standard_devices(void)
537{ 602{
538 platform_add_devices(sh7372_early_devices, 603 platform_add_devices(sh7372_early_devices,
539 ARRAY_SIZE(sh7372_early_devices)); 604 ARRAY_SIZE(sh7372_early_devices));
605
606 platform_add_devices(sh7372_late_devices,
607 ARRAY_SIZE(sh7372_late_devices));
540} 608}
541 609
542void __init sh7372_add_early_devices(void) 610void __init sh7372_add_early_devices(void)
diff --git a/arch/arm/mach-shmobile/setup-sh7377.c b/arch/arm/mach-shmobile/setup-sh7377.c
index bb4adf17dbf4..575dbd6c2f1d 100644
--- a/arch/arm/mach-shmobile/setup-sh7377.c
+++ b/arch/arm/mach-shmobile/setup-sh7377.c
@@ -172,7 +172,6 @@ static struct sh_timer_config cmt10_platform_data = {
172 .name = "CMT10", 172 .name = "CMT10",
173 .channel_offset = 0x10, 173 .channel_offset = 0x10,
174 .timer_bit = 0, 174 .timer_bit = 0,
175 .clk = "r_clk",
176 .clockevent_rating = 125, 175 .clockevent_rating = 125,
177 .clocksource_rating = 125, 176 .clocksource_rating = 125,
178}; 177};
diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c
index 60acf9e708ae..7458fc6df5c6 100644
--- a/arch/arm/mach-u300/clock.c
+++ b/arch/arm/mach-u300/clock.c
@@ -66,7 +66,7 @@ static DEFINE_SPINLOCK(syscon_resetreg_lock);
66 * AMBA bus 66 * AMBA bus
67 * | 67 * |
68 * +- CPU 68 * +- CPU
69 * +- NANDIF NAND Flash interface 69 * +- FSMC NANDIF NAND Flash interface
70 * +- SEMI Shared Memory interface 70 * +- SEMI Shared Memory interface
71 * +- ISP Image Signal Processor (U335 only) 71 * +- ISP Image Signal Processor (U335 only)
72 * +- CDS (U335 only) 72 * +- CDS (U335 only)
@@ -726,7 +726,7 @@ static struct clk cpu_clk = {
726}; 726};
727 727
728static struct clk nandif_clk = { 728static struct clk nandif_clk = {
729 .name = "NANDIF", 729 .name = "FSMC",
730 .parent = &amba_clk, 730 .parent = &amba_clk,
731 .hw_ctrld = false, 731 .hw_ctrld = false,
732 .reset = true, 732 .reset = true,
@@ -1259,7 +1259,7 @@ static struct clk_lookup lookups[] = {
1259 /* Connected directly to the AMBA bus */ 1259 /* Connected directly to the AMBA bus */
1260 DEF_LOOKUP("amba", &amba_clk), 1260 DEF_LOOKUP("amba", &amba_clk),
1261 DEF_LOOKUP("cpu", &cpu_clk), 1261 DEF_LOOKUP("cpu", &cpu_clk),
1262 DEF_LOOKUP("fsmc", &nandif_clk), 1262 DEF_LOOKUP("fsmc-nand", &nandif_clk),
1263 DEF_LOOKUP("semi", &semi_clk), 1263 DEF_LOOKUP("semi", &semi_clk),
1264#ifdef CONFIG_MACH_U300_BS335 1264#ifdef CONFIG_MACH_U300_BS335
1265 DEF_LOOKUP("isp", &isp_clk), 1265 DEF_LOOKUP("isp", &isp_clk),
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index ea41c236be0f..aa53ee22438f 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -21,7 +21,8 @@
21#include <linux/gpio.h> 21#include <linux/gpio.h>
22#include <linux/clk.h> 22#include <linux/clk.h>
23#include <linux/err.h> 23#include <linux/err.h>
24#include <mach/coh901318.h> 24#include <linux/mtd/nand.h>
25#include <linux/mtd/fsmc.h>
25 26
26#include <asm/types.h> 27#include <asm/types.h>
27#include <asm/setup.h> 28#include <asm/setup.h>
@@ -30,6 +31,7 @@
30#include <asm/mach/map.h> 31#include <asm/mach/map.h>
31#include <asm/mach/irq.h> 32#include <asm/mach/irq.h>
32 33
34#include <mach/coh901318.h>
33#include <mach/hardware.h> 35#include <mach/hardware.h>
34#include <mach/syscon.h> 36#include <mach/syscon.h>
35#include <mach/dma_channels.h> 37#include <mach/dma_channels.h>
@@ -285,6 +287,13 @@ static struct resource rtc_resources[] = {
285 */ 287 */
286static struct resource fsmc_resources[] = { 288static struct resource fsmc_resources[] = {
287 { 289 {
290 .name = "nand_data",
291 .start = U300_NAND_CS0_PHYS_BASE,
292 .end = U300_NAND_CS0_PHYS_BASE + SZ_16K - 1,
293 .flags = IORESOURCE_MEM,
294 },
295 {
296 .name = "fsmc_regs",
288 .start = U300_NAND_IF_PHYS_BASE, 297 .start = U300_NAND_IF_PHYS_BASE,
289 .end = U300_NAND_IF_PHYS_BASE + SZ_4K - 1, 298 .end = U300_NAND_IF_PHYS_BASE + SZ_4K - 1,
290 .flags = IORESOURCE_MEM, 299 .flags = IORESOURCE_MEM,
@@ -1429,11 +1438,39 @@ static struct platform_device rtc_device = {
1429 .resource = rtc_resources, 1438 .resource = rtc_resources,
1430}; 1439};
1431 1440
1432static struct platform_device fsmc_device = { 1441static struct mtd_partition u300_partitions[] = {
1433 .name = "nandif", 1442 {
1443 .name = "bootrecords",
1444 .offset = 0,
1445 .size = SZ_128K,
1446 },
1447 {
1448 .name = "free",
1449 .offset = SZ_128K,
1450 .size = 8064 * SZ_1K,
1451 },
1452 {
1453 .name = "platform",
1454 .offset = 8192 * SZ_1K,
1455 .size = 253952 * SZ_1K,
1456 },
1457};
1458
1459static struct fsmc_nand_platform_data nand_platform_data = {
1460 .partitions = u300_partitions,
1461 .nr_partitions = ARRAY_SIZE(u300_partitions),
1462 .options = NAND_SKIP_BBTSCAN,
1463 .width = FSMC_NAND_BW8,
1464};
1465
1466static struct platform_device nand_device = {
1467 .name = "fsmc-nand",
1434 .id = -1, 1468 .id = -1,
1435 .num_resources = ARRAY_SIZE(fsmc_resources),
1436 .resource = fsmc_resources, 1469 .resource = fsmc_resources,
1470 .num_resources = ARRAY_SIZE(fsmc_resources),
1471 .dev = {
1472 .platform_data = &nand_platform_data,
1473 },
1437}; 1474};
1438 1475
1439static struct platform_device ave_device = { 1476static struct platform_device ave_device = {
@@ -1465,7 +1502,7 @@ static struct platform_device *platform_devs[] __initdata = {
1465 &keypad_device, 1502 &keypad_device,
1466 &rtc_device, 1503 &rtc_device,
1467 &gpio_device, 1504 &gpio_device,
1468 &fsmc_device, 1505 &nand_device,
1469 &wdog_device, 1506 &wdog_device,
1470 &ave_device 1507 &ave_device
1471}; 1508};
diff --git a/arch/arm/mach-u300/include/mach/u300-regs.h b/arch/arm/mach-u300/include/mach/u300-regs.h
index 56721a0cd2af..8b85df4c8d8f 100644
--- a/arch/arm/mach-u300/include/mach/u300-regs.h
+++ b/arch/arm/mach-u300/include/mach/u300-regs.h
@@ -20,11 +20,9 @@
20 20
21/* NAND Flash CS0 */ 21/* NAND Flash CS0 */
22#define U300_NAND_CS0_PHYS_BASE 0x80000000 22#define U300_NAND_CS0_PHYS_BASE 0x80000000
23#define U300_NAND_CS0_VIRT_BASE 0xff040000
24 23
25/* NFIF */ 24/* NFIF */
26#define U300_NAND_IF_PHYS_BASE 0x9f800000 25#define U300_NAND_IF_PHYS_BASE 0x9f800000
27#define U300_NAND_IF_VIRT_BASE 0xff030000
28 26
29/* AHB Peripherals */ 27/* AHB Peripherals */
30#define U300_AHB_PER_PHYS_BASE 0xa0000000 28#define U300_AHB_PER_PHYS_BASE 0xa0000000
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index e0fd747e447a..73fb1a551ec6 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -10,6 +10,7 @@
10#include <linux/io.h> 10#include <linux/io.h>
11#include <linux/clk.h> 11#include <linux/clk.h>
12 12
13#include <asm/cacheflush.h>
13#include <asm/hardware/cache-l2x0.h> 14#include <asm/hardware/cache-l2x0.h>
14#include <asm/hardware/gic.h> 15#include <asm/hardware/gic.h>
15#include <asm/mach/map.h> 16#include <asm/mach/map.h>
@@ -71,6 +72,46 @@ void __init ux500_init_irq(void)
71} 72}
72 73
73#ifdef CONFIG_CACHE_L2X0 74#ifdef CONFIG_CACHE_L2X0
75static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
76{
77 /* wait for the operation to complete */
78 while (readl(reg) & mask)
79 ;
80}
81
82static inline void ux500_cache_sync(void)
83{
84 void __iomem *base = __io_address(UX500_L2CC_BASE);
85 writel(0, base + L2X0_CACHE_SYNC);
86 ux500_cache_wait(base + L2X0_CACHE_SYNC, 1);
87}
88
89/*
90 * The L2 cache cannot be turned off in the non-secure world.
91 * Dummy until a secure service is in place.
92 */
93static void ux500_l2x0_disable(void)
94{
95}
96
97/*
98 * This is only called when doing a kexec, just after turning off the L2
99 * and L1 cache, and it is surrounded by a spinlock in the generic version.
100 * However, we're not really turning off the L2 cache right now and the
101 * PL310 does not support exclusive accesses (used to implement the spinlock).
102 * So, the invalidation needs to be done without the spinlock.
103 */
104static void ux500_l2x0_inv_all(void)
105{
106 void __iomem *l2x0_base = __io_address(UX500_L2CC_BASE);
107 uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */
108
109 /* invalidate all ways */
110 writel(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
111 ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
112 ux500_cache_sync();
113}
114
74static int ux500_l2x0_init(void) 115static int ux500_l2x0_init(void)
75{ 116{
76 void __iomem *l2x0_base; 117 void __iomem *l2x0_base;
@@ -80,6 +121,10 @@ static int ux500_l2x0_init(void)
80 /* 64KB way size, 8 way associativity, force WA */ 121 /* 64KB way size, 8 way associativity, force WA */
81 l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); 122 l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
82 123
124 /* Override invalidate function */
125 outer_cache.disable = ux500_l2x0_disable;
126 outer_cache.inv_all = ux500_l2x0_inv_all;
127
83 return 0; 128 return 0;
84} 129}
85early_initcall(ux500_l2x0_init); 130early_initcall(ux500_l2x0_init);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index a0a2928ae4dd..4414a01e1e8a 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -779,6 +779,14 @@ config CACHE_L2X0
779 help 779 help
780 This option enables the L2x0 PrimeCell. 780 This option enables the L2x0 PrimeCell.
781 781
782config CACHE_PL310
783 bool
784 depends on CACHE_L2X0
785 default y if CPU_V7 && !CPU_V6
786 help
787 This option enables optimisations for the PL310 cache
788 controller.
789
782config CACHE_TAUROS2 790config CACHE_TAUROS2
783 bool "Enable the Tauros2 L2 cache controller" 791 bool "Enable the Tauros2 L2 cache controller"
784 depends on (ARCH_DOVE || ARCH_MMP) 792 depends on (ARCH_DOVE || ARCH_MMP)
diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S
index 7148e53e6078..1fa6f71470de 100644
--- a/arch/arm/mm/cache-fa.S
+++ b/arch/arm/mm/cache-fa.S
@@ -38,6 +38,17 @@
38#define CACHE_DLIMIT (CACHE_DSIZE * 2) 38#define CACHE_DLIMIT (CACHE_DSIZE * 2)
39 39
40/* 40/*
41 * flush_icache_all()
42 *
43 * Unconditionally clean and invalidate the entire icache.
44 */
45ENTRY(fa_flush_icache_all)
46 mov r0, #0
47 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
48 mov pc, lr
49ENDPROC(fa_flush_icache_all)
50
51/*
41 * flush_user_cache_all() 52 * flush_user_cache_all()
42 * 53 *
43 * Clean and invalidate all cache entries in a particular address 54 * Clean and invalidate all cache entries in a particular address
@@ -233,6 +244,7 @@ ENDPROC(fa_dma_unmap_area)
233 244
234 .type fa_cache_fns, #object 245 .type fa_cache_fns, #object
235ENTRY(fa_cache_fns) 246ENTRY(fa_cache_fns)
247 .long fa_flush_icache_all
236 .long fa_flush_kern_cache_all 248 .long fa_flush_kern_cache_all
237 .long fa_flush_user_cache_all 249 .long fa_flush_user_cache_all
238 .long fa_flush_user_cache_range 250 .long fa_flush_user_cache_range
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 9982eb385c0f..170c9bb95866 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -28,14 +28,24 @@
28static void __iomem *l2x0_base; 28static void __iomem *l2x0_base;
29static DEFINE_SPINLOCK(l2x0_lock); 29static DEFINE_SPINLOCK(l2x0_lock);
30static uint32_t l2x0_way_mask; /* Bitmask of active ways */ 30static uint32_t l2x0_way_mask; /* Bitmask of active ways */
31static uint32_t l2x0_size;
31 32
32static inline void cache_wait(void __iomem *reg, unsigned long mask) 33static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
33{ 34{
34 /* wait for the operation to complete */ 35 /* wait for cache operation by line or way to complete */
35 while (readl_relaxed(reg) & mask) 36 while (readl_relaxed(reg) & mask)
36 ; 37 ;
37} 38}
38 39
40#ifdef CONFIG_CACHE_PL310
41static inline void cache_wait(void __iomem *reg, unsigned long mask)
42{
43 /* cache operations by line are atomic on PL310 */
44}
45#else
46#define cache_wait cache_wait_way
47#endif
48
39static inline void cache_sync(void) 49static inline void cache_sync(void)
40{ 50{
41 void __iomem *base = l2x0_base; 51 void __iomem *base = l2x0_base;
@@ -103,14 +113,40 @@ static void l2x0_cache_sync(void)
103 spin_unlock_irqrestore(&l2x0_lock, flags); 113 spin_unlock_irqrestore(&l2x0_lock, flags);
104} 114}
105 115
106static inline void l2x0_inv_all(void) 116static void l2x0_flush_all(void)
117{
118 unsigned long flags;
119
120 /* clean all ways */
121 spin_lock_irqsave(&l2x0_lock, flags);
122 writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY);
123 cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask);
124 cache_sync();
125 spin_unlock_irqrestore(&l2x0_lock, flags);
126}
127
128static void l2x0_clean_all(void)
129{
130 unsigned long flags;
131
132 /* clean all ways */
133 spin_lock_irqsave(&l2x0_lock, flags);
134 writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY);
135 cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask);
136 cache_sync();
137 spin_unlock_irqrestore(&l2x0_lock, flags);
138}
139
140static void l2x0_inv_all(void)
107{ 141{
108 unsigned long flags; 142 unsigned long flags;
109 143
110 /* invalidate all ways */ 144 /* invalidate all ways */
111 spin_lock_irqsave(&l2x0_lock, flags); 145 spin_lock_irqsave(&l2x0_lock, flags);
146 /* Invalidating when L2 is enabled is a nono */
147 BUG_ON(readl(l2x0_base + L2X0_CTRL) & 1);
112 writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); 148 writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
113 cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); 149 cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
114 cache_sync(); 150 cache_sync();
115 spin_unlock_irqrestore(&l2x0_lock, flags); 151 spin_unlock_irqrestore(&l2x0_lock, flags);
116} 152}
@@ -159,6 +195,11 @@ static void l2x0_clean_range(unsigned long start, unsigned long end)
159 void __iomem *base = l2x0_base; 195 void __iomem *base = l2x0_base;
160 unsigned long flags; 196 unsigned long flags;
161 197
198 if ((end - start) >= l2x0_size) {
199 l2x0_clean_all();
200 return;
201 }
202
162 spin_lock_irqsave(&l2x0_lock, flags); 203 spin_lock_irqsave(&l2x0_lock, flags);
163 start &= ~(CACHE_LINE_SIZE - 1); 204 start &= ~(CACHE_LINE_SIZE - 1);
164 while (start < end) { 205 while (start < end) {
@@ -184,6 +225,11 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)
184 void __iomem *base = l2x0_base; 225 void __iomem *base = l2x0_base;
185 unsigned long flags; 226 unsigned long flags;
186 227
228 if ((end - start) >= l2x0_size) {
229 l2x0_flush_all();
230 return;
231 }
232
187 spin_lock_irqsave(&l2x0_lock, flags); 233 spin_lock_irqsave(&l2x0_lock, flags);
188 start &= ~(CACHE_LINE_SIZE - 1); 234 start &= ~(CACHE_LINE_SIZE - 1);
189 while (start < end) { 235 while (start < end) {
@@ -206,10 +252,20 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)
206 spin_unlock_irqrestore(&l2x0_lock, flags); 252 spin_unlock_irqrestore(&l2x0_lock, flags);
207} 253}
208 254
255static void l2x0_disable(void)
256{
257 unsigned long flags;
258
259 spin_lock_irqsave(&l2x0_lock, flags);
260 writel(0, l2x0_base + L2X0_CTRL);
261 spin_unlock_irqrestore(&l2x0_lock, flags);
262}
263
209void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) 264void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
210{ 265{
211 __u32 aux; 266 __u32 aux;
212 __u32 cache_id; 267 __u32 cache_id;
268 __u32 way_size = 0;
213 int ways; 269 int ways;
214 const char *type; 270 const char *type;
215 271
@@ -244,6 +300,13 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
244 l2x0_way_mask = (1 << ways) - 1; 300 l2x0_way_mask = (1 << ways) - 1;
245 301
246 /* 302 /*
303 * L2 cache Size = Way size * Number of ways
304 */
305 way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17;
306 way_size = 1 << (way_size + 3);
307 l2x0_size = ways * way_size * SZ_1K;
308
309 /*
247 * Check if l2x0 controller is already enabled. 310 * Check if l2x0 controller is already enabled.
248 * If you are booting from non-secure mode 311 * If you are booting from non-secure mode
249 * accessing the below registers will fault. 312 * accessing the below registers will fault.
@@ -263,8 +326,11 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
263 outer_cache.clean_range = l2x0_clean_range; 326 outer_cache.clean_range = l2x0_clean_range;
264 outer_cache.flush_range = l2x0_flush_range; 327 outer_cache.flush_range = l2x0_flush_range;
265 outer_cache.sync = l2x0_cache_sync; 328 outer_cache.sync = l2x0_cache_sync;
329 outer_cache.flush_all = l2x0_flush_all;
330 outer_cache.inv_all = l2x0_inv_all;
331 outer_cache.disable = l2x0_disable;
266 332
267 printk(KERN_INFO "%s cache controller enabled\n", type); 333 printk(KERN_INFO "%s cache controller enabled\n", type);
268 printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n", 334 printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",
269 ways, cache_id, aux); 335 ways, cache_id, aux, l2x0_size);
270} 336}
diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S
index c2ff3c599fee..2e2bc406a18d 100644
--- a/arch/arm/mm/cache-v3.S
+++ b/arch/arm/mm/cache-v3.S
@@ -13,6 +13,15 @@
13#include "proc-macros.S" 13#include "proc-macros.S"
14 14
15/* 15/*
16 * flush_icache_all()
17 *
18 * Unconditionally clean and invalidate the entire icache.
19 */
20ENTRY(v3_flush_icache_all)
21 mov pc, lr
22ENDPROC(v3_flush_icache_all)
23
24/*
16 * flush_user_cache_all() 25 * flush_user_cache_all()
17 * 26 *
18 * Invalidate all cache entries in a particular address 27 * Invalidate all cache entries in a particular address
@@ -122,6 +131,7 @@ ENDPROC(v3_dma_map_area)
122 131
123 .type v3_cache_fns, #object 132 .type v3_cache_fns, #object
124ENTRY(v3_cache_fns) 133ENTRY(v3_cache_fns)
134 .long v3_flush_icache_all
125 .long v3_flush_kern_cache_all 135 .long v3_flush_kern_cache_all
126 .long v3_flush_user_cache_all 136 .long v3_flush_user_cache_all
127 .long v3_flush_user_cache_range 137 .long v3_flush_user_cache_range
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S
index 4810f7e3e813..a8fefb523f19 100644
--- a/arch/arm/mm/cache-v4.S
+++ b/arch/arm/mm/cache-v4.S
@@ -13,6 +13,15 @@
13#include "proc-macros.S" 13#include "proc-macros.S"
14 14
15/* 15/*
16 * flush_icache_all()
17 *
18 * Unconditionally clean and invalidate the entire icache.
19 */
20ENTRY(v4_flush_icache_all)
21 mov pc, lr
22ENDPROC(v4_flush_icache_all)
23
24/*
16 * flush_user_cache_all() 25 * flush_user_cache_all()
17 * 26 *
18 * Invalidate all cache entries in a particular address 27 * Invalidate all cache entries in a particular address
@@ -134,6 +143,7 @@ ENDPROC(v4_dma_map_area)
134 143
135 .type v4_cache_fns, #object 144 .type v4_cache_fns, #object
136ENTRY(v4_cache_fns) 145ENTRY(v4_cache_fns)
146 .long v4_flush_icache_all
137 .long v4_flush_kern_cache_all 147 .long v4_flush_kern_cache_all
138 .long v4_flush_user_cache_all 148 .long v4_flush_user_cache_all
139 .long v4_flush_user_cache_range 149 .long v4_flush_user_cache_range
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
index df8368afa102..d3644db467b7 100644
--- a/arch/arm/mm/cache-v4wb.S
+++ b/arch/arm/mm/cache-v4wb.S
@@ -51,6 +51,17 @@ flush_base:
51 .text 51 .text
52 52
53/* 53/*
54 * flush_icache_all()
55 *
56 * Unconditionally clean and invalidate the entire icache.
57 */
58ENTRY(v4wb_flush_icache_all)
59 mov r0, #0
60 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
61 mov pc, lr
62ENDPROC(v4wb_flush_icache_all)
63
64/*
54 * flush_user_cache_all() 65 * flush_user_cache_all()
55 * 66 *
56 * Clean and invalidate all cache entries in a particular address 67 * Clean and invalidate all cache entries in a particular address
@@ -244,6 +255,7 @@ ENDPROC(v4wb_dma_unmap_area)
244 255
245 .type v4wb_cache_fns, #object 256 .type v4wb_cache_fns, #object
246ENTRY(v4wb_cache_fns) 257ENTRY(v4wb_cache_fns)
258 .long v4wb_flush_icache_all
247 .long v4wb_flush_kern_cache_all 259 .long v4wb_flush_kern_cache_all
248 .long v4wb_flush_user_cache_all 260 .long v4wb_flush_user_cache_all
249 .long v4wb_flush_user_cache_range 261 .long v4wb_flush_user_cache_range
diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S
index 45c70312f43b..49c2b66cf3dd 100644
--- a/arch/arm/mm/cache-v4wt.S
+++ b/arch/arm/mm/cache-v4wt.S
@@ -41,6 +41,17 @@
41#define CACHE_DLIMIT 16384 41#define CACHE_DLIMIT 16384
42 42
43/* 43/*
44 * flush_icache_all()
45 *
46 * Unconditionally clean and invalidate the entire icache.
47 */
48ENTRY(v4wt_flush_icache_all)
49 mov r0, #0
50 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
51 mov pc, lr
52ENDPROC(v4wt_flush_icache_all)
53
54/*
44 * flush_user_cache_all() 55 * flush_user_cache_all()
45 * 56 *
46 * Invalidate all cache entries in a particular address 57 * Invalidate all cache entries in a particular address
@@ -188,6 +199,7 @@ ENDPROC(v4wt_dma_map_area)
188 199
189 .type v4wt_cache_fns, #object 200 .type v4wt_cache_fns, #object
190ENTRY(v4wt_cache_fns) 201ENTRY(v4wt_cache_fns)
202 .long v4wt_flush_icache_all
191 .long v4wt_flush_kern_cache_all 203 .long v4wt_flush_kern_cache_all
192 .long v4wt_flush_user_cache_all 204 .long v4wt_flush_user_cache_all
193 .long v4wt_flush_user_cache_range 205 .long v4wt_flush_user_cache_range
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index c493d7244d3d..83e59f870426 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -66,6 +66,30 @@ static int do_adjust_pte(struct vm_area_struct *vma, unsigned long address,
66 return ret; 66 return ret;
67} 67}
68 68
69#if USE_SPLIT_PTLOCKS
70/*
71 * If we are using split PTE locks, then we need to take the page
72 * lock here. Otherwise we are using shared mm->page_table_lock
73 * which is already locked, thus cannot take it.
74 */
75static inline void do_pte_lock(spinlock_t *ptl)
76{
77 /*
78 * Use nested version here to indicate that we are already
79 * holding one similar spinlock.
80 */
81 spin_lock_nested(ptl, SINGLE_DEPTH_NESTING);
82}
83
84static inline void do_pte_unlock(spinlock_t *ptl)
85{
86 spin_unlock(ptl);
87}
88#else /* !USE_SPLIT_PTLOCKS */
89static inline void do_pte_lock(spinlock_t *ptl) {}
90static inline void do_pte_unlock(spinlock_t *ptl) {}
91#endif /* USE_SPLIT_PTLOCKS */
92
69static int adjust_pte(struct vm_area_struct *vma, unsigned long address, 93static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
70 unsigned long pfn) 94 unsigned long pfn)
71{ 95{
@@ -90,11 +114,11 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
90 */ 114 */
91 ptl = pte_lockptr(vma->vm_mm, pmd); 115 ptl = pte_lockptr(vma->vm_mm, pmd);
92 pte = pte_offset_map(pmd, address); 116 pte = pte_offset_map(pmd, address);
93 spin_lock(ptl); 117 do_pte_lock(ptl);
94 118
95 ret = do_adjust_pte(vma, address, pfn, pte); 119 ret = do_adjust_pte(vma, address, pfn, pte);
96 120
97 spin_unlock(ptl); 121 do_pte_unlock(ptl);
98 pte_unmap(pte); 122 pte_unmap(pte);
99 123
100 return ret; 124 return ret;
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 7fd9b5eb177f..5164069ced42 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -18,6 +18,7 @@
18#include <linux/highmem.h> 18#include <linux/highmem.h>
19#include <linux/gfp.h> 19#include <linux/gfp.h>
20#include <linux/memblock.h> 20#include <linux/memblock.h>
21#include <linux/sort.h>
21 22
22#include <asm/mach-types.h> 23#include <asm/mach-types.h>
23#include <asm/sections.h> 24#include <asm/sections.h>
@@ -121,9 +122,10 @@ void show_mem(void)
121 printk("%d pages swap cached\n", cached); 122 printk("%d pages swap cached\n", cached);
122} 123}
123 124
124static void __init find_limits(struct meminfo *mi, 125static void __init find_limits(unsigned long *min, unsigned long *max_low,
125 unsigned long *min, unsigned long *max_low, unsigned long *max_high) 126 unsigned long *max_high)
126{ 127{
128 struct meminfo *mi = &meminfo;
127 int i; 129 int i;
128 130
129 *min = -1UL; 131 *min = -1UL;
@@ -147,14 +149,13 @@ static void __init find_limits(struct meminfo *mi,
147 } 149 }
148} 150}
149 151
150static void __init arm_bootmem_init(struct meminfo *mi, 152static void __init arm_bootmem_init(unsigned long start_pfn,
151 unsigned long start_pfn, unsigned long end_pfn) 153 unsigned long end_pfn)
152{ 154{
153 struct memblock_region *reg; 155 struct memblock_region *reg;
154 unsigned int boot_pages; 156 unsigned int boot_pages;
155 phys_addr_t bitmap; 157 phys_addr_t bitmap;
156 pg_data_t *pgdat; 158 pg_data_t *pgdat;
157 int i;
158 159
159 /* 160 /*
160 * Allocate the bootmem bitmap page. This must be in a region 161 * Allocate the bootmem bitmap page. This must be in a region
@@ -172,30 +173,39 @@ static void __init arm_bootmem_init(struct meminfo *mi,
172 pgdat = NODE_DATA(0); 173 pgdat = NODE_DATA(0);
173 init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn); 174 init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn);
174 175
175 for_each_bank(i, mi) { 176 /* Free the lowmem regions from memblock into bootmem. */
176 struct membank *bank = &mi->bank[i]; 177 for_each_memblock(memory, reg) {
177 if (!bank->highmem) 178 unsigned long start = memblock_region_memory_base_pfn(reg);
178 free_bootmem(bank_phys_start(bank), bank_phys_size(bank)); 179 unsigned long end = memblock_region_memory_end_pfn(reg);
180
181 if (end >= end_pfn)
182 end = end_pfn;
183 if (start >= end)
184 break;
185
186 free_bootmem(__pfn_to_phys(start), (end - start) << PAGE_SHIFT);
179 } 187 }
180 188
181 /* 189 /* Reserve the lowmem memblock reserved regions in bootmem. */
182 * Reserve the memblock reserved regions in bootmem.
183 */
184 for_each_memblock(reserved, reg) { 190 for_each_memblock(reserved, reg) {
185 phys_addr_t start = memblock_region_reserved_base_pfn(reg); 191 unsigned long start = memblock_region_reserved_base_pfn(reg);
186 phys_addr_t end = memblock_region_reserved_end_pfn(reg); 192 unsigned long end = memblock_region_reserved_end_pfn(reg);
187 if (start >= start_pfn && end <= end_pfn) 193
188 reserve_bootmem_node(pgdat, __pfn_to_phys(start), 194 if (end >= end_pfn)
189 (end - start) << PAGE_SHIFT, 195 end = end_pfn;
190 BOOTMEM_DEFAULT); 196 if (start >= end)
197 break;
198
199 reserve_bootmem(__pfn_to_phys(start),
200 (end - start) << PAGE_SHIFT, BOOTMEM_DEFAULT);
191 } 201 }
192} 202}
193 203
194static void __init arm_bootmem_free(struct meminfo *mi, unsigned long min, 204static void __init arm_bootmem_free(unsigned long min, unsigned long max_low,
195 unsigned long max_low, unsigned long max_high) 205 unsigned long max_high)
196{ 206{
197 unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; 207 unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
198 int i; 208 struct memblock_region *reg;
199 209
200 /* 210 /*
201 * initialise the zones. 211 * initialise the zones.
@@ -217,13 +227,20 @@ static void __init arm_bootmem_free(struct meminfo *mi, unsigned long min,
217 * holes = node_size - sum(bank_sizes) 227 * holes = node_size - sum(bank_sizes)
218 */ 228 */
219 memcpy(zhole_size, zone_size, sizeof(zhole_size)); 229 memcpy(zhole_size, zone_size, sizeof(zhole_size));
220 for_each_bank(i, mi) { 230 for_each_memblock(memory, reg) {
221 int idx = 0; 231 unsigned long start = memblock_region_memory_base_pfn(reg);
232 unsigned long end = memblock_region_memory_end_pfn(reg);
233
234 if (start < max_low) {
235 unsigned long low_end = min(end, max_low);
236 zhole_size[0] -= low_end - start;
237 }
222#ifdef CONFIG_HIGHMEM 238#ifdef CONFIG_HIGHMEM
223 if (mi->bank[i].highmem) 239 if (end > max_low) {
224 idx = ZONE_HIGHMEM; 240 unsigned long high_start = max(start, max_low);
241 zhole_size[ZONE_HIGHMEM] -= end - high_start;
242 }
225#endif 243#endif
226 zhole_size[idx] -= bank_pfn_size(&mi->bank[i]);
227 } 244 }
228 245
229 /* 246 /*
@@ -256,10 +273,19 @@ static void arm_memory_present(void)
256} 273}
257#endif 274#endif
258 275
276static int __init meminfo_cmp(const void *_a, const void *_b)
277{
278 const struct membank *a = _a, *b = _b;
279 long cmp = bank_pfn_start(a) - bank_pfn_start(b);
280 return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
281}
282
259void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) 283void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
260{ 284{
261 int i; 285 int i;
262 286
287 sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
288
263 memblock_init(); 289 memblock_init();
264 for (i = 0; i < mi->nr_banks; i++) 290 for (i = 0; i < mi->nr_banks; i++)
265 memblock_add(mi->bank[i].start, mi->bank[i].size); 291 memblock_add(mi->bank[i].start, mi->bank[i].size);
@@ -292,14 +318,13 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
292 318
293void __init bootmem_init(void) 319void __init bootmem_init(void)
294{ 320{
295 struct meminfo *mi = &meminfo;
296 unsigned long min, max_low, max_high; 321 unsigned long min, max_low, max_high;
297 322
298 max_low = max_high = 0; 323 max_low = max_high = 0;
299 324
300 find_limits(mi, &min, &max_low, &max_high); 325 find_limits(&min, &max_low, &max_high);
301 326
302 arm_bootmem_init(mi, min, max_low); 327 arm_bootmem_init(min, max_low);
303 328
304 /* 329 /*
305 * Sparsemem tries to allocate bootmem in memory_present(), 330 * Sparsemem tries to allocate bootmem in memory_present(),
@@ -317,7 +342,7 @@ void __init bootmem_init(void)
317 * the sparse mem_map arrays initialized by sparse_init() 342 * the sparse mem_map arrays initialized by sparse_init()
318 * for memmap_init_zone(), otherwise all PFNs are invalid. 343 * for memmap_init_zone(), otherwise all PFNs are invalid.
319 */ 344 */
320 arm_bootmem_free(mi, min, max_low, max_high); 345 arm_bootmem_free(min, max_low, max_high);
321 346
322 high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1; 347 high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
323 348
@@ -411,6 +436,56 @@ static void __init free_unused_memmap(struct meminfo *mi)
411 } 436 }
412} 437}
413 438
439static void __init free_highpages(void)
440{
441#ifdef CONFIG_HIGHMEM
442 unsigned long max_low = max_low_pfn + PHYS_PFN_OFFSET;
443 struct memblock_region *mem, *res;
444
445 /* set highmem page free */
446 for_each_memblock(memory, mem) {
447 unsigned long start = memblock_region_memory_base_pfn(mem);
448 unsigned long end = memblock_region_memory_end_pfn(mem);
449
450 /* Ignore complete lowmem entries */
451 if (end <= max_low)
452 continue;
453
454 /* Truncate partial highmem entries */
455 if (start < max_low)
456 start = max_low;
457
458 /* Find and exclude any reserved regions */
459 for_each_memblock(reserved, res) {
460 unsigned long res_start, res_end;
461
462 res_start = memblock_region_reserved_base_pfn(res);
463 res_end = memblock_region_reserved_end_pfn(res);
464
465 if (res_end < start)
466 continue;
467 if (res_start < start)
468 res_start = start;
469 if (res_start > end)
470 res_start = end;
471 if (res_end > end)
472 res_end = end;
473 if (res_start != start)
474 totalhigh_pages += free_area(start, res_start,
475 NULL);
476 start = res_end;
477 if (start == end)
478 break;
479 }
480
481 /* And now free anything which remains */
482 if (start < end)
483 totalhigh_pages += free_area(start, end, NULL);
484 }
485 totalram_pages += totalhigh_pages;
486#endif
487}
488
414/* 489/*
415 * mem_init() marks the free areas in the mem_map and tells us how much 490 * mem_init() marks the free areas in the mem_map and tells us how much
416 * memory is free. This is done after various parts of the system have 491 * memory is free. This is done after various parts of the system have
@@ -419,6 +494,7 @@ static void __init free_unused_memmap(struct meminfo *mi)
419void __init mem_init(void) 494void __init mem_init(void)
420{ 495{
421 unsigned long reserved_pages, free_pages; 496 unsigned long reserved_pages, free_pages;
497 struct memblock_region *reg;
422 int i; 498 int i;
423#ifdef CONFIG_HAVE_TCM 499#ifdef CONFIG_HAVE_TCM
424 /* These pointers are filled in on TCM detection */ 500 /* These pointers are filled in on TCM detection */
@@ -439,16 +515,7 @@ void __init mem_init(void)
439 __phys_to_pfn(__pa(swapper_pg_dir)), NULL); 515 __phys_to_pfn(__pa(swapper_pg_dir)), NULL);
440#endif 516#endif
441 517
442#ifdef CONFIG_HIGHMEM 518 free_highpages();
443 /* set highmem page free */
444 for_each_bank (i, &meminfo) {
445 unsigned long start = bank_pfn_start(&meminfo.bank[i]);
446 unsigned long end = bank_pfn_end(&meminfo.bank[i]);
447 if (start >= max_low_pfn + PHYS_PFN_OFFSET)
448 totalhigh_pages += free_area(start, end, NULL);
449 }
450 totalram_pages += totalhigh_pages;
451#endif
452 519
453 reserved_pages = free_pages = 0; 520 reserved_pages = free_pages = 0;
454 521
@@ -478,9 +545,11 @@ void __init mem_init(void)
478 */ 545 */
479 printk(KERN_INFO "Memory:"); 546 printk(KERN_INFO "Memory:");
480 num_physpages = 0; 547 num_physpages = 0;
481 for (i = 0; i < meminfo.nr_banks; i++) { 548 for_each_memblock(memory, reg) {
482 num_physpages += bank_pfn_size(&meminfo.bank[i]); 549 unsigned long pages = memblock_region_memory_end_pfn(reg) -
483 printk(" %ldMB", bank_phys_size(&meminfo.bank[i]) >> 20); 550 memblock_region_memory_base_pfn(reg);
551 num_physpages += pages;
552 printk(" %ldMB", pages >> (20 - PAGE_SHIFT));
484 } 553 }
485 printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT)); 554 printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
486 555
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index c32f731d56d3..72ad3e1f56cf 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -14,7 +14,6 @@
14#include <linux/mman.h> 14#include <linux/mman.h>
15#include <linux/nodemask.h> 15#include <linux/nodemask.h>
16#include <linux/memblock.h> 16#include <linux/memblock.h>
17#include <linux/sort.h>
18#include <linux/fs.h> 17#include <linux/fs.h>
19 18
20#include <asm/cputype.h> 19#include <asm/cputype.h>
@@ -265,17 +264,17 @@ static struct mem_type mem_types[] = {
265 .domain = DOMAIN_KERNEL, 264 .domain = DOMAIN_KERNEL,
266 }, 265 },
267 [MT_MEMORY_DTCM] = { 266 [MT_MEMORY_DTCM] = {
268 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | 267 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
269 L_PTE_DIRTY | L_PTE_WRITE, 268 L_PTE_WRITE,
270 .prot_l1 = PMD_TYPE_TABLE, 269 .prot_l1 = PMD_TYPE_TABLE,
271 .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, 270 .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
272 .domain = DOMAIN_KERNEL, 271 .domain = DOMAIN_KERNEL,
273 }, 272 },
274 [MT_MEMORY_ITCM] = { 273 [MT_MEMORY_ITCM] = {
275 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 274 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
276 L_PTE_USER | L_PTE_EXEC, 275 L_PTE_WRITE | L_PTE_EXEC,
277 .prot_l1 = PMD_TYPE_TABLE, 276 .prot_l1 = PMD_TYPE_TABLE,
278 .domain = DOMAIN_IO, 277 .domain = DOMAIN_KERNEL,
279 }, 278 },
280}; 279};
281 280
@@ -745,13 +744,14 @@ static int __init early_vmalloc(char *arg)
745} 744}
746early_param("vmalloc", early_vmalloc); 745early_param("vmalloc", early_vmalloc);
747 746
748phys_addr_t lowmem_end_addr; 747static phys_addr_t lowmem_limit __initdata = 0;
749 748
750static void __init sanity_check_meminfo(void) 749static void __init sanity_check_meminfo(void)
751{ 750{
752 int i, j, highmem = 0; 751 int i, j, highmem = 0;
753 752
754 lowmem_end_addr = __pa(vmalloc_min - 1) + 1; 753 lowmem_limit = __pa(vmalloc_min - 1) + 1;
754 memblock_set_current_limit(lowmem_limit);
755 755
756 for (i = 0, j = 0; i < meminfo.nr_banks; i++) { 756 for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
757 struct membank *bank = &meminfo.bank[j]; 757 struct membank *bank = &meminfo.bank[j];
@@ -852,6 +852,7 @@ static void __init sanity_check_meminfo(void)
852static inline void prepare_page_table(void) 852static inline void prepare_page_table(void)
853{ 853{
854 unsigned long addr; 854 unsigned long addr;
855 phys_addr_t end;
855 856
856 /* 857 /*
857 * Clear out all the mappings below the kernel image. 858 * Clear out all the mappings below the kernel image.
@@ -867,10 +868,17 @@ static inline void prepare_page_table(void)
867 pmd_clear(pmd_off_k(addr)); 868 pmd_clear(pmd_off_k(addr));
868 869
869 /* 870 /*
871 * Find the end of the first block of lowmem.
872 */
873 end = memblock.memory.regions[0].base + memblock.memory.regions[0].size;
874 if (end >= lowmem_limit)
875 end = lowmem_limit;
876
877 /*
870 * Clear out all the kernel space mappings, except for the first 878 * Clear out all the kernel space mappings, except for the first
871 * memory bank, up to the end of the vmalloc region. 879 * memory bank, up to the end of the vmalloc region.
872 */ 880 */
873 for (addr = __phys_to_virt(bank_phys_end(&meminfo.bank[0])); 881 for (addr = __phys_to_virt(end);
874 addr < VMALLOC_END; addr += PGDIR_SIZE) 882 addr < VMALLOC_END; addr += PGDIR_SIZE)
875 pmd_clear(pmd_off_k(addr)); 883 pmd_clear(pmd_off_k(addr));
876} 884}
@@ -987,37 +995,28 @@ static void __init kmap_init(void)
987#endif 995#endif
988} 996}
989 997
990static inline void map_memory_bank(struct membank *bank)
991{
992 struct map_desc map;
993
994 map.pfn = bank_pfn_start(bank);
995 map.virtual = __phys_to_virt(bank_phys_start(bank));
996 map.length = bank_phys_size(bank);
997 map.type = MT_MEMORY;
998
999 create_mapping(&map);
1000}
1001
1002static void __init map_lowmem(void) 998static void __init map_lowmem(void)
1003{ 999{
1004 struct meminfo *mi = &meminfo; 1000 struct memblock_region *reg;
1005 int i;
1006 1001
1007 /* Map all the lowmem memory banks. */ 1002 /* Map all the lowmem memory banks. */
1008 for (i = 0; i < mi->nr_banks; i++) { 1003 for_each_memblock(memory, reg) {
1009 struct membank *bank = &mi->bank[i]; 1004 phys_addr_t start = reg->base;
1005 phys_addr_t end = start + reg->size;
1006 struct map_desc map;
1007
1008 if (end > lowmem_limit)
1009 end = lowmem_limit;
1010 if (start >= end)
1011 break;
1010 1012
1011 if (!bank->highmem) 1013 map.pfn = __phys_to_pfn(start);
1012 map_memory_bank(bank); 1014 map.virtual = __phys_to_virt(start);
1013 } 1015 map.length = end - start;
1014} 1016 map.type = MT_MEMORY;
1015 1017
1016static int __init meminfo_cmp(const void *_a, const void *_b) 1018 create_mapping(&map);
1017{ 1019 }
1018 const struct membank *a = _a, *b = _b;
1019 long cmp = bank_pfn_start(a) - bank_pfn_start(b);
1020 return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
1021} 1020}
1022 1021
1023/* 1022/*
@@ -1028,8 +1027,6 @@ void __init paging_init(struct machine_desc *mdesc)
1028{ 1027{
1029 void *zero_page; 1028 void *zero_page;
1030 1029
1031 sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
1032
1033 build_mem_type_table(); 1030 build_mem_type_table();
1034 sanity_check_meminfo(); 1031 sanity_check_meminfo();
1035 prepare_page_table(); 1032 prepare_page_table();
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index a6f5f8475b96..bcf748d9f4e2 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -119,6 +119,20 @@ ENTRY(cpu_arm1020_do_idle)
119/* ================================= CACHE ================================ */ 119/* ================================= CACHE ================================ */
120 120
121 .align 5 121 .align 5
122
123/*
124 * flush_icache_all()
125 *
126 * Unconditionally clean and invalidate the entire icache.
127 */
128ENTRY(arm1020_flush_icache_all)
129#ifndef CONFIG_CPU_ICACHE_DISABLE
130 mov r0, #0
131 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
132#endif
133 mov pc, lr
134ENDPROC(arm1020_flush_icache_all)
135
122/* 136/*
123 * flush_user_cache_all() 137 * flush_user_cache_all()
124 * 138 *
@@ -351,6 +365,7 @@ ENTRY(arm1020_dma_unmap_area)
351ENDPROC(arm1020_dma_unmap_area) 365ENDPROC(arm1020_dma_unmap_area)
352 366
353ENTRY(arm1020_cache_fns) 367ENTRY(arm1020_cache_fns)
368 .long arm1020_flush_icache_all
354 .long arm1020_flush_kern_cache_all 369 .long arm1020_flush_kern_cache_all
355 .long arm1020_flush_user_cache_all 370 .long arm1020_flush_user_cache_all
356 .long arm1020_flush_user_cache_range 371 .long arm1020_flush_user_cache_range
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index afc06b9c3133..ab7ec26657ea 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -119,6 +119,20 @@ ENTRY(cpu_arm1020e_do_idle)
119/* ================================= CACHE ================================ */ 119/* ================================= CACHE ================================ */
120 120
121 .align 5 121 .align 5
122
123/*
124 * flush_icache_all()
125 *
126 * Unconditionally clean and invalidate the entire icache.
127 */
128ENTRY(arm1020e_flush_icache_all)
129#ifndef CONFIG_CPU_ICACHE_DISABLE
130 mov r0, #0
131 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
132#endif
133 mov pc, lr
134ENDPROC(arm1020e_flush_icache_all)
135
122/* 136/*
123 * flush_user_cache_all() 137 * flush_user_cache_all()
124 * 138 *
@@ -337,6 +351,7 @@ ENTRY(arm1020e_dma_unmap_area)
337ENDPROC(arm1020e_dma_unmap_area) 351ENDPROC(arm1020e_dma_unmap_area)
338 352
339ENTRY(arm1020e_cache_fns) 353ENTRY(arm1020e_cache_fns)
354 .long arm1020e_flush_icache_all
340 .long arm1020e_flush_kern_cache_all 355 .long arm1020e_flush_kern_cache_all
341 .long arm1020e_flush_user_cache_all 356 .long arm1020e_flush_user_cache_all
342 .long arm1020e_flush_user_cache_range 357 .long arm1020e_flush_user_cache_range
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 8915e0ba3fe5..831c5e54e22f 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -108,6 +108,20 @@ ENTRY(cpu_arm1022_do_idle)
108/* ================================= CACHE ================================ */ 108/* ================================= CACHE ================================ */
109 109
110 .align 5 110 .align 5
111
112/*
113 * flush_icache_all()
114 *
115 * Unconditionally clean and invalidate the entire icache.
116 */
117ENTRY(arm1022_flush_icache_all)
118#ifndef CONFIG_CPU_ICACHE_DISABLE
119 mov r0, #0
120 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
121#endif
122 mov pc, lr
123ENDPROC(arm1022_flush_icache_all)
124
111/* 125/*
112 * flush_user_cache_all() 126 * flush_user_cache_all()
113 * 127 *
@@ -326,6 +340,7 @@ ENTRY(arm1022_dma_unmap_area)
326ENDPROC(arm1022_dma_unmap_area) 340ENDPROC(arm1022_dma_unmap_area)
327 341
328ENTRY(arm1022_cache_fns) 342ENTRY(arm1022_cache_fns)
343 .long arm1022_flush_icache_all
329 .long arm1022_flush_kern_cache_all 344 .long arm1022_flush_kern_cache_all
330 .long arm1022_flush_user_cache_all 345 .long arm1022_flush_user_cache_all
331 .long arm1022_flush_user_cache_range 346 .long arm1022_flush_user_cache_range
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index ff446c5d476f..e3f7e9a166bf 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -108,6 +108,20 @@ ENTRY(cpu_arm1026_do_idle)
108/* ================================= CACHE ================================ */ 108/* ================================= CACHE ================================ */
109 109
110 .align 5 110 .align 5
111
112/*
113 * flush_icache_all()
114 *
115 * Unconditionally clean and invalidate the entire icache.
116 */
117ENTRY(arm1026_flush_icache_all)
118#ifndef CONFIG_CPU_ICACHE_DISABLE
119 mov r0, #0
120 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
121#endif
122 mov pc, lr
123ENDPROC(arm1026_flush_icache_all)
124
111/* 125/*
112 * flush_user_cache_all() 126 * flush_user_cache_all()
113 * 127 *
@@ -320,6 +334,7 @@ ENTRY(arm1026_dma_unmap_area)
320ENDPROC(arm1026_dma_unmap_area) 334ENDPROC(arm1026_dma_unmap_area)
321 335
322ENTRY(arm1026_cache_fns) 336ENTRY(arm1026_cache_fns)
337 .long arm1026_flush_icache_all
323 .long arm1026_flush_kern_cache_all 338 .long arm1026_flush_kern_cache_all
324 .long arm1026_flush_user_cache_all 339 .long arm1026_flush_user_cache_all
325 .long arm1026_flush_user_cache_range 340 .long arm1026_flush_user_cache_range
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index fecf570939f3..6109f278a904 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -110,6 +110,17 @@ ENTRY(cpu_arm920_do_idle)
110#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 110#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
111 111
112/* 112/*
113 * flush_icache_all()
114 *
115 * Unconditionally clean and invalidate the entire icache.
116 */
117ENTRY(arm920_flush_icache_all)
118 mov r0, #0
119 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
120 mov pc, lr
121ENDPROC(arm920_flush_icache_all)
122
123/*
113 * flush_user_cache_all() 124 * flush_user_cache_all()
114 * 125 *
115 * Invalidate all cache entries in a particular address 126 * Invalidate all cache entries in a particular address
@@ -305,6 +316,7 @@ ENTRY(arm920_dma_unmap_area)
305ENDPROC(arm920_dma_unmap_area) 316ENDPROC(arm920_dma_unmap_area)
306 317
307ENTRY(arm920_cache_fns) 318ENTRY(arm920_cache_fns)
319 .long arm920_flush_icache_all
308 .long arm920_flush_kern_cache_all 320 .long arm920_flush_kern_cache_all
309 .long arm920_flush_user_cache_all 321 .long arm920_flush_user_cache_all
310 .long arm920_flush_user_cache_range 322 .long arm920_flush_user_cache_range
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index e3cbf87c9480..bb2f0f46a5e6 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -112,6 +112,17 @@ ENTRY(cpu_arm922_do_idle)
112#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 112#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
113 113
114/* 114/*
115 * flush_icache_all()
116 *
117 * Unconditionally clean and invalidate the entire icache.
118 */
119ENTRY(arm922_flush_icache_all)
120 mov r0, #0
121 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
122 mov pc, lr
123ENDPROC(arm922_flush_icache_all)
124
125/*
115 * flush_user_cache_all() 126 * flush_user_cache_all()
116 * 127 *
117 * Clean and invalidate all cache entries in a particular 128 * Clean and invalidate all cache entries in a particular
@@ -307,6 +318,7 @@ ENTRY(arm922_dma_unmap_area)
307ENDPROC(arm922_dma_unmap_area) 318ENDPROC(arm922_dma_unmap_area)
308 319
309ENTRY(arm922_cache_fns) 320ENTRY(arm922_cache_fns)
321 .long arm922_flush_icache_all
310 .long arm922_flush_kern_cache_all 322 .long arm922_flush_kern_cache_all
311 .long arm922_flush_user_cache_all 323 .long arm922_flush_user_cache_all
312 .long arm922_flush_user_cache_range 324 .long arm922_flush_user_cache_range
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index 572424c867b5..c13e01accfe2 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -145,6 +145,17 @@ ENTRY(cpu_arm925_do_idle)
145 mov pc, lr 145 mov pc, lr
146 146
147/* 147/*
148 * flush_icache_all()
149 *
150 * Unconditionally clean and invalidate the entire icache.
151 */
152ENTRY(arm925_flush_icache_all)
153 mov r0, #0
154 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
155 mov pc, lr
156ENDPROC(arm925_flush_icache_all)
157
158/*
148 * flush_user_cache_all() 159 * flush_user_cache_all()
149 * 160 *
150 * Clean and invalidate all cache entries in a particular 161 * Clean and invalidate all cache entries in a particular
@@ -362,6 +373,7 @@ ENTRY(arm925_dma_unmap_area)
362ENDPROC(arm925_dma_unmap_area) 373ENDPROC(arm925_dma_unmap_area)
363 374
364ENTRY(arm925_cache_fns) 375ENTRY(arm925_cache_fns)
376 .long arm925_flush_icache_all
365 .long arm925_flush_kern_cache_all 377 .long arm925_flush_kern_cache_all
366 .long arm925_flush_user_cache_all 378 .long arm925_flush_user_cache_all
367 .long arm925_flush_user_cache_range 379 .long arm925_flush_user_cache_range
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 63d168b4ebe6..42eb4315740b 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -111,6 +111,17 @@ ENTRY(cpu_arm926_do_idle)
111 mov pc, lr 111 mov pc, lr
112 112
113/* 113/*
114 * flush_icache_all()
115 *
116 * Unconditionally clean and invalidate the entire icache.
117 */
118ENTRY(arm926_flush_icache_all)
119 mov r0, #0
120 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
121 mov pc, lr
122ENDPROC(arm926_flush_icache_all)
123
124/*
114 * flush_user_cache_all() 125 * flush_user_cache_all()
115 * 126 *
116 * Clean and invalidate all cache entries in a particular 127 * Clean and invalidate all cache entries in a particular
@@ -325,6 +336,7 @@ ENTRY(arm926_dma_unmap_area)
325ENDPROC(arm926_dma_unmap_area) 336ENDPROC(arm926_dma_unmap_area)
326 337
327ENTRY(arm926_cache_fns) 338ENTRY(arm926_cache_fns)
339 .long arm926_flush_icache_all
328 .long arm926_flush_kern_cache_all 340 .long arm926_flush_kern_cache_all
329 .long arm926_flush_user_cache_all 341 .long arm926_flush_user_cache_all
330 .long arm926_flush_user_cache_range 342 .long arm926_flush_user_cache_range
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index f6a62822418e..7b11cdb9935f 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -68,6 +68,17 @@ ENTRY(cpu_arm940_do_idle)
68 mov pc, lr 68 mov pc, lr
69 69
70/* 70/*
71 * flush_icache_all()
72 *
73 * Unconditionally clean and invalidate the entire icache.
74 */
75ENTRY(arm940_flush_icache_all)
76 mov r0, #0
77 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
78 mov pc, lr
79ENDPROC(arm940_flush_icache_all)
80
81/*
71 * flush_user_cache_all() 82 * flush_user_cache_all()
72 */ 83 */
73ENTRY(arm940_flush_user_cache_all) 84ENTRY(arm940_flush_user_cache_all)
@@ -254,6 +265,7 @@ ENTRY(arm940_dma_unmap_area)
254ENDPROC(arm940_dma_unmap_area) 265ENDPROC(arm940_dma_unmap_area)
255 266
256ENTRY(arm940_cache_fns) 267ENTRY(arm940_cache_fns)
268 .long arm940_flush_icache_all
257 .long arm940_flush_kern_cache_all 269 .long arm940_flush_kern_cache_all
258 .long arm940_flush_user_cache_all 270 .long arm940_flush_user_cache_all
259 .long arm940_flush_user_cache_range 271 .long arm940_flush_user_cache_range
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index ea2e7f2eb95b..1a5bbf080342 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -75,6 +75,17 @@ ENTRY(cpu_arm946_do_idle)
75 mov pc, lr 75 mov pc, lr
76 76
77/* 77/*
78 * flush_icache_all()
79 *
80 * Unconditionally clean and invalidate the entire icache.
81 */
82ENTRY(arm946_flush_icache_all)
83 mov r0, #0
84 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
85 mov pc, lr
86ENDPROC(arm946_flush_icache_all)
87
88/*
78 * flush_user_cache_all() 89 * flush_user_cache_all()
79 */ 90 */
80ENTRY(arm946_flush_user_cache_all) 91ENTRY(arm946_flush_user_cache_all)
@@ -296,6 +307,7 @@ ENTRY(arm946_dma_unmap_area)
296ENDPROC(arm946_dma_unmap_area) 307ENDPROC(arm946_dma_unmap_area)
297 308
298ENTRY(arm946_cache_fns) 309ENTRY(arm946_cache_fns)
310 .long arm946_flush_icache_all
299 .long arm946_flush_kern_cache_all 311 .long arm946_flush_kern_cache_all
300 .long arm946_flush_user_cache_all 312 .long arm946_flush_user_cache_all
301 .long arm946_flush_user_cache_range 313 .long arm946_flush_user_cache_range
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index 578da69200cf..b4597edbff97 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -124,6 +124,17 @@ ENTRY(cpu_feroceon_do_idle)
124 mov pc, lr 124 mov pc, lr
125 125
126/* 126/*
127 * flush_icache_all()
128 *
129 * Unconditionally clean and invalidate the entire icache.
130 */
131ENTRY(feroceon_flush_icache_all)
132 mov r0, #0
133 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
134 mov pc, lr
135ENDPROC(feroceon_flush_icache_all)
136
137/*
127 * flush_user_cache_all() 138 * flush_user_cache_all()
128 * 139 *
129 * Clean and invalidate all cache entries in a particular 140 * Clean and invalidate all cache entries in a particular
@@ -401,6 +412,7 @@ ENTRY(feroceon_dma_unmap_area)
401ENDPROC(feroceon_dma_unmap_area) 412ENDPROC(feroceon_dma_unmap_area)
402 413
403ENTRY(feroceon_cache_fns) 414ENTRY(feroceon_cache_fns)
415 .long feroceon_flush_icache_all
404 .long feroceon_flush_kern_cache_all 416 .long feroceon_flush_kern_cache_all
405 .long feroceon_flush_user_cache_all 417 .long feroceon_flush_user_cache_all
406 .long feroceon_flush_user_cache_range 418 .long feroceon_flush_user_cache_range
@@ -412,6 +424,7 @@ ENTRY(feroceon_cache_fns)
412 .long feroceon_dma_flush_range 424 .long feroceon_dma_flush_range
413 425
414ENTRY(feroceon_range_cache_fns) 426ENTRY(feroceon_range_cache_fns)
427 .long feroceon_flush_icache_all
415 .long feroceon_flush_kern_cache_all 428 .long feroceon_flush_kern_cache_all
416 .long feroceon_flush_user_cache_all 429 .long feroceon_flush_user_cache_all
417 .long feroceon_flush_user_cache_range 430 .long feroceon_flush_user_cache_range
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index cad07e403044..ec26355cb7c2 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -141,6 +141,17 @@ ENTRY(cpu_xsc3_do_idle)
141/* ================================= CACHE ================================ */ 141/* ================================= CACHE ================================ */
142 142
143/* 143/*
144 * flush_icache_all()
145 *
146 * Unconditionally clean and invalidate the entire icache.
147 */
148ENTRY(xsc3_flush_icache_all)
149 mov r0, #0
150 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
151 mov pc, lr
152ENDPROC(xsc3_flush_icache_all)
153
154/*
144 * flush_user_cache_all() 155 * flush_user_cache_all()
145 * 156 *
146 * Invalidate all cache entries in a particular address 157 * Invalidate all cache entries in a particular address
@@ -325,6 +336,7 @@ ENTRY(xsc3_dma_unmap_area)
325ENDPROC(xsc3_dma_unmap_area) 336ENDPROC(xsc3_dma_unmap_area)
326 337
327ENTRY(xsc3_cache_fns) 338ENTRY(xsc3_cache_fns)
339 .long xsc3_flush_icache_all
328 .long xsc3_flush_kern_cache_all 340 .long xsc3_flush_kern_cache_all
329 .long xsc3_flush_user_cache_all 341 .long xsc3_flush_user_cache_all
330 .long xsc3_flush_user_cache_range 342 .long xsc3_flush_user_cache_range
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index cb245edb2c2b..523408c0bb38 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -181,6 +181,17 @@ ENTRY(cpu_xscale_do_idle)
181/* ================================= CACHE ================================ */ 181/* ================================= CACHE ================================ */
182 182
183/* 183/*
184 * flush_icache_all()
185 *
186 * Unconditionally clean and invalidate the entire icache.
187 */
188ENTRY(xscale_flush_icache_all)
189 mov r0, #0
190 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
191 mov pc, lr
192ENDPROC(xscale_flush_icache_all)
193
194/*
184 * flush_user_cache_all() 195 * flush_user_cache_all()
185 * 196 *
186 * Invalidate all cache entries in a particular address 197 * Invalidate all cache entries in a particular address
@@ -397,6 +408,7 @@ ENTRY(xscale_dma_unmap_area)
397ENDPROC(xscale_dma_unmap_area) 408ENDPROC(xscale_dma_unmap_area)
398 409
399ENTRY(xscale_cache_fns) 410ENTRY(xscale_cache_fns)
411 .long xscale_flush_icache_all
400 .long xscale_flush_kern_cache_all 412 .long xscale_flush_kern_cache_all
401 .long xscale_flush_user_cache_all 413 .long xscale_flush_user_cache_all
402 .long xscale_flush_user_cache_range 414 .long xscale_flush_user_cache_range
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 06875b4dd70f..372670952789 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_MXC_USE_EPIT) += epit.o
18obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o 18obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o
19obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o 19obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o
20obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o 20obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
21obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o
21ifdef CONFIG_SND_IMX_SOC 22ifdef CONFIG_SND_IMX_SOC
22obj-y += ssi-fiq.o 23obj-y += ssi-fiq.o
23obj-y += ssi-fiq-ksym.o 24obj-y += ssi-fiq-ksym.o
diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c
new file mode 100644
index 000000000000..039538e68793
--- /dev/null
+++ b/arch/arm/plat-mxc/cpufreq.c
@@ -0,0 +1,206 @@
1/*
2 * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
3 */
4
5/*
6 * The code contained herein is licensed under the GNU General Public
7 * License. You may obtain a copy of the GNU General Public License
8 * Version 2 or later at the following locations:
9 *
10 * http://www.opensource.org/licenses/gpl-license.html
11 * http://www.gnu.org/copyleft/gpl.html
12 */
13
14/*
15 * A driver for the Freescale Semiconductor i.MXC CPUfreq module.
16 * The CPUFREQ driver is for controling CPU frequency. It allows you to change
17 * the CPU clock speed on the fly.
18 */
19
20#include <linux/cpufreq.h>
21#include <linux/clk.h>
22#include <linux/err.h>
23#include <linux/slab.h>
24#include <mach/hardware.h>
25#include <mach/clock.h>
26
27#define CLK32_FREQ 32768
28#define NANOSECOND (1000 * 1000 * 1000)
29
30struct cpu_op *(*get_cpu_op)(int *op);
31
32static int cpu_freq_khz_min;
33static int cpu_freq_khz_max;
34
35static struct clk *cpu_clk;
36static struct cpufreq_frequency_table *imx_freq_table;
37
38static int cpu_op_nr;
39static struct cpu_op *cpu_op_tbl;
40
41static int set_cpu_freq(int freq)
42{
43 int ret = 0;
44 int org_cpu_rate;
45
46 org_cpu_rate = clk_get_rate(cpu_clk);
47 if (org_cpu_rate == freq)
48 return ret;
49
50 ret = clk_set_rate(cpu_clk, freq);
51 if (ret != 0) {
52 printk(KERN_DEBUG "cannot set CPU clock rate\n");
53 return ret;
54 }
55
56 return ret;
57}
58
59static int mxc_verify_speed(struct cpufreq_policy *policy)
60{
61 if (policy->cpu != 0)
62 return -EINVAL;
63
64 return cpufreq_frequency_table_verify(policy, imx_freq_table);
65}
66
67static unsigned int mxc_get_speed(unsigned int cpu)
68{
69 if (cpu)
70 return 0;
71
72 return clk_get_rate(cpu_clk) / 1000;
73}
74
75static int mxc_set_target(struct cpufreq_policy *policy,
76 unsigned int target_freq, unsigned int relation)
77{
78 struct cpufreq_freqs freqs;
79 int freq_Hz;
80 int ret = 0;
81 unsigned int index;
82
83 cpufreq_frequency_table_target(policy, imx_freq_table,
84 target_freq, relation, &index);
85 freq_Hz = imx_freq_table[index].frequency * 1000;
86
87 freqs.old = clk_get_rate(cpu_clk) / 1000;
88 freqs.new = freq_Hz / 1000;
89 freqs.cpu = 0;
90 freqs.flags = 0;
91 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
92
93 ret = set_cpu_freq(freq_Hz);
94
95 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
96
97 return ret;
98}
99
100static int __init mxc_cpufreq_init(struct cpufreq_policy *policy)
101{
102 int ret;
103 int i;
104
105 printk(KERN_INFO "i.MXC CPU frequency driver\n");
106
107 if (policy->cpu != 0)
108 return -EINVAL;
109
110 if (!get_cpu_op)
111 return -EINVAL;
112
113 cpu_clk = clk_get(NULL, "cpu_clk");
114 if (IS_ERR(cpu_clk)) {
115 printk(KERN_ERR "%s: failed to get cpu clock\n", __func__);
116 return PTR_ERR(cpu_clk);
117 }
118
119 cpu_op_tbl = get_cpu_op(&cpu_op_nr);
120
121 cpu_freq_khz_min = cpu_op_tbl[0].cpu_rate / 1000;
122 cpu_freq_khz_max = cpu_op_tbl[0].cpu_rate / 1000;
123
124 imx_freq_table = kmalloc(
125 sizeof(struct cpufreq_frequency_table) * (cpu_op_nr + 1),
126 GFP_KERNEL);
127 if (!imx_freq_table) {
128 ret = -ENOMEM;
129 goto err1;
130 }
131
132 for (i = 0; i < cpu_op_nr; i++) {
133 imx_freq_table[i].index = i;
134 imx_freq_table[i].frequency = cpu_op_tbl[i].cpu_rate / 1000;
135
136 if ((cpu_op_tbl[i].cpu_rate / 1000) < cpu_freq_khz_min)
137 cpu_freq_khz_min = cpu_op_tbl[i].cpu_rate / 1000;
138
139 if ((cpu_op_tbl[i].cpu_rate / 1000) > cpu_freq_khz_max)
140 cpu_freq_khz_max = cpu_op_tbl[i].cpu_rate / 1000;
141 }
142
143 imx_freq_table[i].index = i;
144 imx_freq_table[i].frequency = CPUFREQ_TABLE_END;
145
146 policy->cur = clk_get_rate(cpu_clk) / 1000;
147 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
148 policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min;
149 policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max;
150
151 /* Manual states, that PLL stabilizes in two CLK32 periods */
152 policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ;
153
154 ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table);
155
156 if (ret < 0) {
157 printk(KERN_ERR "%s: failed to register i.MXC CPUfreq \
158 with error code %d\n", __func__, ret);
159 goto err;
160 }
161
162 cpufreq_frequency_table_get_attr(imx_freq_table, policy->cpu);
163 return 0;
164err:
165 kfree(imx_freq_table);
166err1:
167 clk_put(cpu_clk);
168 return ret;
169}
170
171static int mxc_cpufreq_exit(struct cpufreq_policy *policy)
172{
173 cpufreq_frequency_table_put_attr(policy->cpu);
174
175 set_cpu_freq(cpu_freq_khz_max * 1000);
176 clk_put(cpu_clk);
177 kfree(imx_freq_table);
178 return 0;
179}
180
181static struct cpufreq_driver mxc_driver = {
182 .flags = CPUFREQ_STICKY,
183 .verify = mxc_verify_speed,
184 .target = mxc_set_target,
185 .get = mxc_get_speed,
186 .init = mxc_cpufreq_init,
187 .exit = mxc_cpufreq_exit,
188 .name = "imx",
189};
190
191static int __devinit mxc_cpufreq_driver_init(void)
192{
193 return cpufreq_register_driver(&mxc_driver);
194}
195
196static void mxc_cpufreq_driver_exit(void)
197{
198 cpufreq_unregister_driver(&mxc_driver);
199}
200
201module_init(mxc_cpufreq_driver_init);
202module_exit(mxc_cpufreq_driver_exit);
203
204MODULE_AUTHOR("Freescale Semiconductor Inc. Yong Shen <yong.shen@linaro.org>");
205MODULE_DESCRIPTION("CPUfreq driver for i.MX");
206MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig
index 404799487f17..9aa6f3ea9012 100644
--- a/arch/arm/plat-mxc/devices/Kconfig
+++ b/arch/arm/plat-mxc/devices/Kconfig
@@ -6,9 +6,13 @@ config IMX_HAVE_PLATFORM_FEC
6 default y if ARCH_MX25 || SOC_IMX27 || ARCH_MX35 || ARCH_MX51 6 default y if ARCH_MX25 || SOC_IMX27 || ARCH_MX35 || ARCH_MX51
7 7
8config IMX_HAVE_PLATFORM_FLEXCAN 8config IMX_HAVE_PLATFORM_FLEXCAN
9 select HAVE_CAN_FLEXCAN 9 select HAVE_CAN_FLEXCAN if CAN
10 bool 10 bool
11 11
12config IMX_HAVE_PLATFORM_GPIO_KEYS
13 bool
14 default y if ARCH_MX51
15
12config IMX_HAVE_PLATFORM_IMX_I2C 16config IMX_HAVE_PLATFORM_IMX_I2C
13 bool 17 bool
14 18
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
index 0a3c1f089413..45aefeb283ba 100644
--- a/arch/arm/plat-mxc/devices/Makefile
+++ b/arch/arm/plat-mxc/devices/Makefile
@@ -1,6 +1,7 @@
1obj-$(CONFIG_IMX_HAVE_PLATFORM_ESDHC) += platform-esdhc.o 1obj-$(CONFIG_IMX_HAVE_PLATFORM_ESDHC) += platform-esdhc.o
2obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o 2obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o
3obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o 3obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
4obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o
4obj-y += platform-imx-dma.o 5obj-y += platform-imx-dma.o
5obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o 6obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
6obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o 7obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o
diff --git a/arch/arm/plat-mxc/devices/platform-gpio_keys.c b/arch/arm/plat-mxc/devices/platform-gpio_keys.c
new file mode 100644
index 000000000000..1c53a532ea0e
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-gpio_keys.c
@@ -0,0 +1,27 @@
1/*
2 * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301, USA.
17 */
18#include <asm/sizes.h>
19#include <mach/hardware.h>
20#include <mach/devices-common.h>
21
22struct platform_device *__init imx_add_gpio_keys(
23 const struct gpio_keys_platform_data *pdata)
24{
25 return imx_add_platform_device("gpio-keys", -1, NULL,
26 0, pdata, sizeof(*pdata));
27}
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index 9d38da077edb..9c3e36232b5b 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -20,6 +20,7 @@
20 */ 20 */
21 21
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/interrupt.h>
23#include <linux/io.h> 24#include <linux/io.h>
24#include <linux/irq.h> 25#include <linux/irq.h>
25#include <linux/gpio.h> 26#include <linux/gpio.h>
@@ -201,11 +202,42 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
201 } 202 }
202} 203}
203 204
205/*
206 * Set interrupt number "irq" in the GPIO as a wake-up source.
207 * While system is running, all registered GPIO interrupts need to have
208 * wake-up enabled. When system is suspended, only selected GPIO interrupts
209 * need to have wake-up enabled.
210 * @param irq interrupt source number
211 * @param enable enable as wake-up if equal to non-zero
212 * @return This function returns 0 on success.
213 */
214static int gpio_set_wake_irq(u32 irq, u32 enable)
215{
216 u32 gpio = irq_to_gpio(irq);
217 u32 gpio_idx = gpio & 0x1F;
218 struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
219
220 if (enable) {
221 if (port->irq_high && (gpio_idx >= 16))
222 enable_irq_wake(port->irq_high);
223 else
224 enable_irq_wake(port->irq);
225 } else {
226 if (port->irq_high && (gpio_idx >= 16))
227 disable_irq_wake(port->irq_high);
228 else
229 disable_irq_wake(port->irq);
230 }
231
232 return 0;
233}
234
204static struct irq_chip gpio_irq_chip = { 235static struct irq_chip gpio_irq_chip = {
205 .ack = gpio_ack_irq, 236 .ack = gpio_ack_irq,
206 .mask = gpio_mask_irq, 237 .mask = gpio_mask_irq,
207 .unmask = gpio_unmask_irq, 238 .unmask = gpio_unmask_irq,
208 .set_type = gpio_set_irq_type, 239 .set_type = gpio_set_irq_type,
240 .set_wake = gpio_set_wake_irq,
209}; 241};
210 242
211static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, 243static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index 86d7575a564d..8c6896fd1e5f 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -29,6 +29,10 @@ struct platform_device *__init imx_add_flexcan(int id,
29 resource_size_t irq, 29 resource_size_t irq,
30 const struct flexcan_platform_data *pdata); 30 const struct flexcan_platform_data *pdata);
31 31
32#include <linux/gpio_keys.h>
33struct platform_device *__init imx_add_gpio_keys(
34 const struct gpio_keys_platform_data *pdata);
35
32#include <mach/i2c.h> 36#include <mach/i2c.h>
33struct imx_imx_i2c_data { 37struct imx_imx_i2c_data {
34 int id; 38 int id;
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
index e46b1c2836d4..d7a41e9a2605 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
@@ -45,6 +45,8 @@ typedef enum iomux_config {
45 PAD_CTL_PKE | PAD_CTL_HYS) 45 PAD_CTL_PKE | PAD_CTL_HYS)
46#define MX51_GPIO_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | \ 46#define MX51_GPIO_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | \
47 PAD_CTL_SRE_FAST) 47 PAD_CTL_SRE_FAST)
48#define MX51_GPIO_PAD_CTRL_2 (PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \
49 PAD_CTL_PUS_100K_UP)
48#define MX51_ECSPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \ 50#define MX51_ECSPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
49 PAD_CTL_SRE_FAST) 51 PAD_CTL_SRE_FAST)
50#define MX51_SDHCI_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP | \ 52#define MX51_SDHCI_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP | \
diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h
index 03e2afabc9fc..61cfe827498b 100644
--- a/arch/arm/plat-mxc/include/mach/mx31.h
+++ b/arch/arm/plat-mxc/include/mach/mx31.h
@@ -240,7 +240,6 @@ static inline void mx31_setup_weimcs(size_t cs,
240#define MPEG4_ENC_BASE_ADDR MX31_MPEG4_ENC_BASE_ADDR 240#define MPEG4_ENC_BASE_ADDR MX31_MPEG4_ENC_BASE_ADDR
241#define MXC_INT_MPEG4_ENCODER MX31_INT_MPEG4_ENCODER 241#define MXC_INT_MPEG4_ENCODER MX31_INT_MPEG4_ENCODER
242#define MXC_INT_FIRI MX31_INT_FIRI 242#define MXC_INT_FIRI MX31_INT_FIRI
243#define MXC_INT_MMC_SDHC1 MX31_INT_MMC_SDHC1
244#define MXC_INT_MBX MX31_INT_MBX 243#define MXC_INT_MBX MX31_INT_MBX
245#define MXC_INT_CSPI3 MX31_INT_CSPI3 244#define MXC_INT_CSPI3 MX31_INT_CSPI3
246#define MXC_INT_SIM2 MX31_INT_SIM2 245#define MXC_INT_SIM2 MX31_INT_SIM2
diff --git a/arch/arm/plat-mxc/include/mach/mx35.h b/arch/arm/plat-mxc/include/mach/mx35.h
index ff905cb32458..6267cff6035d 100644
--- a/arch/arm/plat-mxc/include/mach/mx35.h
+++ b/arch/arm/plat-mxc/include/mach/mx35.h
@@ -197,8 +197,6 @@
197/* these should go away */ 197/* these should go away */
198#define MXC_FEC_BASE_ADDR MX35_FEC_BASE_ADDR 198#define MXC_FEC_BASE_ADDR MX35_FEC_BASE_ADDR
199#define MXC_INT_OWIRE MX35_INT_OWIRE 199#define MXC_INT_OWIRE MX35_INT_OWIRE
200#define MXC_INT_MMC_SDHC2 MX35_INT_MMC_SDHC2
201#define MXC_INT_MMC_SDHC3 MX35_INT_MMC_SDHC3
202#define MXC_INT_GPU2D MX35_INT_GPU2D 200#define MXC_INT_GPU2D MX35_INT_GPU2D
203#define MXC_INT_ASRC MX35_INT_ASRC 201#define MXC_INT_ASRC MX35_INT_ASRC
204#define MXC_INT_USBHS MX35_INT_USBHS 202#define MXC_INT_USBHS MX35_INT_USBHS
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index a790bf212972..a42c7207082d 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. 2 * Copyright 2004-2007, 2010 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) 3 * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -20,6 +20,8 @@
20#ifndef __ASM_ARCH_MXC_H__ 20#ifndef __ASM_ARCH_MXC_H__
21#define __ASM_ARCH_MXC_H__ 21#define __ASM_ARCH_MXC_H__
22 22
23#include <linux/types.h>
24
23#ifndef __ASM_ARCH_MXC_HARDWARE_H__ 25#ifndef __ASM_ARCH_MXC_HARDWARE_H__
24#error "Do not include directly." 26#error "Do not include directly."
25#endif 27#endif
@@ -133,6 +135,15 @@ extern unsigned int __mxc_cpu_type;
133# define cpu_is_mxc91231() (0) 135# define cpu_is_mxc91231() (0)
134#endif 136#endif
135 137
138#ifndef __ASSEMBLY__
139
140struct cpu_op {
141 u32 cpu_rate;
142};
143
144extern struct cpu_op *(*get_cpu_op)(int *op);
145#endif
146
136#if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX2) 147#if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX2)
137/* These are deprecated, use mx[23][157]_setup_weimcs instead. */ 148/* These are deprecated, use mx[23][157]_setup_weimcs instead. */
138#define CSCR_U(n) (IO_ADDRESS(WEIM_BASE_ADDR + n * 0x10)) 149#define CSCR_U(n) (IO_ADDRESS(WEIM_BASE_ADDR + n * 0x10))
diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 3478eae32d8a..01a8448e471c 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -30,15 +30,15 @@ struct pxa3xx_nand_cmdset {
30}; 30};
31 31
32struct pxa3xx_nand_flash { 32struct pxa3xx_nand_flash {
33 const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ 33 uint32_t chip_id;
34 const struct pxa3xx_nand_cmdset *cmdset; 34 unsigned int page_per_block; /* Pages per block (PG_PER_BLK) */
35 35 unsigned int page_size; /* Page size in bytes (PAGE_SZ) */
36 uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */ 36 unsigned int flash_width; /* Width of Flash memory (DWIDTH_M) */
37 uint32_t page_size; /* Page size in bytes (PAGE_SZ) */ 37 unsigned int dfc_width; /* Width of flash controller(DWIDTH_C) */
38 uint32_t flash_width; /* Width of Flash memory (DWIDTH_M) */ 38 unsigned int num_blocks; /* Number of physical blocks in Flash */
39 uint32_t dfc_width; /* Width of flash controller(DWIDTH_C) */ 39
40 uint32_t num_blocks; /* Number of physical blocks in Flash */ 40 struct pxa3xx_nand_cmdset *cmdset; /* NAND command set */
41 uint32_t chip_id; 41 struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
42}; 42};
43 43
44struct pxa3xx_nand_platform_data { 44struct pxa3xx_nand_platform_data {
diff --git a/arch/arm/plat-s3c24xx/common-smdk.c b/arch/arm/plat-s3c24xx/common-smdk.c
index 7b44d0c592b5..bcc43f346272 100644
--- a/arch/arm/plat-s3c24xx/common-smdk.c
+++ b/arch/arm/plat-s3c24xx/common-smdk.c
@@ -147,7 +147,7 @@ static struct mtd_partition smdk_default_nand_part[] = {
147 [7] = { 147 [7] = {
148 .name = "S3C2410 flash partition 7", 148 .name = "S3C2410 flash partition 7",
149 .offset = SZ_1M * 48, 149 .offset = SZ_1M * 48,
150 .size = SZ_16M, 150 .size = MTDPART_SIZ_FULL,
151 } 151 }
152}; 152};
153 153
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c
index ae9d3c2403f0..24c6f5a30596 100644
--- a/arch/arm/plat-s3c24xx/gpiolib.c
+++ b/arch/arm/plat-s3c24xx/gpiolib.c
@@ -74,11 +74,6 @@ static int s3c24xx_gpiolib_bankf_toirq(struct gpio_chip *chip, unsigned offset)
74 return -EINVAL; 74 return -EINVAL;
75} 75}
76 76
77static int s3c24xx_gpiolib_bankg_toirq(struct gpio_chip *chip, unsigned offset)
78{
79 return IRQ_EINT8 + offset;
80}
81
82static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = { 77static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
83 .set_config = s3c_gpio_setcfg_s3c24xx_a, 78 .set_config = s3c_gpio_setcfg_s3c24xx_a,
84 .get_config = s3c_gpio_getcfg_s3c24xx_a, 79 .get_config = s3c_gpio_getcfg_s3c24xx_a,
@@ -159,12 +154,13 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
159 [6] = { 154 [6] = {
160 .base = S3C2410_GPGCON, 155 .base = S3C2410_GPGCON,
161 .pm = __gpio_pm(&s3c_gpio_pm_2bit), 156 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
157 .irq_base = IRQ_EINT8,
162 .chip = { 158 .chip = {
163 .base = S3C2410_GPG(0), 159 .base = S3C2410_GPG(0),
164 .owner = THIS_MODULE, 160 .owner = THIS_MODULE,
165 .label = "GPIOG", 161 .label = "GPIOG",
166 .ngpio = 16, 162 .ngpio = 16,
167 .to_irq = s3c24xx_gpiolib_bankg_toirq, 163 .to_irq = samsung_gpiolib_to_irq,
168 }, 164 },
169 }, { 165 }, {
170 .base = S3C2410_GPHCON, 166 .base = S3C2410_GPHCON,
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 25960966af7c..65dbfa8e0a86 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -32,6 +32,11 @@ config S5P_EXT_INT
32 Use the external interrupts (other than GPIO interrupts.) 32 Use the external interrupts (other than GPIO interrupts.)
33 Note: Do not choose this for S5P6440 and S5P6450. 33 Note: Do not choose this for S5P6440 and S5P6450.
34 34
35config S5P_GPIO_INT
36 bool
37 help
38 Common code for the GPIO interrupts (other than external interrupts.)
39
35config S5P_DEV_FIMC0 40config S5P_DEV_FIMC0
36 bool 41 bool
37 help 42 help
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index f3e917e27da8..de65238a7aef 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -18,6 +18,9 @@ obj-y += cpu.o
18obj-y += clock.o 18obj-y += clock.o
19obj-y += irq.o 19obj-y += irq.o
20obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o 20obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o
21obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o
22obj-$(CONFIG_PM) += pm.o
23obj-$(CONFIG_PM) += irq-pm.o
21 24
22# devices 25# devices
23 26
diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c
index 8aaf4e6b60c3..8d081d968c58 100644
--- a/arch/arm/plat-s5p/clock.c
+++ b/arch/arm/plat-s5p/clock.c
@@ -21,6 +21,8 @@
21#include <linux/io.h> 21#include <linux/io.h>
22#include <asm/div64.h> 22#include <asm/div64.h>
23 23
24#include <mach/regs-clock.h>
25
24#include <plat/clock.h> 26#include <plat/clock.h>
25#include <plat/clock-clksrc.h> 27#include <plat/clock-clksrc.h>
26#include <plat/s5p-clock.h> 28#include <plat/s5p-clock.h>
@@ -88,14 +90,6 @@ struct clk clk_fout_vpll = {
88 .ctrlbit = (1 << 31), 90 .ctrlbit = (1 << 31),
89}; 91};
90 92
91/* ARM clock */
92struct clk clk_arm = {
93 .name = "armclk",
94 .id = -1,
95 .rate = 0,
96 .ctrlbit = 0,
97};
98
99/* Possible clock sources for APLL Mux */ 93/* Possible clock sources for APLL Mux */
100static struct clk *clk_src_apll_list[] = { 94static struct clk *clk_src_apll_list[] = {
101 [0] = &clk_fin_apll, 95 [0] = &clk_fin_apll,
@@ -156,6 +150,24 @@ int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable)
156 return 0; 150 return 0;
157} 151}
158 152
153int s5p_epll_enable(struct clk *clk, int enable)
154{
155 unsigned int ctrlbit = clk->ctrlbit;
156 unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit;
157
158 if (enable)
159 __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON);
160 else
161 __raw_writel(epll_con, S5P_EPLL_CON);
162
163 return 0;
164}
165
166unsigned long s5p_epll_get_rate(struct clk *clk)
167{
168 return clk->rate;
169}
170
159static struct clk *s5p_clks[] __initdata = { 171static struct clk *s5p_clks[] __initdata = {
160 &clk_ext_xtal_mux, 172 &clk_ext_xtal_mux,
161 &clk_48m, 173 &clk_48m,
@@ -165,7 +177,6 @@ static struct clk *s5p_clks[] __initdata = {
165 &clk_fout_epll, 177 &clk_fout_epll,
166 &clk_fout_dpll, 178 &clk_fout_dpll,
167 &clk_fout_vpll, 179 &clk_fout_vpll,
168 &clk_arm,
169 &clk_vpll, 180 &clk_vpll,
170 &clk_xusbxti, 181 &clk_xusbxti,
171}; 182};
diff --git a/arch/arm/plat-s5p/include/plat/irqs.h b/arch/arm/plat-s5p/include/plat/irqs.h
index 3fb3a3a17465..ba9121c60a2a 100644
--- a/arch/arm/plat-s5p/include/plat/irqs.h
+++ b/arch/arm/plat-s5p/include/plat/irqs.h
@@ -94,4 +94,22 @@
94 ((irq) - S5P_EINT_BASE1) : \ 94 ((irq) - S5P_EINT_BASE1) : \
95 ((irq) + 16 - S5P_EINT_BASE2)) 95 ((irq) + 16 - S5P_EINT_BASE2))
96 96
97#define IRQ_EINT_BIT(x) EINT_OFFSET(x)
98
99/* Typically only a few gpio chips require gpio interrupt support.
100 To avoid memory waste irq descriptors are allocated only for
101 S5P_GPIOINT_GROUP_COUNT chips, each with total number of
102 S5P_GPIOINT_GROUP_SIZE pins/irqs. Each GPIOINT group can be assiged
103 to any gpio chip with the s5p_register_gpio_interrupt() function */
104#define S5P_GPIOINT_GROUP_COUNT 4
105#define S5P_GPIOINT_GROUP_SIZE 8
106#define S5P_GPIOINT_COUNT (S5P_GPIOINT_GROUP_COUNT * S5P_GPIOINT_GROUP_SIZE)
107
108/* IRQ types common for all s5p platforms */
109#define S5P_IRQ_TYPE_LEVEL_LOW (0x00)
110#define S5P_IRQ_TYPE_LEVEL_HIGH (0x01)
111#define S5P_IRQ_TYPE_EDGE_FALLING (0x02)
112#define S5P_IRQ_TYPE_EDGE_RISING (0x03)
113#define S5P_IRQ_TYPE_EDGE_BOTH (0x04)
114
97#endif /* __ASM_PLAT_S5P_IRQS_H */ 115#endif /* __ASM_PLAT_S5P_IRQS_H */
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h
index c4ff88bf6477..fef353d44513 100644
--- a/arch/arm/plat-s5p/include/plat/map-s5p.h
+++ b/arch/arm/plat-s5p/include/plat/map-s5p.h
@@ -13,24 +13,38 @@
13#ifndef __ASM_PLAT_MAP_S5P_H 13#ifndef __ASM_PLAT_MAP_S5P_H
14#define __ASM_PLAT_MAP_S5P_H __FILE__ 14#define __ASM_PLAT_MAP_S5P_H __FILE__
15 15
16#define S5P_VA_CHIPID S3C_ADDR(0x00700000) 16#define S5P_VA_CHIPID S3C_ADDR(0x02000000)
17#define S5P_VA_GPIO S3C_ADDR(0x00500000) 17#define S5P_VA_CMU S3C_ADDR(0x02100000)
18#define S5P_VA_SYSTIMER S3C_ADDR(0x01200000) 18#define S5P_VA_GPIO S3C_ADDR(0x02200000)
19#define S5P_VA_SROMC S3C_ADDR(0x01100000) 19#define S5P_VA_GPIO1 S5P_VA_GPIO
20#define S5P_VA_SYSRAM S3C_ADDR(0x01180000) 20#define S5P_VA_GPIO2 S3C_ADDR(0x02240000)
21 21#define S5P_VA_GPIO3 S3C_ADDR(0x02280000)
22#define S5P_VA_COMBINER_BASE S3C_ADDR(0x00600000) 22
23#define S5P_VA_SYSRAM S3C_ADDR(0x02400000)
24#define S5P_VA_DMC0 S3C_ADDR(0x02440000)
25#define S5P_VA_DMC1 S3C_ADDR(0x02480000)
26#define S5P_VA_SROMC S3C_ADDR(0x024C0000)
27
28#define S5P_VA_SYSTIMER S3C_ADDR(0x02500000)
29#define S5P_VA_L2CC S3C_ADDR(0x02600000)
30
31#define S5P_VA_COMBINER_BASE S3C_ADDR(0x02700000)
23#define S5P_VA_COMBINER(x) (S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10) 32#define S5P_VA_COMBINER(x) (S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10)
24 33
25#define S5P_VA_COREPERI_BASE S3C_ADDR(0x00800000) 34#define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000)
26#define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x)) 35#define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x))
27#define S5P_VA_SCU S5P_VA_COREPERI(0x0) 36#define S5P_VA_SCU S5P_VA_COREPERI(0x0)
28#define S5P_VA_GIC_CPU S5P_VA_COREPERI(0x100) 37#define S5P_VA_GIC_CPU S5P_VA_COREPERI(0x100)
29#define S5P_VA_TWD S5P_VA_COREPERI(0x600) 38#define S5P_VA_TWD S5P_VA_COREPERI(0x600)
30#define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000) 39#define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000)
31 40
32#define S5P_VA_L2CC S3C_ADDR(0x00900000) 41#define S3C_VA_USB_HSPHY S3C_ADDR(0x02900000)
33#define S5P_VA_CMU S3C_ADDR(0x00920000) 42
43#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000))
44#define VA_VIC0 VA_VIC(0)
45#define VA_VIC1 VA_VIC(1)
46#define VA_VIC2 VA_VIC(2)
47#define VA_VIC3 VA_VIC(3)
34 48
35#define S5P_VA_UART(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) 49#define S5P_VA_UART(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
36#define S5P_VA_UART0 S5P_VA_UART(0) 50#define S5P_VA_UART0 S5P_VA_UART(0)
@@ -42,10 +56,4 @@
42#define S3C_UART_OFFSET (0x400) 56#define S3C_UART_OFFSET (0x400)
43#endif 57#endif
44 58
45#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000))
46#define VA_VIC0 VA_VIC(0)
47#define VA_VIC1 VA_VIC(1)
48#define VA_VIC2 VA_VIC(2)
49#define VA_VIC3 VA_VIC(3)
50
51#endif /* __ASM_PLAT_MAP_S5P_H */ 59#endif /* __ASM_PLAT_MAP_S5P_H */
diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h
index 17036c898409..2b6dcff8ab2b 100644
--- a/arch/arm/plat-s5p/include/plat/s5p-clock.h
+++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h
@@ -43,4 +43,8 @@ extern struct clksrc_sources clk_src_dpll;
43 43
44extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable); 44extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
45 45
46/* Common EPLL operations for S5P platform */
47extern int s5p_epll_enable(struct clk *clk, int enable);
48extern unsigned long s5p_epll_get_rate(struct clk *clk);
49
46#endif /* __ASM_PLAT_S5P_CLOCK_H */ 50#endif /* __ASM_PLAT_S5P_CLOCK_H */
diff --git a/arch/arm/plat-s5p/irq-eint.c b/arch/arm/plat-s5p/irq-eint.c
index f36cd3327025..752f1a645f9d 100644
--- a/arch/arm/plat-s5p/irq-eint.c
+++ b/arch/arm/plat-s5p/irq-eint.c
@@ -67,23 +67,23 @@ static int s5p_irq_eint_set_type(unsigned int irq, unsigned int type)
67 67
68 switch (type) { 68 switch (type) {
69 case IRQ_TYPE_EDGE_RISING: 69 case IRQ_TYPE_EDGE_RISING:
70 newvalue = S5P_EXTINT_RISEEDGE; 70 newvalue = S5P_IRQ_TYPE_EDGE_RISING;
71 break; 71 break;
72 72
73 case IRQ_TYPE_EDGE_FALLING: 73 case IRQ_TYPE_EDGE_FALLING:
74 newvalue = S5P_EXTINT_FALLEDGE; 74 newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
75 break; 75 break;
76 76
77 case IRQ_TYPE_EDGE_BOTH: 77 case IRQ_TYPE_EDGE_BOTH:
78 newvalue = S5P_EXTINT_BOTHEDGE; 78 newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
79 break; 79 break;
80 80
81 case IRQ_TYPE_LEVEL_LOW: 81 case IRQ_TYPE_LEVEL_LOW:
82 newvalue = S5P_EXTINT_LOWLEV; 82 newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
83 break; 83 break;
84 84
85 case IRQ_TYPE_LEVEL_HIGH: 85 case IRQ_TYPE_LEVEL_HIGH:
86 newvalue = S5P_EXTINT_HILEV; 86 newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
87 break; 87 break;
88 88
89 default: 89 default:
diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c
new file mode 100644
index 000000000000..0e5dc8cbf5e3
--- /dev/null
+++ b/arch/arm/plat-s5p/irq-gpioint.c
@@ -0,0 +1,237 @@
1/* linux/arch/arm/plat-s5p/irq-gpioint.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * Author: Kyungmin Park <kyungmin.park@samsung.com>
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6 * Author: Marek Szyprowski <m.szyprowski@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <linux/interrupt.h>
17#include <linux/irq.h>
18#include <linux/io.h>
19#include <linux/gpio.h>
20
21#include <mach/map.h>
22#include <plat/gpio-core.h>
23#include <plat/gpio-cfg.h>
24
25#define S5P_GPIOREG(x) (S5P_VA_GPIO + (x))
26
27#define GPIOINT_CON_OFFSET 0x700
28#define GPIOINT_MASK_OFFSET 0x900
29#define GPIOINT_PEND_OFFSET 0xA00
30
31static struct s3c_gpio_chip *irq_chips[S5P_GPIOINT_GROUP_MAXNR];
32
33static int s5p_gpioint_get_group(unsigned int irq)
34{
35 struct gpio_chip *chip = get_irq_data(irq);
36 struct s3c_gpio_chip *s3c_chip = container_of(chip,
37 struct s3c_gpio_chip, chip);
38 int group;
39
40 for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++)
41 if (s3c_chip == irq_chips[group])
42 break;
43
44 return group;
45}
46
47static int s5p_gpioint_get_offset(unsigned int irq)
48{
49 struct gpio_chip *chip = get_irq_data(irq);
50 struct s3c_gpio_chip *s3c_chip = container_of(chip,
51 struct s3c_gpio_chip, chip);
52
53 return irq - s3c_chip->irq_base;
54}
55
56static void s5p_gpioint_ack(unsigned int irq)
57{
58 int group, offset, pend_offset;
59 unsigned int value;
60
61 group = s5p_gpioint_get_group(irq);
62 offset = s5p_gpioint_get_offset(irq);
63 pend_offset = group << 2;
64
65 value = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
66 value |= 1 << offset;
67 __raw_writel(value, S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
68}
69
70static void s5p_gpioint_mask(unsigned int irq)
71{
72 int group, offset, mask_offset;
73 unsigned int value;
74
75 group = s5p_gpioint_get_group(irq);
76 offset = s5p_gpioint_get_offset(irq);
77 mask_offset = group << 2;
78
79 value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
80 value |= 1 << offset;
81 __raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
82}
83
84static void s5p_gpioint_unmask(unsigned int irq)
85{
86 int group, offset, mask_offset;
87 unsigned int value;
88
89 group = s5p_gpioint_get_group(irq);
90 offset = s5p_gpioint_get_offset(irq);
91 mask_offset = group << 2;
92
93 value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
94 value &= ~(1 << offset);
95 __raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
96}
97
98static void s5p_gpioint_mask_ack(unsigned int irq)
99{
100 s5p_gpioint_mask(irq);
101 s5p_gpioint_ack(irq);
102}
103
104static int s5p_gpioint_set_type(unsigned int irq, unsigned int type)
105{
106 int group, offset, con_offset;
107 unsigned int value;
108
109 group = s5p_gpioint_get_group(irq);
110 offset = s5p_gpioint_get_offset(irq);
111 con_offset = group << 2;
112
113 switch (type) {
114 case IRQ_TYPE_EDGE_RISING:
115 type = S5P_IRQ_TYPE_EDGE_RISING;
116 break;
117 case IRQ_TYPE_EDGE_FALLING:
118 type = S5P_IRQ_TYPE_EDGE_FALLING;
119 break;
120 case IRQ_TYPE_EDGE_BOTH:
121 type = S5P_IRQ_TYPE_EDGE_BOTH;
122 break;
123 case IRQ_TYPE_LEVEL_HIGH:
124 type = S5P_IRQ_TYPE_LEVEL_HIGH;
125 break;
126 case IRQ_TYPE_LEVEL_LOW:
127 type = S5P_IRQ_TYPE_LEVEL_LOW;
128 break;
129 case IRQ_TYPE_NONE:
130 default:
131 printk(KERN_WARNING "No irq type\n");
132 return -EINVAL;
133 }
134
135 value = __raw_readl(S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset);
136 value &= ~(0x7 << (offset * 0x4));
137 value |= (type << (offset * 0x4));
138 __raw_writel(value, S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset);
139
140 return 0;
141}
142
143struct irq_chip s5p_gpioint = {
144 .name = "s5p_gpioint",
145 .ack = s5p_gpioint_ack,
146 .mask = s5p_gpioint_mask,
147 .mask_ack = s5p_gpioint_mask_ack,
148 .unmask = s5p_gpioint_unmask,
149 .set_type = s5p_gpioint_set_type,
150};
151
152static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
153{
154 int group, offset, pend_offset, mask_offset;
155 int real_irq;
156 unsigned int pend, mask;
157
158 for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++) {
159 pend_offset = group << 2;
160 pend = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) +
161 pend_offset);
162 if (!pend)
163 continue;
164
165 mask_offset = group << 2;
166 mask = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) +
167 mask_offset);
168 pend &= ~mask;
169
170 for (offset = 0; offset < 8; offset++) {
171 if (pend & (1 << offset)) {
172 struct s3c_gpio_chip *chip = irq_chips[group];
173 if (chip) {
174 real_irq = chip->irq_base + offset;
175 generic_handle_irq(real_irq);
176 }
177 }
178 }
179 }
180}
181
182static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
183{
184 static int used_gpioint_groups = 0;
185 static bool handler_registered = 0;
186 int irq, group = chip->group;
187 int i;
188
189 if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT)
190 return -ENOMEM;
191
192 chip->irq_base = S5P_GPIOINT_BASE +
193 used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE;
194 used_gpioint_groups++;
195
196 if (!handler_registered) {
197 set_irq_chained_handler(IRQ_GPIOINT, s5p_gpioint_handler);
198 handler_registered = 1;
199 }
200
201 irq_chips[group] = chip;
202 for (i = 0; i < chip->chip.ngpio; i++) {
203 irq = chip->irq_base + i;
204 set_irq_chip(irq, &s5p_gpioint);
205 set_irq_data(irq, &chip->chip);
206 set_irq_handler(irq, handle_level_irq);
207 set_irq_flags(irq, IRQF_VALID);
208 }
209 return 0;
210}
211
212int __init s5p_register_gpio_interrupt(int pin)
213{
214 struct s3c_gpio_chip *my_chip = s3c_gpiolib_getchip(pin);
215 int offset, group;
216 int ret;
217
218 if (!my_chip)
219 return -EINVAL;
220
221 offset = pin - my_chip->chip.base;
222 group = my_chip->group;
223
224 /* check if the group has been already registered */
225 if (my_chip->irq_base)
226 return my_chip->irq_base + offset;
227
228 /* register gpio group */
229 ret = s5p_gpioint_add(my_chip);
230 if (ret == 0) {
231 my_chip->chip.to_irq = samsung_gpiolib_to_irq;
232 printk(KERN_INFO "Registered interrupt support for gpio group %d.\n",
233 group);
234 return my_chip->irq_base + offset;
235 }
236 return ret;
237}
diff --git a/arch/arm/plat-s5p/irq-pm.c b/arch/arm/plat-s5p/irq-pm.c
new file mode 100644
index 000000000000..dc33b9ecda45
--- /dev/null
+++ b/arch/arm/plat-s5p/irq-pm.c
@@ -0,0 +1,93 @@
1/* linux/arch/arm/plat-s5p/irq-pm.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * Based on arch/arm/plat-s3c24xx/irq-pm.c,
7 * Copyright (c) 2003,2004 Simtec Electronics
8 * Ben Dooks <ben@simtec.co.uk>
9 * http://armlinux.simtec.co.uk/
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14*/
15
16#include <linux/init.h>
17#include <linux/module.h>
18#include <linux/interrupt.h>
19#include <linux/sysdev.h>
20
21#include <plat/cpu.h>
22#include <plat/irqs.h>
23#include <plat/pm.h>
24#include <mach/map.h>
25
26#include <mach/regs-gpio.h>
27#include <mach/regs-irq.h>
28
29/* state for IRQs over sleep */
30
31/* default is to allow for EINT0..EINT31, and IRQ_RTC_TIC, IRQ_RTC_ALARM,
32 * as wakeup sources
33 *
34 * set bit to 1 in allow bitfield to enable the wakeup settings on it
35*/
36
37unsigned long s3c_irqwake_intallow = 0x00000006L;
38unsigned long s3c_irqwake_eintallow = 0xffffffffL;
39
40int s3c_irq_wake(unsigned int irqno, unsigned int state)
41{
42 unsigned long irqbit;
43
44 switch (irqno) {
45 case IRQ_RTC_TIC:
46 case IRQ_RTC_ALARM:
47 irqbit = 1 << (irqno + 1 - IRQ_RTC_ALARM);
48 if (!state)
49 s3c_irqwake_intmask |= irqbit;
50 else
51 s3c_irqwake_intmask &= ~irqbit;
52 break;
53 default:
54 return -ENOENT;
55 }
56 return 0;
57}
58
59static struct sleep_save eint_save[] = {
60 SAVE_ITEM(S5P_EINT_CON(0)),
61 SAVE_ITEM(S5P_EINT_CON(1)),
62 SAVE_ITEM(S5P_EINT_CON(2)),
63 SAVE_ITEM(S5P_EINT_CON(3)),
64
65 SAVE_ITEM(S5P_EINT_FLTCON(0)),
66 SAVE_ITEM(S5P_EINT_FLTCON(1)),
67 SAVE_ITEM(S5P_EINT_FLTCON(2)),
68 SAVE_ITEM(S5P_EINT_FLTCON(3)),
69 SAVE_ITEM(S5P_EINT_FLTCON(4)),
70 SAVE_ITEM(S5P_EINT_FLTCON(5)),
71 SAVE_ITEM(S5P_EINT_FLTCON(6)),
72 SAVE_ITEM(S5P_EINT_FLTCON(7)),
73
74 SAVE_ITEM(S5P_EINT_MASK(0)),
75 SAVE_ITEM(S5P_EINT_MASK(1)),
76 SAVE_ITEM(S5P_EINT_MASK(2)),
77 SAVE_ITEM(S5P_EINT_MASK(3)),
78};
79
80int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
81{
82 s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save));
83
84 return 0;
85}
86
87int s3c24xx_irq_resume(struct sys_device *dev)
88{
89 s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save));
90
91 return 0;
92}
93
diff --git a/arch/arm/plat-s5p/pm.c b/arch/arm/plat-s5p/pm.c
new file mode 100644
index 000000000000..d592b6304b48
--- /dev/null
+++ b/arch/arm/plat-s5p/pm.c
@@ -0,0 +1,52 @@
1/* linux/arch/arm/plat-s5p/pm.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * S5P Power Manager (Suspend-To-RAM) support
7 *
8 * Based on arch/arm/plat-s3c24xx/pm.c
9 * Copyright (c) 2004,2006 Simtec Electronics
10 * Ben Dooks <ben@simtec.co.uk>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15*/
16
17#include <linux/suspend.h>
18#include <plat/pm.h>
19
20#define PFX "s5p pm: "
21
22/* s3c_pm_check_resume_pin
23 *
24 * check to see if the pin is configured correctly for sleep mode, and
25 * make any necessary adjustments if it is not
26*/
27
28static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
29{
30 /* nothing here yet */
31}
32
33/* s3c_pm_configure_extint
34 *
35 * configure all external interrupt pins
36*/
37
38void s3c_pm_configure_extint(void)
39{
40 /* nothing here yet */
41}
42
43void s3c_pm_restore_core(void)
44{
45 /* nothing here yet */
46}
47
48void s3c_pm_save_core(void)
49{
50 /* nothing here yet */
51}
52
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 7c0bde781167..dcd6eff4ee53 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -180,6 +180,31 @@ config S3C_DEV_I2C2
180 help 180 help
181 Compile in platform device definitions for I2C channel 2 181 Compile in platform device definitions for I2C channel 2
182 182
183config S3C_DEV_I2C3
184 bool
185 help
186 Compile in platform device definition for I2C controller 3
187
188config S3C_DEV_I2C4
189 bool
190 help
191 Compile in platform device definition for I2C controller 4
192
193config S3C_DEV_I2C5
194 bool
195 help
196 Compile in platform device definition for I2C controller 5
197
198config S3C_DEV_I2C6
199 bool
200 help
201 Compile in platform device definition for I2C controller 6
202
203config S3C_DEV_I2C7
204 bool
205 help
206 Compile in platform device definition for I2C controller 7
207
183config S3C_DEV_FB 208config S3C_DEV_FB
184 bool 209 bool
185 help 210 help
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 4d8ff923207a..afcce474af8e 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -40,6 +40,11 @@ obj-$(CONFIG_S3C_DEV_HWMON) += dev-hwmon.o
40obj-y += dev-i2c0.o 40obj-y += dev-i2c0.o
41obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o 41obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o
42obj-$(CONFIG_S3C_DEV_I2C2) += dev-i2c2.o 42obj-$(CONFIG_S3C_DEV_I2C2) += dev-i2c2.o
43obj-$(CONFIG_S3C_DEV_I2C3) += dev-i2c3.o
44obj-$(CONFIG_S3C_DEV_I2C4) += dev-i2c4.o
45obj-$(CONFIG_S3C_DEV_I2C5) += dev-i2c5.o
46obj-$(CONFIG_S3C_DEV_I2C6) += dev-i2c6.o
47obj-$(CONFIG_S3C_DEV_I2C7) += dev-i2c7.o
43obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o 48obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o
44obj-y += dev-uart.o 49obj-y += dev-uart.o
45obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o 50obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o
diff --git a/arch/arm/plat-samsung/dev-hsmmc.c b/arch/arm/plat-samsung/dev-hsmmc.c
index 9d2be0941410..db7a65c7f127 100644
--- a/arch/arm/plat-samsung/dev-hsmmc.c
+++ b/arch/arm/plat-samsung/dev-hsmmc.c
@@ -41,6 +41,7 @@ struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = {
41 .max_width = 4, 41 .max_width = 4,
42 .host_caps = (MMC_CAP_4_BIT_DATA | 42 .host_caps = (MMC_CAP_4_BIT_DATA |
43 MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), 43 MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
44 .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL,
44}; 45};
45 46
46struct platform_device s3c_device_hsmmc0 = { 47struct platform_device s3c_device_hsmmc0 = {
@@ -59,17 +60,20 @@ void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
59{ 60{
60 struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata; 61 struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata;
61 62
62 set->max_width = pd->max_width;
63 set->cd_type = pd->cd_type; 63 set->cd_type = pd->cd_type;
64 set->ext_cd_init = pd->ext_cd_init; 64 set->ext_cd_init = pd->ext_cd_init;
65 set->ext_cd_cleanup = pd->ext_cd_cleanup; 65 set->ext_cd_cleanup = pd->ext_cd_cleanup;
66 set->ext_cd_gpio = pd->ext_cd_gpio; 66 set->ext_cd_gpio = pd->ext_cd_gpio;
67 set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; 67 set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
68 68
69 if (pd->max_width)
70 set->max_width = pd->max_width;
69 if (pd->cfg_gpio) 71 if (pd->cfg_gpio)
70 set->cfg_gpio = pd->cfg_gpio; 72 set->cfg_gpio = pd->cfg_gpio;
71 if (pd->cfg_card) 73 if (pd->cfg_card)
72 set->cfg_card = pd->cfg_card; 74 set->cfg_card = pd->cfg_card;
73 if (pd->host_caps) 75 if (pd->host_caps)
74 set->host_caps = pd->host_caps; 76 set->host_caps |= pd->host_caps;
77 if (pd->clk_type)
78 set->clk_type = pd->clk_type;
75} 79}
diff --git a/arch/arm/plat-samsung/dev-hsmmc1.c b/arch/arm/plat-samsung/dev-hsmmc1.c
index a6c8295840af..2497321f08d7 100644
--- a/arch/arm/plat-samsung/dev-hsmmc1.c
+++ b/arch/arm/plat-samsung/dev-hsmmc1.c
@@ -41,6 +41,7 @@ struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = {
41 .max_width = 4, 41 .max_width = 4,
42 .host_caps = (MMC_CAP_4_BIT_DATA | 42 .host_caps = (MMC_CAP_4_BIT_DATA |
43 MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), 43 MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
44 .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL,
44}; 45};
45 46
46struct platform_device s3c_device_hsmmc1 = { 47struct platform_device s3c_device_hsmmc1 = {
@@ -59,17 +60,20 @@ void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
59{ 60{
60 struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata; 61 struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata;
61 62
62 set->max_width = pd->max_width;
63 set->cd_type = pd->cd_type; 63 set->cd_type = pd->cd_type;
64 set->ext_cd_init = pd->ext_cd_init; 64 set->ext_cd_init = pd->ext_cd_init;
65 set->ext_cd_cleanup = pd->ext_cd_cleanup; 65 set->ext_cd_cleanup = pd->ext_cd_cleanup;
66 set->ext_cd_gpio = pd->ext_cd_gpio; 66 set->ext_cd_gpio = pd->ext_cd_gpio;
67 set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; 67 set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
68 68
69 if (pd->max_width)
70 set->max_width = pd->max_width;
69 if (pd->cfg_gpio) 71 if (pd->cfg_gpio)
70 set->cfg_gpio = pd->cfg_gpio; 72 set->cfg_gpio = pd->cfg_gpio;
71 if (pd->cfg_card) 73 if (pd->cfg_card)
72 set->cfg_card = pd->cfg_card; 74 set->cfg_card = pd->cfg_card;
73 if (pd->host_caps) 75 if (pd->host_caps)
74 set->host_caps = pd->host_caps; 76 set->host_caps |= pd->host_caps;
77 if (pd->clk_type)
78 set->clk_type = pd->clk_type;
75} 79}
diff --git a/arch/arm/plat-samsung/dev-hsmmc2.c b/arch/arm/plat-samsung/dev-hsmmc2.c
index cb0d7143381a..f60aedba417c 100644
--- a/arch/arm/plat-samsung/dev-hsmmc2.c
+++ b/arch/arm/plat-samsung/dev-hsmmc2.c
@@ -42,6 +42,7 @@ struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = {
42 .max_width = 4, 42 .max_width = 4,
43 .host_caps = (MMC_CAP_4_BIT_DATA | 43 .host_caps = (MMC_CAP_4_BIT_DATA |
44 MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), 44 MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
45 .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL,
45}; 46};
46 47
47struct platform_device s3c_device_hsmmc2 = { 48struct platform_device s3c_device_hsmmc2 = {
@@ -60,17 +61,20 @@ void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
60{ 61{
61 struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata; 62 struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata;
62 63
63 set->max_width = pd->max_width;
64 set->cd_type = pd->cd_type; 64 set->cd_type = pd->cd_type;
65 set->ext_cd_init = pd->ext_cd_init; 65 set->ext_cd_init = pd->ext_cd_init;
66 set->ext_cd_cleanup = pd->ext_cd_cleanup; 66 set->ext_cd_cleanup = pd->ext_cd_cleanup;
67 set->ext_cd_gpio = pd->ext_cd_gpio; 67 set->ext_cd_gpio = pd->ext_cd_gpio;
68 set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; 68 set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
69 69
70 if (pd->max_width)
71 set->max_width = pd->max_width;
70 if (pd->cfg_gpio) 72 if (pd->cfg_gpio)
71 set->cfg_gpio = pd->cfg_gpio; 73 set->cfg_gpio = pd->cfg_gpio;
72 if (pd->cfg_card) 74 if (pd->cfg_card)
73 set->cfg_card = pd->cfg_card; 75 set->cfg_card = pd->cfg_card;
74 if (pd->host_caps) 76 if (pd->host_caps)
75 set->host_caps = pd->host_caps; 77 set->host_caps |= pd->host_caps;
78 if (pd->clk_type)
79 set->clk_type = pd->clk_type;
76} 80}
diff --git a/arch/arm/plat-samsung/dev-hsmmc3.c b/arch/arm/plat-samsung/dev-hsmmc3.c
index 85aaf0f2842f..ede776f20e62 100644
--- a/arch/arm/plat-samsung/dev-hsmmc3.c
+++ b/arch/arm/plat-samsung/dev-hsmmc3.c
@@ -33,8 +33,8 @@ static struct resource s3c_hsmmc3_resource[] = {
33 .flags = IORESOURCE_MEM, 33 .flags = IORESOURCE_MEM,
34 }, 34 },
35 [1] = { 35 [1] = {
36 .start = IRQ_MMC3, 36 .start = IRQ_HSMMC3,
37 .end = IRQ_MMC3, 37 .end = IRQ_HSMMC3,
38 .flags = IORESOURCE_IRQ, 38 .flags = IORESOURCE_IRQ,
39 } 39 }
40}; 40};
@@ -45,6 +45,7 @@ struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = {
45 .max_width = 4, 45 .max_width = 4,
46 .host_caps = (MMC_CAP_4_BIT_DATA | 46 .host_caps = (MMC_CAP_4_BIT_DATA |
47 MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), 47 MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
48 .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL,
48}; 49};
49 50
50struct platform_device s3c_device_hsmmc3 = { 51struct platform_device s3c_device_hsmmc3 = {
@@ -63,15 +64,20 @@ void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
63{ 64{
64 struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata; 65 struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata;
65 66
66 set->max_width = pd->max_width;
67 set->cd_type = pd->cd_type; 67 set->cd_type = pd->cd_type;
68 set->ext_cd_init = pd->ext_cd_init; 68 set->ext_cd_init = pd->ext_cd_init;
69 set->ext_cd_cleanup = pd->ext_cd_cleanup; 69 set->ext_cd_cleanup = pd->ext_cd_cleanup;
70 set->ext_cd_gpio = pd->ext_cd_gpio; 70 set->ext_cd_gpio = pd->ext_cd_gpio;
71 set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; 71 set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
72 72
73 if (pd->max_width)
74 set->max_width = pd->max_width;
73 if (pd->cfg_gpio) 75 if (pd->cfg_gpio)
74 set->cfg_gpio = pd->cfg_gpio; 76 set->cfg_gpio = pd->cfg_gpio;
75 if (pd->cfg_card) 77 if (pd->cfg_card)
76 set->cfg_card = pd->cfg_card; 78 set->cfg_card = pd->cfg_card;
79 if (pd->host_caps)
80 set->host_caps |= pd->host_caps;
81 if (pd->clk_type)
82 set->clk_type = pd->clk_type;
77} 83}
diff --git a/arch/arm/plat-samsung/dev-i2c2.c b/arch/arm/plat-samsung/dev-i2c2.c
index 07036dee09e7..ff4ba69b6830 100644
--- a/arch/arm/plat-samsung/dev-i2c2.c
+++ b/arch/arm/plat-samsung/dev-i2c2.c
@@ -32,8 +32,8 @@ static struct resource s3c_i2c_resource[] = {
32 .flags = IORESOURCE_MEM, 32 .flags = IORESOURCE_MEM,
33 }, 33 },
34 [1] = { 34 [1] = {
35 .start = IRQ_CAN0, 35 .start = IRQ_IIC2,
36 .end = IRQ_CAN0, 36 .end = IRQ_IIC2,
37 .flags = IORESOURCE_IRQ, 37 .flags = IORESOURCE_IRQ,
38 }, 38 },
39}; 39};
diff --git a/arch/arm/plat-samsung/dev-i2c3.c b/arch/arm/plat-samsung/dev-i2c3.c
new file mode 100644
index 000000000000..8586a10014b7
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-i2c3.c
@@ -0,0 +1,68 @@
1/* linux/arch/arm/plat-samsung/dev-i2c3.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5P series device definition for i2c device 3
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/gfp.h>
14#include <linux/kernel.h>
15#include <linux/string.h>
16#include <linux/platform_device.h>
17
18#include <mach/irqs.h>
19#include <mach/map.h>
20
21#include <plat/regs-iic.h>
22#include <plat/iic.h>
23#include <plat/devs.h>
24#include <plat/cpu.h>
25
26static struct resource s3c_i2c_resource[] = {
27 [0] = {
28 .start = S3C_PA_IIC3,
29 .end = S3C_PA_IIC3 + SZ_4K - 1,
30 .flags = IORESOURCE_MEM,
31 },
32 [1] = {
33 .start = IRQ_IIC3,
34 .end = IRQ_IIC3,
35 .flags = IORESOURCE_IRQ,
36 },
37};
38
39struct platform_device s3c_device_i2c3 = {
40 .name = "s3c2440-i2c",
41 .id = 3,
42 .num_resources = ARRAY_SIZE(s3c_i2c_resource),
43 .resource = s3c_i2c_resource,
44};
45
46static struct s3c2410_platform_i2c default_i2c_data3 __initdata = {
47 .flags = 0,
48 .bus_num = 3,
49 .slave_addr = 0x10,
50 .frequency = 100*1000,
51 .sda_delay = 100,
52};
53
54void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd)
55{
56 struct s3c2410_platform_i2c *npd;
57
58 if (!pd)
59 pd = &default_i2c_data3;
60
61 npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
62 if (!npd)
63 printk(KERN_ERR "%s: no memory for platform data\n", __func__);
64 else if (!npd->cfg_gpio)
65 npd->cfg_gpio = s3c_i2c3_cfg_gpio;
66
67 s3c_device_i2c3.dev.platform_data = npd;
68}
diff --git a/arch/arm/plat-samsung/dev-i2c4.c b/arch/arm/plat-samsung/dev-i2c4.c
new file mode 100644
index 000000000000..df2159e2daa6
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-i2c4.c
@@ -0,0 +1,68 @@
1/* linux/arch/arm/plat-samsung/dev-i2c4.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5P series device definition for i2c device 3
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/gfp.h>
14#include <linux/kernel.h>
15#include <linux/string.h>
16#include <linux/platform_device.h>
17
18#include <mach/irqs.h>
19#include <mach/map.h>
20
21#include <plat/regs-iic.h>
22#include <plat/iic.h>
23#include <plat/devs.h>
24#include <plat/cpu.h>
25
26static struct resource s3c_i2c_resource[] = {
27 [0] = {
28 .start = S3C_PA_IIC4,
29 .end = S3C_PA_IIC4 + SZ_4K - 1,
30 .flags = IORESOURCE_MEM,
31 },
32 [1] = {
33 .start = IRQ_IIC4,
34 .end = IRQ_IIC4,
35 .flags = IORESOURCE_IRQ,
36 },
37};
38
39struct platform_device s3c_device_i2c4 = {
40 .name = "s3c2440-i2c",
41 .id = 4,
42 .num_resources = ARRAY_SIZE(s3c_i2c_resource),
43 .resource = s3c_i2c_resource,
44};
45
46static struct s3c2410_platform_i2c default_i2c_data4 __initdata = {
47 .flags = 0,
48 .bus_num = 4,
49 .slave_addr = 0x10,
50 .frequency = 100*1000,
51 .sda_delay = 100,
52};
53
54void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd)
55{
56 struct s3c2410_platform_i2c *npd;
57
58 if (!pd)
59 pd = &default_i2c_data4;
60
61 npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
62 if (!npd)
63 printk(KERN_ERR "%s: no memory for platform data\n", __func__);
64 else if (!npd->cfg_gpio)
65 npd->cfg_gpio = s3c_i2c4_cfg_gpio;
66
67 s3c_device_i2c4.dev.platform_data = npd;
68}
diff --git a/arch/arm/plat-samsung/dev-i2c5.c b/arch/arm/plat-samsung/dev-i2c5.c
new file mode 100644
index 000000000000..0499c2c3877b
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-i2c5.c
@@ -0,0 +1,68 @@
1/* linux/arch/arm/plat-samsung/dev-i2c3.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5P series device definition for i2c device 3
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/gfp.h>
14#include <linux/kernel.h>
15#include <linux/string.h>
16#include <linux/platform_device.h>
17
18#include <mach/irqs.h>
19#include <mach/map.h>
20
21#include <plat/regs-iic.h>
22#include <plat/iic.h>
23#include <plat/devs.h>
24#include <plat/cpu.h>
25
26static struct resource s3c_i2c_resource[] = {
27 [0] = {
28 .start = S3C_PA_IIC5,
29 .end = S3C_PA_IIC5 + SZ_4K - 1,
30 .flags = IORESOURCE_MEM,
31 },
32 [1] = {
33 .start = IRQ_IIC5,
34 .end = IRQ_IIC5,
35 .flags = IORESOURCE_IRQ,
36 },
37};
38
39struct platform_device s3c_device_i2c5 = {
40 .name = "s3c2440-i2c",
41 .id = 5,
42 .num_resources = ARRAY_SIZE(s3c_i2c_resource),
43 .resource = s3c_i2c_resource,
44};
45
46static struct s3c2410_platform_i2c default_i2c_data5 __initdata = {
47 .flags = 0,
48 .bus_num = 5,
49 .slave_addr = 0x10,
50 .frequency = 100*1000,
51 .sda_delay = 100,
52};
53
54void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd)
55{
56 struct s3c2410_platform_i2c *npd;
57
58 if (!pd)
59 pd = &default_i2c_data5;
60
61 npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
62 if (!npd)
63 printk(KERN_ERR "%s: no memory for platform data\n", __func__);
64 else if (!npd->cfg_gpio)
65 npd->cfg_gpio = s3c_i2c5_cfg_gpio;
66
67 s3c_device_i2c5.dev.platform_data = npd;
68}
diff --git a/arch/arm/plat-samsung/dev-i2c6.c b/arch/arm/plat-samsung/dev-i2c6.c
new file mode 100644
index 000000000000..4083108908a8
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-i2c6.c
@@ -0,0 +1,68 @@
1/* linux/arch/arm/plat-samsung/dev-i2c6.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5P series device definition for i2c device 6
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/gfp.h>
14#include <linux/kernel.h>
15#include <linux/string.h>
16#include <linux/platform_device.h>
17
18#include <mach/irqs.h>
19#include <mach/map.h>
20
21#include <plat/regs-iic.h>
22#include <plat/iic.h>
23#include <plat/devs.h>
24#include <plat/cpu.h>
25
26static struct resource s3c_i2c_resource[] = {
27 [0] = {
28 .start = S3C_PA_IIC6,
29 .end = S3C_PA_IIC6 + SZ_4K - 1,
30 .flags = IORESOURCE_MEM,
31 },
32 [1] = {
33 .start = IRQ_IIC6,
34 .end = IRQ_IIC6,
35 .flags = IORESOURCE_IRQ,
36 },
37};
38
39struct platform_device s3c_device_i2c6 = {
40 .name = "s3c2440-i2c",
41 .id = 6,
42 .num_resources = ARRAY_SIZE(s3c_i2c_resource),
43 .resource = s3c_i2c_resource,
44};
45
46static struct s3c2410_platform_i2c default_i2c_data6 __initdata = {
47 .flags = 0,
48 .bus_num = 6,
49 .slave_addr = 0x10,
50 .frequency = 100*1000,
51 .sda_delay = 100,
52};
53
54void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd)
55{
56 struct s3c2410_platform_i2c *npd;
57
58 if (!pd)
59 pd = &default_i2c_data6;
60
61 npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
62 if (!npd)
63 printk(KERN_ERR "%s: no memory for platform data\n", __func__);
64 else if (!npd->cfg_gpio)
65 npd->cfg_gpio = s3c_i2c6_cfg_gpio;
66
67 s3c_device_i2c6.dev.platform_data = npd;
68}
diff --git a/arch/arm/plat-samsung/dev-i2c7.c b/arch/arm/plat-samsung/dev-i2c7.c
new file mode 100644
index 000000000000..1182451d7dce
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-i2c7.c
@@ -0,0 +1,68 @@
1/* linux/arch/arm/plat-samsung/dev-i2c7.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5P series device definition for i2c device 7
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/gfp.h>
14#include <linux/kernel.h>
15#include <linux/string.h>
16#include <linux/platform_device.h>
17
18#include <mach/irqs.h>
19#include <mach/map.h>
20
21#include <plat/regs-iic.h>
22#include <plat/iic.h>
23#include <plat/devs.h>
24#include <plat/cpu.h>
25
26static struct resource s3c_i2c_resource[] = {
27 [0] = {
28 .start = S3C_PA_IIC7,
29 .end = S3C_PA_IIC7 + SZ_4K - 1,
30 .flags = IORESOURCE_MEM,
31 },
32 [1] = {
33 .start = IRQ_IIC7,
34 .end = IRQ_IIC7,
35 .flags = IORESOURCE_IRQ,
36 },
37};
38
39struct platform_device s3c_device_i2c7 = {
40 .name = "s3c2440-i2c",
41 .id = 7,
42 .num_resources = ARRAY_SIZE(s3c_i2c_resource),
43 .resource = s3c_i2c_resource,
44};
45
46static struct s3c2410_platform_i2c default_i2c_data7 __initdata = {
47 .flags = 0,
48 .bus_num = 7,
49 .slave_addr = 0x10,
50 .frequency = 100*1000,
51 .sda_delay = 100,
52};
53
54void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd)
55{
56 struct s3c2410_platform_i2c *npd;
57
58 if (!pd)
59 pd = &default_i2c_data7;
60
61 npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
62 if (!npd)
63 printk(KERN_ERR "%s: no memory for platform data\n", __func__);
64 else if (!npd->cfg_gpio)
65 npd->cfg_gpio = s3c_i2c7_cfg_gpio;
66
67 s3c_device_i2c7.dev.platform_data = npd;
68}
diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c
index e3d41eaed1ff..b732b773b9af 100644
--- a/arch/arm/plat-samsung/gpio-config.c
+++ b/arch/arm/plat-samsung/gpio-config.c
@@ -41,6 +41,37 @@ int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
41} 41}
42EXPORT_SYMBOL(s3c_gpio_cfgpin); 42EXPORT_SYMBOL(s3c_gpio_cfgpin);
43 43
44int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
45 unsigned int cfg)
46{
47 int ret;
48
49 for (; nr > 0; nr--, start++) {
50 ret = s3c_gpio_cfgpin(start, cfg);
51 if (ret != 0)
52 return ret;
53 }
54
55 return 0;
56}
57EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
58
59int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
60 unsigned int cfg, s3c_gpio_pull_t pull)
61{
62 int ret;
63
64 for (; nr > 0; nr--, start++) {
65 s3c_gpio_setpull(start, pull);
66 ret = s3c_gpio_cfgpin(start, cfg);
67 if (ret != 0)
68 return ret;
69 }
70
71 return 0;
72}
73EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
74
44unsigned s3c_gpio_getcfg(unsigned int pin) 75unsigned s3c_gpio_getcfg(unsigned int pin)
45{ 76{
46 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); 77 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
@@ -80,6 +111,25 @@ int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
80} 111}
81EXPORT_SYMBOL(s3c_gpio_setpull); 112EXPORT_SYMBOL(s3c_gpio_setpull);
82 113
114s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
115{
116 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
117 unsigned long flags;
118 int offset;
119 u32 pup = 0;
120
121 if (chip) {
122 offset = pin - chip->chip.base;
123
124 s3c_gpio_lock(chip, flags);
125 pup = s3c_gpio_do_getpull(chip, offset);
126 s3c_gpio_unlock(chip, flags);
127 }
128
129 return (__force s3c_gpio_pull_t)pup;
130}
131EXPORT_SYMBOL(s3c_gpio_getpull);
132
83#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX 133#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
84int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, 134int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
85 unsigned int off, unsigned int cfg) 135 unsigned int off, unsigned int cfg)
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c
index b83a83351cea..7743c4b8b2fb 100644
--- a/arch/arm/plat-samsung/gpio.c
+++ b/arch/arm/plat-samsung/gpio.c
@@ -157,3 +157,11 @@ __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
157 if (ret >= 0) 157 if (ret >= 0)
158 s3c_gpiolib_track(chip); 158 s3c_gpiolib_track(chip);
159} 159}
160
161int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
162{
163 struct s3c_gpio_chip *s3c_chip = container_of(chip,
164 struct s3c_gpio_chip, chip);
165
166 return s3c_chip->irq_base + offset;
167}
diff --git a/arch/arm/plat-samsung/include/plat/audio.h b/arch/arm/plat-samsung/include/plat/audio.h
index e32f9edfd4b7..7712ff6336f4 100644
--- a/arch/arm/plat-samsung/include/plat/audio.h
+++ b/arch/arm/plat-samsung/include/plat/audio.h
@@ -16,6 +16,15 @@
16#define S3C64XX_AC97_GPE 1 16#define S3C64XX_AC97_GPE 1
17extern void s3c64xx_ac97_setup_gpio(int); 17extern void s3c64xx_ac97_setup_gpio(int);
18 18
19/*
20 * The machine init code calls s5p*_spdif_setup_gpio with
21 * one of these defines in order to select appropriate bank
22 * of GPIO for S/PDIF pins
23 */
24#define S5PC100_SPDIF_GPD 0
25#define S5PC100_SPDIF_GPG3 1
26extern void s5pc100_spdif_setup_gpio(int);
27
19/** 28/**
20 * struct s3c_audio_pdata - common platform data for audio device drivers 29 * struct s3c_audio_pdata - common platform data for audio device drivers
21 * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode 30 * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index c8b94279bad1..2d82a6cb1444 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -48,6 +48,11 @@ extern struct platform_device s3c_device_wdt;
48extern struct platform_device s3c_device_i2c0; 48extern struct platform_device s3c_device_i2c0;
49extern struct platform_device s3c_device_i2c1; 49extern struct platform_device s3c_device_i2c1;
50extern struct platform_device s3c_device_i2c2; 50extern struct platform_device s3c_device_i2c2;
51extern struct platform_device s3c_device_i2c3;
52extern struct platform_device s3c_device_i2c4;
53extern struct platform_device s3c_device_i2c5;
54extern struct platform_device s3c_device_i2c6;
55extern struct platform_device s3c_device_i2c7;
51extern struct platform_device s3c_device_rtc; 56extern struct platform_device s3c_device_rtc;
52extern struct platform_device s3c_device_adc; 57extern struct platform_device s3c_device_adc;
53extern struct platform_device s3c_device_sdi; 58extern struct platform_device s3c_device_sdi;
@@ -89,6 +94,7 @@ extern struct platform_device s5pv210_device_pcm2;
89extern struct platform_device s5pv210_device_iis0; 94extern struct platform_device s5pv210_device_iis0;
90extern struct platform_device s5pv210_device_iis1; 95extern struct platform_device s5pv210_device_iis1;
91extern struct platform_device s5pv210_device_iis2; 96extern struct platform_device s5pv210_device_iis2;
97extern struct platform_device s5pv210_device_spdif;
92 98
93extern struct platform_device s5p6442_device_pcm0; 99extern struct platform_device s5p6442_device_pcm0;
94extern struct platform_device s5p6442_device_pcm1; 100extern struct platform_device s5p6442_device_pcm1;
@@ -108,6 +114,7 @@ extern struct platform_device s5pc100_device_pcm1;
108extern struct platform_device s5pc100_device_iis0; 114extern struct platform_device s5pc100_device_iis0;
109extern struct platform_device s5pc100_device_iis1; 115extern struct platform_device s5pc100_device_iis1;
110extern struct platform_device s5pc100_device_iis2; 116extern struct platform_device s5pc100_device_iis2;
117extern struct platform_device s5pc100_device_spdif;
111 118
112extern struct platform_device samsung_device_keypad; 119extern struct platform_device samsung_device_keypad;
113 120
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
index 3e21c75feefa..8fd65d8b5863 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
@@ -42,6 +42,12 @@ static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip,
42 return (chip->config->set_pull)(chip, off, pull); 42 return (chip->config->set_pull)(chip, off, pull);
43} 43}
44 44
45static inline s3c_gpio_pull_t s3c_gpio_do_getpull(struct s3c_gpio_chip *chip,
46 unsigned int off)
47{
48 return chip->config->get_pull(chip, off);
49}
50
45/** 51/**
46 * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration. 52 * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
47 * @chip: The gpio chip that is being configured. 53 * @chip: The gpio chip that is being configured.
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
index 1c6b92947c5d..e4b5cf126fa9 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
@@ -108,6 +108,19 @@ extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to);
108 */ 108 */
109extern unsigned s3c_gpio_getcfg(unsigned int pin); 109extern unsigned s3c_gpio_getcfg(unsigned int pin);
110 110
111/**
112 * s3c_gpio_cfgpin_range() - Change the GPIO function for configuring pin range
113 * @start: The pin number to start at
114 * @nr: The number of pins to configure from @start.
115 * @cfg: The configuration for the pin's function
116 *
117 * Call s3c_gpio_cfgpin() for the @nr pins starting at @start.
118 *
119 * @sa s3c_gpio_cfgpin.
120 */
121extern int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
122 unsigned int cfg);
123
111/* Define values for the pull-{up,down} available for each gpio pin. 124/* Define values for the pull-{up,down} available for each gpio pin.
112 * 125 *
113 * These values control the state of the weak pull-{up,down} resistors 126 * These values control the state of the weak pull-{up,down} resistors
@@ -140,6 +153,31 @@ extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);
140*/ 153*/
141extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin); 154extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
142 155
156/* configure `all` aspects of an gpio */
157
158/**
159 * s3c_gpio_cfgall_range() - configure range of gpio functtion and pull.
160 * @start: The gpio number to start at.
161 * @nr: The number of gpio to configure from @start.
162 * @cfg: The configuration to use
163 * @pull: The pull setting to use.
164 *
165 * Run s3c_gpio_cfgpin() and s3c_gpio_setpull() over the gpio range starting
166 * @gpio and running for @size.
167 *
168 * @sa s3c_gpio_cfgpin
169 * @sa s3c_gpio_setpull
170 * @sa s3c_gpio_cfgpin_range
171 */
172extern int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
173 unsigned int cfg, s3c_gpio_pull_t pull);
174
175static inline int s3c_gpio_cfgrange_nopull(unsigned int pin, unsigned int size,
176 unsigned int cfg)
177{
178 return s3c_gpio_cfgall_range(pin, size, cfg, S3C_GPIO_PULL_NONE);
179}
180
143/* Define values for the drvstr available for each gpio pin. 181/* Define values for the drvstr available for each gpio pin.
144 * 182 *
145 * These values control the value of the output signal driver strength, 183 * These values control the value of the output signal driver strength,
@@ -169,4 +207,22 @@ extern s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin);
169*/ 207*/
170extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr); 208extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr);
171 209
210/**
211 * s5p_register_gpio_interrupt() - register interrupt support for a gpio group
212 * @pin: The pin number from the group to be registered
213 *
214 * This function registers gpio interrupt support for the group that the
215 * specified pin belongs to.
216 *
217 * The total number of gpio pins is quite large ob s5p series. Registering
218 * irq support for all of them would be a resource waste. Because of that the
219 * interrupt support for standard gpio pins is registered dynamically.
220 *
221 * It will return the irq number of the interrupt that has been registered
222 * or -ENOMEM if no more gpio interrupts can be registered. It is allowed
223 * to call this function more than once for the same gpio group (the group
224 * will be registered only once).
225 */
226extern int s5p_register_gpio_interrupt(int pin);
227
172#endif /* __PLAT_GPIO_CFG_H */ 228#endif /* __PLAT_GPIO_CFG_H */
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h
index e358c7da8480..13a22b8861ef 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-core.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-core.h
@@ -43,6 +43,8 @@ struct s3c_gpio_cfg;
43 * struct s3c_gpio_chip - wrapper for specific implementation of gpio 43 * struct s3c_gpio_chip - wrapper for specific implementation of gpio
44 * @chip: The chip structure to be exported via gpiolib. 44 * @chip: The chip structure to be exported via gpiolib.
45 * @base: The base pointer to the gpio configuration registers. 45 * @base: The base pointer to the gpio configuration registers.
46 * @group: The group register number for gpio interrupt support.
47 * @irq_base: The base irq number.
46 * @config: special function and pull-resistor control information. 48 * @config: special function and pull-resistor control information.
47 * @lock: Lock for exclusive access to this gpio bank. 49 * @lock: Lock for exclusive access to this gpio bank.
48 * @pm_save: Save information for suspend/resume support. 50 * @pm_save: Save information for suspend/resume support.
@@ -63,6 +65,8 @@ struct s3c_gpio_chip {
63 struct s3c_gpio_cfg *config; 65 struct s3c_gpio_cfg *config;
64 struct s3c_gpio_pm *pm; 66 struct s3c_gpio_pm *pm;
65 void __iomem *base; 67 void __iomem *base;
68 int irq_base;
69 int group;
66 spinlock_t lock; 70 spinlock_t lock;
67#ifdef CONFIG_PM 71#ifdef CONFIG_PM
68 u32 pm_save[4]; 72 u32 pm_save[4];
@@ -118,6 +122,17 @@ extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
118extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip); 122extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip);
119extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip); 123extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
120 124
125
126/**
127 * samsung_gpiolib_to_irq - convert gpio pin to irq number
128 * @chip: The gpio chip that the pin belongs to.
129 * @offset: The offset of the pin in the chip.
130 *
131 * This helper returns the irq number calculated from the chip->irq_base and
132 * the provided offset.
133 */
134extern int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset);
135
121/* exported for core SoC support to change */ 136/* exported for core SoC support to change */
122extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default; 137extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default;
123 138
diff --git a/arch/arm/plat-samsung/include/plat/iic.h b/arch/arm/plat-samsung/include/plat/iic.h
index 133308bf595d..1543da8f85c1 100644
--- a/arch/arm/plat-samsung/include/plat/iic.h
+++ b/arch/arm/plat-samsung/include/plat/iic.h
@@ -55,10 +55,20 @@ struct s3c2410_platform_i2c {
55extern void s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *i2c); 55extern void s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *i2c);
56extern void s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *i2c); 56extern void s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *i2c);
57extern void s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *i2c); 57extern void s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *i2c);
58extern void s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *i2c);
59extern void s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *i2c);
60extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c);
61extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c);
62extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c);
58 63
59/* defined by architecture to configure gpio */ 64/* defined by architecture to configure gpio */
60extern void s3c_i2c0_cfg_gpio(struct platform_device *dev); 65extern void s3c_i2c0_cfg_gpio(struct platform_device *dev);
61extern void s3c_i2c1_cfg_gpio(struct platform_device *dev); 66extern void s3c_i2c1_cfg_gpio(struct platform_device *dev);
62extern void s3c_i2c2_cfg_gpio(struct platform_device *dev); 67extern void s3c_i2c2_cfg_gpio(struct platform_device *dev);
68extern void s3c_i2c3_cfg_gpio(struct platform_device *dev);
69extern void s3c_i2c4_cfg_gpio(struct platform_device *dev);
70extern void s3c_i2c5_cfg_gpio(struct platform_device *dev);
71extern void s3c_i2c6_cfg_gpio(struct platform_device *dev);
72extern void s3c_i2c7_cfg_gpio(struct platform_device *dev);
63 73
64#endif /* __ASM_ARCH_IIC_H */ 74#endif /* __ASM_ARCH_IIC_H */
diff --git a/arch/arm/plat-samsung/include/plat/map-base.h b/arch/arm/plat-samsung/include/plat/map-base.h
index 250be311c85b..3ffac4d2e4f0 100644
--- a/arch/arm/plat-samsung/include/plat/map-base.h
+++ b/arch/arm/plat-samsung/include/plat/map-base.h
@@ -14,7 +14,7 @@
14#ifndef __ASM_PLAT_MAP_H 14#ifndef __ASM_PLAT_MAP_H
15#define __ASM_PLAT_MAP_H __FILE__ 15#define __ASM_PLAT_MAP_H __FILE__
16 16
17/* Fit all our registers in at 0xF4000000 upwards, trying to use as 17/* Fit all our registers in at 0xF6000000 upwards, trying to use as
18 * little of the VA space as possible so vmalloc and friends have a 18 * little of the VA space as possible so vmalloc and friends have a
19 * better chance of getting memory. 19 * better chance of getting memory.
20 * 20 *
@@ -22,7 +22,7 @@
22 * an single MOVS instruction (ie, only 8 bits of set data) 22 * an single MOVS instruction (ie, only 8 bits of set data)
23 */ 23 */
24 24
25#define S3C_ADDR_BASE (0xF4000000) 25#define S3C_ADDR_BASE 0xF6000000
26 26
27#ifndef __ASSEMBLY__ 27#ifndef __ASSEMBLY__
28#define S3C_ADDR(x) ((void __iomem __force *)S3C_ADDR_BASE + (x)) 28#define S3C_ADDR(x) ((void __iomem __force *)S3C_ADDR_BASE + (x))
diff --git a/arch/arm/plat-samsung/include/plat/nand-core.h b/arch/arm/plat-samsung/include/plat/nand-core.h
new file mode 100644
index 000000000000..6de20789a95e
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/nand-core.h
@@ -0,0 +1,28 @@
1/* arch/arm/plat-samsung/include/plat/nand-core.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S3C - Nand Controller core functions
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_NAND_CORE_H
14#define __ASM_ARCH_NAND_CORE_H __FILE__
15
16/* These functions are only for use with the core support code, such as
17 * the cpu specific initialisation code
18 */
19
20/* re-define device name depending on support. */
21static inline void s3c_nand_setname(char *name)
22{
23#ifdef CONFIG_S3C_DEV_NAND
24 s3c_device_nand.name = name;
25#endif
26}
27
28#endif /* __ASM_ARCH_NAND_CORE_H */
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
index 30844c263d03..85853f8c4c5d 100644
--- a/arch/arm/plat-samsung/include/plat/sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -28,11 +28,17 @@ enum cd_types {
28 S3C_SDHCI_CD_PERMANENT, /* no CD line, card permanently wired to host */ 28 S3C_SDHCI_CD_PERMANENT, /* no CD line, card permanently wired to host */
29}; 29};
30 30
31enum clk_types {
32 S3C_SDHCI_CLK_DIV_INTERNAL, /* use mmc internal clock divider */
33 S3C_SDHCI_CLK_DIV_EXTERNAL, /* use external clock divider */
34};
35
31/** 36/**
32 * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI 37 * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI
33 * @max_width: The maximum number of data bits supported. 38 * @max_width: The maximum number of data bits supported.
34 * @host_caps: Standard MMC host capabilities bit field. 39 * @host_caps: Standard MMC host capabilities bit field.
35 * @cd_type: Type of Card Detection method (see cd_types enum above) 40 * @cd_type: Type of Card Detection method (see cd_types enum above)
41 * @clk_type: Type of clock divider method (see clk_types enum above)
36 * @ext_cd_init: Initialize external card detect subsystem. Called on 42 * @ext_cd_init: Initialize external card detect subsystem. Called on
37 * sdhci-s3c driver probe when cd_type == S3C_SDHCI_CD_EXTERNAL. 43 * sdhci-s3c driver probe when cd_type == S3C_SDHCI_CD_EXTERNAL.
38 * notify_func argument is a callback to the sdhci-s3c driver 44 * notify_func argument is a callback to the sdhci-s3c driver
@@ -59,6 +65,7 @@ struct s3c_sdhci_platdata {
59 unsigned int max_width; 65 unsigned int max_width;
60 unsigned int host_caps; 66 unsigned int host_caps;
61 enum cd_types cd_type; 67 enum cd_types cd_type;
68 enum clk_types clk_type;
62 69
63 char **clocks; /* set of clock sources */ 70 char **clocks; /* set of clock sources */
64 71
@@ -110,6 +117,10 @@ extern void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
110extern void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *, int w); 117extern void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
111extern void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *, int w); 118extern void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
112extern void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *, int w); 119extern void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
120extern void s5pv310_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
121extern void s5pv310_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
122extern void s5pv310_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
123extern void s5pv310_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
113 124
114/* S3C64XX SDHCI setup */ 125/* S3C64XX SDHCI setup */
115 126
@@ -288,4 +299,57 @@ static inline void s5pv210_default_sdhci3(void) { }
288 299
289#endif /* CONFIG_S5PV210_SETUP_SDHCI */ 300#endif /* CONFIG_S5PV210_SETUP_SDHCI */
290 301
302/* S5PV310 SDHCI setup */
303#ifdef CONFIG_S5PV310_SETUP_SDHCI
304extern char *s5pv310_hsmmc_clksrcs[4];
305
306extern void s5pv310_setup_sdhci_cfg_card(struct platform_device *dev,
307 void __iomem *r,
308 struct mmc_ios *ios,
309 struct mmc_card *card);
310
311static inline void s5pv310_default_sdhci0(void)
312{
313#ifdef CONFIG_S3C_DEV_HSMMC
314 s3c_hsmmc0_def_platdata.clocks = s5pv310_hsmmc_clksrcs;
315 s3c_hsmmc0_def_platdata.cfg_gpio = s5pv310_setup_sdhci0_cfg_gpio;
316 s3c_hsmmc0_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card;
317#endif
318}
319
320static inline void s5pv310_default_sdhci1(void)
321{
322#ifdef CONFIG_S3C_DEV_HSMMC1
323 s3c_hsmmc1_def_platdata.clocks = s5pv310_hsmmc_clksrcs;
324 s3c_hsmmc1_def_platdata.cfg_gpio = s5pv310_setup_sdhci1_cfg_gpio;
325 s3c_hsmmc1_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card;
326#endif
327}
328
329static inline void s5pv310_default_sdhci2(void)
330{
331#ifdef CONFIG_S3C_DEV_HSMMC2
332 s3c_hsmmc2_def_platdata.clocks = s5pv310_hsmmc_clksrcs;
333 s3c_hsmmc2_def_platdata.cfg_gpio = s5pv310_setup_sdhci2_cfg_gpio;
334 s3c_hsmmc2_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card;
335#endif
336}
337
338static inline void s5pv310_default_sdhci3(void)
339{
340#ifdef CONFIG_S3C_DEV_HSMMC3
341 s3c_hsmmc3_def_platdata.clocks = s5pv310_hsmmc_clksrcs;
342 s3c_hsmmc3_def_platdata.cfg_gpio = s5pv310_setup_sdhci3_cfg_gpio;
343 s3c_hsmmc3_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card;
344#endif
345}
346
347#else
348static inline void s5pv310_default_sdhci0(void) { }
349static inline void s5pv310_default_sdhci1(void) { }
350static inline void s5pv310_default_sdhci2(void) { }
351static inline void s5pv310_default_sdhci3(void) { }
352
353#endif /* CONFIG_S5PV310_SETUP_SDHCI */
354
291#endif /* __PLAT_S3C_SDHCI_H */ 355#endif /* __PLAT_S3C_SDHCI_H */
diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c
index 7df03f87fbfa..96528200eb79 100644
--- a/arch/arm/plat-samsung/pm-gpio.c
+++ b/arch/arm/plat-samsung/pm-gpio.c
@@ -192,7 +192,7 @@ struct s3c_gpio_pm s3c_gpio_pm_2bit = {
192 .resume = s3c_gpio_pm_2bit_resume, 192 .resume = s3c_gpio_pm_2bit_resume,
193}; 193};
194 194
195#ifdef CONFIG_ARCH_S3C64XX 195#if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P)
196static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip) 196static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
197{ 197{
198 chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON); 198 chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
@@ -302,7 +302,7 @@ struct s3c_gpio_pm s3c_gpio_pm_4bit = {
302 .save = s3c_gpio_pm_4bit_save, 302 .save = s3c_gpio_pm_4bit_save,
303 .resume = s3c_gpio_pm_4bit_resume, 303 .resume = s3c_gpio_pm_4bit_resume,
304}; 304};
305#endif /* CONFIG_ARCH_S3C64XX */ 305#endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */
306 306
307/** 307/**
308 * s3c_pm_save_gpio() - save gpio chip data for suspend 308 * s3c_pm_save_gpio() - save gpio chip data for suspend
diff --git a/arch/arm/plat-samsung/s3c-pl330.c b/arch/arm/plat-samsung/s3c-pl330.c
index a91305a60aed..b4ff8d74ac40 100644
--- a/arch/arm/plat-samsung/s3c-pl330.c
+++ b/arch/arm/plat-samsung/s3c-pl330.c
@@ -15,6 +15,8 @@
15#include <linux/io.h> 15#include <linux/io.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/clk.h>
19#include <linux/err.h>
18 20
19#include <asm/hardware/pl330.h> 21#include <asm/hardware/pl330.h>
20 22
@@ -27,6 +29,7 @@
27 * @node: To attach to the global list of DMACs. 29 * @node: To attach to the global list of DMACs.
28 * @pi: PL330 configuration info for the DMAC. 30 * @pi: PL330 configuration info for the DMAC.
29 * @kmcache: Pool to quickly allocate xfers for all channels in the dmac. 31 * @kmcache: Pool to quickly allocate xfers for all channels in the dmac.
32 * @clk: Pointer of DMAC operation clock.
30 */ 33 */
31struct s3c_pl330_dmac { 34struct s3c_pl330_dmac {
32 unsigned busy_chan; 35 unsigned busy_chan;
@@ -34,6 +37,7 @@ struct s3c_pl330_dmac {
34 struct list_head node; 37 struct list_head node;
35 struct pl330_info *pi; 38 struct pl330_info *pi;
36 struct kmem_cache *kmcache; 39 struct kmem_cache *kmcache;
40 struct clk *clk;
37}; 41};
38 42
39/** 43/**
@@ -1072,16 +1076,25 @@ static int pl330_probe(struct platform_device *pdev)
1072 if (ret) 1076 if (ret)
1073 goto probe_err4; 1077 goto probe_err4;
1074 1078
1075 ret = pl330_add(pl330_info);
1076 if (ret)
1077 goto probe_err5;
1078
1079 /* Allocate a new DMAC */ 1079 /* Allocate a new DMAC */
1080 s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL); 1080 s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL);
1081 if (!s3c_pl330_dmac) { 1081 if (!s3c_pl330_dmac) {
1082 ret = -ENOMEM; 1082 ret = -ENOMEM;
1083 goto probe_err5;
1084 }
1085
1086 /* Get operation clock and enable it */
1087 s3c_pl330_dmac->clk = clk_get(&pdev->dev, "pdma");
1088 if (IS_ERR(s3c_pl330_dmac->clk)) {
1089 dev_err(&pdev->dev, "Cannot get operation clock.\n");
1090 ret = -EINVAL;
1083 goto probe_err6; 1091 goto probe_err6;
1084 } 1092 }
1093 clk_enable(s3c_pl330_dmac->clk);
1094
1095 ret = pl330_add(pl330_info);
1096 if (ret)
1097 goto probe_err7;
1085 1098
1086 /* Hook the info */ 1099 /* Hook the info */
1087 s3c_pl330_dmac->pi = pl330_info; 1100 s3c_pl330_dmac->pi = pl330_info;
@@ -1094,7 +1107,7 @@ static int pl330_probe(struct platform_device *pdev)
1094 1107
1095 if (!s3c_pl330_dmac->kmcache) { 1108 if (!s3c_pl330_dmac->kmcache) {
1096 ret = -ENOMEM; 1109 ret = -ENOMEM;
1097 goto probe_err7; 1110 goto probe_err8;
1098 } 1111 }
1099 1112
1100 /* Get the list of peripherals */ 1113 /* Get the list of peripherals */
@@ -1120,10 +1133,13 @@ static int pl330_probe(struct platform_device *pdev)
1120 1133
1121 return 0; 1134 return 0;
1122 1135
1136probe_err8:
1137 pl330_del(pl330_info);
1123probe_err7: 1138probe_err7:
1124 kfree(s3c_pl330_dmac); 1139 clk_disable(s3c_pl330_dmac->clk);
1140 clk_put(s3c_pl330_dmac->clk);
1125probe_err6: 1141probe_err6:
1126 pl330_del(pl330_info); 1142 kfree(s3c_pl330_dmac);
1127probe_err5: 1143probe_err5:
1128 free_irq(irq, pl330_info); 1144 free_irq(irq, pl330_info);
1129probe_err4: 1145probe_err4:
@@ -1188,6 +1204,10 @@ static int pl330_remove(struct platform_device *pdev)
1188 } 1204 }
1189 } 1205 }
1190 1206
1207 /* Disable operation clock */
1208 clk_disable(dmac->clk);
1209 clk_put(dmac->clk);
1210
1191 /* Remove the DMAC */ 1211 /* Remove the DMAC */
1192 list_del(&dmac->node); 1212 list_del(&dmac->node);
1193 kfree(dmac); 1213 kfree(dmac);
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h b/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
new file mode 100644
index 000000000000..5325084d5c48
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
@@ -0,0 +1,97 @@
1#ifndef __BCM963XX_TAG_H
2#define __BCM963XX_TAG_H
3
4#define TAGVER_LEN 4 /* Length of Tag Version */
5#define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */
6#define SIG1_LEN 20 /* Company Signature 1 Length */
7#define SIG2_LEN 14 /* Company Signature 2 Lenght */
8#define BOARDID_LEN 16 /* Length of BoardId */
9#define ENDIANFLAG_LEN 2 /* Endian Flag Length */
10#define CHIPID_LEN 6 /* Chip Id Length */
11#define IMAGE_LEN 10 /* Length of Length Field */
12#define ADDRESS_LEN 12 /* Length of Address field */
13#define DUALFLAG_LEN 2 /* Dual Image flag Length */
14#define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */
15#define RSASIG_LEN 20 /* Length of RSA Signature in tag */
16#define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */
17#define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */
18#define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */
19#define CRC_LEN 4 /* Length of CRC in bytes */
20#define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */
21
22#define NUM_PIRELLI 2
23#define IMAGETAG_CRC_START 0xFFFFFFFF
24
25#define PIRELLI_BOARDS { \
26 "AGPF-S0", \
27 "DWV-S0", \
28}
29
30/*
31 * The broadcom firmware assumes the rootfs starts the image,
32 * therefore uses the rootfs start (flash_image_address)
33 * to determine where to flash the image. Since we have the kernel first
34 * we have to give it the kernel address, but the crc uses the length
35 * associated with this address (root_length), which is added to the kernel
36 * length (kernel_length) to determine the length of image to flash and thus
37 * needs to be rootfs + deadcode (jffs2 EOF marker)
38*/
39
40struct bcm_tag {
41 /* 0-3: Version of the image tag */
42 char tag_version[TAGVER_LEN];
43 /* 4-23: Company Line 1 */
44 char sig_1[SIG1_LEN];
45 /* 24-37: Company Line 2 */
46 char sig_2[SIG2_LEN];
47 /* 38-43: Chip this image is for */
48 char chip_id[CHIPID_LEN];
49 /* 44-59: Board name */
50 char board_id[BOARDID_LEN];
51 /* 60-61: Map endianness -- 1 BE 0 LE */
52 char big_endian[ENDIANFLAG_LEN];
53 /* 62-71: Total length of image */
54 char total_length[IMAGE_LEN];
55 /* 72-83: Address in memory of CFE */
56 char cfe__address[ADDRESS_LEN];
57 /* 84-93: Size of CFE */
58 char cfe_length[IMAGE_LEN];
59 /* 94-105: Address in memory of image start
60 * (kernel for OpenWRT, rootfs for stock firmware)
61 */
62 char flash_image_start[ADDRESS_LEN];
63 /* 106-115: Size of rootfs */
64 char root_length[IMAGE_LEN];
65 /* 116-127: Address in memory of kernel */
66 char kernel_address[ADDRESS_LEN];
67 /* 128-137: Size of kernel */
68 char kernel_length[IMAGE_LEN];
69 /* 138-139: Unused at the moment */
70 char dual_image[DUALFLAG_LEN];
71 /* 140-141: Unused at the moment */
72 char inactive_flag[INACTIVEFLAG_LEN];
73 /* 142-161: RSA Signature (not used; some vendors may use this) */
74 char rsa_signature[RSASIG_LEN];
75 /* 162-191: Compilation and related information (not used in OpenWrt) */
76 char information1[TAGINFO1_LEN];
77 /* 192-195: Version flash layout */
78 char flash_layout_ver[FLASHLAYOUTVER_LEN];
79 /* 196-199: kernel+rootfs CRC32 */
80 char fskernel_crc[CRC_LEN];
81 /* 200-215: Unused except on Alice Gate where is is information */
82 char information2[TAGINFO2_LEN];
83 /* 216-219: CRC32 of image less imagetag (kernel for Alice Gate) */
84 char image_crc[CRC_LEN];
85 /* 220-223: CRC32 of rootfs partition */
86 char rootfs_crc[CRC_LEN];
87 /* 224-227: CRC32 of kernel partition */
88 char kernel_crc[CRC_LEN];
89 /* 228-235: Unused at present */
90 char reserved1[8];
91 /* 236-239: CRC32 of header excluding tagVersion */
92 char header_crc[CRC_LEN];
93 /* 240-255: Unused at present */
94 char reserved2[16];
95};
96
97#endif /* __BCM63XX_TAG_H */
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c7e40b37aa65..b6447190e1a2 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -682,9 +682,12 @@ config 4xx_SOC
682 bool 682 bool
683 683
684config FSL_LBC 684config FSL_LBC
685 bool 685 bool "Freescale Local Bus support"
686 depends on FSL_SOC
686 help 687 help
687 Freescale Localbus support 688 Enables reporting of errors from the Freescale local bus
689 controller. Also contains some common code used by
690 drivers for specific local bus peripherals.
688 691
689config FSL_GTM 692config FSL_GTM
690 bool 693 bool
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index 1b5a21041f9b..5c1bf3466749 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -1,9 +1,10 @@
1/* Freescale Local Bus Controller 1/* Freescale Local Bus Controller
2 * 2 *
3 * Copyright (c) 2006-2007 Freescale Semiconductor 3 * Copyright © 2006-2007, 2010 Freescale Semiconductor
4 * 4 *
5 * Authors: Nick Spence <nick.spence@freescale.com>, 5 * Authors: Nick Spence <nick.spence@freescale.com>,
6 * Scott Wood <scottwood@freescale.com> 6 * Scott Wood <scottwood@freescale.com>
7 * Jack Lan <jack.lan@freescale.com>
7 * 8 *
8 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
@@ -26,6 +27,8 @@
26#include <linux/compiler.h> 27#include <linux/compiler.h>
27#include <linux/types.h> 28#include <linux/types.h>
28#include <linux/io.h> 29#include <linux/io.h>
30#include <linux/device.h>
31#include <linux/spinlock.h>
29 32
30struct fsl_lbc_bank { 33struct fsl_lbc_bank {
31 __be32 br; /**< Base Register */ 34 __be32 br; /**< Base Register */
@@ -125,13 +128,23 @@ struct fsl_lbc_regs {
125#define LTESR_ATMW 0x00800000 128#define LTESR_ATMW 0x00800000
126#define LTESR_ATMR 0x00400000 129#define LTESR_ATMR 0x00400000
127#define LTESR_CS 0x00080000 130#define LTESR_CS 0x00080000
131#define LTESR_UPM 0x00000002
128#define LTESR_CC 0x00000001 132#define LTESR_CC 0x00000001
129#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC) 133#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
134#define LTESR_MASK (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
135 | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
136 | LTESR_CC)
137#define LTESR_CLEAR 0xFFFFFFFF
138#define LTECCR_CLEAR 0xFFFFFFFF
139#define LTESR_STATUS LTESR_MASK
140#define LTEIR_ENABLE LTESR_MASK
141#define LTEDR_ENABLE 0x00000000
130 __be32 ltedr; /**< Transfer Error Disable Register */ 142 __be32 ltedr; /**< Transfer Error Disable Register */
131 __be32 lteir; /**< Transfer Error Interrupt Register */ 143 __be32 lteir; /**< Transfer Error Interrupt Register */
132 __be32 lteatr; /**< Transfer Error Attributes Register */ 144 __be32 lteatr; /**< Transfer Error Attributes Register */
133 __be32 ltear; /**< Transfer Error Address Register */ 145 __be32 ltear; /**< Transfer Error Address Register */
134 u8 res6[0xC]; 146 __be32 lteccr; /**< Transfer Error ECC Register */
147 u8 res6[0x8];
135 __be32 lbcr; /**< Configuration Register */ 148 __be32 lbcr; /**< Configuration Register */
136#define LBCR_LDIS 0x80000000 149#define LBCR_LDIS 0x80000000
137#define LBCR_LDIS_SHIFT 31 150#define LBCR_LDIS_SHIFT 31
@@ -235,6 +248,7 @@ struct fsl_upm {
235 int width; 248 int width;
236}; 249};
237 250
251extern u32 fsl_lbc_addr(phys_addr_t addr_base);
238extern int fsl_lbc_find(phys_addr_t addr_base); 252extern int fsl_lbc_find(phys_addr_t addr_base);
239extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm); 253extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm);
240 254
@@ -265,7 +279,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
265 cpu_relax(); 279 cpu_relax();
266} 280}
267 281
282/* overview of the fsl lbc controller */
283
284struct fsl_lbc_ctrl {
285 /* device info */
286 struct device *dev;
287 struct fsl_lbc_regs __iomem *regs;
288 int irq;
289 wait_queue_head_t irq_wait;
290 spinlock_t lock;
291 void *nand;
292
293 /* status read from LTESR by irq handler */
294 unsigned int irq_status;
295};
296
268extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, 297extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
269 u32 mar); 298 u32 mar);
299extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
270 300
271#endif /* __ASM_FSL_LBC_H */ 301#endif /* __ASM_FSL_LBC_H */
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index dceb8d1a843d..4fcb5a4e60dd 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -1,9 +1,12 @@
1/* 1/*
2 * Freescale LBC and UPM routines. 2 * Freescale LBC and UPM routines.
3 * 3 *
4 * Copyright (c) 2007-2008 MontaVista Software, Inc. 4 * Copyright © 2007-2008 MontaVista Software, Inc.
5 * Copyright © 2010 Freescale Semiconductor
5 * 6 *
6 * Author: Anton Vorontsov <avorontsov@ru.mvista.com> 7 * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
8 * Author: Jack Lan <Jack.Lan@freescale.com>
9 * Author: Roy Zang <tie-fei.zang@freescale.com>
7 * 10 *
8 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 12 * it under the terms of the GNU General Public License as published by
@@ -19,39 +22,37 @@
19#include <linux/types.h> 22#include <linux/types.h>
20#include <linux/io.h> 23#include <linux/io.h>
21#include <linux/of.h> 24#include <linux/of.h>
25#include <linux/slab.h>
26#include <linux/platform_device.h>
27#include <linux/interrupt.h>
28#include <linux/mod_devicetable.h>
22#include <asm/prom.h> 29#include <asm/prom.h>
23#include <asm/fsl_lbc.h> 30#include <asm/fsl_lbc.h>
24 31
25static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); 32static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
26static struct fsl_lbc_regs __iomem *fsl_lbc_regs; 33struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
34EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
27 35
28static char __initdata *compat_lbc[] = { 36/**
29 "fsl,pq2-localbus", 37 * fsl_lbc_addr - convert the base address
30 "fsl,pq2pro-localbus", 38 * @addr_base: base address of the memory bank
31 "fsl,pq3-localbus", 39 *
32 "fsl,elbc", 40 * This function converts a base address of lbc into the right format for the
33}; 41 * BR register. If the SOC has eLBC then it returns 32bit physical address
34 42 * else it convers a 34bit local bus physical address to correct format of
35static int __init fsl_lbc_init(void) 43 * 32bit address for BR register (Example: MPC8641).
44 */
45u32 fsl_lbc_addr(phys_addr_t addr_base)
36{ 46{
37 struct device_node *lbus; 47 struct device_node *np = fsl_lbc_ctrl_dev->dev->of_node;
38 int i; 48 u32 addr = addr_base & 0xffff8000;
39 49
40 for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) { 50 if (of_device_is_compatible(np, "fsl,elbc"))
41 lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]); 51 return addr;
42 if (lbus)
43 goto found;
44 }
45 return -ENODEV;
46 52
47found: 53 return addr | ((addr_base & 0x300000000ull) >> 19);
48 fsl_lbc_regs = of_iomap(lbus, 0);
49 of_node_put(lbus);
50 if (!fsl_lbc_regs)
51 return -ENOMEM;
52 return 0;
53} 54}
54arch_initcall(fsl_lbc_init); 55EXPORT_SYMBOL(fsl_lbc_addr);
55 56
56/** 57/**
57 * fsl_lbc_find - find Localbus bank 58 * fsl_lbc_find - find Localbus bank
@@ -65,15 +66,17 @@ arch_initcall(fsl_lbc_init);
65int fsl_lbc_find(phys_addr_t addr_base) 66int fsl_lbc_find(phys_addr_t addr_base)
66{ 67{
67 int i; 68 int i;
69 struct fsl_lbc_regs __iomem *lbc;
68 70
69 if (!fsl_lbc_regs) 71 if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
70 return -ENODEV; 72 return -ENODEV;
71 73
72 for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) { 74 lbc = fsl_lbc_ctrl_dev->regs;
73 __be32 br = in_be32(&fsl_lbc_regs->bank[i].br); 75 for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
74 __be32 or = in_be32(&fsl_lbc_regs->bank[i].or); 76 __be32 br = in_be32(&lbc->bank[i].br);
77 __be32 or = in_be32(&lbc->bank[i].or);
75 78
76 if (br & BR_V && (br & or & BR_BA) == addr_base) 79 if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base))
77 return i; 80 return i;
78 } 81 }
79 82
@@ -94,22 +97,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
94{ 97{
95 int bank; 98 int bank;
96 __be32 br; 99 __be32 br;
100 struct fsl_lbc_regs __iomem *lbc;
97 101
98 bank = fsl_lbc_find(addr_base); 102 bank = fsl_lbc_find(addr_base);
99 if (bank < 0) 103 if (bank < 0)
100 return bank; 104 return bank;
101 105
102 br = in_be32(&fsl_lbc_regs->bank[bank].br); 106 if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
107 return -ENODEV;
108
109 lbc = fsl_lbc_ctrl_dev->regs;
110 br = in_be32(&lbc->bank[bank].br);
103 111
104 switch (br & BR_MSEL) { 112 switch (br & BR_MSEL) {
105 case BR_MS_UPMA: 113 case BR_MS_UPMA:
106 upm->mxmr = &fsl_lbc_regs->mamr; 114 upm->mxmr = &lbc->mamr;
107 break; 115 break;
108 case BR_MS_UPMB: 116 case BR_MS_UPMB:
109 upm->mxmr = &fsl_lbc_regs->mbmr; 117 upm->mxmr = &lbc->mbmr;
110 break; 118 break;
111 case BR_MS_UPMC: 119 case BR_MS_UPMC:
112 upm->mxmr = &fsl_lbc_regs->mcmr; 120 upm->mxmr = &lbc->mcmr;
113 break; 121 break;
114 default: 122 default:
115 return -EINVAL; 123 return -EINVAL;
@@ -148,9 +156,12 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
148 int ret = 0; 156 int ret = 0;
149 unsigned long flags; 157 unsigned long flags;
150 158
159 if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
160 return -ENODEV;
161
151 spin_lock_irqsave(&fsl_lbc_lock, flags); 162 spin_lock_irqsave(&fsl_lbc_lock, flags);
152 163
153 out_be32(&fsl_lbc_regs->mar, mar); 164 out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
154 165
155 switch (upm->width) { 166 switch (upm->width) {
156 case 8: 167 case 8:
@@ -172,3 +183,166 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
172 return ret; 183 return ret;
173} 184}
174EXPORT_SYMBOL(fsl_upm_run_pattern); 185EXPORT_SYMBOL(fsl_upm_run_pattern);
186
187static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
188{
189 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
190
191 /* clear event registers */
192 setbits32(&lbc->ltesr, LTESR_CLEAR);
193 out_be32(&lbc->lteatr, 0);
194 out_be32(&lbc->ltear, 0);
195 out_be32(&lbc->lteccr, LTECCR_CLEAR);
196 out_be32(&lbc->ltedr, LTEDR_ENABLE);
197
198 /* Enable interrupts for any detected events */
199 out_be32(&lbc->lteir, LTEIR_ENABLE);
200
201 return 0;
202}
203
204/*
205 * NOTE: This interrupt is used to report localbus events of various kinds,
206 * such as transaction errors on the chipselects.
207 */
208
209static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
210{
211 struct fsl_lbc_ctrl *ctrl = data;
212 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
213 u32 status;
214
215 status = in_be32(&lbc->ltesr);
216 if (!status)
217 return IRQ_NONE;
218
219 out_be32(&lbc->ltesr, LTESR_CLEAR);
220 out_be32(&lbc->lteatr, 0);
221 out_be32(&lbc->ltear, 0);
222 ctrl->irq_status = status;
223
224 if (status & LTESR_BM)
225 dev_err(ctrl->dev, "Local bus monitor time-out: "
226 "LTESR 0x%08X\n", status);
227 if (status & LTESR_WP)
228 dev_err(ctrl->dev, "Write protect error: "
229 "LTESR 0x%08X\n", status);
230 if (status & LTESR_ATMW)
231 dev_err(ctrl->dev, "Atomic write error: "
232 "LTESR 0x%08X\n", status);
233 if (status & LTESR_ATMR)
234 dev_err(ctrl->dev, "Atomic read error: "
235 "LTESR 0x%08X\n", status);
236 if (status & LTESR_CS)
237 dev_err(ctrl->dev, "Chip select error: "
238 "LTESR 0x%08X\n", status);
239 if (status & LTESR_UPM)
240 ;
241 if (status & LTESR_FCT) {
242 dev_err(ctrl->dev, "FCM command time-out: "
243 "LTESR 0x%08X\n", status);
244 smp_wmb();
245 wake_up(&ctrl->irq_wait);
246 }
247 if (status & LTESR_PAR) {
248 dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
249 "LTESR 0x%08X\n", status);
250 smp_wmb();
251 wake_up(&ctrl->irq_wait);
252 }
253 if (status & LTESR_CC) {
254 smp_wmb();
255 wake_up(&ctrl->irq_wait);
256 }
257 if (status & ~LTESR_MASK)
258 dev_err(ctrl->dev, "Unknown error: "
259 "LTESR 0x%08X\n", status);
260 return IRQ_HANDLED;
261}
262
263/*
264 * fsl_lbc_ctrl_probe
265 *
266 * called by device layer when it finds a device matching
267 * one our driver can handled. This code allocates all of
268 * the resources needed for the controller only. The
269 * resources for the NAND banks themselves are allocated
270 * in the chip probe function.
271*/
272
273static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
274{
275 int ret;
276
277 if (!dev->dev.of_node) {
278 dev_err(&dev->dev, "Device OF-Node is NULL");
279 return -EFAULT;
280 }
281
282 fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
283 if (!fsl_lbc_ctrl_dev)
284 return -ENOMEM;
285
286 dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev);
287
288 spin_lock_init(&fsl_lbc_ctrl_dev->lock);
289 init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
290
291 fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
292 if (!fsl_lbc_ctrl_dev->regs) {
293 dev_err(&dev->dev, "failed to get memory region\n");
294 ret = -ENODEV;
295 goto err;
296 }
297
298 fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
299 if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
300 dev_err(&dev->dev, "failed to get irq resource\n");
301 ret = -ENODEV;
302 goto err;
303 }
304
305 fsl_lbc_ctrl_dev->dev = &dev->dev;
306
307 ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
308 if (ret < 0)
309 goto err;
310
311 ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
312 "fsl-lbc", fsl_lbc_ctrl_dev);
313 if (ret != 0) {
314 dev_err(&dev->dev, "failed to install irq (%d)\n",
315 fsl_lbc_ctrl_dev->irq);
316 ret = fsl_lbc_ctrl_dev->irq;
317 goto err;
318 }
319
320 return 0;
321
322err:
323 iounmap(fsl_lbc_ctrl_dev->regs);
324 kfree(fsl_lbc_ctrl_dev);
325 return ret;
326}
327
328static const struct of_device_id fsl_lbc_match[] = {
329 { .compatible = "fsl,elbc", },
330 { .compatible = "fsl,pq3-localbus", },
331 { .compatible = "fsl,pq2-localbus", },
332 { .compatible = "fsl,pq2pro-localbus", },
333 {},
334};
335
336static struct platform_driver fsl_lbc_ctrl_driver = {
337 .driver = {
338 .name = "fsl-lbc",
339 .of_match_table = fsl_lbc_match,
340 },
341 .probe = fsl_lbc_ctrl_probe,
342};
343
344static int __init fsl_lbc_init(void)
345{
346 return platform_driver_register(&fsl_lbc_ctrl_driver);
347}
348module_init(fsl_lbc_init);
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
index 881a3a5f5647..07ea908c510d 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -176,6 +176,21 @@ static void ap320_wvga_power_off(void *board_data)
176 __raw_writew(0, FPGA_LCDREG); 176 __raw_writew(0, FPGA_LCDREG);
177} 177}
178 178
179const static struct fb_videomode ap325rxa_lcdc_modes[] = {
180 {
181 .name = "LB070WV1",
182 .xres = 800,
183 .yres = 480,
184 .left_margin = 32,
185 .right_margin = 160,
186 .hsync_len = 8,
187 .upper_margin = 63,
188 .lower_margin = 80,
189 .vsync_len = 1,
190 .sync = 0, /* hsync and vsync are active low */
191 },
192};
193
179static struct sh_mobile_lcdc_info lcdc_info = { 194static struct sh_mobile_lcdc_info lcdc_info = {
180 .clock_source = LCDC_CLK_EXTERNAL, 195 .clock_source = LCDC_CLK_EXTERNAL,
181 .ch[0] = { 196 .ch[0] = {
@@ -183,18 +198,8 @@ static struct sh_mobile_lcdc_info lcdc_info = {
183 .bpp = 16, 198 .bpp = 16,
184 .interface_type = RGB18, 199 .interface_type = RGB18,
185 .clock_divider = 1, 200 .clock_divider = 1,
186 .lcd_cfg = { 201 .lcd_cfg = ap325rxa_lcdc_modes,
187 .name = "LB070WV1", 202 .num_cfg = ARRAY_SIZE(ap325rxa_lcdc_modes),
188 .xres = 800,
189 .yres = 480,
190 .left_margin = 32,
191 .right_margin = 160,
192 .hsync_len = 8,
193 .upper_margin = 63,
194 .lower_margin = 80,
195 .vsync_len = 1,
196 .sync = 0, /* hsync and vsync are active low */
197 },
198 .lcd_size_cfg = { /* 7.0 inch */ 203 .lcd_size_cfg = { /* 7.0 inch */
199 .width = 152, 204 .width = 152,
200 .height = 91, 205 .height = 91,
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index ddc7e4e4d2a0..2eaeb9e59585 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -231,14 +231,41 @@ static struct platform_device usb1_common_device = {
231}; 231};
232 232
233/* LCDC */ 233/* LCDC */
234const static struct fb_videomode ecovec_lcd_modes[] = {
235 {
236 .name = "Panel",
237 .xres = 800,
238 .yres = 480,
239 .left_margin = 220,
240 .right_margin = 110,
241 .hsync_len = 70,
242 .upper_margin = 20,
243 .lower_margin = 5,
244 .vsync_len = 5,
245 .sync = 0, /* hsync and vsync are active low */
246 },
247};
248
249const static struct fb_videomode ecovec_dvi_modes[] = {
250 {
251 .name = "DVI",
252 .xres = 1280,
253 .yres = 720,
254 .left_margin = 220,
255 .right_margin = 110,
256 .hsync_len = 40,
257 .upper_margin = 20,
258 .lower_margin = 5,
259 .vsync_len = 5,
260 .sync = 0, /* hsync and vsync are active low */
261 },
262};
263
234static struct sh_mobile_lcdc_info lcdc_info = { 264static struct sh_mobile_lcdc_info lcdc_info = {
235 .ch[0] = { 265 .ch[0] = {
236 .interface_type = RGB18, 266 .interface_type = RGB18,
237 .chan = LCDC_CHAN_MAINLCD, 267 .chan = LCDC_CHAN_MAINLCD,
238 .bpp = 16, 268 .bpp = 16,
239 .lcd_cfg = {
240 .sync = 0, /* hsync and vsync are active low */
241 },
242 .lcd_size_cfg = { /* 7.0 inch */ 269 .lcd_size_cfg = { /* 7.0 inch */
243 .width = 152, 270 .width = 152,
244 .height = 91, 271 .height = 91,
@@ -1075,33 +1102,18 @@ static int __init arch_setup(void)
1075 if (gpio_get_value(GPIO_PTE6)) { 1102 if (gpio_get_value(GPIO_PTE6)) {
1076 /* DVI */ 1103 /* DVI */
1077 lcdc_info.clock_source = LCDC_CLK_EXTERNAL; 1104 lcdc_info.clock_source = LCDC_CLK_EXTERNAL;
1078 lcdc_info.ch[0].clock_divider = 1, 1105 lcdc_info.ch[0].clock_divider = 1;
1079 lcdc_info.ch[0].lcd_cfg.name = "DVI"; 1106 lcdc_info.ch[0].lcd_cfg = ecovec_dvi_modes;
1080 lcdc_info.ch[0].lcd_cfg.xres = 1280; 1107 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(ecovec_dvi_modes);
1081 lcdc_info.ch[0].lcd_cfg.yres = 720;
1082 lcdc_info.ch[0].lcd_cfg.left_margin = 220;
1083 lcdc_info.ch[0].lcd_cfg.right_margin = 110;
1084 lcdc_info.ch[0].lcd_cfg.hsync_len = 40;
1085 lcdc_info.ch[0].lcd_cfg.upper_margin = 20;
1086 lcdc_info.ch[0].lcd_cfg.lower_margin = 5;
1087 lcdc_info.ch[0].lcd_cfg.vsync_len = 5;
1088 1108
1089 gpio_set_value(GPIO_PTA2, 1); 1109 gpio_set_value(GPIO_PTA2, 1);
1090 gpio_set_value(GPIO_PTU1, 1); 1110 gpio_set_value(GPIO_PTU1, 1);
1091 } else { 1111 } else {
1092 /* Panel */ 1112 /* Panel */
1093
1094 lcdc_info.clock_source = LCDC_CLK_PERIPHERAL; 1113 lcdc_info.clock_source = LCDC_CLK_PERIPHERAL;
1095 lcdc_info.ch[0].clock_divider = 2, 1114 lcdc_info.ch[0].clock_divider = 2;
1096 lcdc_info.ch[0].lcd_cfg.name = "Panel"; 1115 lcdc_info.ch[0].lcd_cfg = ecovec_lcd_modes;
1097 lcdc_info.ch[0].lcd_cfg.xres = 800; 1116 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(ecovec_lcd_modes);
1098 lcdc_info.ch[0].lcd_cfg.yres = 480;
1099 lcdc_info.ch[0].lcd_cfg.left_margin = 220;
1100 lcdc_info.ch[0].lcd_cfg.right_margin = 110;
1101 lcdc_info.ch[0].lcd_cfg.hsync_len = 70;
1102 lcdc_info.ch[0].lcd_cfg.upper_margin = 20;
1103 lcdc_info.ch[0].lcd_cfg.lower_margin = 5;
1104 lcdc_info.ch[0].lcd_cfg.vsync_len = 5;
1105 1117
1106 gpio_set_value(GPIO_PTR1, 1); 1118 gpio_set_value(GPIO_PTR1, 1);
1107 1119
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
index 1742849db648..9b60eaabf8f3 100644
--- a/arch/sh/boards/mach-kfr2r09/setup.c
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -126,6 +126,21 @@ static struct platform_device kfr2r09_sh_keysc_device = {
126 }, 126 },
127}; 127};
128 128
129const static struct fb_videomode kfr2r09_lcdc_modes[] = {
130 {
131 .name = "TX07D34VM0AAA",
132 .xres = 240,
133 .yres = 400,
134 .left_margin = 0,
135 .right_margin = 16,
136 .hsync_len = 8,
137 .upper_margin = 0,
138 .lower_margin = 1,
139 .vsync_len = 1,
140 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
141 },
142};
143
129static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = { 144static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
130 .clock_source = LCDC_CLK_BUS, 145 .clock_source = LCDC_CLK_BUS,
131 .ch[0] = { 146 .ch[0] = {
@@ -134,18 +149,8 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
134 .interface_type = SYS18, 149 .interface_type = SYS18,
135 .clock_divider = 6, 150 .clock_divider = 6,
136 .flags = LCDC_FLAGS_DWPOL, 151 .flags = LCDC_FLAGS_DWPOL,
137 .lcd_cfg = { 152 .lcd_cfg = kfr2r09_lcdc_modes,
138 .name = "TX07D34VM0AAA", 153 .num_cfg = ARRAY_SIZE(kfr2r09_lcdc_modes),
139 .xres = 240,
140 .yres = 400,
141 .left_margin = 0,
142 .right_margin = 16,
143 .hsync_len = 8,
144 .upper_margin = 0,
145 .lower_margin = 1,
146 .vsync_len = 1,
147 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
148 },
149 .lcd_size_cfg = { 154 .lcd_size_cfg = {
150 .width = 35, 155 .width = 35,
151 .height = 58, 156 .height = 58,
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 03af84842559..c8acfec98695 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -213,51 +213,55 @@ static struct platform_device migor_nand_flash_device = {
213 } 213 }
214}; 214};
215 215
216const static struct fb_videomode migor_lcd_modes[] = {
217 {
218#if defined(CONFIG_SH_MIGOR_RTA_WVGA)
219 .name = "LB070WV1",
220 .xres = 800,
221 .yres = 480,
222 .left_margin = 64,
223 .right_margin = 16,
224 .hsync_len = 120,
225 .sync = 0,
226#elif defined(CONFIG_SH_MIGOR_QVGA)
227 .name = "PH240320T",
228 .xres = 320,
229 .yres = 240,
230 .left_margin = 0,
231 .right_margin = 16,
232 .hsync_len = 8,
233 .sync = FB_SYNC_HOR_HIGH_ACT,
234#endif
235 .upper_margin = 1,
236 .lower_margin = 17,
237 .vsync_len = 2,
238 },
239};
240
216static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = { 241static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
217#ifdef CONFIG_SH_MIGOR_RTA_WVGA 242#if defined(CONFIG_SH_MIGOR_RTA_WVGA)
218 .clock_source = LCDC_CLK_BUS, 243 .clock_source = LCDC_CLK_BUS,
219 .ch[0] = { 244 .ch[0] = {
220 .chan = LCDC_CHAN_MAINLCD, 245 .chan = LCDC_CHAN_MAINLCD,
221 .bpp = 16, 246 .bpp = 16,
222 .interface_type = RGB16, 247 .interface_type = RGB16,
223 .clock_divider = 2, 248 .clock_divider = 2,
224 .lcd_cfg = { 249 .lcd_cfg = migor_lcd_modes,
225 .name = "LB070WV1", 250 .num_cfg = ARRAY_SIZE(migor_lcd_modes),
226 .xres = 800,
227 .yres = 480,
228 .left_margin = 64,
229 .right_margin = 16,
230 .hsync_len = 120,
231 .upper_margin = 1,
232 .lower_margin = 17,
233 .vsync_len = 2,
234 .sync = 0,
235 },
236 .lcd_size_cfg = { /* 7.0 inch */ 251 .lcd_size_cfg = { /* 7.0 inch */
237 .width = 152, 252 .width = 152,
238 .height = 91, 253 .height = 91,
239 }, 254 },
240 } 255 }
241#endif 256#elif defined(CONFIG_SH_MIGOR_QVGA)
242#ifdef CONFIG_SH_MIGOR_QVGA
243 .clock_source = LCDC_CLK_PERIPHERAL, 257 .clock_source = LCDC_CLK_PERIPHERAL,
244 .ch[0] = { 258 .ch[0] = {
245 .chan = LCDC_CHAN_MAINLCD, 259 .chan = LCDC_CHAN_MAINLCD,
246 .bpp = 16, 260 .bpp = 16,
247 .interface_type = SYS16A, 261 .interface_type = SYS16A,
248 .clock_divider = 10, 262 .clock_divider = 10,
249 .lcd_cfg = { 263 .lcd_cfg = migor_lcd_modes,
250 .name = "PH240320T", 264 .num_cfg = ARRAY_SIZE(migor_lcd_modes),
251 .xres = 320,
252 .yres = 240,
253 .left_margin = 0,
254 .right_margin = 16,
255 .hsync_len = 8,
256 .upper_margin = 1,
257 .lower_margin = 17,
258 .vsync_len = 2,
259 .sync = FB_SYNC_HOR_HIGH_ACT,
260 },
261 .lcd_size_cfg = { /* 2.4 inch */ 265 .lcd_size_cfg = { /* 2.4 inch */
262 .width = 49, 266 .width = 49,
263 .height = 37, 267 .height = 37,
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 8cc1d7295d85..c31d228fdfc6 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -144,16 +144,42 @@ static struct platform_device nor_flash_device = {
144}; 144};
145 145
146/* LCDC */ 146/* LCDC */
147const static struct fb_videomode lcdc_720p_modes[] = {
148 {
149 .name = "LB070WV1",
150 .sync = 0, /* hsync and vsync are active low */
151 .xres = 1280,
152 .yres = 720,
153 .left_margin = 220,
154 .right_margin = 110,
155 .hsync_len = 40,
156 .upper_margin = 20,
157 .lower_margin = 5,
158 .vsync_len = 5,
159 },
160};
161
162const static struct fb_videomode lcdc_vga_modes[] = {
163 {
164 .name = "LB070WV1",
165 .sync = 0, /* hsync and vsync are active low */
166 .xres = 640,
167 .yres = 480,
168 .left_margin = 105,
169 .right_margin = 50,
170 .hsync_len = 96,
171 .upper_margin = 33,
172 .lower_margin = 10,
173 .vsync_len = 2,
174 },
175};
176
147static struct sh_mobile_lcdc_info lcdc_info = { 177static struct sh_mobile_lcdc_info lcdc_info = {
148 .clock_source = LCDC_CLK_EXTERNAL, 178 .clock_source = LCDC_CLK_EXTERNAL,
149 .ch[0] = { 179 .ch[0] = {
150 .chan = LCDC_CHAN_MAINLCD, 180 .chan = LCDC_CHAN_MAINLCD,
151 .bpp = 16, 181 .bpp = 16,
152 .clock_divider = 1, 182 .clock_divider = 1,
153 .lcd_cfg = {
154 .name = "LB070WV1",
155 .sync = 0, /* hsync and vsync are active low */
156 },
157 .lcd_size_cfg = { /* 7.0 inch */ 183 .lcd_size_cfg = { /* 7.0 inch */
158 .width = 152, 184 .width = 152,
159 .height = 91, 185 .height = 91,
@@ -908,24 +934,12 @@ static int __init devices_setup(void)
908 934
909 if (sw & SW41_B) { 935 if (sw & SW41_B) {
910 /* 720p */ 936 /* 720p */
911 lcdc_info.ch[0].lcd_cfg.xres = 1280; 937 lcdc_info.ch[0].lcd_cfg = lcdc_720p_modes;
912 lcdc_info.ch[0].lcd_cfg.yres = 720; 938 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(lcdc_720p_modes);
913 lcdc_info.ch[0].lcd_cfg.left_margin = 220;
914 lcdc_info.ch[0].lcd_cfg.right_margin = 110;
915 lcdc_info.ch[0].lcd_cfg.hsync_len = 40;
916 lcdc_info.ch[0].lcd_cfg.upper_margin = 20;
917 lcdc_info.ch[0].lcd_cfg.lower_margin = 5;
918 lcdc_info.ch[0].lcd_cfg.vsync_len = 5;
919 } else { 939 } else {
920 /* VGA */ 940 /* VGA */
921 lcdc_info.ch[0].lcd_cfg.xres = 640; 941 lcdc_info.ch[0].lcd_cfg = lcdc_vga_modes;
922 lcdc_info.ch[0].lcd_cfg.yres = 480; 942 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(lcdc_vga_modes);
923 lcdc_info.ch[0].lcd_cfg.left_margin = 105;
924 lcdc_info.ch[0].lcd_cfg.right_margin = 50;
925 lcdc_info.ch[0].lcd_cfg.hsync_len = 96;
926 lcdc_info.ch[0].lcd_cfg.upper_margin = 33;
927 lcdc_info.ch[0].lcd_cfg.lower_margin = 10;
928 lcdc_info.ch[0].lcd_cfg.vsync_len = 2;
929 } 943 }
930 944
931 if (sw & SW41_A) { 945 if (sw & SW41_A) {
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 9e2b7e9e0ad9..ad9268b44416 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -1496,7 +1496,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
1496 1496
1497 switch (mode) { 1497 switch (mode) {
1498 case FL_WRITING: 1498 case FL_WRITING:
1499 write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41); 1499 write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0x40) : CMD(0x41);
1500 break; 1500 break;
1501 case FL_OTP_WRITE: 1501 case FL_OTP_WRITE:
1502 write_cmd = CMD(0xc0); 1502 write_cmd = CMD(0xc0);
@@ -1661,7 +1661,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
1661 cmd_adr = adr & ~(wbufsize-1); 1661 cmd_adr = adr & ~(wbufsize-1);
1662 1662
1663 /* Let's determine this according to the interleave only once */ 1663 /* Let's determine this according to the interleave only once */
1664 write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9); 1664 write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0xe8) : CMD(0xe9);
1665 1665
1666 mutex_lock(&chip->mutex); 1666 mutex_lock(&chip->mutex);
1667 ret = get_chip(map, chip, cmd_adr, FL_WRITING); 1667 ret = get_chip(map, chip, cmd_adr, FL_WRITING);
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index ba29d2f0ffd7..3b8e32d87977 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -291,6 +291,23 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
291 291
292 cfi->addr_unlock1 = 0x555; 292 cfi->addr_unlock1 = 0x555;
293 cfi->addr_unlock2 = 0x2AA; 293 cfi->addr_unlock2 = 0x2AA;
294
295 cfi->sector_erase_cmd = CMD(0x50);
296}
297
298static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
299{
300 struct map_info *map = mtd->priv;
301 struct cfi_private *cfi = map->fldrv_priv;
302
303 fixup_sst39vf_rev_b(mtd, param);
304
305 /*
306 * CFI reports 1024 sectors (0x03ff+1) of 64KBytes (0x0100*256) where
307 * it should report a size of 8KBytes (0x0020*256).
308 */
309 cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
310 pr_warning("%s: Bad 38VF640x CFI data; adjusting sector size from 64 to 8KiB\n", mtd->name);
294} 311}
295 312
296static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param) 313static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
@@ -317,14 +334,14 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param)
317 334
318/* Used to fix CFI-Tables of chips without Extended Query Tables */ 335/* Used to fix CFI-Tables of chips without Extended Query Tables */
319static struct cfi_fixup cfi_nopri_fixup_table[] = { 336static struct cfi_fixup cfi_nopri_fixup_table[] = {
320 { CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, // SST39VF1602 337 { CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, /* SST39VF1602 */
321 { CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, // SST39VF1601 338 { CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, /* SST39VF1601 */
322 { CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, // SST39VF3202 339 { CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, /* SST39VF3202 */
323 { CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, // SST39VF3201 340 { CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, /* SST39VF3201 */
324 { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, // SST39VF3202B 341 { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3202B */
325 { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, // SST39VF3201B 342 { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3201B */
326 { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, // SST39VF6402B 343 { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6402B */
327 { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B 344 { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6401B */
328 { 0, 0, NULL, NULL } 345 { 0, 0, NULL, NULL }
329}; 346};
330 347
@@ -344,6 +361,10 @@ static struct cfi_fixup cfi_fixup_table[] = {
344 { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, }, 361 { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
345 { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, }, 362 { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
346 { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, }, 363 { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
364 { CFI_MFR_SST, 0x536A, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6402 */
365 { CFI_MFR_SST, 0x536B, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6401 */
366 { CFI_MFR_SST, 0x536C, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6404 */
367 { CFI_MFR_SST, 0x536D, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6403 */
347#if !FORCE_WORD_WRITE 368#if !FORCE_WORD_WRITE
348 { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, 369 { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
349#endif 370#endif
@@ -374,6 +395,13 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi,
374 if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e && 395 if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e &&
375 extp->MajorVersion == '0') 396 extp->MajorVersion == '0')
376 extp->MajorVersion = '1'; 397 extp->MajorVersion = '1';
398 /*
399 * SST 38VF640x chips report major=0xFF / minor=0xFF.
400 */
401 if (cfi->mfr == CFI_MFR_SST && (cfi->id >> 4) == 0x0536) {
402 extp->MajorVersion = '1';
403 extp->MinorVersion = '0';
404 }
377} 405}
378 406
379struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) 407struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
@@ -545,15 +573,6 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
545 printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); 573 printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
546 goto setup_err; 574 goto setup_err;
547 } 575 }
548#if 0
549 // debug
550 for (i=0; i<mtd->numeraseregions;i++){
551 printk("%d: offset=0x%x,size=0x%x,blocks=%d\n",
552 i,mtd->eraseregions[i].offset,
553 mtd->eraseregions[i].erasesize,
554 mtd->eraseregions[i].numblocks);
555 }
556#endif
557 576
558 __module_get(THIS_MODULE); 577 __module_get(THIS_MODULE);
559 register_reboot_notifier(&mtd->reboot_notifier); 578 register_reboot_notifier(&mtd->reboot_notifier);
@@ -674,7 +693,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
674 * there was an error (so leave the erase 693 * there was an error (so leave the erase
675 * routine to recover from it) or we trying to 694 * routine to recover from it) or we trying to
676 * use the erase-in-progress sector. */ 695 * use the erase-in-progress sector. */
677 map_write(map, CMD(0x30), chip->in_progress_block_addr); 696 map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr);
678 chip->state = FL_ERASING; 697 chip->state = FL_ERASING;
679 chip->oldstate = FL_READY; 698 chip->oldstate = FL_READY;
680 printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); 699 printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
@@ -727,7 +746,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
727 switch(chip->oldstate) { 746 switch(chip->oldstate) {
728 case FL_ERASING: 747 case FL_ERASING:
729 chip->state = chip->oldstate; 748 chip->state = chip->oldstate;
730 map_write(map, CMD(0x30), chip->in_progress_block_addr); 749 map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr);
731 chip->oldstate = FL_READY; 750 chip->oldstate = FL_READY;
732 chip->state = FL_ERASING; 751 chip->state = FL_ERASING;
733 break; 752 break;
@@ -870,7 +889,7 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
870 local_irq_disable(); 889 local_irq_disable();
871 890
872 /* Resume the write or erase operation */ 891 /* Resume the write or erase operation */
873 map_write(map, CMD(0x30), adr); 892 map_write(map, cfi->sector_erase_cmd, adr);
874 chip->state = oldstate; 893 chip->state = oldstate;
875 start = xip_currtime(); 894 start = xip_currtime();
876 } else if (usec >= 1000000/HZ) { 895 } else if (usec >= 1000000/HZ) {
@@ -1025,9 +1044,6 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi
1025 mutex_lock(&chip->mutex); 1044 mutex_lock(&chip->mutex);
1026 1045
1027 if (chip->state != FL_READY){ 1046 if (chip->state != FL_READY){
1028#if 0
1029 printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state);
1030#endif
1031 set_current_state(TASK_UNINTERRUPTIBLE); 1047 set_current_state(TASK_UNINTERRUPTIBLE);
1032 add_wait_queue(&chip->wq, &wait); 1048 add_wait_queue(&chip->wq, &wait);
1033 1049
@@ -1035,10 +1051,6 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi
1035 1051
1036 schedule(); 1052 schedule();
1037 remove_wait_queue(&chip->wq, &wait); 1053 remove_wait_queue(&chip->wq, &wait);
1038#if 0
1039 if(signal_pending(current))
1040 return -EINTR;
1041#endif
1042 timeo = jiffies + HZ; 1054 timeo = jiffies + HZ;
1043 1055
1044 goto retry; 1056 goto retry;
@@ -1246,9 +1258,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
1246 mutex_lock(&cfi->chips[chipnum].mutex); 1258 mutex_lock(&cfi->chips[chipnum].mutex);
1247 1259
1248 if (cfi->chips[chipnum].state != FL_READY) { 1260 if (cfi->chips[chipnum].state != FL_READY) {
1249#if 0
1250 printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);
1251#endif
1252 set_current_state(TASK_UNINTERRUPTIBLE); 1261 set_current_state(TASK_UNINTERRUPTIBLE);
1253 add_wait_queue(&cfi->chips[chipnum].wq, &wait); 1262 add_wait_queue(&cfi->chips[chipnum].wq, &wait);
1254 1263
@@ -1256,10 +1265,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
1256 1265
1257 schedule(); 1266 schedule();
1258 remove_wait_queue(&cfi->chips[chipnum].wq, &wait); 1267 remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
1259#if 0
1260 if(signal_pending(current))
1261 return -EINTR;
1262#endif
1263 goto retry; 1268 goto retry;
1264 } 1269 }
1265 1270
@@ -1324,9 +1329,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
1324 mutex_lock(&cfi->chips[chipnum].mutex); 1329 mutex_lock(&cfi->chips[chipnum].mutex);
1325 1330
1326 if (cfi->chips[chipnum].state != FL_READY) { 1331 if (cfi->chips[chipnum].state != FL_READY) {
1327#if 0
1328 printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);
1329#endif
1330 set_current_state(TASK_UNINTERRUPTIBLE); 1332 set_current_state(TASK_UNINTERRUPTIBLE);
1331 add_wait_queue(&cfi->chips[chipnum].wq, &wait); 1333 add_wait_queue(&cfi->chips[chipnum].wq, &wait);
1332 1334
@@ -1334,10 +1336,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
1334 1336
1335 schedule(); 1337 schedule();
1336 remove_wait_queue(&cfi->chips[chipnum].wq, &wait); 1338 remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
1337#if 0
1338 if(signal_pending(current))
1339 return -EINTR;
1340#endif
1341 goto retry1; 1339 goto retry1;
1342 } 1340 }
1343 1341
@@ -1396,7 +1394,6 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
1396 1394
1397 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); 1395 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1398 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); 1396 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
1399 //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1400 1397
1401 /* Write Buffer Load */ 1398 /* Write Buffer Load */
1402 map_write(map, CMD(0x25), cmd_adr); 1399 map_write(map, CMD(0x25), cmd_adr);
@@ -1675,7 +1672,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
1675 cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); 1672 cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1676 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); 1673 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1677 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); 1674 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
1678 map_write(map, CMD(0x30), adr); 1675 map_write(map, cfi->sector_erase_cmd, adr);
1679 1676
1680 chip->state = FL_ERASING; 1677 chip->state = FL_ERASING;
1681 chip->erase_suspended = 0; 1678 chip->erase_suspended = 0;
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
index 8f5b96aa87a0..d25535279404 100644
--- a/drivers/mtd/chips/cfi_probe.c
+++ b/drivers/mtd/chips/cfi_probe.c
@@ -177,6 +177,8 @@ static int __xipram cfi_chip_setup(struct map_info *map,
177 177
178 cfi->cfi_mode = CFI_MODE_CFI; 178 cfi->cfi_mode = CFI_MODE_CFI;
179 179
180 cfi->sector_erase_cmd = CMD(0x30);
181
180 /* Read the CFI info structure */ 182 /* Read the CFI info structure */
181 xip_disable_qry(base, map, cfi); 183 xip_disable_qry(base, map, cfi);
182 for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) 184 for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++)
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
index e503b2ca894d..360525c637d2 100644
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
@@ -77,6 +77,13 @@ int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
77 cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); 77 cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
78 if (cfi_qry_present(map, base, cfi)) 78 if (cfi_qry_present(map, base, cfi))
79 return 1; 79 return 1;
80 /* SST 39VF640xB */
81 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
82 cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL);
83 cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL);
84 cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
85 if (cfi_qry_present(map, base, cfi))
86 return 1;
80 /* QRY not found */ 87 /* QRY not found */
81 return 0; 88 return 0;
82} 89}
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 93651865ddbe..2cf0cc6a4189 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -91,7 +91,6 @@ static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
91 } else 91 } else
92 instr->state = MTD_ERASE_DONE; 92 instr->state = MTD_ERASE_DONE;
93 93
94 instr->state = MTD_ERASE_DONE;
95 mtd_erase_callback(instr); 94 mtd_erase_callback(instr);
96 return err; 95 return err;
97} 96}
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index ea22520c0406..bf5a002209bd 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -661,11 +661,14 @@ static const struct spi_device_id m25p_ids[] = {
661 { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, 661 { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) },
662 { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, 662 { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) },
663 { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, 663 { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) },
664 { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SECT_4K) },
664 { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, 665 { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) },
665 { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, 666 { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
666 { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, 667 { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
667 { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, 668 { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) },
668 { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, 669 { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) },
670 { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) },
671 { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
669 672
670 /* SST -- large erase sizes are "overlays", "sectors" are 4K */ 673 /* SST -- large erase sizes are "overlays", "sectors" are 4K */
671 { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K) }, 674 { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K) },
@@ -714,6 +717,7 @@ static const struct spi_device_id m25p_ids[] = {
714 { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, 717 { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
715 { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, 718 { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) },
716 { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, 719 { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
720 { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
717 721
718 /* Catalyst / On Semiconductor -- non-JEDEC */ 722 /* Catalyst / On Semiconductor -- non-JEDEC */
719 { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, 723 { "cat25c11", CAT25_INFO( 16, 8, 16, 1) },
@@ -924,7 +928,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
924 nr_parts = data->nr_parts; 928 nr_parts = data->nr_parts;
925 } 929 }
926 930
927#ifdef CONFIG_OF 931#ifdef CONFIG_MTD_OF_PARTS
928 if (nr_parts <= 0 && spi->dev.of_node) { 932 if (nr_parts <= 0 && spi->dev.of_node) {
929 nr_parts = of_mtd_parse_partitions(&spi->dev, 933 nr_parts = of_mtd_parse_partitions(&spi->dev,
930 spi->dev.of_node, &parts); 934 spi->dev.of_node, &parts);
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index 1696bbecaa7e..52393282eaf1 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -15,7 +15,7 @@
15 * phram=swap,64Mi,128Mi phram=test,900Mi,1Mi 15 * phram=swap,64Mi,128Mi phram=test,900Mi,1Mi
16 */ 16 */
17 17
18#define pr_fmt(fmt) "phram: " fmt 18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19 19
20#include <asm/io.h> 20#include <asm/io.h>
21#include <linux/init.h> 21#include <linux/init.h>
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 962212628f6e..a0dd7bba9481 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -251,6 +251,15 @@ config MTD_NETtel
251 help 251 help
252 Support for flash chips on NETtel/SecureEdge/SnapGear boards. 252 Support for flash chips on NETtel/SecureEdge/SnapGear boards.
253 253
254config MTD_BCM963XX
255 tristate "Map driver for Broadcom BCM963xx boards"
256 depends on BCM63XX
257 select MTD_MAP_BANK_WIDTH_2
258 select MTD_CFI_I1
259 help
260 Support for parsing CFE image tag and creating MTD partitions on
261 Broadcom BCM63xx boards.
262
254config MTD_DILNETPC 263config MTD_DILNETPC
255 tristate "CFI Flash device mapped on DIL/Net PC" 264 tristate "CFI Flash device mapped on DIL/Net PC"
256 depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN 265 depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index f216bb573713..c7869c7a6b18 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -58,3 +58,4 @@ obj-$(CONFIG_MTD_BFIN_ASYNC) += bfin-async-flash.o
58obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o 58obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o
59obj-$(CONFIG_MTD_VMU) += vmu-flash.o 59obj-$(CONFIG_MTD_VMU) += vmu-flash.o
60obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o 60obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o
61obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o
diff --git a/drivers/mtd/maps/bcm963xx-flash.c b/drivers/mtd/maps/bcm963xx-flash.c
new file mode 100644
index 000000000000..d175c120ee84
--- /dev/null
+++ b/drivers/mtd/maps/bcm963xx-flash.c
@@ -0,0 +1,271 @@
1/*
2 * Copyright © 2006-2008 Florian Fainelli <florian@openwrt.org>
3 * Mike Albon <malbon@openwrt.org>
4 * Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <linux/init.h>
22#include <linux/kernel.h>
23#include <linux/slab.h>
24#include <linux/mtd/map.h>
25#include <linux/mtd/mtd.h>
26#include <linux/mtd/partitions.h>
27#include <linux/vmalloc.h>
28#include <linux/platform_device.h>
29#include <linux/io.h>
30
31#include <asm/mach-bcm63xx/bcm963xx_tag.h>
32
33#define BCM63XX_BUSWIDTH 2 /* Buswidth */
34#define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */
35
36#define PFX KBUILD_MODNAME ": "
37
38static struct mtd_partition *parsed_parts;
39
40static struct mtd_info *bcm963xx_mtd_info;
41
42static struct map_info bcm963xx_map = {
43 .name = "bcm963xx",
44 .bankwidth = BCM63XX_BUSWIDTH,
45};
46
47static int parse_cfe_partitions(struct mtd_info *master,
48 struct mtd_partition **pparts)
49{
50 /* CFE, NVRAM and global Linux are always present */
51 int nrparts = 3, curpart = 0;
52 struct bcm_tag *buf;
53 struct mtd_partition *parts;
54 int ret;
55 size_t retlen;
56 unsigned int rootfsaddr, kerneladdr, spareaddr;
57 unsigned int rootfslen, kernellen, sparelen, totallen;
58 int namelen = 0;
59 int i;
60 char *boardid;
61 char *tagversion;
62
63 /* Allocate memory for buffer */
64 buf = vmalloc(sizeof(struct bcm_tag));
65 if (!buf)
66 return -ENOMEM;
67
68 /* Get the tag */
69 ret = master->read(master, master->erasesize, sizeof(struct bcm_tag),
70 &retlen, (void *)buf);
71 if (retlen != sizeof(struct bcm_tag)) {
72 vfree(buf);
73 return -EIO;
74 }
75
76 sscanf(buf->kernel_address, "%u", &kerneladdr);
77 sscanf(buf->kernel_length, "%u", &kernellen);
78 sscanf(buf->total_length, "%u", &totallen);
79 tagversion = &(buf->tag_version[0]);
80 boardid = &(buf->board_id[0]);
81
82 printk(KERN_INFO PFX "CFE boot tag found with version %s "
83 "and board type %s\n", tagversion, boardid);
84
85 kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE;
86 rootfsaddr = kerneladdr + kernellen;
87 spareaddr = roundup(totallen, master->erasesize) + master->erasesize;
88 sparelen = master->size - spareaddr - master->erasesize;
89 rootfslen = spareaddr - rootfsaddr;
90
91 /* Determine number of partitions */
92 namelen = 8;
93 if (rootfslen > 0) {
94 nrparts++;
95 namelen += 6;
96 };
97 if (kernellen > 0) {
98 nrparts++;
99 namelen += 6;
100 };
101
102 /* Ask kernel for more memory */
103 parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
104 if (!parts) {
105 vfree(buf);
106 return -ENOMEM;
107 };
108
109 /* Start building partition list */
110 parts[curpart].name = "CFE";
111 parts[curpart].offset = 0;
112 parts[curpart].size = master->erasesize;
113 curpart++;
114
115 if (kernellen > 0) {
116 parts[curpart].name = "kernel";
117 parts[curpart].offset = kerneladdr;
118 parts[curpart].size = kernellen;
119 curpart++;
120 };
121
122 if (rootfslen > 0) {
123 parts[curpart].name = "rootfs";
124 parts[curpart].offset = rootfsaddr;
125 parts[curpart].size = rootfslen;
126 if (sparelen > 0)
127 parts[curpart].size += sparelen;
128 curpart++;
129 };
130
131 parts[curpart].name = "nvram";
132 parts[curpart].offset = master->size - master->erasesize;
133 parts[curpart].size = master->erasesize;
134
135 /* Global partition "linux" to make easy firmware upgrade */
136 curpart++;
137 parts[curpart].name = "linux";
138 parts[curpart].offset = parts[0].size;
139 parts[curpart].size = master->size - parts[0].size - parts[3].size;
140
141 for (i = 0; i < nrparts; i++)
142 printk(KERN_INFO PFX "Partition %d is %s offset %lx and "
143 "length %lx\n", i, parts[i].name,
144 (long unsigned int)(parts[i].offset),
145 (long unsigned int)(parts[i].size));
146
147 printk(KERN_INFO PFX "Spare partition is %x offset and length %x\n",
148 spareaddr, sparelen);
149 *pparts = parts;
150 vfree(buf);
151
152 return nrparts;
153};
154
155static int bcm963xx_detect_cfe(struct mtd_info *master)
156{
157 int idoffset = 0x4e0;
158 static char idstring[8] = "CFE1CFE1";
159 char buf[9];
160 int ret;
161 size_t retlen;
162
163 ret = master->read(master, idoffset, 8, &retlen, (void *)buf);
164 buf[retlen] = 0;
165 printk(KERN_INFO PFX "Read Signature value of %s\n", buf);
166
167 return strncmp(idstring, buf, 8);
168}
169
170static int bcm963xx_probe(struct platform_device *pdev)
171{
172 int err = 0;
173 int parsed_nr_parts = 0;
174 char *part_type;
175 struct resource *r;
176
177 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
178 if (!r) {
179 dev_err(&pdev->dev, "no resource supplied\n");
180 return -ENODEV;
181 }
182
183 bcm963xx_map.phys = r->start;
184 bcm963xx_map.size = resource_size(r);
185 bcm963xx_map.virt = ioremap(r->start, resource_size(r));
186 if (!bcm963xx_map.virt) {
187 dev_err(&pdev->dev, "failed to ioremap\n");
188 return -EIO;
189 }
190
191 dev_info(&pdev->dev, "0x%08lx at 0x%08x\n",
192 bcm963xx_map.size, bcm963xx_map.phys);
193
194 simple_map_init(&bcm963xx_map);
195
196 bcm963xx_mtd_info = do_map_probe("cfi_probe", &bcm963xx_map);
197 if (!bcm963xx_mtd_info) {
198 dev_err(&pdev->dev, "failed to probe using CFI\n");
199 err = -EIO;
200 goto err_probe;
201 }
202
203 bcm963xx_mtd_info->owner = THIS_MODULE;
204
205 /* This is mutually exclusive */
206 if (bcm963xx_detect_cfe(bcm963xx_mtd_info) == 0) {
207 dev_info(&pdev->dev, "CFE bootloader detected\n");
208 if (parsed_nr_parts == 0) {
209 int ret = parse_cfe_partitions(bcm963xx_mtd_info,
210 &parsed_parts);
211 if (ret > 0) {
212 part_type = "CFE";
213 parsed_nr_parts = ret;
214 }
215 }
216 } else {
217 dev_info(&pdev->dev, "unsupported bootloader\n");
218 err = -ENODEV;
219 goto err_probe;
220 }
221
222 return add_mtd_partitions(bcm963xx_mtd_info, parsed_parts,
223 parsed_nr_parts);
224
225err_probe:
226 iounmap(bcm963xx_map.virt);
227 return err;
228}
229
230static int bcm963xx_remove(struct platform_device *pdev)
231{
232 if (bcm963xx_mtd_info) {
233 del_mtd_partitions(bcm963xx_mtd_info);
234 map_destroy(bcm963xx_mtd_info);
235 }
236
237 if (bcm963xx_map.virt) {
238 iounmap(bcm963xx_map.virt);
239 bcm963xx_map.virt = 0;
240 }
241
242 return 0;
243}
244
245static struct platform_driver bcm63xx_mtd_dev = {
246 .probe = bcm963xx_probe,
247 .remove = bcm963xx_remove,
248 .driver = {
249 .name = "bcm963xx-flash",
250 .owner = THIS_MODULE,
251 },
252};
253
254static int __init bcm963xx_mtd_init(void)
255{
256 return platform_driver_register(&bcm63xx_mtd_dev);
257}
258
259static void __exit bcm963xx_mtd_exit(void)
260{
261 platform_driver_unregister(&bcm63xx_mtd_dev);
262}
263
264module_init(bcm963xx_mtd_init);
265module_exit(bcm963xx_mtd_exit);
266
267MODULE_LICENSE("GPL");
268MODULE_DESCRIPTION("Broadcom BCM63xx MTD driver for CFE and RedBoot");
269MODULE_AUTHOR("Daniel Dickinson <openwrt@cshore.neomailbox.net>");
270MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
271MODULE_AUTHOR("Mike Albon <malbon@openwrt.org>");
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index 32e89d773b4e..af5707a80205 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -208,10 +208,14 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev)
208 if (!state) 208 if (!state)
209 return -ENOMEM; 209 return -ENOMEM;
210 210
211 /*
212 * We cast start/end to known types in the boards file, so cast
213 * away their pointer types here to the known types (gpios->xxx).
214 */
211 state->gpio_count = gpios->end; 215 state->gpio_count = gpios->end;
212 state->gpio_addrs = (void *)gpios->start; 216 state->gpio_addrs = (void *)(unsigned long)gpios->start;
213 state->gpio_values = (void *)(state + 1); 217 state->gpio_values = (void *)(state + 1);
214 state->win_size = memory->end - memory->start + 1; 218 state->win_size = resource_size(memory);
215 memset(state->gpio_values, 0xff, arr_size); 219 memset(state->gpio_values, 0xff, arr_size);
216 220
217 state->map.name = DRIVER_NAME; 221 state->map.name = DRIVER_NAME;
@@ -221,7 +225,7 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev)
221 state->map.copy_to = gf_copy_to; 225 state->map.copy_to = gf_copy_to;
222 state->map.bankwidth = pdata->width; 226 state->map.bankwidth = pdata->width;
223 state->map.size = state->win_size * (1 << state->gpio_count); 227 state->map.size = state->win_size * (1 << state->gpio_count);
224 state->map.virt = (void __iomem *)memory->start; 228 state->map.virt = ioremap_nocache(memory->start, state->map.size);
225 state->map.phys = NO_XIP; 229 state->map.phys = NO_XIP;
226 state->map.map_priv_1 = (unsigned long)state; 230 state->map.map_priv_1 = (unsigned long)state;
227 231
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 57a1acfe22c4..917022948399 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -640,10 +640,6 @@ static int pcmciamtd_config(struct pcmcia_device *link)
640 } 640 }
641 dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name); 641 dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name);
642 return 0; 642 return 0;
643
644 dev_err(&dev->p_dev->dev, "CS Error, exiting\n");
645 pcmciamtd_release(link);
646 return -ENODEV;
647} 643}
648 644
649 645
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index ec3edf6e68b4..9861814aa027 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -50,7 +50,7 @@ static int parse_obsolete_partitions(struct platform_device *dev,
50{ 50{
51 int i, plen, nr_parts; 51 int i, plen, nr_parts;
52 const struct { 52 const struct {
53 u32 offset, len; 53 __be32 offset, len;
54 } *part; 54 } *part;
55 const char *names; 55 const char *names;
56 56
@@ -69,9 +69,9 @@ static int parse_obsolete_partitions(struct platform_device *dev,
69 names = of_get_property(dp, "partition-names", &plen); 69 names = of_get_property(dp, "partition-names", &plen);
70 70
71 for (i = 0; i < nr_parts; i++) { 71 for (i = 0; i < nr_parts; i++) {
72 info->parts[i].offset = part->offset; 72 info->parts[i].offset = be32_to_cpu(part->offset);
73 info->parts[i].size = part->len & ~1; 73 info->parts[i].size = be32_to_cpu(part->len) & ~1;
74 if (part->len & 1) /* bit 0 set signifies read only partition */ 74 if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */
75 info->parts[i].mask_flags = MTD_WRITEABLE; 75 info->parts[i].mask_flags = MTD_WRITEABLE;
76 76
77 if (names && (plen > 0)) { 77 if (names && (plen > 0)) {
@@ -226,11 +226,11 @@ static int __devinit of_flash_probe(struct platform_device *dev,
226 struct resource res; 226 struct resource res;
227 struct of_flash *info; 227 struct of_flash *info;
228 const char *probe_type = match->data; 228 const char *probe_type = match->data;
229 const u32 *width; 229 const __be32 *width;
230 int err; 230 int err;
231 int i; 231 int i;
232 int count; 232 int count;
233 const u32 *p; 233 const __be32 *p;
234 int reg_tuple_size; 234 int reg_tuple_size;
235 struct mtd_info **mtd_list = NULL; 235 struct mtd_info **mtd_list = NULL;
236 resource_size_t res_size; 236 resource_size_t res_size;
@@ -267,9 +267,11 @@ static int __devinit of_flash_probe(struct platform_device *dev,
267 for (i = 0; i < count; i++) { 267 for (i = 0; i < count; i++) {
268 err = -ENXIO; 268 err = -ENXIO;
269 if (of_address_to_resource(dp, i, &res)) { 269 if (of_address_to_resource(dp, i, &res)) {
270 dev_err(&dev->dev, "Can't get IO address from device" 270 /*
271 " tree\n"); 271 * Continue with next register tuple if this
272 goto err_out; 272 * one is not mappable
273 */
274 continue;
273 } 275 }
274 276
275 dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n", 277 dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 50ab431b24eb..cb20c67995d8 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -37,7 +37,6 @@
37 37
38#include "mtdcore.h" 38#include "mtdcore.h"
39 39
40static DEFINE_MUTEX(mtd_blkdevs_mutex);
41static LIST_HEAD(blktrans_majors); 40static LIST_HEAD(blktrans_majors);
42static DEFINE_MUTEX(blktrans_ref_mutex); 41static DEFINE_MUTEX(blktrans_ref_mutex);
43 42
@@ -133,6 +132,10 @@ static int mtd_blktrans_thread(void *arg)
133 132
134 if (!req && !(req = blk_fetch_request(rq))) { 133 if (!req && !(req = blk_fetch_request(rq))) {
135 set_current_state(TASK_INTERRUPTIBLE); 134 set_current_state(TASK_INTERRUPTIBLE);
135
136 if (kthread_should_stop())
137 set_current_state(TASK_RUNNING);
138
136 spin_unlock_irq(rq->queue_lock); 139 spin_unlock_irq(rq->queue_lock);
137 schedule(); 140 schedule();
138 spin_lock_irq(rq->queue_lock); 141 spin_lock_irq(rq->queue_lock);
@@ -176,54 +179,53 @@ static void mtd_blktrans_request(struct request_queue *rq)
176static int blktrans_open(struct block_device *bdev, fmode_t mode) 179static int blktrans_open(struct block_device *bdev, fmode_t mode)
177{ 180{
178 struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); 181 struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk);
179 int ret; 182 int ret = 0;
180 183
181 if (!dev) 184 if (!dev)
182 return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ 185 return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/
183 186
184 mutex_lock(&mtd_blkdevs_mutex);
185 mutex_lock(&dev->lock); 187 mutex_lock(&dev->lock);
186 188
187 if (!dev->mtd) { 189 if (dev->open++)
188 ret = -ENXIO;
189 goto unlock; 190 goto unlock;
190 }
191 191
192 ret = !dev->open++ && dev->tr->open ? dev->tr->open(dev) : 0; 192 kref_get(&dev->ref);
193 __module_get(dev->tr->owner);
194
195 if (dev->mtd) {
196 ret = dev->tr->open ? dev->tr->open(dev) : 0;
197 __get_mtd_device(dev->mtd);
198 }
193 199
194 /* Take another reference on the device so it won't go away till
195 last release */
196 if (!ret)
197 kref_get(&dev->ref);
198unlock: 200unlock:
199 mutex_unlock(&dev->lock); 201 mutex_unlock(&dev->lock);
200 blktrans_dev_put(dev); 202 blktrans_dev_put(dev);
201 mutex_unlock(&mtd_blkdevs_mutex);
202 return ret; 203 return ret;
203} 204}
204 205
205static int blktrans_release(struct gendisk *disk, fmode_t mode) 206static int blktrans_release(struct gendisk *disk, fmode_t mode)
206{ 207{
207 struct mtd_blktrans_dev *dev = blktrans_dev_get(disk); 208 struct mtd_blktrans_dev *dev = blktrans_dev_get(disk);
208 int ret = -ENXIO; 209 int ret = 0;
209 210
210 if (!dev) 211 if (!dev)
211 return ret; 212 return ret;
212 213
213 mutex_lock(&mtd_blkdevs_mutex);
214 mutex_lock(&dev->lock); 214 mutex_lock(&dev->lock);
215 215
216 /* Release one reference, we sure its not the last one here*/ 216 if (--dev->open)
217 kref_put(&dev->ref, blktrans_dev_release);
218
219 if (!dev->mtd)
220 goto unlock; 217 goto unlock;
221 218
222 ret = !--dev->open && dev->tr->release ? dev->tr->release(dev) : 0; 219 kref_put(&dev->ref, blktrans_dev_release);
220 module_put(dev->tr->owner);
221
222 if (dev->mtd) {
223 ret = dev->tr->release ? dev->tr->release(dev) : 0;
224 __put_mtd_device(dev->mtd);
225 }
223unlock: 226unlock:
224 mutex_unlock(&dev->lock); 227 mutex_unlock(&dev->lock);
225 blktrans_dev_put(dev); 228 blktrans_dev_put(dev);
226 mutex_unlock(&mtd_blkdevs_mutex);
227 return ret; 229 return ret;
228} 230}
229 231
@@ -256,7 +258,6 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode,
256 if (!dev) 258 if (!dev)
257 return ret; 259 return ret;
258 260
259 mutex_lock(&mtd_blkdevs_mutex);
260 mutex_lock(&dev->lock); 261 mutex_lock(&dev->lock);
261 262
262 if (!dev->mtd) 263 if (!dev->mtd)
@@ -271,7 +272,6 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode,
271 } 272 }
272unlock: 273unlock:
273 mutex_unlock(&dev->lock); 274 mutex_unlock(&dev->lock);
274 mutex_unlock(&mtd_blkdevs_mutex);
275 blktrans_dev_put(dev); 275 blktrans_dev_put(dev);
276 return ret; 276 return ret;
277} 277}
@@ -385,9 +385,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
385 385
386 gd->queue = new->rq; 386 gd->queue = new->rq;
387 387
388 __get_mtd_device(new->mtd);
389 __module_get(tr->owner);
390
391 /* Create processing thread */ 388 /* Create processing thread */
392 /* TODO: workqueue ? */ 389 /* TODO: workqueue ? */
393 new->thread = kthread_run(mtd_blktrans_thread, new, 390 new->thread = kthread_run(mtd_blktrans_thread, new,
@@ -410,8 +407,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
410 } 407 }
411 return 0; 408 return 0;
412error4: 409error4:
413 module_put(tr->owner);
414 __put_mtd_device(new->mtd);
415 blk_cleanup_queue(new->rq); 410 blk_cleanup_queue(new->rq);
416error3: 411error3:
417 put_disk(new->disk); 412 put_disk(new->disk);
@@ -448,17 +443,15 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
448 blk_start_queue(old->rq); 443 blk_start_queue(old->rq);
449 spin_unlock_irqrestore(&old->queue_lock, flags); 444 spin_unlock_irqrestore(&old->queue_lock, flags);
450 445
451 /* Ask trans driver for release to the mtd device */ 446 /* If the device is currently open, tell trans driver to close it,
447 then put mtd device, and don't touch it again */
452 mutex_lock(&old->lock); 448 mutex_lock(&old->lock);
453 if (old->open && old->tr->release) { 449 if (old->open) {
454 old->tr->release(old); 450 if (old->tr->release)
455 old->open = 0; 451 old->tr->release(old);
452 __put_mtd_device(old->mtd);
456 } 453 }
457 454
458 __put_mtd_device(old->mtd);
459 module_put(old->tr->owner);
460
461 /* At that point, we don't touch the mtd anymore */
462 old->mtd = NULL; 455 old->mtd = NULL;
463 456
464 mutex_unlock(&old->lock); 457 mutex_unlock(&old->lock);
@@ -508,13 +501,16 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
508 mutex_lock(&mtd_table_mutex); 501 mutex_lock(&mtd_table_mutex);
509 502
510 ret = register_blkdev(tr->major, tr->name); 503 ret = register_blkdev(tr->major, tr->name);
511 if (ret) { 504 if (ret < 0) {
512 printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", 505 printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n",
513 tr->name, tr->major, ret); 506 tr->name, tr->major, ret);
514 mutex_unlock(&mtd_table_mutex); 507 mutex_unlock(&mtd_table_mutex);
515 return ret; 508 return ret;
516 } 509 }
517 510
511 if (ret)
512 tr->major = ret;
513
518 tr->blkshift = ffs(tr->blksize) - 1; 514 tr->blkshift = ffs(tr->blksize) - 1;
519 515
520 INIT_LIST_HEAD(&tr->devs); 516 INIT_LIST_HEAD(&tr->devs);
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index a34a0fe14884..4759d827e8c7 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -30,8 +30,9 @@
30#include <linux/backing-dev.h> 30#include <linux/backing-dev.h>
31#include <linux/compat.h> 31#include <linux/compat.h>
32#include <linux/mount.h> 32#include <linux/mount.h>
33 33#include <linux/blkpg.h>
34#include <linux/mtd/mtd.h> 34#include <linux/mtd/mtd.h>
35#include <linux/mtd/partitions.h>
35#include <linux/mtd/map.h> 36#include <linux/mtd/map.h>
36 37
37#include <asm/uaccess.h> 38#include <asm/uaccess.h>
@@ -478,6 +479,78 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
478 return ret; 479 return ret;
479} 480}
480 481
482/*
483 * Copies (and truncates, if necessary) data from the larger struct,
484 * nand_ecclayout, to the smaller, deprecated layout struct,
485 * nand_ecclayout_user. This is necessary only to suppport the deprecated
486 * API ioctl ECCGETLAYOUT while allowing all new functionality to use
487 * nand_ecclayout flexibly (i.e. the struct may change size in new
488 * releases without requiring major rewrites).
489 */
490static int shrink_ecclayout(const struct nand_ecclayout *from,
491 struct nand_ecclayout_user *to)
492{
493 int i;
494
495 if (!from || !to)
496 return -EINVAL;
497
498 memset(to, 0, sizeof(*to));
499
500 to->eccbytes = min((int)from->eccbytes, MTD_MAX_ECCPOS_ENTRIES);
501 for (i = 0; i < to->eccbytes; i++)
502 to->eccpos[i] = from->eccpos[i];
503
504 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) {
505 if (from->oobfree[i].length == 0 &&
506 from->oobfree[i].offset == 0)
507 break;
508 to->oobavail += from->oobfree[i].length;
509 to->oobfree[i] = from->oobfree[i];
510 }
511
512 return 0;
513}
514
515#ifdef CONFIG_MTD_PARTITIONS
516static int mtd_blkpg_ioctl(struct mtd_info *mtd,
517 struct blkpg_ioctl_arg __user *arg)
518{
519 struct blkpg_ioctl_arg a;
520 struct blkpg_partition p;
521
522 if (!capable(CAP_SYS_ADMIN))
523 return -EPERM;
524
525 /* Only master mtd device must be used to control partitions */
526 if (!mtd_is_master(mtd))
527 return -EINVAL;
528
529 if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
530 return -EFAULT;
531
532 if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
533 return -EFAULT;
534
535 switch (a.op) {
536 case BLKPG_ADD_PARTITION:
537
538 return mtd_add_partition(mtd, p.devname, p.start, p.length);
539
540 case BLKPG_DEL_PARTITION:
541
542 if (p.pno < 0)
543 return -EINVAL;
544
545 return mtd_del_partition(mtd, p.pno);
546
547 default:
548 return -EINVAL;
549 }
550}
551#endif
552
553
481static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) 554static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
482{ 555{
483 struct mtd_file_info *mfi = file->private_data; 556 struct mtd_file_info *mfi = file->private_data;
@@ -514,6 +587,9 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
514 if (get_user(ur_idx, &(ur->regionindex))) 587 if (get_user(ur_idx, &(ur->regionindex)))
515 return -EFAULT; 588 return -EFAULT;
516 589
590 if (ur_idx >= mtd->numeraseregions)
591 return -EINVAL;
592
517 kr = &(mtd->eraseregions[ur_idx]); 593 kr = &(mtd->eraseregions[ur_idx]);
518 594
519 if (put_user(kr->offset, &(ur->offset)) 595 if (put_user(kr->offset, &(ur->offset))
@@ -813,14 +889,23 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
813 } 889 }
814#endif 890#endif
815 891
892 /* This ioctl is being deprecated - it truncates the ecc layout */
816 case ECCGETLAYOUT: 893 case ECCGETLAYOUT:
817 { 894 {
895 struct nand_ecclayout_user *usrlay;
896
818 if (!mtd->ecclayout) 897 if (!mtd->ecclayout)
819 return -EOPNOTSUPP; 898 return -EOPNOTSUPP;
820 899
821 if (copy_to_user(argp, mtd->ecclayout, 900 usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL);
822 sizeof(struct nand_ecclayout))) 901 if (!usrlay)
823 return -EFAULT; 902 return -ENOMEM;
903
904 shrink_ecclayout(mtd->ecclayout, usrlay);
905
906 if (copy_to_user(argp, usrlay, sizeof(*usrlay)))
907 ret = -EFAULT;
908 kfree(usrlay);
824 break; 909 break;
825 } 910 }
826 911
@@ -856,6 +941,22 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
856 break; 941 break;
857 } 942 }
858 943
944#ifdef CONFIG_MTD_PARTITIONS
945 case BLKPG:
946 {
947 ret = mtd_blkpg_ioctl(mtd,
948 (struct blkpg_ioctl_arg __user *)arg);
949 break;
950 }
951
952 case BLKRRPART:
953 {
954 /* No reread partition feature. Just return ok */
955 ret = 0;
956 break;
957 }
958#endif
959
859 default: 960 default:
860 ret = -ENOTTY; 961 ret = -ENOTTY;
861 } 962 }
@@ -1033,7 +1134,7 @@ static const struct file_operations mtd_fops = {
1033static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type, 1134static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type,
1034 int flags, const char *dev_name, void *data) 1135 int flags, const char *dev_name, void *data)
1035{ 1136{
1036 return mount_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC); 1137 return mount_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC);
1037} 1138}
1038 1139
1039static struct file_system_type mtd_inodefs_type = { 1140static struct file_system_type mtd_inodefs_type = {
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index dc6558568876..79e3689f1e16 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -29,9 +29,11 @@
29#include <linux/kmod.h> 29#include <linux/kmod.h>
30#include <linux/mtd/mtd.h> 30#include <linux/mtd/mtd.h>
31#include <linux/mtd/partitions.h> 31#include <linux/mtd/partitions.h>
32#include <linux/err.h>
32 33
33/* Our partition linked list */ 34/* Our partition linked list */
34static LIST_HEAD(mtd_partitions); 35static LIST_HEAD(mtd_partitions);
36static DEFINE_MUTEX(mtd_partitions_mutex);
35 37
36/* Our partition node structure */ 38/* Our partition node structure */
37struct mtd_part { 39struct mtd_part {
@@ -326,6 +328,12 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
326 return res; 328 return res;
327} 329}
328 330
331static inline void free_partition(struct mtd_part *p)
332{
333 kfree(p->mtd.name);
334 kfree(p);
335}
336
329/* 337/*
330 * This function unregisters and destroy all slave MTD objects which are 338 * This function unregisters and destroy all slave MTD objects which are
331 * attached to the given master MTD object. 339 * attached to the given master MTD object.
@@ -334,33 +342,42 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
334int del_mtd_partitions(struct mtd_info *master) 342int del_mtd_partitions(struct mtd_info *master)
335{ 343{
336 struct mtd_part *slave, *next; 344 struct mtd_part *slave, *next;
345 int ret, err = 0;
337 346
347 mutex_lock(&mtd_partitions_mutex);
338 list_for_each_entry_safe(slave, next, &mtd_partitions, list) 348 list_for_each_entry_safe(slave, next, &mtd_partitions, list)
339 if (slave->master == master) { 349 if (slave->master == master) {
350 ret = del_mtd_device(&slave->mtd);
351 if (ret < 0) {
352 err = ret;
353 continue;
354 }
340 list_del(&slave->list); 355 list_del(&slave->list);
341 del_mtd_device(&slave->mtd); 356 free_partition(slave);
342 kfree(slave);
343 } 357 }
358 mutex_unlock(&mtd_partitions_mutex);
344 359
345 return 0; 360 return err;
346} 361}
347EXPORT_SYMBOL(del_mtd_partitions); 362EXPORT_SYMBOL(del_mtd_partitions);
348 363
349static struct mtd_part *add_one_partition(struct mtd_info *master, 364static struct mtd_part *allocate_partition(struct mtd_info *master,
350 const struct mtd_partition *part, int partno, 365 const struct mtd_partition *part, int partno,
351 uint64_t cur_offset) 366 uint64_t cur_offset)
352{ 367{
353 struct mtd_part *slave; 368 struct mtd_part *slave;
369 char *name;
354 370
355 /* allocate the partition structure */ 371 /* allocate the partition structure */
356 slave = kzalloc(sizeof(*slave), GFP_KERNEL); 372 slave = kzalloc(sizeof(*slave), GFP_KERNEL);
357 if (!slave) { 373 name = kstrdup(part->name, GFP_KERNEL);
374 if (!name || !slave) {
358 printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n", 375 printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n",
359 master->name); 376 master->name);
360 del_mtd_partitions(master); 377 kfree(name);
361 return NULL; 378 kfree(slave);
379 return ERR_PTR(-ENOMEM);
362 } 380 }
363 list_add(&slave->list, &mtd_partitions);
364 381
365 /* set up the MTD object for this partition */ 382 /* set up the MTD object for this partition */
366 slave->mtd.type = master->type; 383 slave->mtd.type = master->type;
@@ -371,7 +388,7 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
371 slave->mtd.oobavail = master->oobavail; 388 slave->mtd.oobavail = master->oobavail;
372 slave->mtd.subpage_sft = master->subpage_sft; 389 slave->mtd.subpage_sft = master->subpage_sft;
373 390
374 slave->mtd.name = part->name; 391 slave->mtd.name = name;
375 slave->mtd.owner = master->owner; 392 slave->mtd.owner = master->owner;
376 slave->mtd.backing_dev_info = master->backing_dev_info; 393 slave->mtd.backing_dev_info = master->backing_dev_info;
377 394
@@ -518,12 +535,89 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
518 } 535 }
519 536
520out_register: 537out_register:
521 /* register our partition */
522 add_mtd_device(&slave->mtd);
523
524 return slave; 538 return slave;
525} 539}
526 540
541int mtd_add_partition(struct mtd_info *master, char *name,
542 long long offset, long long length)
543{
544 struct mtd_partition part;
545 struct mtd_part *p, *new;
546 uint64_t start, end;
547 int ret = 0;
548
549 /* the direct offset is expected */
550 if (offset == MTDPART_OFS_APPEND ||
551 offset == MTDPART_OFS_NXTBLK)
552 return -EINVAL;
553
554 if (length == MTDPART_SIZ_FULL)
555 length = master->size - offset;
556
557 if (length <= 0)
558 return -EINVAL;
559
560 part.name = name;
561 part.size = length;
562 part.offset = offset;
563 part.mask_flags = 0;
564 part.ecclayout = NULL;
565
566 new = allocate_partition(master, &part, -1, offset);
567 if (IS_ERR(new))
568 return PTR_ERR(new);
569
570 start = offset;
571 end = offset + length;
572
573 mutex_lock(&mtd_partitions_mutex);
574 list_for_each_entry(p, &mtd_partitions, list)
575 if (p->master == master) {
576 if ((start >= p->offset) &&
577 (start < (p->offset + p->mtd.size)))
578 goto err_inv;
579
580 if ((end >= p->offset) &&
581 (end < (p->offset + p->mtd.size)))
582 goto err_inv;
583 }
584
585 list_add(&new->list, &mtd_partitions);
586 mutex_unlock(&mtd_partitions_mutex);
587
588 add_mtd_device(&new->mtd);
589
590 return ret;
591err_inv:
592 mutex_unlock(&mtd_partitions_mutex);
593 free_partition(new);
594 return -EINVAL;
595}
596EXPORT_SYMBOL_GPL(mtd_add_partition);
597
598int mtd_del_partition(struct mtd_info *master, int partno)
599{
600 struct mtd_part *slave, *next;
601 int ret = -EINVAL;
602
603 mutex_lock(&mtd_partitions_mutex);
604 list_for_each_entry_safe(slave, next, &mtd_partitions, list)
605 if ((slave->master == master) &&
606 (slave->mtd.index == partno)) {
607 ret = del_mtd_device(&slave->mtd);
608 if (ret < 0)
609 break;
610
611 list_del(&slave->list);
612 free_partition(slave);
613 break;
614 }
615 mutex_unlock(&mtd_partitions_mutex);
616
617 return ret;
618}
619EXPORT_SYMBOL_GPL(mtd_del_partition);
620
527/* 621/*
528 * This function, given a master MTD object and a partition table, creates 622 * This function, given a master MTD object and a partition table, creates
529 * and registers slave MTD objects which are bound to the master according to 623 * and registers slave MTD objects which are bound to the master according to
@@ -544,9 +638,16 @@ int add_mtd_partitions(struct mtd_info *master,
544 printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); 638 printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
545 639
546 for (i = 0; i < nbparts; i++) { 640 for (i = 0; i < nbparts; i++) {
547 slave = add_one_partition(master, parts + i, i, cur_offset); 641 slave = allocate_partition(master, parts + i, i, cur_offset);
548 if (!slave) 642 if (IS_ERR(slave))
549 return -ENOMEM; 643 return PTR_ERR(slave);
644
645 mutex_lock(&mtd_partitions_mutex);
646 list_add(&slave->list, &mtd_partitions);
647 mutex_unlock(&mtd_partitions_mutex);
648
649 add_mtd_device(&slave->mtd);
650
550 cur_offset = slave->offset + slave->mtd.size; 651 cur_offset = slave->offset + slave->mtd.size;
551 } 652 }
552 653
@@ -618,3 +719,20 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
618 return ret; 719 return ret;
619} 720}
620EXPORT_SYMBOL_GPL(parse_mtd_partitions); 721EXPORT_SYMBOL_GPL(parse_mtd_partitions);
722
723int mtd_is_master(struct mtd_info *mtd)
724{
725 struct mtd_part *part;
726 int nopart = 0;
727
728 mutex_lock(&mtd_partitions_mutex);
729 list_for_each_entry(part, &mtd_partitions, list)
730 if (&part->mtd == mtd) {
731 nopart = 1;
732 break;
733 }
734 mutex_unlock(&mtd_partitions_mutex);
735
736 return nopart;
737}
738EXPORT_SYMBOL_GPL(mtd_is_master);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 8b4b67c8a391..8229802b4346 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -400,13 +400,6 @@ config MTD_NAND_PXA3xx
400 This enables the driver for the NAND flash device found on 400 This enables the driver for the NAND flash device found on
401 PXA3xx processors 401 PXA3xx processors
402 402
403config MTD_NAND_PXA3xx_BUILTIN
404 bool "Use builtin definitions for some NAND chips (deprecated)"
405 depends on MTD_NAND_PXA3xx
406 help
407 This enables builtin definitions for some NAND chips. This
408 is deprecated in favor of platform specific data.
409
410config MTD_NAND_CM_X270 403config MTD_NAND_CM_X270
411 tristate "Support for NAND Flash on CM-X270 modules" 404 tristate "Support for NAND Flash on CM-X270 modules"
412 depends on MACH_ARMCORE 405 depends on MACH_ARMCORE
@@ -458,6 +451,7 @@ config MTD_NAND_ORION
458config MTD_NAND_FSL_ELBC 451config MTD_NAND_FSL_ELBC
459 tristate "NAND support for Freescale eLBC controllers" 452 tristate "NAND support for Freescale eLBC controllers"
460 depends on PPC_OF 453 depends on PPC_OF
454 select FSL_LBC
461 help 455 help
462 Various Freescale chips, including the 8313, include a NAND Flash 456 Various Freescale chips, including the 8313, include a NAND Flash
463 Controller Module with built-in hardware ECC capabilities. 457 Controller Module with built-in hardware ECC capabilities.
@@ -531,4 +525,11 @@ config MTD_NAND_JZ4740
531 help 525 help
532 Enables support for NAND Flash on JZ4740 SoC based boards. 526 Enables support for NAND Flash on JZ4740 SoC based boards.
533 527
528config MTD_NAND_FSMC
529 tristate "Support for NAND on ST Micros FSMC"
530 depends on PLAT_SPEAR || PLAT_NOMADIK || MACH_U300
531 help
532 Enables support for NAND Flash chips on the ST Microelectronics
533 Flexible Static Memory Controller (FSMC)
534
534endif # MTD_NAND 535endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index ac83dcdac5d6..8ad6faec72cb 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o
19obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o 19obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o
20obj-$(CONFIG_MTD_NAND_DAVINCI) += davinci_nand.o 20obj-$(CONFIG_MTD_NAND_DAVINCI) += davinci_nand.o
21obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o 21obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o
22obj-$(CONFIG_MTD_NAND_FSMC) += fsmc_nand.o
22obj-$(CONFIG_MTD_NAND_H1900) += h1910.o 23obj-$(CONFIG_MTD_NAND_H1900) += h1910.o
23obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o 24obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o
24obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o 25obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index 6fbeefa3a766..79947bea4d57 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -110,15 +110,6 @@ static const unsigned short bfin_nfc_pin_req[] =
110 0}; 110 0};
111 111
112#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC 112#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
113static uint8_t bbt_pattern[] = { 0xff };
114
115static struct nand_bbt_descr bootrom_bbt = {
116 .options = 0,
117 .offs = 63,
118 .len = 1,
119 .pattern = bbt_pattern,
120};
121
122static struct nand_ecclayout bootrom_ecclayout = { 113static struct nand_ecclayout bootrom_ecclayout = {
123 .eccbytes = 24, 114 .eccbytes = 24,
124 .eccpos = { 115 .eccpos = {
@@ -809,7 +800,6 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
809 /* setup hardware ECC data struct */ 800 /* setup hardware ECC data struct */
810 if (hardware_ecc) { 801 if (hardware_ecc) {
811#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC 802#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
812 chip->badblock_pattern = &bootrom_bbt;
813 chip->ecc.layout = &bootrom_ecclayout; 803 chip->ecc.layout = &bootrom_ecclayout;
814#endif 804#endif
815 chip->read_buf = bf5xx_nand_dma_read_buf; 805 chip->read_buf = bf5xx_nand_dma_read_buf;
@@ -830,6 +820,10 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
830 goto out_err_nand_scan; 820 goto out_err_nand_scan;
831 } 821 }
832 822
823#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
824 chip->badblockpos = 63;
825#endif
826
833 /* add NAND partition */ 827 /* add NAND partition */
834 bf5xx_nand_add_partition(info); 828 bf5xx_nand_add_partition(info);
835 829
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 8beb0d0233b5..a90fde3ede28 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -316,7 +316,7 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
316 u32 syndrome[4]; 316 u32 syndrome[4];
317 u32 ecc_state; 317 u32 ecc_state;
318 unsigned num_errors, corrected; 318 unsigned num_errors, corrected;
319 unsigned long timeo = jiffies + msecs_to_jiffies(100); 319 unsigned long timeo;
320 320
321 /* All bytes 0xff? It's an erased page; ignore its ECC. */ 321 /* All bytes 0xff? It's an erased page; ignore its ECC. */
322 for (i = 0; i < 10; i++) { 322 for (i = 0; i < 10; i++) {
@@ -372,9 +372,11 @@ compare:
372 * after setting the 4BITECC_ADD_CALC_START bit. So if you immediately 372 * after setting the 4BITECC_ADD_CALC_START bit. So if you immediately
373 * begin trying to poll for the state, you may fall right out of your 373 * begin trying to poll for the state, you may fall right out of your
374 * loop without any of the correction calculations having taken place. 374 * loop without any of the correction calculations having taken place.
375 * The recommendation from the hardware team is to wait till ECC_STATE 375 * The recommendation from the hardware team is to initially delay as
376 * reads less than 4, which means ECC HW has entered correction state. 376 * long as ECC_STATE reads less than 4. After that, ECC HW has entered
377 * correction state.
377 */ 378 */
379 timeo = jiffies + usecs_to_jiffies(100);
378 do { 380 do {
379 ecc_state = (davinci_nand_readl(info, 381 ecc_state = (davinci_nand_readl(info,
380 NANDFSR_OFFSET) >> 8) & 0x0f; 382 NANDFSR_OFFSET) >> 8) & 0x0f;
@@ -733,6 +735,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
733 * breaks userspace ioctl interface with mtd-utils. Once we 735 * breaks userspace ioctl interface with mtd-utils. Once we
734 * resolve this issue, NAND_ECC_HW_OOB_FIRST mode can be used 736 * resolve this issue, NAND_ECC_HW_OOB_FIRST mode can be used
735 * for the 4KiB page chips. 737 * for the 4KiB page chips.
738 *
739 * TODO: Note that nand_ecclayout has now been expanded and can
740 * hold plenty of OOB entries.
736 */ 741 */
737 dev_warn(&pdev->dev, "no 4-bit ECC support yet " 742 dev_warn(&pdev->dev, "no 4-bit ECC support yet "
738 "for 4KiB-page NAND\n"); 743 "for 4KiB-page NAND\n");
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 532fe07cf886..8c8d3c86c0e8 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1292,6 +1292,7 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
1292 read_status(denali); 1292 read_status(denali);
1293 break; 1293 break;
1294 case NAND_CMD_READID: 1294 case NAND_CMD_READID:
1295 case NAND_CMD_PARAM:
1295 reset_buf(denali); 1296 reset_buf(denali);
1296 /*sometimes ManufactureId read from register is not right 1297 /*sometimes ManufactureId read from register is not right
1297 * e.g. some of Micron MT29F32G08QAA MLC NAND chips 1298 * e.g. some of Micron MT29F32G08QAA MLC NAND chips
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 80de0bff6c3a..c141b07b25d1 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -1,9 +1,11 @@
1/* Freescale Enhanced Local Bus Controller NAND driver 1/* Freescale Enhanced Local Bus Controller NAND driver
2 * 2 *
3 * Copyright (c) 2006-2007 Freescale Semiconductor 3 * Copyright © 2006-2007, 2010 Freescale Semiconductor
4 * 4 *
5 * Authors: Nick Spence <nick.spence@freescale.com>, 5 * Authors: Nick Spence <nick.spence@freescale.com>,
6 * Scott Wood <scottwood@freescale.com> 6 * Scott Wood <scottwood@freescale.com>
7 * Jack Lan <jack.lan@freescale.com>
8 * Roy Zang <tie-fei.zang@freescale.com>
7 * 9 *
8 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -27,6 +29,7 @@
27#include <linux/string.h> 29#include <linux/string.h>
28#include <linux/ioport.h> 30#include <linux/ioport.h>
29#include <linux/of_platform.h> 31#include <linux/of_platform.h>
32#include <linux/platform_device.h>
30#include <linux/slab.h> 33#include <linux/slab.h>
31#include <linux/interrupt.h> 34#include <linux/interrupt.h>
32 35
@@ -42,14 +45,12 @@
42#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ 45#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
43#define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */ 46#define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
44 47
45struct fsl_elbc_ctrl;
46
47/* mtd information per set */ 48/* mtd information per set */
48 49
49struct fsl_elbc_mtd { 50struct fsl_elbc_mtd {
50 struct mtd_info mtd; 51 struct mtd_info mtd;
51 struct nand_chip chip; 52 struct nand_chip chip;
52 struct fsl_elbc_ctrl *ctrl; 53 struct fsl_lbc_ctrl *ctrl;
53 54
54 struct device *dev; 55 struct device *dev;
55 int bank; /* Chip select bank number */ 56 int bank; /* Chip select bank number */
@@ -58,18 +59,12 @@ struct fsl_elbc_mtd {
58 unsigned int fmr; /* FCM Flash Mode Register value */ 59 unsigned int fmr; /* FCM Flash Mode Register value */
59}; 60};
60 61
61/* overview of the fsl elbc controller */ 62/* Freescale eLBC FCM controller infomation */
62 63
63struct fsl_elbc_ctrl { 64struct fsl_elbc_fcm_ctrl {
64 struct nand_hw_control controller; 65 struct nand_hw_control controller;
65 struct fsl_elbc_mtd *chips[MAX_BANKS]; 66 struct fsl_elbc_mtd *chips[MAX_BANKS];
66 67
67 /* device info */
68 struct device *dev;
69 struct fsl_lbc_regs __iomem *regs;
70 int irq;
71 wait_queue_head_t irq_wait;
72 unsigned int irq_status; /* status read from LTESR by irq handler */
73 u8 __iomem *addr; /* Address of assigned FCM buffer */ 68 u8 __iomem *addr; /* Address of assigned FCM buffer */
74 unsigned int page; /* Last page written to / read from */ 69 unsigned int page; /* Last page written to / read from */
75 unsigned int read_bytes; /* Number of bytes read during command */ 70 unsigned int read_bytes; /* Number of bytes read during command */
@@ -79,6 +74,7 @@ struct fsl_elbc_ctrl {
79 unsigned int mdr; /* UPM/FCM Data Register value */ 74 unsigned int mdr; /* UPM/FCM Data Register value */
80 unsigned int use_mdr; /* Non zero if the MDR is to be set */ 75 unsigned int use_mdr; /* Non zero if the MDR is to be set */
81 unsigned int oob; /* Non zero if operating on OOB data */ 76 unsigned int oob; /* Non zero if operating on OOB data */
77 unsigned int counter; /* counter for the initializations */
82 char *oob_poi; /* Place to write ECC after read back */ 78 char *oob_poi; /* Place to write ECC after read back */
83}; 79};
84 80
@@ -164,11 +160,12 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
164{ 160{
165 struct nand_chip *chip = mtd->priv; 161 struct nand_chip *chip = mtd->priv;
166 struct fsl_elbc_mtd *priv = chip->priv; 162 struct fsl_elbc_mtd *priv = chip->priv;
167 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 163 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
168 struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 164 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
165 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
169 int buf_num; 166 int buf_num;
170 167
171 ctrl->page = page_addr; 168 elbc_fcm_ctrl->page = page_addr;
172 169
173 out_be32(&lbc->fbar, 170 out_be32(&lbc->fbar,
174 page_addr >> (chip->phys_erase_shift - chip->page_shift)); 171 page_addr >> (chip->phys_erase_shift - chip->page_shift));
@@ -185,16 +182,18 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
185 buf_num = page_addr & 7; 182 buf_num = page_addr & 7;
186 } 183 }
187 184
188 ctrl->addr = priv->vbase + buf_num * 1024; 185 elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024;
189 ctrl->index = column; 186 elbc_fcm_ctrl->index = column;
190 187
191 /* for OOB data point to the second half of the buffer */ 188 /* for OOB data point to the second half of the buffer */
192 if (oob) 189 if (oob)
193 ctrl->index += priv->page_size ? 2048 : 512; 190 elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512;
194 191
195 dev_vdbg(ctrl->dev, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), " 192 dev_vdbg(priv->dev, "set_addr: bank=%d, "
193 "elbc_fcm_ctrl->addr=0x%p (0x%p), "
196 "index %x, pes %d ps %d\n", 194 "index %x, pes %d ps %d\n",
197 buf_num, ctrl->addr, priv->vbase, ctrl->index, 195 buf_num, elbc_fcm_ctrl->addr, priv->vbase,
196 elbc_fcm_ctrl->index,
198 chip->phys_erase_shift, chip->page_shift); 197 chip->phys_erase_shift, chip->page_shift);
199} 198}
200 199
@@ -205,18 +204,19 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
205{ 204{
206 struct nand_chip *chip = mtd->priv; 205 struct nand_chip *chip = mtd->priv;
207 struct fsl_elbc_mtd *priv = chip->priv; 206 struct fsl_elbc_mtd *priv = chip->priv;
208 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 207 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
208 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
209 struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 209 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
210 210
211 /* Setup the FMR[OP] to execute without write protection */ 211 /* Setup the FMR[OP] to execute without write protection */
212 out_be32(&lbc->fmr, priv->fmr | 3); 212 out_be32(&lbc->fmr, priv->fmr | 3);
213 if (ctrl->use_mdr) 213 if (elbc_fcm_ctrl->use_mdr)
214 out_be32(&lbc->mdr, ctrl->mdr); 214 out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr);
215 215
216 dev_vdbg(ctrl->dev, 216 dev_vdbg(priv->dev,
217 "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n", 217 "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
218 in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr)); 218 in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
219 dev_vdbg(ctrl->dev, 219 dev_vdbg(priv->dev,
220 "fsl_elbc_run_command: fbar=%08x fpar=%08x " 220 "fsl_elbc_run_command: fbar=%08x fpar=%08x "
221 "fbcr=%08x bank=%d\n", 221 "fbcr=%08x bank=%d\n",
222 in_be32(&lbc->fbar), in_be32(&lbc->fpar), 222 in_be32(&lbc->fbar), in_be32(&lbc->fpar),
@@ -229,19 +229,18 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
229 /* wait for FCM complete flag or timeout */ 229 /* wait for FCM complete flag or timeout */
230 wait_event_timeout(ctrl->irq_wait, ctrl->irq_status, 230 wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
231 FCM_TIMEOUT_MSECS * HZ/1000); 231 FCM_TIMEOUT_MSECS * HZ/1000);
232 ctrl->status = ctrl->irq_status; 232 elbc_fcm_ctrl->status = ctrl->irq_status;
233
234 /* store mdr value in case it was needed */ 233 /* store mdr value in case it was needed */
235 if (ctrl->use_mdr) 234 if (elbc_fcm_ctrl->use_mdr)
236 ctrl->mdr = in_be32(&lbc->mdr); 235 elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr);
237 236
238 ctrl->use_mdr = 0; 237 elbc_fcm_ctrl->use_mdr = 0;
239 238
240 if (ctrl->status != LTESR_CC) { 239 if (elbc_fcm_ctrl->status != LTESR_CC) {
241 dev_info(ctrl->dev, 240 dev_info(priv->dev,
242 "command failed: fir %x fcr %x status %x mdr %x\n", 241 "command failed: fir %x fcr %x status %x mdr %x\n",
243 in_be32(&lbc->fir), in_be32(&lbc->fcr), 242 in_be32(&lbc->fir), in_be32(&lbc->fcr),
244 ctrl->status, ctrl->mdr); 243 elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr);
245 return -EIO; 244 return -EIO;
246 } 245 }
247 246
@@ -251,7 +250,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
251static void fsl_elbc_do_read(struct nand_chip *chip, int oob) 250static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
252{ 251{
253 struct fsl_elbc_mtd *priv = chip->priv; 252 struct fsl_elbc_mtd *priv = chip->priv;
254 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 253 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
255 struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 254 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
256 255
257 if (priv->page_size) { 256 if (priv->page_size) {
@@ -284,15 +283,16 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
284{ 283{
285 struct nand_chip *chip = mtd->priv; 284 struct nand_chip *chip = mtd->priv;
286 struct fsl_elbc_mtd *priv = chip->priv; 285 struct fsl_elbc_mtd *priv = chip->priv;
287 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 286 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
287 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
288 struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 288 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
289 289
290 ctrl->use_mdr = 0; 290 elbc_fcm_ctrl->use_mdr = 0;
291 291
292 /* clear the read buffer */ 292 /* clear the read buffer */
293 ctrl->read_bytes = 0; 293 elbc_fcm_ctrl->read_bytes = 0;
294 if (command != NAND_CMD_PAGEPROG) 294 if (command != NAND_CMD_PAGEPROG)
295 ctrl->index = 0; 295 elbc_fcm_ctrl->index = 0;
296 296
297 switch (command) { 297 switch (command) {
298 /* READ0 and READ1 read the entire buffer to use hardware ECC. */ 298 /* READ0 and READ1 read the entire buffer to use hardware ECC. */
@@ -301,7 +301,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
301 301
302 /* fall-through */ 302 /* fall-through */
303 case NAND_CMD_READ0: 303 case NAND_CMD_READ0:
304 dev_dbg(ctrl->dev, 304 dev_dbg(priv->dev,
305 "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:" 305 "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
306 " 0x%x, column: 0x%x.\n", page_addr, column); 306 " 0x%x, column: 0x%x.\n", page_addr, column);
307 307
@@ -309,8 +309,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
309 out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */ 309 out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
310 set_addr(mtd, 0, page_addr, 0); 310 set_addr(mtd, 0, page_addr, 0);
311 311
312 ctrl->read_bytes = mtd->writesize + mtd->oobsize; 312 elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
313 ctrl->index += column; 313 elbc_fcm_ctrl->index += column;
314 314
315 fsl_elbc_do_read(chip, 0); 315 fsl_elbc_do_read(chip, 0);
316 fsl_elbc_run_command(mtd); 316 fsl_elbc_run_command(mtd);
@@ -318,14 +318,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
318 318
319 /* READOOB reads only the OOB because no ECC is performed. */ 319 /* READOOB reads only the OOB because no ECC is performed. */
320 case NAND_CMD_READOOB: 320 case NAND_CMD_READOOB:
321 dev_vdbg(ctrl->dev, 321 dev_vdbg(priv->dev,
322 "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:" 322 "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
323 " 0x%x, column: 0x%x.\n", page_addr, column); 323 " 0x%x, column: 0x%x.\n", page_addr, column);
324 324
325 out_be32(&lbc->fbcr, mtd->oobsize - column); 325 out_be32(&lbc->fbcr, mtd->oobsize - column);
326 set_addr(mtd, column, page_addr, 1); 326 set_addr(mtd, column, page_addr, 1);
327 327
328 ctrl->read_bytes = mtd->writesize + mtd->oobsize; 328 elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
329 329
330 fsl_elbc_do_read(chip, 1); 330 fsl_elbc_do_read(chip, 1);
331 fsl_elbc_run_command(mtd); 331 fsl_elbc_run_command(mtd);
@@ -333,7 +333,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
333 333
334 /* READID must read all 5 possible bytes while CEB is active */ 334 /* READID must read all 5 possible bytes while CEB is active */
335 case NAND_CMD_READID: 335 case NAND_CMD_READID:
336 dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n"); 336 dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
337 337
338 out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) | 338 out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
339 (FIR_OP_UA << FIR_OP1_SHIFT) | 339 (FIR_OP_UA << FIR_OP1_SHIFT) |
@@ -341,9 +341,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
341 out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT); 341 out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
342 /* 5 bytes for manuf, device and exts */ 342 /* 5 bytes for manuf, device and exts */
343 out_be32(&lbc->fbcr, 5); 343 out_be32(&lbc->fbcr, 5);
344 ctrl->read_bytes = 5; 344 elbc_fcm_ctrl->read_bytes = 5;
345 ctrl->use_mdr = 1; 345 elbc_fcm_ctrl->use_mdr = 1;
346 ctrl->mdr = 0; 346 elbc_fcm_ctrl->mdr = 0;
347 347
348 set_addr(mtd, 0, 0, 0); 348 set_addr(mtd, 0, 0, 0);
349 fsl_elbc_run_command(mtd); 349 fsl_elbc_run_command(mtd);
@@ -351,7 +351,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
351 351
352 /* ERASE1 stores the block and page address */ 352 /* ERASE1 stores the block and page address */
353 case NAND_CMD_ERASE1: 353 case NAND_CMD_ERASE1:
354 dev_vdbg(ctrl->dev, 354 dev_vdbg(priv->dev,
355 "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, " 355 "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
356 "page_addr: 0x%x.\n", page_addr); 356 "page_addr: 0x%x.\n", page_addr);
357 set_addr(mtd, 0, page_addr, 0); 357 set_addr(mtd, 0, page_addr, 0);
@@ -359,7 +359,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
359 359
360 /* ERASE2 uses the block and page address from ERASE1 */ 360 /* ERASE2 uses the block and page address from ERASE1 */
361 case NAND_CMD_ERASE2: 361 case NAND_CMD_ERASE2:
362 dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n"); 362 dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
363 363
364 out_be32(&lbc->fir, 364 out_be32(&lbc->fir,
365 (FIR_OP_CM0 << FIR_OP0_SHIFT) | 365 (FIR_OP_CM0 << FIR_OP0_SHIFT) |
@@ -374,8 +374,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
374 (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT)); 374 (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
375 375
376 out_be32(&lbc->fbcr, 0); 376 out_be32(&lbc->fbcr, 0);
377 ctrl->read_bytes = 0; 377 elbc_fcm_ctrl->read_bytes = 0;
378 ctrl->use_mdr = 1; 378 elbc_fcm_ctrl->use_mdr = 1;
379 379
380 fsl_elbc_run_command(mtd); 380 fsl_elbc_run_command(mtd);
381 return; 381 return;
@@ -383,14 +383,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
383 /* SEQIN sets up the addr buffer and all registers except the length */ 383 /* SEQIN sets up the addr buffer and all registers except the length */
384 case NAND_CMD_SEQIN: { 384 case NAND_CMD_SEQIN: {
385 __be32 fcr; 385 __be32 fcr;
386 dev_vdbg(ctrl->dev, 386 dev_vdbg(priv->dev,
387 "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, " 387 "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
388 "page_addr: 0x%x, column: 0x%x.\n", 388 "page_addr: 0x%x, column: 0x%x.\n",
389 page_addr, column); 389 page_addr, column);
390 390
391 ctrl->column = column; 391 elbc_fcm_ctrl->use_mdr = 1;
392 ctrl->oob = 0;
393 ctrl->use_mdr = 1;
394 392
395 fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | 393 fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
396 (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | 394 (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) |
@@ -420,7 +418,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
420 /* OOB area --> READOOB */ 418 /* OOB area --> READOOB */
421 column -= mtd->writesize; 419 column -= mtd->writesize;
422 fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; 420 fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
423 ctrl->oob = 1; 421 elbc_fcm_ctrl->oob = 1;
424 } else { 422 } else {
425 WARN_ON(column != 0); 423 WARN_ON(column != 0);
426 /* First 256 bytes --> READ0 */ 424 /* First 256 bytes --> READ0 */
@@ -429,24 +427,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
429 } 427 }
430 428
431 out_be32(&lbc->fcr, fcr); 429 out_be32(&lbc->fcr, fcr);
432 set_addr(mtd, column, page_addr, ctrl->oob); 430 set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob);
433 return; 431 return;
434 } 432 }
435 433
436 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ 434 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
437 case NAND_CMD_PAGEPROG: { 435 case NAND_CMD_PAGEPROG: {
438 int full_page; 436 int full_page;
439 dev_vdbg(ctrl->dev, 437 dev_vdbg(priv->dev,
440 "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " 438 "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
441 "writing %d bytes.\n", ctrl->index); 439 "writing %d bytes.\n", elbc_fcm_ctrl->index);
442 440
443 /* if the write did not start at 0 or is not a full page 441 /* if the write did not start at 0 or is not a full page
444 * then set the exact length, otherwise use a full page 442 * then set the exact length, otherwise use a full page
445 * write so the HW generates the ECC. 443 * write so the HW generates the ECC.
446 */ 444 */
447 if (ctrl->oob || ctrl->column != 0 || 445 if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
448 ctrl->index != mtd->writesize + mtd->oobsize) { 446 elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) {
449 out_be32(&lbc->fbcr, ctrl->index); 447 out_be32(&lbc->fbcr, elbc_fcm_ctrl->index);
450 full_page = 0; 448 full_page = 0;
451 } else { 449 } else {
452 out_be32(&lbc->fbcr, 0); 450 out_be32(&lbc->fbcr, 0);
@@ -458,21 +456,21 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
458 /* Read back the page in order to fill in the ECC for the 456 /* Read back the page in order to fill in the ECC for the
459 * caller. Is this really needed? 457 * caller. Is this really needed?
460 */ 458 */
461 if (full_page && ctrl->oob_poi) { 459 if (full_page && elbc_fcm_ctrl->oob_poi) {
462 out_be32(&lbc->fbcr, 3); 460 out_be32(&lbc->fbcr, 3);
463 set_addr(mtd, 6, page_addr, 1); 461 set_addr(mtd, 6, page_addr, 1);
464 462
465 ctrl->read_bytes = mtd->writesize + 9; 463 elbc_fcm_ctrl->read_bytes = mtd->writesize + 9;
466 464
467 fsl_elbc_do_read(chip, 1); 465 fsl_elbc_do_read(chip, 1);
468 fsl_elbc_run_command(mtd); 466 fsl_elbc_run_command(mtd);
469 467
470 memcpy_fromio(ctrl->oob_poi + 6, 468 memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6,
471 &ctrl->addr[ctrl->index], 3); 469 &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3);
472 ctrl->index += 3; 470 elbc_fcm_ctrl->index += 3;
473 } 471 }
474 472
475 ctrl->oob_poi = NULL; 473 elbc_fcm_ctrl->oob_poi = NULL;
476 return; 474 return;
477 } 475 }
478 476
@@ -485,26 +483,26 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
485 out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT); 483 out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
486 out_be32(&lbc->fbcr, 1); 484 out_be32(&lbc->fbcr, 1);
487 set_addr(mtd, 0, 0, 0); 485 set_addr(mtd, 0, 0, 0);
488 ctrl->read_bytes = 1; 486 elbc_fcm_ctrl->read_bytes = 1;
489 487
490 fsl_elbc_run_command(mtd); 488 fsl_elbc_run_command(mtd);
491 489
492 /* The chip always seems to report that it is 490 /* The chip always seems to report that it is
493 * write-protected, even when it is not. 491 * write-protected, even when it is not.
494 */ 492 */
495 setbits8(ctrl->addr, NAND_STATUS_WP); 493 setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP);
496 return; 494 return;
497 495
498 /* RESET without waiting for the ready line */ 496 /* RESET without waiting for the ready line */
499 case NAND_CMD_RESET: 497 case NAND_CMD_RESET:
500 dev_dbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n"); 498 dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
501 out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT); 499 out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
502 out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT); 500 out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
503 fsl_elbc_run_command(mtd); 501 fsl_elbc_run_command(mtd);
504 return; 502 return;
505 503
506 default: 504 default:
507 dev_err(ctrl->dev, 505 dev_err(priv->dev,
508 "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n", 506 "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
509 command); 507 command);
510 } 508 }
@@ -524,24 +522,24 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
524{ 522{
525 struct nand_chip *chip = mtd->priv; 523 struct nand_chip *chip = mtd->priv;
526 struct fsl_elbc_mtd *priv = chip->priv; 524 struct fsl_elbc_mtd *priv = chip->priv;
527 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 525 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
528 unsigned int bufsize = mtd->writesize + mtd->oobsize; 526 unsigned int bufsize = mtd->writesize + mtd->oobsize;
529 527
530 if (len <= 0) { 528 if (len <= 0) {
531 dev_err(ctrl->dev, "write_buf of %d bytes", len); 529 dev_err(priv->dev, "write_buf of %d bytes", len);
532 ctrl->status = 0; 530 elbc_fcm_ctrl->status = 0;
533 return; 531 return;
534 } 532 }
535 533
536 if ((unsigned int)len > bufsize - ctrl->index) { 534 if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) {
537 dev_err(ctrl->dev, 535 dev_err(priv->dev,
538 "write_buf beyond end of buffer " 536 "write_buf beyond end of buffer "
539 "(%d requested, %u available)\n", 537 "(%d requested, %u available)\n",
540 len, bufsize - ctrl->index); 538 len, bufsize - elbc_fcm_ctrl->index);
541 len = bufsize - ctrl->index; 539 len = bufsize - elbc_fcm_ctrl->index;
542 } 540 }
543 541
544 memcpy_toio(&ctrl->addr[ctrl->index], buf, len); 542 memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len);
545 /* 543 /*
546 * This is workaround for the weird elbc hangs during nand write, 544 * This is workaround for the weird elbc hangs during nand write,
547 * Scott Wood says: "...perhaps difference in how long it takes a 545 * Scott Wood says: "...perhaps difference in how long it takes a
@@ -549,9 +547,9 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
549 * is causing problems, and sync isn't helping for some reason." 547 * is causing problems, and sync isn't helping for some reason."
550 * Reading back the last byte helps though. 548 * Reading back the last byte helps though.
551 */ 549 */
552 in_8(&ctrl->addr[ctrl->index] + len - 1); 550 in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1);
553 551
554 ctrl->index += len; 552 elbc_fcm_ctrl->index += len;
555} 553}
556 554
557/* 555/*
@@ -562,13 +560,13 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
562{ 560{
563 struct nand_chip *chip = mtd->priv; 561 struct nand_chip *chip = mtd->priv;
564 struct fsl_elbc_mtd *priv = chip->priv; 562 struct fsl_elbc_mtd *priv = chip->priv;
565 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 563 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
566 564
567 /* If there are still bytes in the FCM, then use the next byte. */ 565 /* If there are still bytes in the FCM, then use the next byte. */
568 if (ctrl->index < ctrl->read_bytes) 566 if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes)
569 return in_8(&ctrl->addr[ctrl->index++]); 567 return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]);
570 568
571 dev_err(ctrl->dev, "read_byte beyond end of buffer\n"); 569 dev_err(priv->dev, "read_byte beyond end of buffer\n");
572 return ERR_BYTE; 570 return ERR_BYTE;
573} 571}
574 572
@@ -579,18 +577,19 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
579{ 577{
580 struct nand_chip *chip = mtd->priv; 578 struct nand_chip *chip = mtd->priv;
581 struct fsl_elbc_mtd *priv = chip->priv; 579 struct fsl_elbc_mtd *priv = chip->priv;
582 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 580 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
583 int avail; 581 int avail;
584 582
585 if (len < 0) 583 if (len < 0)
586 return; 584 return;
587 585
588 avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index); 586 avail = min((unsigned int)len,
589 memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail); 587 elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
590 ctrl->index += avail; 588 memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail);
589 elbc_fcm_ctrl->index += avail;
591 590
592 if (len > avail) 591 if (len > avail)
593 dev_err(ctrl->dev, 592 dev_err(priv->dev,
594 "read_buf beyond end of buffer " 593 "read_buf beyond end of buffer "
595 "(%d requested, %d available)\n", 594 "(%d requested, %d available)\n",
596 len, avail); 595 len, avail);
@@ -603,30 +602,32 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
603{ 602{
604 struct nand_chip *chip = mtd->priv; 603 struct nand_chip *chip = mtd->priv;
605 struct fsl_elbc_mtd *priv = chip->priv; 604 struct fsl_elbc_mtd *priv = chip->priv;
606 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 605 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
607 int i; 606 int i;
608 607
609 if (len < 0) { 608 if (len < 0) {
610 dev_err(ctrl->dev, "write_buf of %d bytes", len); 609 dev_err(priv->dev, "write_buf of %d bytes", len);
611 return -EINVAL; 610 return -EINVAL;
612 } 611 }
613 612
614 if ((unsigned int)len > ctrl->read_bytes - ctrl->index) { 613 if ((unsigned int)len >
615 dev_err(ctrl->dev, 614 elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index) {
616 "verify_buf beyond end of buffer " 615 dev_err(priv->dev,
617 "(%d requested, %u available)\n", 616 "verify_buf beyond end of buffer "
618 len, ctrl->read_bytes - ctrl->index); 617 "(%d requested, %u available)\n",
618 len, elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
619 619
620 ctrl->index = ctrl->read_bytes; 620 elbc_fcm_ctrl->index = elbc_fcm_ctrl->read_bytes;
621 return -EINVAL; 621 return -EINVAL;
622 } 622 }
623 623
624 for (i = 0; i < len; i++) 624 for (i = 0; i < len; i++)
625 if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i]) 625 if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i])
626 != buf[i])
626 break; 627 break;
627 628
628 ctrl->index += len; 629 elbc_fcm_ctrl->index += len;
629 return i == len && ctrl->status == LTESR_CC ? 0 : -EIO; 630 return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO;
630} 631}
631 632
632/* This function is called after Program and Erase Operations to 633/* This function is called after Program and Erase Operations to
@@ -635,22 +636,22 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
635static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) 636static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
636{ 637{
637 struct fsl_elbc_mtd *priv = chip->priv; 638 struct fsl_elbc_mtd *priv = chip->priv;
638 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 639 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
639 640
640 if (ctrl->status != LTESR_CC) 641 if (elbc_fcm_ctrl->status != LTESR_CC)
641 return NAND_STATUS_FAIL; 642 return NAND_STATUS_FAIL;
642 643
643 /* The chip always seems to report that it is 644 /* The chip always seems to report that it is
644 * write-protected, even when it is not. 645 * write-protected, even when it is not.
645 */ 646 */
646 return (ctrl->mdr & 0xff) | NAND_STATUS_WP; 647 return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
647} 648}
648 649
649static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) 650static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
650{ 651{
651 struct nand_chip *chip = mtd->priv; 652 struct nand_chip *chip = mtd->priv;
652 struct fsl_elbc_mtd *priv = chip->priv; 653 struct fsl_elbc_mtd *priv = chip->priv;
653 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 654 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
654 struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 655 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
655 unsigned int al; 656 unsigned int al;
656 657
@@ -665,41 +666,41 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
665 priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */ 666 priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */
666 (al << FMR_AL_SHIFT); 667 (al << FMR_AL_SHIFT);
667 668
668 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n", 669 dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
669 chip->numchips); 670 chip->numchips);
670 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n", 671 dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
671 chip->chipsize); 672 chip->chipsize);
672 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n", 673 dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
673 chip->pagemask); 674 chip->pagemask);
674 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_delay = %d\n", 675 dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
675 chip->chip_delay); 676 chip->chip_delay);
676 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->badblockpos = %d\n", 677 dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
677 chip->badblockpos); 678 chip->badblockpos);
678 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_shift = %d\n", 679 dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
679 chip->chip_shift); 680 chip->chip_shift);
680 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->page_shift = %d\n", 681 dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n",
681 chip->page_shift); 682 chip->page_shift);
682 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", 683 dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
683 chip->phys_erase_shift); 684 chip->phys_erase_shift);
684 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecclayout = %p\n", 685 dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
685 chip->ecclayout); 686 chip->ecclayout);
686 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.mode = %d\n", 687 dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
687 chip->ecc.mode); 688 chip->ecc.mode);
688 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", 689 dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
689 chip->ecc.steps); 690 chip->ecc.steps);
690 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", 691 dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
691 chip->ecc.bytes); 692 chip->ecc.bytes);
692 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.total = %d\n", 693 dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
693 chip->ecc.total); 694 chip->ecc.total);
694 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n", 695 dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
695 chip->ecc.layout); 696 chip->ecc.layout);
696 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); 697 dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
697 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); 698 dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
698 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n", 699 dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
699 mtd->erasesize); 700 mtd->erasesize);
700 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n", 701 dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n",
701 mtd->writesize); 702 mtd->writesize);
702 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->oobsize = %d\n", 703 dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
703 mtd->oobsize); 704 mtd->oobsize);
704 705
705 /* adjust Option Register and ECC to match Flash page size */ 706 /* adjust Option Register and ECC to match Flash page size */
@@ -719,7 +720,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
719 chip->badblock_pattern = &largepage_memorybased; 720 chip->badblock_pattern = &largepage_memorybased;
720 } 721 }
721 } else { 722 } else {
722 dev_err(ctrl->dev, 723 dev_err(priv->dev,
723 "fsl_elbc_init: page size %d is not supported\n", 724 "fsl_elbc_init: page size %d is not supported\n",
724 mtd->writesize); 725 mtd->writesize);
725 return -1; 726 return -1;
@@ -750,18 +751,19 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
750 const uint8_t *buf) 751 const uint8_t *buf)
751{ 752{
752 struct fsl_elbc_mtd *priv = chip->priv; 753 struct fsl_elbc_mtd *priv = chip->priv;
753 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 754 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
754 755
755 fsl_elbc_write_buf(mtd, buf, mtd->writesize); 756 fsl_elbc_write_buf(mtd, buf, mtd->writesize);
756 fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); 757 fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
757 758
758 ctrl->oob_poi = chip->oob_poi; 759 elbc_fcm_ctrl->oob_poi = chip->oob_poi;
759} 760}
760 761
761static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) 762static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
762{ 763{
763 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 764 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
764 struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 765 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
766 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
765 struct nand_chip *chip = &priv->chip; 767 struct nand_chip *chip = &priv->chip;
766 768
767 dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); 769 dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
@@ -790,7 +792,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
790 chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR | 792 chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
791 NAND_USE_FLASH_BBT; 793 NAND_USE_FLASH_BBT;
792 794
793 chip->controller = &ctrl->controller; 795 chip->controller = &elbc_fcm_ctrl->controller;
794 chip->priv = priv; 796 chip->priv = priv;
795 797
796 chip->ecc.read_page = fsl_elbc_read_page; 798 chip->ecc.read_page = fsl_elbc_read_page;
@@ -815,8 +817,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
815 817
816static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) 818static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
817{ 819{
818 struct fsl_elbc_ctrl *ctrl = priv->ctrl; 820 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
819
820 nand_release(&priv->mtd); 821 nand_release(&priv->mtd);
821 822
822 kfree(priv->mtd.name); 823 kfree(priv->mtd.name);
@@ -824,18 +825,21 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
824 if (priv->vbase) 825 if (priv->vbase)
825 iounmap(priv->vbase); 826 iounmap(priv->vbase);
826 827
827 ctrl->chips[priv->bank] = NULL; 828 elbc_fcm_ctrl->chips[priv->bank] = NULL;
828 kfree(priv); 829 kfree(priv);
829 830 kfree(elbc_fcm_ctrl);
830 return 0; 831 return 0;
831} 832}
832 833
833static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, 834static DEFINE_MUTEX(fsl_elbc_nand_mutex);
834 struct device_node *node) 835
836static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
835{ 837{
836 struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 838 struct fsl_lbc_regs __iomem *lbc;
837 struct fsl_elbc_mtd *priv; 839 struct fsl_elbc_mtd *priv;
838 struct resource res; 840 struct resource res;
841 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
842
839#ifdef CONFIG_MTD_PARTITIONS 843#ifdef CONFIG_MTD_PARTITIONS
840 static const char *part_probe_types[] 844 static const char *part_probe_types[]
841 = { "cmdlinepart", "RedBoot", NULL }; 845 = { "cmdlinepart", "RedBoot", NULL };
@@ -843,11 +847,18 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
843#endif 847#endif
844 int ret; 848 int ret;
845 int bank; 849 int bank;
850 struct device *dev;
851 struct device_node *node = pdev->dev.of_node;
852
853 if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
854 return -ENODEV;
855 lbc = fsl_lbc_ctrl_dev->regs;
856 dev = fsl_lbc_ctrl_dev->dev;
846 857
847 /* get, allocate and map the memory resource */ 858 /* get, allocate and map the memory resource */
848 ret = of_address_to_resource(node, 0, &res); 859 ret = of_address_to_resource(node, 0, &res);
849 if (ret) { 860 if (ret) {
850 dev_err(ctrl->dev, "failed to get resource\n"); 861 dev_err(dev, "failed to get resource\n");
851 return ret; 862 return ret;
852 } 863 }
853 864
@@ -857,11 +868,11 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
857 (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM && 868 (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM &&
858 (in_be32(&lbc->bank[bank].br) & 869 (in_be32(&lbc->bank[bank].br) &
859 in_be32(&lbc->bank[bank].or) & BR_BA) 870 in_be32(&lbc->bank[bank].or) & BR_BA)
860 == res.start) 871 == fsl_lbc_addr(res.start))
861 break; 872 break;
862 873
863 if (bank >= MAX_BANKS) { 874 if (bank >= MAX_BANKS) {
864 dev_err(ctrl->dev, "address did not match any chip selects\n"); 875 dev_err(dev, "address did not match any chip selects\n");
865 return -ENODEV; 876 return -ENODEV;
866 } 877 }
867 878
@@ -869,14 +880,33 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
869 if (!priv) 880 if (!priv)
870 return -ENOMEM; 881 return -ENOMEM;
871 882
872 ctrl->chips[bank] = priv; 883 mutex_lock(&fsl_elbc_nand_mutex);
884 if (!fsl_lbc_ctrl_dev->nand) {
885 elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
886 if (!elbc_fcm_ctrl) {
887 dev_err(dev, "failed to allocate memory\n");
888 mutex_unlock(&fsl_elbc_nand_mutex);
889 ret = -ENOMEM;
890 goto err;
891 }
892 elbc_fcm_ctrl->counter++;
893
894 spin_lock_init(&elbc_fcm_ctrl->controller.lock);
895 init_waitqueue_head(&elbc_fcm_ctrl->controller.wq);
896 fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
897 } else {
898 elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
899 }
900 mutex_unlock(&fsl_elbc_nand_mutex);
901
902 elbc_fcm_ctrl->chips[bank] = priv;
873 priv->bank = bank; 903 priv->bank = bank;
874 priv->ctrl = ctrl; 904 priv->ctrl = fsl_lbc_ctrl_dev;
875 priv->dev = ctrl->dev; 905 priv->dev = dev;
876 906
877 priv->vbase = ioremap(res.start, resource_size(&res)); 907 priv->vbase = ioremap(res.start, resource_size(&res));
878 if (!priv->vbase) { 908 if (!priv->vbase) {
879 dev_err(ctrl->dev, "failed to map chip region\n"); 909 dev_err(dev, "failed to map chip region\n");
880 ret = -ENOMEM; 910 ret = -ENOMEM;
881 goto err; 911 goto err;
882 } 912 }
@@ -933,171 +963,53 @@ err:
933 return ret; 963 return ret;
934} 964}
935 965
936static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl) 966static int fsl_elbc_nand_remove(struct platform_device *pdev)
937{ 967{
938 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
939
940 /*
941 * NAND transactions can tie up the bus for a long time, so set the
942 * bus timeout to max by clearing LBCR[BMT] (highest base counter
943 * value) and setting LBCR[BMTPS] to the highest prescaler value.
944 */
945 clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15);
946
947 /* clear event registers */
948 setbits32(&lbc->ltesr, LTESR_NAND_MASK);
949 out_be32(&lbc->lteatr, 0);
950
951 /* Enable interrupts for any detected events */
952 out_be32(&lbc->lteir, LTESR_NAND_MASK);
953
954 ctrl->read_bytes = 0;
955 ctrl->index = 0;
956 ctrl->addr = NULL;
957
958 return 0;
959}
960
961static int fsl_elbc_ctrl_remove(struct platform_device *ofdev)
962{
963 struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
964 int i; 968 int i;
965 969 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
966 for (i = 0; i < MAX_BANKS; i++) 970 for (i = 0; i < MAX_BANKS; i++)
967 if (ctrl->chips[i]) 971 if (elbc_fcm_ctrl->chips[i])
968 fsl_elbc_chip_remove(ctrl->chips[i]); 972 fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]);
969 973
970 if (ctrl->irq) 974 mutex_lock(&fsl_elbc_nand_mutex);
971 free_irq(ctrl->irq, ctrl); 975 elbc_fcm_ctrl->counter--;
972 976 if (!elbc_fcm_ctrl->counter) {
973 if (ctrl->regs) 977 fsl_lbc_ctrl_dev->nand = NULL;
974 iounmap(ctrl->regs); 978 kfree(elbc_fcm_ctrl);
975
976 dev_set_drvdata(&ofdev->dev, NULL);
977 kfree(ctrl);
978 return 0;
979}
980
981/* NOTE: This interrupt is also used to report other localbus events,
982 * such as transaction errors on other chipselects. If we want to
983 * capture those, we'll need to move the IRQ code into a shared
984 * LBC driver.
985 */
986
987static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
988{
989 struct fsl_elbc_ctrl *ctrl = data;
990 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
991 __be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
992
993 if (status) {
994 out_be32(&lbc->ltesr, status);
995 out_be32(&lbc->lteatr, 0);
996
997 ctrl->irq_status = status;
998 smp_wmb();
999 wake_up(&ctrl->irq_wait);
1000
1001 return IRQ_HANDLED;
1002 } 979 }
1003 980 mutex_unlock(&fsl_elbc_nand_mutex);
1004 return IRQ_NONE;
1005}
1006
1007/* fsl_elbc_ctrl_probe
1008 *
1009 * called by device layer when it finds a device matching
1010 * one our driver can handled. This code allocates all of
1011 * the resources needed for the controller only. The
1012 * resources for the NAND banks themselves are allocated
1013 * in the chip probe function.
1014*/
1015
1016static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev,
1017 const struct of_device_id *match)
1018{
1019 struct device_node *child;
1020 struct fsl_elbc_ctrl *ctrl;
1021 int ret;
1022
1023 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
1024 if (!ctrl)
1025 return -ENOMEM;
1026
1027 dev_set_drvdata(&ofdev->dev, ctrl);
1028
1029 spin_lock_init(&ctrl->controller.lock);
1030 init_waitqueue_head(&ctrl->controller.wq);
1031 init_waitqueue_head(&ctrl->irq_wait);
1032
1033 ctrl->regs = of_iomap(ofdev->dev.of_node, 0);
1034 if (!ctrl->regs) {
1035 dev_err(&ofdev->dev, "failed to get memory region\n");
1036 ret = -ENODEV;
1037 goto err;
1038 }
1039
1040 ctrl->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
1041 if (ctrl->irq == NO_IRQ) {
1042 dev_err(&ofdev->dev, "failed to get irq resource\n");
1043 ret = -ENODEV;
1044 goto err;
1045 }
1046
1047 ctrl->dev = &ofdev->dev;
1048
1049 ret = fsl_elbc_ctrl_init(ctrl);
1050 if (ret < 0)
1051 goto err;
1052
1053 ret = request_irq(ctrl->irq, fsl_elbc_ctrl_irq, 0, "fsl-elbc", ctrl);
1054 if (ret != 0) {
1055 dev_err(&ofdev->dev, "failed to install irq (%d)\n",
1056 ctrl->irq);
1057 ret = ctrl->irq;
1058 goto err;
1059 }
1060
1061 for_each_child_of_node(ofdev->dev.of_node, child)
1062 if (of_device_is_compatible(child, "fsl,elbc-fcm-nand"))
1063 fsl_elbc_chip_probe(ctrl, child);
1064 981
1065 return 0; 982 return 0;
1066 983
1067err:
1068 fsl_elbc_ctrl_remove(ofdev);
1069 return ret;
1070} 984}
1071 985
1072static const struct of_device_id fsl_elbc_match[] = { 986static const struct of_device_id fsl_elbc_nand_match[] = {
1073 { 987 { .compatible = "fsl,elbc-fcm-nand", },
1074 .compatible = "fsl,elbc",
1075 },
1076 {} 988 {}
1077}; 989};
1078 990
1079static struct of_platform_driver fsl_elbc_ctrl_driver = { 991static struct platform_driver fsl_elbc_nand_driver = {
1080 .driver = { 992 .driver = {
1081 .name = "fsl-elbc", 993 .name = "fsl,elbc-fcm-nand",
1082 .owner = THIS_MODULE, 994 .owner = THIS_MODULE,
1083 .of_match_table = fsl_elbc_match, 995 .of_match_table = fsl_elbc_nand_match,
1084 }, 996 },
1085 .probe = fsl_elbc_ctrl_probe, 997 .probe = fsl_elbc_nand_probe,
1086 .remove = fsl_elbc_ctrl_remove, 998 .remove = fsl_elbc_nand_remove,
1087}; 999};
1088 1000
1089static int __init fsl_elbc_init(void) 1001static int __init fsl_elbc_nand_init(void)
1090{ 1002{
1091 return of_register_platform_driver(&fsl_elbc_ctrl_driver); 1003 return platform_driver_register(&fsl_elbc_nand_driver);
1092} 1004}
1093 1005
1094static void __exit fsl_elbc_exit(void) 1006static void __exit fsl_elbc_nand_exit(void)
1095{ 1007{
1096 of_unregister_platform_driver(&fsl_elbc_ctrl_driver); 1008 platform_driver_unregister(&fsl_elbc_nand_driver);
1097} 1009}
1098 1010
1099module_init(fsl_elbc_init); 1011module_init(fsl_elbc_nand_init);
1100module_exit(fsl_elbc_exit); 1012module_exit(fsl_elbc_nand_exit);
1101 1013
1102MODULE_LICENSE("GPL"); 1014MODULE_LICENSE("GPL");
1103MODULE_AUTHOR("Freescale"); 1015MODULE_AUTHOR("Freescale");
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 4eff8b25e5af..efdcca94ce55 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -186,7 +186,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
186 if (!flash_np) 186 if (!flash_np)
187 return -ENODEV; 187 return -ENODEV;
188 188
189 fun->mtd.name = kasprintf(GFP_KERNEL, "%x.%s", io_res->start, 189 fun->mtd.name = kasprintf(GFP_KERNEL, "0x%llx.%s", (u64)io_res->start,
190 flash_np->name); 190 flash_np->name);
191 if (!fun->mtd.name) { 191 if (!fun->mtd.name) {
192 ret = -ENOMEM; 192 ret = -ENOMEM;
@@ -222,7 +222,7 @@ static int __devinit fun_probe(struct platform_device *ofdev,
222{ 222{
223 struct fsl_upm_nand *fun; 223 struct fsl_upm_nand *fun;
224 struct resource io_res; 224 struct resource io_res;
225 const uint32_t *prop; 225 const __be32 *prop;
226 int rnb_gpio; 226 int rnb_gpio;
227 int ret; 227 int ret;
228 int size; 228 int size;
@@ -270,7 +270,7 @@ static int __devinit fun_probe(struct platform_device *ofdev,
270 goto err1; 270 goto err1;
271 } 271 }
272 for (i = 0; i < fun->mchip_count; i++) 272 for (i = 0; i < fun->mchip_count; i++)
273 fun->mchip_offsets[i] = prop[i]; 273 fun->mchip_offsets[i] = be32_to_cpu(prop[i]);
274 } else { 274 } else {
275 fun->mchip_count = 1; 275 fun->mchip_count = 1;
276 } 276 }
@@ -295,13 +295,13 @@ static int __devinit fun_probe(struct platform_device *ofdev,
295 295
296 prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL); 296 prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL);
297 if (prop) 297 if (prop)
298 fun->chip_delay = *prop; 298 fun->chip_delay = be32_to_cpup(prop);
299 else 299 else
300 fun->chip_delay = 50; 300 fun->chip_delay = 50;
301 301
302 prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size); 302 prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size);
303 if (prop && size == sizeof(uint32_t)) 303 if (prop && size == sizeof(uint32_t))
304 fun->wait_flags = *prop; 304 fun->wait_flags = be32_to_cpup(prop);
305 else 305 else
306 fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | 306 fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN |
307 FSL_UPM_WAIT_WRITE_BYTE; 307 FSL_UPM_WAIT_WRITE_BYTE;
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
new file mode 100644
index 000000000000..02edfba25b0c
--- /dev/null
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -0,0 +1,866 @@
1/*
2 * drivers/mtd/nand/fsmc_nand.c
3 *
4 * ST Microelectronics
5 * Flexible Static Memory Controller (FSMC)
6 * Driver for NAND portions
7 *
8 * Copyright © 2010 ST Microelectronics
9 * Vipin Kumar <vipin.kumar@st.com>
10 * Ashish Priyadarshi
11 *
12 * Based on drivers/mtd/nand/nomadik_nand.c
13 *
14 * This file is licensed under the terms of the GNU General Public
15 * License version 2. This program is licensed "as is" without any
16 * warranty of any kind, whether express or implied.
17 */
18
19#include <linux/clk.h>
20#include <linux/err.h>
21#include <linux/init.h>
22#include <linux/module.h>
23#include <linux/resource.h>
24#include <linux/sched.h>
25#include <linux/types.h>
26#include <linux/mtd/mtd.h>
27#include <linux/mtd/nand.h>
28#include <linux/mtd/nand_ecc.h>
29#include <linux/platform_device.h>
30#include <linux/mtd/partitions.h>
31#include <linux/io.h>
32#include <linux/slab.h>
33#include <linux/mtd/fsmc.h>
34#include <mtd/mtd-abi.h>
35
36static struct nand_ecclayout fsmc_ecc1_layout = {
37 .eccbytes = 24,
38 .eccpos = {2, 3, 4, 18, 19, 20, 34, 35, 36, 50, 51, 52,
39 66, 67, 68, 82, 83, 84, 98, 99, 100, 114, 115, 116},
40 .oobfree = {
41 {.offset = 8, .length = 8},
42 {.offset = 24, .length = 8},
43 {.offset = 40, .length = 8},
44 {.offset = 56, .length = 8},
45 {.offset = 72, .length = 8},
46 {.offset = 88, .length = 8},
47 {.offset = 104, .length = 8},
48 {.offset = 120, .length = 8}
49 }
50};
51
52static struct nand_ecclayout fsmc_ecc4_lp_layout = {
53 .eccbytes = 104,
54 .eccpos = { 2, 3, 4, 5, 6, 7, 8,
55 9, 10, 11, 12, 13, 14,
56 18, 19, 20, 21, 22, 23, 24,
57 25, 26, 27, 28, 29, 30,
58 34, 35, 36, 37, 38, 39, 40,
59 41, 42, 43, 44, 45, 46,
60 50, 51, 52, 53, 54, 55, 56,
61 57, 58, 59, 60, 61, 62,
62 66, 67, 68, 69, 70, 71, 72,
63 73, 74, 75, 76, 77, 78,
64 82, 83, 84, 85, 86, 87, 88,
65 89, 90, 91, 92, 93, 94,
66 98, 99, 100, 101, 102, 103, 104,
67 105, 106, 107, 108, 109, 110,
68 114, 115, 116, 117, 118, 119, 120,
69 121, 122, 123, 124, 125, 126
70 },
71 .oobfree = {
72 {.offset = 15, .length = 3},
73 {.offset = 31, .length = 3},
74 {.offset = 47, .length = 3},
75 {.offset = 63, .length = 3},
76 {.offset = 79, .length = 3},
77 {.offset = 95, .length = 3},
78 {.offset = 111, .length = 3},
79 {.offset = 127, .length = 1}
80 }
81};
82
83/*
84 * ECC placement definitions in oobfree type format.
85 * There are 13 bytes of ecc for every 512 byte block and it has to be read
86 * consecutively and immediately after the 512 byte data block for hardware to
87 * generate the error bit offsets in 512 byte data.
88 * Managing the ecc bytes in the following way makes it easier for software to
89 * read ecc bytes consecutive to data bytes. This way is similar to
90 * oobfree structure maintained already in generic nand driver
91 */
92static struct fsmc_eccplace fsmc_ecc4_lp_place = {
93 .eccplace = {
94 {.offset = 2, .length = 13},
95 {.offset = 18, .length = 13},
96 {.offset = 34, .length = 13},
97 {.offset = 50, .length = 13},
98 {.offset = 66, .length = 13},
99 {.offset = 82, .length = 13},
100 {.offset = 98, .length = 13},
101 {.offset = 114, .length = 13}
102 }
103};
104
105static struct nand_ecclayout fsmc_ecc4_sp_layout = {
106 .eccbytes = 13,
107 .eccpos = { 0, 1, 2, 3, 6, 7, 8,
108 9, 10, 11, 12, 13, 14
109 },
110 .oobfree = {
111 {.offset = 15, .length = 1},
112 }
113};
114
115static struct fsmc_eccplace fsmc_ecc4_sp_place = {
116 .eccplace = {
117 {.offset = 0, .length = 4},
118 {.offset = 6, .length = 9}
119 }
120};
121
122/*
123 * Default partition tables to be used if the partition information not
124 * provided through platform data
125 */
126#define PARTITION(n, off, sz) {.name = n, .offset = off, .size = sz}
127
128/*
129 * Default partition layout for small page(= 512 bytes) devices
130 * Size for "Root file system" is updated in driver based on actual device size
131 */
132static struct mtd_partition partition_info_16KB_blk[] = {
133 PARTITION("X-loader", 0, 4 * 0x4000),
134 PARTITION("U-Boot", 0x10000, 20 * 0x4000),
135 PARTITION("Kernel", 0x60000, 256 * 0x4000),
136 PARTITION("Root File System", 0x460000, 0),
137};
138
139/*
140 * Default partition layout for large page(> 512 bytes) devices
141 * Size for "Root file system" is updated in driver based on actual device size
142 */
143static struct mtd_partition partition_info_128KB_blk[] = {
144 PARTITION("X-loader", 0, 4 * 0x20000),
145 PARTITION("U-Boot", 0x80000, 12 * 0x20000),
146 PARTITION("Kernel", 0x200000, 48 * 0x20000),
147 PARTITION("Root File System", 0x800000, 0),
148};
149
150#ifdef CONFIG_MTD_CMDLINE_PARTS
151const char *part_probes[] = { "cmdlinepart", NULL };
152#endif
153
154/**
155 * struct fsmc_nand_data - atructure for FSMC NAND device state
156 *
157 * @mtd: MTD info for a NAND flash.
158 * @nand: Chip related info for a NAND flash.
159 * @partitions: Partition info for a NAND Flash.
160 * @nr_partitions: Total number of partition of a NAND flash.
161 *
162 * @ecc_place: ECC placing locations in oobfree type format.
163 * @bank: Bank number for probed device.
164 * @clk: Clock structure for FSMC.
165 *
166 * @data_va: NAND port for Data.
167 * @cmd_va: NAND port for Command.
168 * @addr_va: NAND port for Address.
169 * @regs_va: FSMC regs base address.
170 */
171struct fsmc_nand_data {
172 struct mtd_info mtd;
173 struct nand_chip nand;
174 struct mtd_partition *partitions;
175 unsigned int nr_partitions;
176
177 struct fsmc_eccplace *ecc_place;
178 unsigned int bank;
179 struct clk *clk;
180
181 struct resource *resregs;
182 struct resource *rescmd;
183 struct resource *resaddr;
184 struct resource *resdata;
185
186 void __iomem *data_va;
187 void __iomem *cmd_va;
188 void __iomem *addr_va;
189 void __iomem *regs_va;
190
191 void (*select_chip)(uint32_t bank, uint32_t busw);
192};
193
194/* Assert CS signal based on chipnr */
195static void fsmc_select_chip(struct mtd_info *mtd, int chipnr)
196{
197 struct nand_chip *chip = mtd->priv;
198 struct fsmc_nand_data *host;
199
200 host = container_of(mtd, struct fsmc_nand_data, mtd);
201
202 switch (chipnr) {
203 case -1:
204 chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
205 break;
206 case 0:
207 case 1:
208 case 2:
209 case 3:
210 if (host->select_chip)
211 host->select_chip(chipnr,
212 chip->options & NAND_BUSWIDTH_16);
213 break;
214
215 default:
216 BUG();
217 }
218}
219
220/*
221 * fsmc_cmd_ctrl - For facilitaing Hardware access
222 * This routine allows hardware specific access to control-lines(ALE,CLE)
223 */
224static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
225{
226 struct nand_chip *this = mtd->priv;
227 struct fsmc_nand_data *host = container_of(mtd,
228 struct fsmc_nand_data, mtd);
229 struct fsmc_regs *regs = host->regs_va;
230 unsigned int bank = host->bank;
231
232 if (ctrl & NAND_CTRL_CHANGE) {
233 if (ctrl & NAND_CLE) {
234 this->IO_ADDR_R = (void __iomem *)host->cmd_va;
235 this->IO_ADDR_W = (void __iomem *)host->cmd_va;
236 } else if (ctrl & NAND_ALE) {
237 this->IO_ADDR_R = (void __iomem *)host->addr_va;
238 this->IO_ADDR_W = (void __iomem *)host->addr_va;
239 } else {
240 this->IO_ADDR_R = (void __iomem *)host->data_va;
241 this->IO_ADDR_W = (void __iomem *)host->data_va;
242 }
243
244 if (ctrl & NAND_NCE) {
245 writel(readl(&regs->bank_regs[bank].pc) | FSMC_ENABLE,
246 &regs->bank_regs[bank].pc);
247 } else {
248 writel(readl(&regs->bank_regs[bank].pc) & ~FSMC_ENABLE,
249 &regs->bank_regs[bank].pc);
250 }
251 }
252
253 mb();
254
255 if (cmd != NAND_CMD_NONE)
256 writeb(cmd, this->IO_ADDR_W);
257}
258
259/*
260 * fsmc_nand_setup - FSMC (Flexible Static Memory Controller) init routine
261 *
262 * This routine initializes timing parameters related to NAND memory access in
263 * FSMC registers
264 */
265static void __init fsmc_nand_setup(struct fsmc_regs *regs, uint32_t bank,
266 uint32_t busw)
267{
268 uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON;
269
270 if (busw)
271 writel(value | FSMC_DEVWID_16, &regs->bank_regs[bank].pc);
272 else
273 writel(value | FSMC_DEVWID_8, &regs->bank_regs[bank].pc);
274
275 writel(readl(&regs->bank_regs[bank].pc) | FSMC_TCLR_1 | FSMC_TAR_1,
276 &regs->bank_regs[bank].pc);
277 writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0,
278 &regs->bank_regs[bank].comm);
279 writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0,
280 &regs->bank_regs[bank].attrib);
281}
282
283/*
284 * fsmc_enable_hwecc - Enables Hardware ECC through FSMC registers
285 */
286static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
287{
288 struct fsmc_nand_data *host = container_of(mtd,
289 struct fsmc_nand_data, mtd);
290 struct fsmc_regs *regs = host->regs_va;
291 uint32_t bank = host->bank;
292
293 writel(readl(&regs->bank_regs[bank].pc) & ~FSMC_ECCPLEN_256,
294 &regs->bank_regs[bank].pc);
295 writel(readl(&regs->bank_regs[bank].pc) & ~FSMC_ECCEN,
296 &regs->bank_regs[bank].pc);
297 writel(readl(&regs->bank_regs[bank].pc) | FSMC_ECCEN,
298 &regs->bank_regs[bank].pc);
299}
300
301/*
302 * fsmc_read_hwecc_ecc4 - Hardware ECC calculator for ecc4 option supported by
303 * FSMC. ECC is 13 bytes for 512 bytes of data (supports error correction upto
304 * max of 8-bits)
305 */
306static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
307 uint8_t *ecc)
308{
309 struct fsmc_nand_data *host = container_of(mtd,
310 struct fsmc_nand_data, mtd);
311 struct fsmc_regs *regs = host->regs_va;
312 uint32_t bank = host->bank;
313 uint32_t ecc_tmp;
314 unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT;
315
316 do {
317 if (readl(&regs->bank_regs[bank].sts) & FSMC_CODE_RDY)
318 break;
319 else
320 cond_resched();
321 } while (!time_after_eq(jiffies, deadline));
322
323 ecc_tmp = readl(&regs->bank_regs[bank].ecc1);
324 ecc[0] = (uint8_t) (ecc_tmp >> 0);
325 ecc[1] = (uint8_t) (ecc_tmp >> 8);
326 ecc[2] = (uint8_t) (ecc_tmp >> 16);
327 ecc[3] = (uint8_t) (ecc_tmp >> 24);
328
329 ecc_tmp = readl(&regs->bank_regs[bank].ecc2);
330 ecc[4] = (uint8_t) (ecc_tmp >> 0);
331 ecc[5] = (uint8_t) (ecc_tmp >> 8);
332 ecc[6] = (uint8_t) (ecc_tmp >> 16);
333 ecc[7] = (uint8_t) (ecc_tmp >> 24);
334
335 ecc_tmp = readl(&regs->bank_regs[bank].ecc3);
336 ecc[8] = (uint8_t) (ecc_tmp >> 0);
337 ecc[9] = (uint8_t) (ecc_tmp >> 8);
338 ecc[10] = (uint8_t) (ecc_tmp >> 16);
339 ecc[11] = (uint8_t) (ecc_tmp >> 24);
340
341 ecc_tmp = readl(&regs->bank_regs[bank].sts);
342 ecc[12] = (uint8_t) (ecc_tmp >> 16);
343
344 return 0;
345}
346
347/*
348 * fsmc_read_hwecc_ecc1 - Hardware ECC calculator for ecc1 option supported by
349 * FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction upto
350 * max of 1-bit)
351 */
352static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data,
353 uint8_t *ecc)
354{
355 struct fsmc_nand_data *host = container_of(mtd,
356 struct fsmc_nand_data, mtd);
357 struct fsmc_regs *regs = host->regs_va;
358 uint32_t bank = host->bank;
359 uint32_t ecc_tmp;
360
361 ecc_tmp = readl(&regs->bank_regs[bank].ecc1);
362 ecc[0] = (uint8_t) (ecc_tmp >> 0);
363 ecc[1] = (uint8_t) (ecc_tmp >> 8);
364 ecc[2] = (uint8_t) (ecc_tmp >> 16);
365
366 return 0;
367}
368
369/*
370 * fsmc_read_page_hwecc
371 * @mtd: mtd info structure
372 * @chip: nand chip info structure
373 * @buf: buffer to store read data
374 * @page: page number to read
375 *
376 * This routine is needed for fsmc verison 8 as reading from NAND chip has to be
377 * performed in a strict sequence as follows:
378 * data(512 byte) -> ecc(13 byte)
379 * After this read, fsmc hardware generates and reports error data bits(upto a
380 * max of 8 bits)
381 */
382static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
383 uint8_t *buf, int page)
384{
385 struct fsmc_nand_data *host = container_of(mtd,
386 struct fsmc_nand_data, mtd);
387 struct fsmc_eccplace *ecc_place = host->ecc_place;
388 int i, j, s, stat, eccsize = chip->ecc.size;
389 int eccbytes = chip->ecc.bytes;
390 int eccsteps = chip->ecc.steps;
391 uint8_t *p = buf;
392 uint8_t *ecc_calc = chip->buffers->ecccalc;
393 uint8_t *ecc_code = chip->buffers->ecccode;
394 int off, len, group = 0;
395 /*
396 * ecc_oob is intentionally taken as uint16_t. In 16bit devices, we
397 * end up reading 14 bytes (7 words) from oob. The local array is
398 * to maintain word alignment
399 */
400 uint16_t ecc_oob[7];
401 uint8_t *oob = (uint8_t *)&ecc_oob[0];
402
403 for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
404
405 chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page);
406 chip->ecc.hwctl(mtd, NAND_ECC_READ);
407 chip->read_buf(mtd, p, eccsize);
408
409 for (j = 0; j < eccbytes;) {
410 off = ecc_place->eccplace[group].offset;
411 len = ecc_place->eccplace[group].length;
412 group++;
413
414 /*
415 * length is intentionally kept a higher multiple of 2
416 * to read at least 13 bytes even in case of 16 bit NAND
417 * devices
418 */
419 len = roundup(len, 2);
420 chip->cmdfunc(mtd, NAND_CMD_READOOB, off, page);
421 chip->read_buf(mtd, oob + j, len);
422 j += len;
423 }
424
425 memcpy(&ecc_code[i], oob, 13);
426 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
427
428 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
429 if (stat < 0)
430 mtd->ecc_stats.failed++;
431 else
432 mtd->ecc_stats.corrected += stat;
433 }
434
435 return 0;
436}
437
438/*
439 * fsmc_correct_data
440 * @mtd: mtd info structure
441 * @dat: buffer of read data
442 * @read_ecc: ecc read from device spare area
443 * @calc_ecc: ecc calculated from read data
444 *
445 * calc_ecc is a 104 bit information containing maximum of 8 error
446 * offset informations of 13 bits each in 512 bytes of read data.
447 */
448static int fsmc_correct_data(struct mtd_info *mtd, uint8_t *dat,
449 uint8_t *read_ecc, uint8_t *calc_ecc)
450{
451 struct fsmc_nand_data *host = container_of(mtd,
452 struct fsmc_nand_data, mtd);
453 struct fsmc_regs *regs = host->regs_va;
454 unsigned int bank = host->bank;
455 uint16_t err_idx[8];
456 uint64_t ecc_data[2];
457 uint32_t num_err, i;
458
459 /* The calculated ecc is actually the correction index in data */
460 memcpy(ecc_data, calc_ecc, 13);
461
462 /*
463 * ------------------- calc_ecc[] bit wise -----------|--13 bits--|
464 * |---idx[7]--|--.....-----|---idx[2]--||---idx[1]--||---idx[0]--|
465 *
466 * calc_ecc is a 104 bit information containing maximum of 8 error
467 * offset informations of 13 bits each. calc_ecc is copied into a
468 * uint64_t array and error offset indexes are populated in err_idx
469 * array
470 */
471 for (i = 0; i < 8; i++) {
472 if (i == 4) {
473 err_idx[4] = ((ecc_data[1] & 0x1) << 12) | ecc_data[0];
474 ecc_data[1] >>= 1;
475 continue;
476 }
477 err_idx[i] = (ecc_data[i/4] & 0x1FFF);
478 ecc_data[i/4] >>= 13;
479 }
480
481 num_err = (readl(&regs->bank_regs[bank].sts) >> 10) & 0xF;
482
483 if (num_err == 0xF)
484 return -EBADMSG;
485
486 i = 0;
487 while (num_err--) {
488 change_bit(0, (unsigned long *)&err_idx[i]);
489 change_bit(1, (unsigned long *)&err_idx[i]);
490
491 if (err_idx[i] <= 512 * 8) {
492 change_bit(err_idx[i], (unsigned long *)dat);
493 i++;
494 }
495 }
496 return i;
497}
498
499/*
500 * fsmc_nand_probe - Probe function
501 * @pdev: platform device structure
502 */
503static int __init fsmc_nand_probe(struct platform_device *pdev)
504{
505 struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
506 struct fsmc_nand_data *host;
507 struct mtd_info *mtd;
508 struct nand_chip *nand;
509 struct fsmc_regs *regs;
510 struct resource *res;
511 int nr_parts, ret = 0;
512
513 if (!pdata) {
514 dev_err(&pdev->dev, "platform data is NULL\n");
515 return -EINVAL;
516 }
517
518 /* Allocate memory for the device structure (and zero it) */
519 host = kzalloc(sizeof(*host), GFP_KERNEL);
520 if (!host) {
521 dev_err(&pdev->dev, "failed to allocate device structure\n");
522 return -ENOMEM;
523 }
524
525 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data");
526 if (!res) {
527 ret = -EIO;
528 goto err_probe1;
529 }
530
531 host->resdata = request_mem_region(res->start, resource_size(res),
532 pdev->name);
533 if (!host->resdata) {
534 ret = -EIO;
535 goto err_probe1;
536 }
537
538 host->data_va = ioremap(res->start, resource_size(res));
539 if (!host->data_va) {
540 ret = -EIO;
541 goto err_probe1;
542 }
543
544 host->resaddr = request_mem_region(res->start + PLAT_NAND_ALE,
545 resource_size(res), pdev->name);
546 if (!host->resaddr) {
547 ret = -EIO;
548 goto err_probe1;
549 }
550
551 host->addr_va = ioremap(res->start + PLAT_NAND_ALE, resource_size(res));
552 if (!host->addr_va) {
553 ret = -EIO;
554 goto err_probe1;
555 }
556
557 host->rescmd = request_mem_region(res->start + PLAT_NAND_CLE,
558 resource_size(res), pdev->name);
559 if (!host->rescmd) {
560 ret = -EIO;
561 goto err_probe1;
562 }
563
564 host->cmd_va = ioremap(res->start + PLAT_NAND_CLE, resource_size(res));
565 if (!host->cmd_va) {
566 ret = -EIO;
567 goto err_probe1;
568 }
569
570 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fsmc_regs");
571 if (!res) {
572 ret = -EIO;
573 goto err_probe1;
574 }
575
576 host->resregs = request_mem_region(res->start, resource_size(res),
577 pdev->name);
578 if (!host->resregs) {
579 ret = -EIO;
580 goto err_probe1;
581 }
582
583 host->regs_va = ioremap(res->start, resource_size(res));
584 if (!host->regs_va) {
585 ret = -EIO;
586 goto err_probe1;
587 }
588
589 host->clk = clk_get(&pdev->dev, NULL);
590 if (IS_ERR(host->clk)) {
591 dev_err(&pdev->dev, "failed to fetch block clock\n");
592 ret = PTR_ERR(host->clk);
593 host->clk = NULL;
594 goto err_probe1;
595 }
596
597 ret = clk_enable(host->clk);
598 if (ret)
599 goto err_probe1;
600
601 host->bank = pdata->bank;
602 host->select_chip = pdata->select_bank;
603 regs = host->regs_va;
604
605 /* Link all private pointers */
606 mtd = &host->mtd;
607 nand = &host->nand;
608 mtd->priv = nand;
609 nand->priv = host;
610
611 host->mtd.owner = THIS_MODULE;
612 nand->IO_ADDR_R = host->data_va;
613 nand->IO_ADDR_W = host->data_va;
614 nand->cmd_ctrl = fsmc_cmd_ctrl;
615 nand->chip_delay = 30;
616
617 nand->ecc.mode = NAND_ECC_HW;
618 nand->ecc.hwctl = fsmc_enable_hwecc;
619 nand->ecc.size = 512;
620 nand->options = pdata->options;
621 nand->select_chip = fsmc_select_chip;
622
623 if (pdata->width == FSMC_NAND_BW16)
624 nand->options |= NAND_BUSWIDTH_16;
625
626 fsmc_nand_setup(regs, host->bank, nand->options & NAND_BUSWIDTH_16);
627
628 if (get_fsmc_version(host->regs_va) == FSMC_VER8) {
629 nand->ecc.read_page = fsmc_read_page_hwecc;
630 nand->ecc.calculate = fsmc_read_hwecc_ecc4;
631 nand->ecc.correct = fsmc_correct_data;
632 nand->ecc.bytes = 13;
633 } else {
634 nand->ecc.calculate = fsmc_read_hwecc_ecc1;
635 nand->ecc.correct = nand_correct_data;
636 nand->ecc.bytes = 3;
637 }
638
639 /*
640 * Scan to find existance of the device
641 */
642 if (nand_scan_ident(&host->mtd, 1, NULL)) {
643 ret = -ENXIO;
644 dev_err(&pdev->dev, "No NAND Device found!\n");
645 goto err_probe;
646 }
647
648 if (get_fsmc_version(host->regs_va) == FSMC_VER8) {
649 if (host->mtd.writesize == 512) {
650 nand->ecc.layout = &fsmc_ecc4_sp_layout;
651 host->ecc_place = &fsmc_ecc4_sp_place;
652 } else {
653 nand->ecc.layout = &fsmc_ecc4_lp_layout;
654 host->ecc_place = &fsmc_ecc4_lp_place;
655 }
656 } else {
657 nand->ecc.layout = &fsmc_ecc1_layout;
658 }
659
660 /* Second stage of scan to fill MTD data-structures */
661 if (nand_scan_tail(&host->mtd)) {
662 ret = -ENXIO;
663 goto err_probe;
664 }
665
666 /*
667 * The partition information can is accessed by (in the same precedence)
668 *
669 * command line through Bootloader,
670 * platform data,
671 * default partition information present in driver.
672 */
673#ifdef CONFIG_MTD_PARTITIONS
674#ifdef CONFIG_MTD_CMDLINE_PARTS
675 /*
676 * Check if partition info passed via command line
677 */
678 host->mtd.name = "nand";
679 nr_parts = parse_mtd_partitions(&host->mtd, part_probes,
680 &host->partitions, 0);
681 if (nr_parts > 0) {
682 host->nr_partitions = nr_parts;
683 } else {
684#endif
685 /*
686 * Check if partition info passed via command line
687 */
688 if (pdata->partitions) {
689 host->partitions = pdata->partitions;
690 host->nr_partitions = pdata->nr_partitions;
691 } else {
692 struct mtd_partition *partition;
693 int i;
694
695 /* Select the default partitions info */
696 switch (host->mtd.size) {
697 case 0x01000000:
698 case 0x02000000:
699 case 0x04000000:
700 host->partitions = partition_info_16KB_blk;
701 host->nr_partitions =
702 sizeof(partition_info_16KB_blk) /
703 sizeof(struct mtd_partition);
704 break;
705 case 0x08000000:
706 case 0x10000000:
707 case 0x20000000:
708 case 0x40000000:
709 host->partitions = partition_info_128KB_blk;
710 host->nr_partitions =
711 sizeof(partition_info_128KB_blk) /
712 sizeof(struct mtd_partition);
713 break;
714 default:
715 ret = -ENXIO;
716 pr_err("Unsupported NAND size\n");
717 goto err_probe;
718 }
719
720 partition = host->partitions;
721 for (i = 0; i < host->nr_partitions; i++, partition++) {
722 if (partition->size == 0) {
723 partition->size = host->mtd.size -
724 partition->offset;
725 break;
726 }
727 }
728 }
729#ifdef CONFIG_MTD_CMDLINE_PARTS
730 }
731#endif
732
733 if (host->partitions) {
734 ret = add_mtd_partitions(&host->mtd, host->partitions,
735 host->nr_partitions);
736 if (ret)
737 goto err_probe;
738 }
739#else
740 dev_info(&pdev->dev, "Registering %s as whole device\n", mtd->name);
741 if (!add_mtd_device(mtd)) {
742 ret = -ENXIO;
743 goto err_probe;
744 }
745#endif
746
747 platform_set_drvdata(pdev, host);
748 dev_info(&pdev->dev, "FSMC NAND driver registration successful\n");
749 return 0;
750
751err_probe:
752 clk_disable(host->clk);
753err_probe1:
754 if (host->clk)
755 clk_put(host->clk);
756 if (host->regs_va)
757 iounmap(host->regs_va);
758 if (host->resregs)
759 release_mem_region(host->resregs->start,
760 resource_size(host->resregs));
761 if (host->cmd_va)
762 iounmap(host->cmd_va);
763 if (host->rescmd)
764 release_mem_region(host->rescmd->start,
765 resource_size(host->rescmd));
766 if (host->addr_va)
767 iounmap(host->addr_va);
768 if (host->resaddr)
769 release_mem_region(host->resaddr->start,
770 resource_size(host->resaddr));
771 if (host->data_va)
772 iounmap(host->data_va);
773 if (host->resdata)
774 release_mem_region(host->resdata->start,
775 resource_size(host->resdata));
776
777 kfree(host);
778 return ret;
779}
780
781/*
782 * Clean up routine
783 */
784static int fsmc_nand_remove(struct platform_device *pdev)
785{
786 struct fsmc_nand_data *host = platform_get_drvdata(pdev);
787
788 platform_set_drvdata(pdev, NULL);
789
790 if (host) {
791#ifdef CONFIG_MTD_PARTITIONS
792 del_mtd_partitions(&host->mtd);
793#else
794 del_mtd_device(&host->mtd);
795#endif
796 clk_disable(host->clk);
797 clk_put(host->clk);
798
799 iounmap(host->regs_va);
800 release_mem_region(host->resregs->start,
801 resource_size(host->resregs));
802 iounmap(host->cmd_va);
803 release_mem_region(host->rescmd->start,
804 resource_size(host->rescmd));
805 iounmap(host->addr_va);
806 release_mem_region(host->resaddr->start,
807 resource_size(host->resaddr));
808 iounmap(host->data_va);
809 release_mem_region(host->resdata->start,
810 resource_size(host->resdata));
811
812 kfree(host);
813 }
814 return 0;
815}
816
817#ifdef CONFIG_PM
818static int fsmc_nand_suspend(struct device *dev)
819{
820 struct fsmc_nand_data *host = dev_get_drvdata(dev);
821 if (host)
822 clk_disable(host->clk);
823 return 0;
824}
825
826static int fsmc_nand_resume(struct device *dev)
827{
828 struct fsmc_nand_data *host = dev_get_drvdata(dev);
829 if (host)
830 clk_enable(host->clk);
831 return 0;
832}
833
834static const struct dev_pm_ops fsmc_nand_pm_ops = {
835 .suspend = fsmc_nand_suspend,
836 .resume = fsmc_nand_resume,
837};
838#endif
839
840static struct platform_driver fsmc_nand_driver = {
841 .remove = fsmc_nand_remove,
842 .driver = {
843 .owner = THIS_MODULE,
844 .name = "fsmc-nand",
845#ifdef CONFIG_PM
846 .pm = &fsmc_nand_pm_ops,
847#endif
848 },
849};
850
851static int __init fsmc_nand_init(void)
852{
853 return platform_driver_probe(&fsmc_nand_driver,
854 fsmc_nand_probe);
855}
856module_init(fsmc_nand_init);
857
858static void __exit fsmc_nand_exit(void)
859{
860 platform_driver_unregister(&fsmc_nand_driver);
861}
862module_exit(fsmc_nand_exit);
863
864MODULE_LICENSE("GPL");
865MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>, Ashish Priyadarshi");
866MODULE_DESCRIPTION("NAND driver for SPEAr Platforms");
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index df0c1da4ff49..469e649c911c 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -568,6 +568,7 @@ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
568 uint rcw_width; 568 uint rcw_width;
569 uint rcwh; 569 uint rcwh;
570 uint romloc, ps; 570 uint romloc, ps;
571 int ret = 0;
571 572
572 rmnode = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset"); 573 rmnode = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset");
573 if (!rmnode) { 574 if (!rmnode) {
@@ -579,7 +580,8 @@ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
579 rm = of_iomap(rmnode, 0); 580 rm = of_iomap(rmnode, 0);
580 if (!rm) { 581 if (!rm) {
581 dev_err(prv->dev, "Error mapping reset module node!\n"); 582 dev_err(prv->dev, "Error mapping reset module node!\n");
582 return -EBUSY; 583 ret = -EBUSY;
584 goto out;
583 } 585 }
584 586
585 rcwh = in_be32(&rm->rcwhr); 587 rcwh = in_be32(&rm->rcwhr);
@@ -628,8 +630,9 @@ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
628 rcw_width * 8, rcw_pagesize, 630 rcw_width * 8, rcw_pagesize,
629 rcw_sparesize); 631 rcw_sparesize);
630 iounmap(rm); 632 iounmap(rm);
633out:
631 of_node_put(rmnode); 634 of_node_put(rmnode);
632 return 0; 635 return ret;
633} 636}
634 637
635/* Free driver resources */ 638/* Free driver resources */
@@ -660,7 +663,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op,
660#endif 663#endif
661 struct nand_chip *chip; 664 struct nand_chip *chip;
662 unsigned long regs_paddr, regs_size; 665 unsigned long regs_paddr, regs_size;
663 const uint *chips_no; 666 const __be32 *chips_no;
664 int resettime = 0; 667 int resettime = 0;
665 int retval = 0; 668 int retval = 0;
666 int rev, len; 669 int rev, len;
@@ -803,7 +806,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op,
803 } 806 }
804 807
805 /* Detect NAND chips */ 808 /* Detect NAND chips */
806 if (nand_scan(mtd, *chips_no)) { 809 if (nand_scan(mtd, be32_to_cpup(chips_no))) {
807 dev_err(dev, "NAND Flash not found !\n"); 810 dev_err(dev, "NAND Flash not found !\n");
808 devm_free_irq(dev, prv->irq, mtd); 811 devm_free_irq(dev, prv->irq, mtd);
809 retval = -ENXIO; 812 retval = -ENXIO;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index d551ddd9537a..1f75a1b1f7c3 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -45,7 +45,7 @@
45#include <linux/interrupt.h> 45#include <linux/interrupt.h>
46#include <linux/bitops.h> 46#include <linux/bitops.h>
47#include <linux/leds.h> 47#include <linux/leds.h>
48#include <asm/io.h> 48#include <linux/io.h>
49 49
50#ifdef CONFIG_MTD_PARTITIONS 50#ifdef CONFIG_MTD_PARTITIONS
51#include <linux/mtd/partitions.h> 51#include <linux/mtd/partitions.h>
@@ -59,7 +59,7 @@ static struct nand_ecclayout nand_oob_8 = {
59 {.offset = 3, 59 {.offset = 3,
60 .length = 2}, 60 .length = 2},
61 {.offset = 6, 61 {.offset = 6,
62 .length = 2}} 62 .length = 2} }
63}; 63};
64 64
65static struct nand_ecclayout nand_oob_16 = { 65static struct nand_ecclayout nand_oob_16 = {
@@ -67,7 +67,7 @@ static struct nand_ecclayout nand_oob_16 = {
67 .eccpos = {0, 1, 2, 3, 6, 7}, 67 .eccpos = {0, 1, 2, 3, 6, 7},
68 .oobfree = { 68 .oobfree = {
69 {.offset = 8, 69 {.offset = 8,
70 . length = 8}} 70 . length = 8} }
71}; 71};
72 72
73static struct nand_ecclayout nand_oob_64 = { 73static struct nand_ecclayout nand_oob_64 = {
@@ -78,7 +78,7 @@ static struct nand_ecclayout nand_oob_64 = {
78 56, 57, 58, 59, 60, 61, 62, 63}, 78 56, 57, 58, 59, 60, 61, 62, 63},
79 .oobfree = { 79 .oobfree = {
80 {.offset = 2, 80 {.offset = 2,
81 .length = 38}} 81 .length = 38} }
82}; 82};
83 83
84static struct nand_ecclayout nand_oob_128 = { 84static struct nand_ecclayout nand_oob_128 = {
@@ -92,7 +92,7 @@ static struct nand_ecclayout nand_oob_128 = {
92 120, 121, 122, 123, 124, 125, 126, 127}, 92 120, 121, 122, 123, 124, 125, 126, 127},
93 .oobfree = { 93 .oobfree = {
94 {.offset = 2, 94 {.offset = 2,
95 .length = 78}} 95 .length = 78} }
96}; 96};
97 97
98static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, 98static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
@@ -612,7 +612,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
612 NAND_CTRL_CLE | NAND_CTRL_CHANGE); 612 NAND_CTRL_CLE | NAND_CTRL_CHANGE);
613 chip->cmd_ctrl(mtd, 613 chip->cmd_ctrl(mtd,
614 NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); 614 NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
615 while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ; 615 while (!(chip->read_byte(mtd) & NAND_STATUS_READY))
616 ;
616 return; 617 return;
617 618
618 /* This applies to read commands */ 619 /* This applies to read commands */
@@ -718,7 +719,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
718 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); 719 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
719 chip->cmd_ctrl(mtd, NAND_CMD_NONE, 720 chip->cmd_ctrl(mtd, NAND_CMD_NONE,
720 NAND_NCE | NAND_CTRL_CHANGE); 721 NAND_NCE | NAND_CTRL_CHANGE);
721 while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ; 722 while (!(chip->read_byte(mtd) & NAND_STATUS_READY))
723 ;
722 return; 724 return;
723 725
724 case NAND_CMD_RNDOUT: 726 case NAND_CMD_RNDOUT:
@@ -784,7 +786,7 @@ nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
784 spinlock_t *lock = &chip->controller->lock; 786 spinlock_t *lock = &chip->controller->lock;
785 wait_queue_head_t *wq = &chip->controller->wq; 787 wait_queue_head_t *wq = &chip->controller->wq;
786 DECLARE_WAITQUEUE(wait, current); 788 DECLARE_WAITQUEUE(wait, current);
787 retry: 789retry:
788 spin_lock(lock); 790 spin_lock(lock);
789 791
790 /* Hardware controller shared among independent devices */ 792 /* Hardware controller shared among independent devices */
@@ -834,7 +836,7 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
834 break; 836 break;
835 } 837 }
836 mdelay(1); 838 mdelay(1);
837 } 839 }
838} 840}
839 841
840/** 842/**
@@ -980,6 +982,7 @@ out:
980 982
981 return ret; 983 return ret;
982} 984}
985EXPORT_SYMBOL(nand_unlock);
983 986
984/** 987/**
985 * nand_lock - [REPLACEABLE] locks all blocks present in the device 988 * nand_lock - [REPLACEABLE] locks all blocks present in the device
@@ -1049,6 +1052,7 @@ out:
1049 1052
1050 return ret; 1053 return ret;
1051} 1054}
1055EXPORT_SYMBOL(nand_lock);
1052 1056
1053/** 1057/**
1054 * nand_read_page_raw - [Intern] read raw page data without ecc 1058 * nand_read_page_raw - [Intern] read raw page data without ecc
@@ -1076,8 +1080,9 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
1076 * 1080 *
1077 * We need a special oob layout and handling even when OOB isn't used. 1081 * We need a special oob layout and handling even when OOB isn't used.
1078 */ 1082 */
1079static int nand_read_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, 1083static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
1080 uint8_t *buf, int page) 1084 struct nand_chip *chip,
1085 uint8_t *buf, int page)
1081{ 1086{
1082 int eccsize = chip->ecc.size; 1087 int eccsize = chip->ecc.size;
1083 int eccbytes = chip->ecc.bytes; 1088 int eccbytes = chip->ecc.bytes;
@@ -1158,7 +1163,8 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
1158 * @readlen: data length 1163 * @readlen: data length
1159 * @bufpoi: buffer to store read data 1164 * @bufpoi: buffer to store read data
1160 */ 1165 */
1161static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) 1166static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
1167 uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
1162{ 1168{
1163 int start_step, end_step, num_steps; 1169 int start_step, end_step, num_steps;
1164 uint32_t *eccpos = chip->ecc.layout->eccpos; 1170 uint32_t *eccpos = chip->ecc.layout->eccpos;
@@ -1166,6 +1172,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint3
1166 int data_col_addr, i, gaps = 0; 1172 int data_col_addr, i, gaps = 0;
1167 int datafrag_len, eccfrag_len, aligned_len, aligned_pos; 1173 int datafrag_len, eccfrag_len, aligned_len, aligned_pos;
1168 int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; 1174 int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
1175 int index = 0;
1169 1176
1170 /* Column address wihin the page aligned to ECC size (256bytes). */ 1177 /* Column address wihin the page aligned to ECC size (256bytes). */
1171 start_step = data_offs / chip->ecc.size; 1178 start_step = data_offs / chip->ecc.size;
@@ -1204,26 +1211,30 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint3
1204 } else { 1211 } else {
1205 /* send the command to read the particular ecc bytes */ 1212 /* send the command to read the particular ecc bytes */
1206 /* take care about buswidth alignment in read_buf */ 1213 /* take care about buswidth alignment in read_buf */
1207 aligned_pos = eccpos[start_step * chip->ecc.bytes] & ~(busw - 1); 1214 index = start_step * chip->ecc.bytes;
1215
1216 aligned_pos = eccpos[index] & ~(busw - 1);
1208 aligned_len = eccfrag_len; 1217 aligned_len = eccfrag_len;
1209 if (eccpos[start_step * chip->ecc.bytes] & (busw - 1)) 1218 if (eccpos[index] & (busw - 1))
1210 aligned_len++; 1219 aligned_len++;
1211 if (eccpos[(start_step + num_steps) * chip->ecc.bytes] & (busw - 1)) 1220 if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1))
1212 aligned_len++; 1221 aligned_len++;
1213 1222
1214 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize + aligned_pos, -1); 1223 chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
1224 mtd->writesize + aligned_pos, -1);
1215 chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); 1225 chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
1216 } 1226 }
1217 1227
1218 for (i = 0; i < eccfrag_len; i++) 1228 for (i = 0; i < eccfrag_len; i++)
1219 chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + start_step * chip->ecc.bytes]]; 1229 chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + index]];
1220 1230
1221 p = bufpoi + data_col_addr; 1231 p = bufpoi + data_col_addr;
1222 for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { 1232 for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) {
1223 int stat; 1233 int stat;
1224 1234
1225 stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); 1235 stat = chip->ecc.correct(mtd, p,
1226 if (stat == -1) 1236 &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
1237 if (stat < 0)
1227 mtd->ecc_stats.failed++; 1238 mtd->ecc_stats.failed++;
1228 else 1239 else
1229 mtd->ecc_stats.corrected += stat; 1240 mtd->ecc_stats.corrected += stat;
@@ -1390,7 +1401,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
1390static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, 1401static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
1391 struct mtd_oob_ops *ops, size_t len) 1402 struct mtd_oob_ops *ops, size_t len)
1392{ 1403{
1393 switch(ops->mode) { 1404 switch (ops->mode) {
1394 1405
1395 case MTD_OOB_PLACE: 1406 case MTD_OOB_PLACE:
1396 case MTD_OOB_RAW: 1407 case MTD_OOB_RAW:
@@ -1402,7 +1413,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
1402 uint32_t boffs = 0, roffs = ops->ooboffs; 1413 uint32_t boffs = 0, roffs = ops->ooboffs;
1403 size_t bytes = 0; 1414 size_t bytes = 0;
1404 1415
1405 for(; free->length && len; free++, len -= bytes) { 1416 for (; free->length && len; free++, len -= bytes) {
1406 /* Read request not from offset 0 ? */ 1417 /* Read request not from offset 0 ? */
1407 if (unlikely(roffs)) { 1418 if (unlikely(roffs)) {
1408 if (roffs >= free->length) { 1419 if (roffs >= free->length) {
@@ -1466,7 +1477,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
1466 buf = ops->datbuf; 1477 buf = ops->datbuf;
1467 oob = ops->oobbuf; 1478 oob = ops->oobbuf;
1468 1479
1469 while(1) { 1480 while (1) {
1470 bytes = min(mtd->writesize - col, readlen); 1481 bytes = min(mtd->writesize - col, readlen);
1471 aligned = (bytes == mtd->writesize); 1482 aligned = (bytes == mtd->writesize);
1472 1483
@@ -1484,7 +1495,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
1484 ret = chip->ecc.read_page_raw(mtd, chip, 1495 ret = chip->ecc.read_page_raw(mtd, chip,
1485 bufpoi, page); 1496 bufpoi, page);
1486 else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) 1497 else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
1487 ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi); 1498 ret = chip->ecc.read_subpage(mtd, chip,
1499 col, bytes, bufpoi);
1488 else 1500 else
1489 ret = chip->ecc.read_page(mtd, chip, bufpoi, 1501 ret = chip->ecc.read_page(mtd, chip, bufpoi,
1490 page); 1502 page);
@@ -1493,7 +1505,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
1493 1505
1494 /* Transfer not aligned data */ 1506 /* Transfer not aligned data */
1495 if (!aligned) { 1507 if (!aligned) {
1496 if (!NAND_SUBPAGE_READ(chip) && !oob) 1508 if (!NAND_SUBPAGE_READ(chip) && !oob &&
1509 !(mtd->ecc_stats.failed - stats.failed))
1497 chip->pagebuf = realpage; 1510 chip->pagebuf = realpage;
1498 memcpy(buf, chip->buffers->databuf + col, bytes); 1511 memcpy(buf, chip->buffers->databuf + col, bytes);
1499 } 1512 }
@@ -1791,7 +1804,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1791 realpage = (int)(from >> chip->page_shift); 1804 realpage = (int)(from >> chip->page_shift);
1792 page = realpage & chip->pagemask; 1805 page = realpage & chip->pagemask;
1793 1806
1794 while(1) { 1807 while (1) {
1795 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); 1808 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
1796 1809
1797 len = min(len, readlen); 1810 len = min(len, readlen);
@@ -1861,7 +1874,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
1861 1874
1862 nand_get_device(chip, mtd, FL_READING); 1875 nand_get_device(chip, mtd, FL_READING);
1863 1876
1864 switch(ops->mode) { 1877 switch (ops->mode) {
1865 case MTD_OOB_PLACE: 1878 case MTD_OOB_PLACE:
1866 case MTD_OOB_AUTO: 1879 case MTD_OOB_AUTO:
1867 case MTD_OOB_RAW: 1880 case MTD_OOB_RAW:
@@ -1876,7 +1889,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
1876 else 1889 else
1877 ret = nand_do_read_ops(mtd, from, ops); 1890 ret = nand_do_read_ops(mtd, from, ops);
1878 1891
1879 out: 1892out:
1880 nand_release_device(mtd); 1893 nand_release_device(mtd);
1881 return ret; 1894 return ret;
1882} 1895}
@@ -1905,8 +1918,9 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
1905 * 1918 *
1906 * We need a special oob layout and handling even when ECC isn't checked. 1919 * We need a special oob layout and handling even when ECC isn't checked.
1907 */ 1920 */
1908static void nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, 1921static void nand_write_page_raw_syndrome(struct mtd_info *mtd,
1909 const uint8_t *buf) 1922 struct nand_chip *chip,
1923 const uint8_t *buf)
1910{ 1924{
1911 int eccsize = chip->ecc.size; 1925 int eccsize = chip->ecc.size;
1912 int eccbytes = chip->ecc.bytes; 1926 int eccbytes = chip->ecc.bytes;
@@ -2099,7 +2113,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
2099static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, 2113static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
2100 struct mtd_oob_ops *ops) 2114 struct mtd_oob_ops *ops)
2101{ 2115{
2102 switch(ops->mode) { 2116 switch (ops->mode) {
2103 2117
2104 case MTD_OOB_PLACE: 2118 case MTD_OOB_PLACE:
2105 case MTD_OOB_RAW: 2119 case MTD_OOB_RAW:
@@ -2111,7 +2125,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
2111 uint32_t boffs = 0, woffs = ops->ooboffs; 2125 uint32_t boffs = 0, woffs = ops->ooboffs;
2112 size_t bytes = 0; 2126 size_t bytes = 0;
2113 2127
2114 for(; free->length && len; free++, len -= bytes) { 2128 for (; free->length && len; free++, len -= bytes) {
2115 /* Write request not from offset 0 ? */ 2129 /* Write request not from offset 0 ? */
2116 if (unlikely(woffs)) { 2130 if (unlikely(woffs)) {
2117 if (woffs >= free->length) { 2131 if (woffs >= free->length) {
@@ -2137,7 +2151,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
2137 return NULL; 2151 return NULL;
2138} 2152}
2139 2153
2140#define NOTALIGNED(x) (x & (chip->subpagesize - 1)) != 0 2154#define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0)
2141 2155
2142/** 2156/**
2143 * nand_do_write_ops - [Internal] NAND write with ECC 2157 * nand_do_write_ops - [Internal] NAND write with ECC
@@ -2200,10 +2214,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
2200 memset(chip->oob_poi, 0xff, mtd->oobsize); 2214 memset(chip->oob_poi, 0xff, mtd->oobsize);
2201 2215
2202 /* Don't allow multipage oob writes with offset */ 2216 /* Don't allow multipage oob writes with offset */
2203 if (ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) 2217 if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen))
2204 return -EINVAL; 2218 return -EINVAL;
2205 2219
2206 while(1) { 2220 while (1) {
2207 int bytes = mtd->writesize; 2221 int bytes = mtd->writesize;
2208 int cached = writelen > bytes && page != blockmask; 2222 int cached = writelen > bytes && page != blockmask;
2209 uint8_t *wbuf = buf; 2223 uint8_t *wbuf = buf;
@@ -2431,7 +2445,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
2431 2445
2432 nand_get_device(chip, mtd, FL_WRITING); 2446 nand_get_device(chip, mtd, FL_WRITING);
2433 2447
2434 switch(ops->mode) { 2448 switch (ops->mode) {
2435 case MTD_OOB_PLACE: 2449 case MTD_OOB_PLACE:
2436 case MTD_OOB_AUTO: 2450 case MTD_OOB_AUTO:
2437 case MTD_OOB_RAW: 2451 case MTD_OOB_RAW:
@@ -2446,7 +2460,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
2446 else 2460 else
2447 ret = nand_do_write_ops(mtd, to, ops); 2461 ret = nand_do_write_ops(mtd, to, ops);
2448 2462
2449 out: 2463out:
2450 nand_release_device(mtd); 2464 nand_release_device(mtd);
2451 return ret; 2465 return ret;
2452} 2466}
@@ -2511,7 +2525,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
2511{ 2525{
2512 int page, status, pages_per_block, ret, chipnr; 2526 int page, status, pages_per_block, ret, chipnr;
2513 struct nand_chip *chip = mtd->priv; 2527 struct nand_chip *chip = mtd->priv;
2514 loff_t rewrite_bbt[NAND_MAX_CHIPS]={0}; 2528 loff_t rewrite_bbt[NAND_MAX_CHIPS] = {0};
2515 unsigned int bbt_masked_page = 0xffffffff; 2529 unsigned int bbt_masked_page = 0xffffffff;
2516 loff_t len; 2530 loff_t len;
2517 2531
@@ -2632,7 +2646,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
2632 } 2646 }
2633 instr->state = MTD_ERASE_DONE; 2647 instr->state = MTD_ERASE_DONE;
2634 2648
2635 erase_exit: 2649erase_exit:
2636 2650
2637 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; 2651 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
2638 2652
@@ -2706,7 +2720,8 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
2706 struct nand_chip *chip = mtd->priv; 2720 struct nand_chip *chip = mtd->priv;
2707 int ret; 2721 int ret;
2708 2722
2709 if ((ret = nand_block_isbad(mtd, ofs))) { 2723 ret = nand_block_isbad(mtd, ofs);
2724 if (ret) {
2710 /* If it was bad already, return success and do nothing. */ 2725 /* If it was bad already, return success and do nothing. */
2711 if (ret > 0) 2726 if (ret > 0)
2712 return 0; 2727 return 0;
@@ -2787,15 +2802,115 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
2787} 2802}
2788 2803
2789/* 2804/*
2805 * sanitize ONFI strings so we can safely print them
2806 */
2807static void sanitize_string(uint8_t *s, size_t len)
2808{
2809 ssize_t i;
2810
2811 /* null terminate */
2812 s[len - 1] = 0;
2813
2814 /* remove non printable chars */
2815 for (i = 0; i < len - 1; i++) {
2816 if (s[i] < ' ' || s[i] > 127)
2817 s[i] = '?';
2818 }
2819
2820 /* remove trailing spaces */
2821 strim(s);
2822}
2823
2824static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
2825{
2826 int i;
2827 while (len--) {
2828 crc ^= *p++ << 8;
2829 for (i = 0; i < 8; i++)
2830 crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
2831 }
2832
2833 return crc;
2834}
2835
2836/*
2837 * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise
2838 */
2839static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
2840 int busw)
2841{
2842 struct nand_onfi_params *p = &chip->onfi_params;
2843 int i;
2844 int val;
2845
2846 /* try ONFI for unknow chip or LP */
2847 chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
2848 if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
2849 chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
2850 return 0;
2851
2852 printk(KERN_INFO "ONFI flash detected\n");
2853 chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
2854 for (i = 0; i < 3; i++) {
2855 chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
2856 if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
2857 le16_to_cpu(p->crc)) {
2858 printk(KERN_INFO "ONFI param page %d valid\n", i);
2859 break;
2860 }
2861 }
2862
2863 if (i == 3)
2864 return 0;
2865
2866 /* check version */
2867 val = le16_to_cpu(p->revision);
2868 if (val == 1 || val > (1 << 4)) {
2869 printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
2870 __func__, val);
2871 return 0;
2872 }
2873
2874 if (val & (1 << 4))
2875 chip->onfi_version = 22;
2876 else if (val & (1 << 3))
2877 chip->onfi_version = 21;
2878 else if (val & (1 << 2))
2879 chip->onfi_version = 20;
2880 else
2881 chip->onfi_version = 10;
2882
2883 sanitize_string(p->manufacturer, sizeof(p->manufacturer));
2884 sanitize_string(p->model, sizeof(p->model));
2885 if (!mtd->name)
2886 mtd->name = p->model;
2887 mtd->writesize = le32_to_cpu(p->byte_per_page);
2888 mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
2889 mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
2890 chip->chipsize = le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
2891 busw = 0;
2892 if (le16_to_cpu(p->features) & 1)
2893 busw = NAND_BUSWIDTH_16;
2894
2895 chip->options &= ~NAND_CHIPOPTIONS_MSK;
2896 chip->options |= (NAND_NO_READRDY |
2897 NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK;
2898
2899 return 1;
2900}
2901
2902/*
2790 * Get the flash and manufacturer id and lookup if the type is supported 2903 * Get the flash and manufacturer id and lookup if the type is supported
2791 */ 2904 */
2792static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, 2905static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2793 struct nand_chip *chip, 2906 struct nand_chip *chip,
2794 int busw, int *maf_id, 2907 int busw,
2908 int *maf_id, int *dev_id,
2795 struct nand_flash_dev *type) 2909 struct nand_flash_dev *type)
2796{ 2910{
2797 int i, dev_id, maf_idx; 2911 int i, maf_idx;
2798 u8 id_data[8]; 2912 u8 id_data[8];
2913 int ret;
2799 2914
2800 /* Select the device */ 2915 /* Select the device */
2801 chip->select_chip(mtd, 0); 2916 chip->select_chip(mtd, 0);
@@ -2811,7 +2926,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2811 2926
2812 /* Read manufacturer and device IDs */ 2927 /* Read manufacturer and device IDs */
2813 *maf_id = chip->read_byte(mtd); 2928 *maf_id = chip->read_byte(mtd);
2814 dev_id = chip->read_byte(mtd); 2929 *dev_id = chip->read_byte(mtd);
2815 2930
2816 /* Try again to make sure, as some systems the bus-hold or other 2931 /* Try again to make sure, as some systems the bus-hold or other
2817 * interface concerns can cause random data which looks like a 2932 * interface concerns can cause random data which looks like a
@@ -2821,15 +2936,13 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2821 2936
2822 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); 2937 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
2823 2938
2824 /* Read entire ID string */ 2939 for (i = 0; i < 2; i++)
2825
2826 for (i = 0; i < 8; i++)
2827 id_data[i] = chip->read_byte(mtd); 2940 id_data[i] = chip->read_byte(mtd);
2828 2941
2829 if (id_data[0] != *maf_id || id_data[1] != dev_id) { 2942 if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
2830 printk(KERN_INFO "%s: second ID read did not match " 2943 printk(KERN_INFO "%s: second ID read did not match "
2831 "%02x,%02x against %02x,%02x\n", __func__, 2944 "%02x,%02x against %02x,%02x\n", __func__,
2832 *maf_id, dev_id, id_data[0], id_data[1]); 2945 *maf_id, *dev_id, id_data[0], id_data[1]);
2833 return ERR_PTR(-ENODEV); 2946 return ERR_PTR(-ENODEV);
2834 } 2947 }
2835 2948
@@ -2837,8 +2950,23 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2837 type = nand_flash_ids; 2950 type = nand_flash_ids;
2838 2951
2839 for (; type->name != NULL; type++) 2952 for (; type->name != NULL; type++)
2840 if (dev_id == type->id) 2953 if (*dev_id == type->id)
2841 break; 2954 break;
2955
2956 chip->onfi_version = 0;
2957 if (!type->name || !type->pagesize) {
2958 /* Check is chip is ONFI compliant */
2959 ret = nand_flash_detect_onfi(mtd, chip, busw);
2960 if (ret)
2961 goto ident_done;
2962 }
2963
2964 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
2965
2966 /* Read entire ID string */
2967
2968 for (i = 0; i < 8; i++)
2969 id_data[i] = chip->read_byte(mtd);
2842 2970
2843 if (!type->name) 2971 if (!type->name)
2844 return ERR_PTR(-ENODEV); 2972 return ERR_PTR(-ENODEV);
@@ -2848,8 +2976,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2848 2976
2849 chip->chipsize = (uint64_t)type->chipsize << 20; 2977 chip->chipsize = (uint64_t)type->chipsize << 20;
2850 2978
2851 /* Newer devices have all the information in additional id bytes */ 2979 if (!type->pagesize && chip->init_size) {
2852 if (!type->pagesize) { 2980 /* set the pagesize, oobsize, erasesize by the driver*/
2981 busw = chip->init_size(mtd, chip, id_data);
2982 } else if (!type->pagesize) {
2853 int extid; 2983 int extid;
2854 /* The 3rd id byte holds MLC / multichip data */ 2984 /* The 3rd id byte holds MLC / multichip data */
2855 chip->cellinfo = id_data[2]; 2985 chip->cellinfo = id_data[2];
@@ -2859,7 +2989,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2859 /* 2989 /*
2860 * Field definitions are in the following datasheets: 2990 * Field definitions are in the following datasheets:
2861 * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) 2991 * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
2862 * New style (6 byte ID): Samsung K9GAG08U0D (p.40) 2992 * New style (6 byte ID): Samsung K9GBG08U0M (p.40)
2863 * 2993 *
2864 * Check for wraparound + Samsung ID + nonzero 6th byte 2994 * Check for wraparound + Samsung ID + nonzero 6th byte
2865 * to decide what to do. 2995 * to decide what to do.
@@ -2872,7 +3002,20 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2872 mtd->writesize = 2048 << (extid & 0x03); 3002 mtd->writesize = 2048 << (extid & 0x03);
2873 extid >>= 2; 3003 extid >>= 2;
2874 /* Calc oobsize */ 3004 /* Calc oobsize */
2875 mtd->oobsize = (extid & 0x03) == 0x01 ? 128 : 218; 3005 switch (extid & 0x03) {
3006 case 1:
3007 mtd->oobsize = 128;
3008 break;
3009 case 2:
3010 mtd->oobsize = 218;
3011 break;
3012 case 3:
3013 mtd->oobsize = 400;
3014 break;
3015 default:
3016 mtd->oobsize = 436;
3017 break;
3018 }
2876 extid >>= 2; 3019 extid >>= 2;
2877 /* Calc blocksize */ 3020 /* Calc blocksize */
2878 mtd->erasesize = (128 * 1024) << 3021 mtd->erasesize = (128 * 1024) <<
@@ -2900,7 +3043,35 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2900 mtd->writesize = type->pagesize; 3043 mtd->writesize = type->pagesize;
2901 mtd->oobsize = mtd->writesize / 32; 3044 mtd->oobsize = mtd->writesize / 32;
2902 busw = type->options & NAND_BUSWIDTH_16; 3045 busw = type->options & NAND_BUSWIDTH_16;
3046
3047 /*
3048 * Check for Spansion/AMD ID + repeating 5th, 6th byte since
3049 * some Spansion chips have erasesize that conflicts with size
3050 * listed in nand_ids table
3051 * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
3052 */
3053 if (*maf_id == NAND_MFR_AMD && id_data[4] != 0x00 &&
3054 id_data[5] == 0x00 && id_data[6] == 0x00 &&
3055 id_data[7] == 0x00 && mtd->writesize == 512) {
3056 mtd->erasesize = 128 * 1024;
3057 mtd->erasesize <<= ((id_data[3] & 0x03) << 1);
3058 }
2903 } 3059 }
3060 /* Get chip options, preserve non chip based options */
3061 chip->options &= ~NAND_CHIPOPTIONS_MSK;
3062 chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
3063
3064 /* Check if chip is a not a samsung device. Do not clear the
3065 * options for chips which are not having an extended id.
3066 */
3067 if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
3068 chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
3069ident_done:
3070
3071 /*
3072 * Set chip as a default. Board drivers can override it, if necessary
3073 */
3074 chip->options |= NAND_NO_AUTOINCR;
2904 3075
2905 /* Try to identify manufacturer */ 3076 /* Try to identify manufacturer */
2906 for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { 3077 for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {
@@ -2915,7 +3086,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2915 if (busw != (chip->options & NAND_BUSWIDTH_16)) { 3086 if (busw != (chip->options & NAND_BUSWIDTH_16)) {
2916 printk(KERN_INFO "NAND device: Manufacturer ID:" 3087 printk(KERN_INFO "NAND device: Manufacturer ID:"
2917 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, 3088 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
2918 dev_id, nand_manuf_ids[maf_idx].name, mtd->name); 3089 *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
2919 printk(KERN_WARNING "NAND bus width %d instead %d bit\n", 3090 printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
2920 (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, 3091 (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
2921 busw ? 16 : 8); 3092 busw ? 16 : 8);
@@ -2931,8 +3102,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2931 ffs(mtd->erasesize) - 1; 3102 ffs(mtd->erasesize) - 1;
2932 if (chip->chipsize & 0xffffffff) 3103 if (chip->chipsize & 0xffffffff)
2933 chip->chip_shift = ffs((unsigned)chip->chipsize) - 1; 3104 chip->chip_shift = ffs((unsigned)chip->chipsize) - 1;
2934 else 3105 else {
2935 chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1; 3106 chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32));
3107 chip->chip_shift += 32 - 1;
3108 }
2936 3109
2937 /* Set the bad block position */ 3110 /* Set the bad block position */
2938 if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16)) 3111 if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16))
@@ -2940,27 +3113,12 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2940 else 3113 else
2941 chip->badblockpos = NAND_SMALL_BADBLOCK_POS; 3114 chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
2942 3115
2943 /* Get chip options, preserve non chip based options */
2944 chip->options &= ~NAND_CHIPOPTIONS_MSK;
2945 chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
2946
2947 /*
2948 * Set chip as a default. Board drivers can override it, if necessary
2949 */
2950 chip->options |= NAND_NO_AUTOINCR;
2951
2952 /* Check if chip is a not a samsung device. Do not clear the
2953 * options for chips which are not having an extended id.
2954 */
2955 if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
2956 chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
2957
2958 /* 3116 /*
2959 * Bad block marker is stored in the last page of each block 3117 * Bad block marker is stored in the last page of each block
2960 * on Samsung and Hynix MLC devices; stored in first two pages 3118 * on Samsung and Hynix MLC devices; stored in first two pages
2961 * of each block on Micron devices with 2KiB pages and on 3119 * of each block on Micron devices with 2KiB pages and on
2962 * SLC Samsung, Hynix, and AMD/Spansion. All others scan only 3120 * SLC Samsung, Hynix, Toshiba and AMD/Spansion. All others scan
2963 * the first page. 3121 * only the first page.
2964 */ 3122 */
2965 if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && 3123 if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
2966 (*maf_id == NAND_MFR_SAMSUNG || 3124 (*maf_id == NAND_MFR_SAMSUNG ||
@@ -2969,6 +3127,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2969 else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && 3127 else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
2970 (*maf_id == NAND_MFR_SAMSUNG || 3128 (*maf_id == NAND_MFR_SAMSUNG ||
2971 *maf_id == NAND_MFR_HYNIX || 3129 *maf_id == NAND_MFR_HYNIX ||
3130 *maf_id == NAND_MFR_TOSHIBA ||
2972 *maf_id == NAND_MFR_AMD)) || 3131 *maf_id == NAND_MFR_AMD)) ||
2973 (mtd->writesize == 2048 && 3132 (mtd->writesize == 2048 &&
2974 *maf_id == NAND_MFR_MICRON)) 3133 *maf_id == NAND_MFR_MICRON))
@@ -2994,9 +3153,11 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2994 if (mtd->writesize > 512 && chip->cmdfunc == nand_command) 3153 if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
2995 chip->cmdfunc = nand_command_lp; 3154 chip->cmdfunc = nand_command_lp;
2996 3155
3156 /* TODO onfi flash name */
2997 printk(KERN_INFO "NAND device: Manufacturer ID:" 3157 printk(KERN_INFO "NAND device: Manufacturer ID:"
2998 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id, 3158 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id,
2999 nand_manuf_ids[maf_idx].name, type->name); 3159 nand_manuf_ids[maf_idx].name,
3160 chip->onfi_version ? type->name : chip->onfi_params.model);
3000 3161
3001 return type; 3162 return type;
3002} 3163}
@@ -3015,7 +3176,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
3015int nand_scan_ident(struct mtd_info *mtd, int maxchips, 3176int nand_scan_ident(struct mtd_info *mtd, int maxchips,
3016 struct nand_flash_dev *table) 3177 struct nand_flash_dev *table)
3017{ 3178{
3018 int i, busw, nand_maf_id; 3179 int i, busw, nand_maf_id, nand_dev_id;
3019 struct nand_chip *chip = mtd->priv; 3180 struct nand_chip *chip = mtd->priv;
3020 struct nand_flash_dev *type; 3181 struct nand_flash_dev *type;
3021 3182
@@ -3025,7 +3186,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
3025 nand_set_defaults(chip, busw); 3186 nand_set_defaults(chip, busw);
3026 3187
3027 /* Read the flash type */ 3188 /* Read the flash type */
3028 type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id, table); 3189 type = nand_get_flash_type(mtd, chip, busw,
3190 &nand_maf_id, &nand_dev_id, table);
3029 3191
3030 if (IS_ERR(type)) { 3192 if (IS_ERR(type)) {
3031 if (!(chip->options & NAND_SCAN_SILENT_NODEV)) 3193 if (!(chip->options & NAND_SCAN_SILENT_NODEV))
@@ -3043,7 +3205,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
3043 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); 3205 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
3044 /* Read manufacturer and device IDs */ 3206 /* Read manufacturer and device IDs */
3045 if (nand_maf_id != chip->read_byte(mtd) || 3207 if (nand_maf_id != chip->read_byte(mtd) ||
3046 type->id != chip->read_byte(mtd)) 3208 nand_dev_id != chip->read_byte(mtd))
3047 break; 3209 break;
3048 } 3210 }
3049 if (i > 1) 3211 if (i > 1)
@@ -3055,6 +3217,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
3055 3217
3056 return 0; 3218 return 0;
3057} 3219}
3220EXPORT_SYMBOL(nand_scan_ident);
3058 3221
3059 3222
3060/** 3223/**
@@ -3219,7 +3382,7 @@ int nand_scan_tail(struct mtd_info *mtd)
3219 * mode 3382 * mode
3220 */ 3383 */
3221 chip->ecc.steps = mtd->writesize / chip->ecc.size; 3384 chip->ecc.steps = mtd->writesize / chip->ecc.size;
3222 if(chip->ecc.steps * chip->ecc.size != mtd->writesize) { 3385 if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {
3223 printk(KERN_WARNING "Invalid ecc parameters\n"); 3386 printk(KERN_WARNING "Invalid ecc parameters\n");
3224 BUG(); 3387 BUG();
3225 } 3388 }
@@ -3231,7 +3394,7 @@ int nand_scan_tail(struct mtd_info *mtd)
3231 */ 3394 */
3232 if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && 3395 if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
3233 !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { 3396 !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
3234 switch(chip->ecc.steps) { 3397 switch (chip->ecc.steps) {
3235 case 2: 3398 case 2:
3236 mtd->subpage_sft = 1; 3399 mtd->subpage_sft = 1;
3237 break; 3400 break;
@@ -3283,10 +3446,11 @@ int nand_scan_tail(struct mtd_info *mtd)
3283 /* Build bad block table */ 3446 /* Build bad block table */
3284 return chip->scan_bbt(mtd); 3447 return chip->scan_bbt(mtd);
3285} 3448}
3449EXPORT_SYMBOL(nand_scan_tail);
3286 3450
3287/* is_module_text_address() isn't exported, and it's mostly a pointless 3451/* is_module_text_address() isn't exported, and it's mostly a pointless
3288 test if this is a module _anyway_ -- they'd have to try _really_ hard 3452 * test if this is a module _anyway_ -- they'd have to try _really_ hard
3289 to call us from in-kernel code if the core NAND support is modular. */ 3453 * to call us from in-kernel code if the core NAND support is modular. */
3290#ifdef MODULE 3454#ifdef MODULE
3291#define caller_is_module() (1) 3455#define caller_is_module() (1)
3292#else 3456#else
@@ -3322,6 +3486,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
3322 ret = nand_scan_tail(mtd); 3486 ret = nand_scan_tail(mtd);
3323 return ret; 3487 return ret;
3324} 3488}
3489EXPORT_SYMBOL(nand_scan);
3325 3490
3326/** 3491/**
3327 * nand_release - [NAND Interface] Free resources held by the NAND device 3492 * nand_release - [NAND Interface] Free resources held by the NAND device
@@ -3348,12 +3513,6 @@ void nand_release(struct mtd_info *mtd)
3348 & NAND_BBT_DYNAMICSTRUCT) 3513 & NAND_BBT_DYNAMICSTRUCT)
3349 kfree(chip->badblock_pattern); 3514 kfree(chip->badblock_pattern);
3350} 3515}
3351
3352EXPORT_SYMBOL_GPL(nand_lock);
3353EXPORT_SYMBOL_GPL(nand_unlock);
3354EXPORT_SYMBOL_GPL(nand_scan);
3355EXPORT_SYMBOL_GPL(nand_scan_ident);
3356EXPORT_SYMBOL_GPL(nand_scan_tail);
3357EXPORT_SYMBOL_GPL(nand_release); 3516EXPORT_SYMBOL_GPL(nand_release);
3358 3517
3359static int __init nand_base_init(void) 3518static int __init nand_base_init(void)
@@ -3371,5 +3530,6 @@ module_init(nand_base_init);
3371module_exit(nand_base_exit); 3530module_exit(nand_base_exit);
3372 3531
3373MODULE_LICENSE("GPL"); 3532MODULE_LICENSE("GPL");
3374MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>"); 3533MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>");
3534MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
3375MODULE_DESCRIPTION("Generic NAND flash driver code"); 3535MODULE_DESCRIPTION("Generic NAND flash driver code");
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 5fedf4a74f16..586b981f0e61 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -13,28 +13,37 @@
13 * Description: 13 * Description:
14 * 14 *
15 * When nand_scan_bbt is called, then it tries to find the bad block table 15 * When nand_scan_bbt is called, then it tries to find the bad block table
16 * depending on the options in the bbt descriptor(s). If a bbt is found 16 * depending on the options in the BBT descriptor(s). If no flash based BBT
17 * then the contents are read and the memory based bbt is created. If a 17 * (NAND_USE_FLASH_BBT) is specified then the device is scanned for factory
18 * mirrored bbt is selected then the mirror is searched too and the 18 * marked good / bad blocks. This information is used to create a memory BBT.
19 * versions are compared. If the mirror has a greater version number 19 * Once a new bad block is discovered then the "factory" information is updated
20 * than the mirror bbt is used to build the memory based bbt. 20 * on the device.
21 * If a flash based BBT is specified then the function first tries to find the
22 * BBT on flash. If a BBT is found then the contents are read and the memory
23 * based BBT is created. If a mirrored BBT is selected then the mirror is
24 * searched too and the versions are compared. If the mirror has a greater
25 * version number than the mirror BBT is used to build the memory based BBT.
21 * If the tables are not versioned, then we "or" the bad block information. 26 * If the tables are not versioned, then we "or" the bad block information.
22 * If one of the bbt's is out of date or does not exist it is (re)created. 27 * If one of the BBTs is out of date or does not exist it is (re)created.
23 * If no bbt exists at all then the device is scanned for factory marked 28 * If no BBT exists at all then the device is scanned for factory marked
24 * good / bad blocks and the bad block tables are created. 29 * good / bad blocks and the bad block tables are created.
25 * 30 *
26 * For manufacturer created bbts like the one found on M-SYS DOC devices 31 * For manufacturer created BBTs like the one found on M-SYS DOC devices
27 * the bbt is searched and read but never created 32 * the BBT is searched and read but never created
28 * 33 *
29 * The autogenerated bad block table is located in the last good blocks 34 * The auto generated bad block table is located in the last good blocks
30 * of the device. The table is mirrored, so it can be updated eventually. 35 * of the device. The table is mirrored, so it can be updated eventually.
31 * The table is marked in the oob area with an ident pattern and a version 36 * The table is marked in the OOB area with an ident pattern and a version
32 * number which indicates which of both tables is more up to date. 37 * number which indicates which of both tables is more up to date. If the NAND
38 * controller needs the complete OOB area for the ECC information then the
39 * option NAND_USE_FLASH_BBT_NO_OOB should be used: it moves the ident pattern
40 * and the version byte into the data area and the OOB area will remain
41 * untouched.
33 * 42 *
34 * The table uses 2 bits per block 43 * The table uses 2 bits per block
35 * 11b: block is good 44 * 11b: block is good
36 * 00b: block is factory marked bad 45 * 00b: block is factory marked bad
37 * 01b, 10b: block is marked bad due to wear 46 * 01b, 10b: block is marked bad due to wear
38 * 47 *
39 * The memory bad block table uses the following scheme: 48 * The memory bad block table uses the following scheme:
40 * 00b: block is good 49 * 00b: block is good
@@ -59,6 +68,16 @@
59#include <linux/delay.h> 68#include <linux/delay.h>
60#include <linux/vmalloc.h> 69#include <linux/vmalloc.h>
61 70
71static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
72{
73 int ret;
74
75 ret = memcmp(buf, td->pattern, td->len);
76 if (!ret)
77 return ret;
78 return -1;
79}
80
62/** 81/**
63 * check_pattern - [GENERIC] check if a pattern is in the buffer 82 * check_pattern - [GENERIC] check if a pattern is in the buffer
64 * @buf: the buffer to search 83 * @buf: the buffer to search
@@ -77,6 +96,9 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc
77 int i, end = 0; 96 int i, end = 0;
78 uint8_t *p = buf; 97 uint8_t *p = buf;
79 98
99 if (td->options & NAND_BBT_NO_OOB)
100 return check_pattern_no_oob(buf, td);
101
80 end = paglen + td->offs; 102 end = paglen + td->offs;
81 if (td->options & NAND_BBT_SCANEMPTY) { 103 if (td->options & NAND_BBT_SCANEMPTY) {
82 for (i = 0; i < end; i++) { 104 for (i = 0; i < end; i++) {
@@ -156,32 +178,63 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
156} 178}
157 179
158/** 180/**
181 * add_marker_len - compute the length of the marker in data area
182 * @td: BBT descriptor used for computation
183 *
184 * The length will be 0 if the markeris located in OOB area.
185 */
186static u32 add_marker_len(struct nand_bbt_descr *td)
187{
188 u32 len;
189
190 if (!(td->options & NAND_BBT_NO_OOB))
191 return 0;
192
193 len = td->len;
194 if (td->options & NAND_BBT_VERSION)
195 len++;
196 return len;
197}
198
199/**
159 * read_bbt - [GENERIC] Read the bad block table starting from page 200 * read_bbt - [GENERIC] Read the bad block table starting from page
160 * @mtd: MTD device structure 201 * @mtd: MTD device structure
161 * @buf: temporary buffer 202 * @buf: temporary buffer
162 * @page: the starting page 203 * @page: the starting page
163 * @num: the number of bbt descriptors to read 204 * @num: the number of bbt descriptors to read
164 * @bits: number of bits per block 205 * @td: the bbt describtion table
165 * @offs: offset in the memory table 206 * @offs: offset in the memory table
166 * @reserved_block_code: Pattern to identify reserved blocks
167 * 207 *
168 * Read the bad block table starting from page. 208 * Read the bad block table starting from page.
169 * 209 *
170 */ 210 */
171static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, 211static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
172 int bits, int offs, int reserved_block_code) 212 struct nand_bbt_descr *td, int offs)
173{ 213{
174 int res, i, j, act = 0; 214 int res, i, j, act = 0;
175 struct nand_chip *this = mtd->priv; 215 struct nand_chip *this = mtd->priv;
176 size_t retlen, len, totlen; 216 size_t retlen, len, totlen;
177 loff_t from; 217 loff_t from;
218 int bits = td->options & NAND_BBT_NRBITS_MSK;
178 uint8_t msk = (uint8_t) ((1 << bits) - 1); 219 uint8_t msk = (uint8_t) ((1 << bits) - 1);
220 u32 marker_len;
221 int reserved_block_code = td->reserved_block_code;
179 222
180 totlen = (num * bits) >> 3; 223 totlen = (num * bits) >> 3;
224 marker_len = add_marker_len(td);
181 from = ((loff_t) page) << this->page_shift; 225 from = ((loff_t) page) << this->page_shift;
182 226
183 while (totlen) { 227 while (totlen) {
184 len = min(totlen, (size_t) (1 << this->bbt_erase_shift)); 228 len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
229 if (marker_len) {
230 /*
231 * In case the BBT marker is not in the OOB area it
232 * will be just in the first page.
233 */
234 len -= marker_len;
235 from += marker_len;
236 marker_len = 0;
237 }
185 res = mtd->read(mtd, from, len, &retlen, buf); 238 res = mtd->read(mtd, from, len, &retlen, buf);
186 if (res < 0) { 239 if (res < 0) {
187 if (retlen != len) { 240 if (retlen != len) {
@@ -238,20 +291,21 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
238{ 291{
239 struct nand_chip *this = mtd->priv; 292 struct nand_chip *this = mtd->priv;
240 int res = 0, i; 293 int res = 0, i;
241 int bits;
242 294
243 bits = td->options & NAND_BBT_NRBITS_MSK;
244 if (td->options & NAND_BBT_PERCHIP) { 295 if (td->options & NAND_BBT_PERCHIP) {
245 int offs = 0; 296 int offs = 0;
246 for (i = 0; i < this->numchips; i++) { 297 for (i = 0; i < this->numchips; i++) {
247 if (chip == -1 || chip == i) 298 if (chip == -1 || chip == i)
248 res = read_bbt (mtd, buf, td->pages[i], this->chipsize >> this->bbt_erase_shift, bits, offs, td->reserved_block_code); 299 res = read_bbt(mtd, buf, td->pages[i],
300 this->chipsize >> this->bbt_erase_shift,
301 td, offs);
249 if (res) 302 if (res)
250 return res; 303 return res;
251 offs += this->chipsize >> (this->bbt_erase_shift + 2); 304 offs += this->chipsize >> (this->bbt_erase_shift + 2);
252 } 305 }
253 } else { 306 } else {
254 res = read_bbt (mtd, buf, td->pages[0], mtd->size >> this->bbt_erase_shift, bits, 0, td->reserved_block_code); 307 res = read_bbt(mtd, buf, td->pages[0],
308 mtd->size >> this->bbt_erase_shift, td, 0);
255 if (res) 309 if (res)
256 return res; 310 return res;
257 } 311 }
@@ -259,9 +313,25 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
259} 313}
260 314
261/* 315/*
316 * BBT marker is in the first page, no OOB.
317 */
318static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
319 struct nand_bbt_descr *td)
320{
321 size_t retlen;
322 size_t len;
323
324 len = td->len;
325 if (td->options & NAND_BBT_VERSION)
326 len++;
327
328 return mtd->read(mtd, offs, len, &retlen, buf);
329}
330
331/*
262 * Scan read raw data from flash 332 * Scan read raw data from flash
263 */ 333 */
264static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs, 334static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
265 size_t len) 335 size_t len)
266{ 336{
267 struct mtd_oob_ops ops; 337 struct mtd_oob_ops ops;
@@ -294,6 +364,15 @@ static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
294 return 0; 364 return 0;
295} 365}
296 366
367static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
368 size_t len, struct nand_bbt_descr *td)
369{
370 if (td->options & NAND_BBT_NO_OOB)
371 return scan_read_raw_data(mtd, buf, offs, td);
372 else
373 return scan_read_raw_oob(mtd, buf, offs, len);
374}
375
297/* 376/*
298 * Scan write data with oob to flash 377 * Scan write data with oob to flash
299 */ 378 */
@@ -312,6 +391,15 @@ static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
312 return mtd->write_oob(mtd, offs, &ops); 391 return mtd->write_oob(mtd, offs, &ops);
313} 392}
314 393
394static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
395{
396 u32 ver_offs = td->veroffs;
397
398 if (!(td->options & NAND_BBT_NO_OOB))
399 ver_offs += mtd->writesize;
400 return ver_offs;
401}
402
315/** 403/**
316 * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page 404 * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
317 * @mtd: MTD device structure 405 * @mtd: MTD device structure
@@ -331,8 +419,8 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
331 /* Read the primary version, if available */ 419 /* Read the primary version, if available */
332 if (td->options & NAND_BBT_VERSION) { 420 if (td->options & NAND_BBT_VERSION) {
333 scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift, 421 scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
334 mtd->writesize); 422 mtd->writesize, td);
335 td->version[0] = buf[mtd->writesize + td->veroffs]; 423 td->version[0] = buf[bbt_get_ver_offs(mtd, td)];
336 printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", 424 printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
337 td->pages[0], td->version[0]); 425 td->pages[0], td->version[0]);
338 } 426 }
@@ -340,8 +428,8 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
340 /* Read the mirror version, if available */ 428 /* Read the mirror version, if available */
341 if (md && (md->options & NAND_BBT_VERSION)) { 429 if (md && (md->options & NAND_BBT_VERSION)) {
342 scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, 430 scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
343 mtd->writesize); 431 mtd->writesize, td);
344 md->version[0] = buf[mtd->writesize + md->veroffs]; 432 md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
345 printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", 433 printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
346 md->pages[0], md->version[0]); 434 md->pages[0], md->version[0]);
347 } 435 }
@@ -357,7 +445,7 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
357{ 445{
358 int ret, j; 446 int ret, j;
359 447
360 ret = scan_read_raw(mtd, buf, offs, readlen); 448 ret = scan_read_raw_oob(mtd, buf, offs, readlen);
361 if (ret) 449 if (ret)
362 return ret; 450 return ret;
363 451
@@ -464,6 +552,8 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
464 for (i = startblock; i < numblocks;) { 552 for (i = startblock; i < numblocks;) {
465 int ret; 553 int ret;
466 554
555 BUG_ON(bd->options & NAND_BBT_NO_OOB);
556
467 if (bd->options & NAND_BBT_SCANALLPAGES) 557 if (bd->options & NAND_BBT_SCANALLPAGES)
468 ret = scan_block_full(mtd, bd, from, buf, readlen, 558 ret = scan_block_full(mtd, bd, from, buf, readlen,
469 scanlen, len); 559 scanlen, len);
@@ -545,11 +635,12 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
545 loff_t offs = (loff_t)actblock << this->bbt_erase_shift; 635 loff_t offs = (loff_t)actblock << this->bbt_erase_shift;
546 636
547 /* Read first page */ 637 /* Read first page */
548 scan_read_raw(mtd, buf, offs, mtd->writesize); 638 scan_read_raw(mtd, buf, offs, mtd->writesize, td);
549 if (!check_pattern(buf, scanlen, mtd->writesize, td)) { 639 if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
550 td->pages[i] = actblock << blocktopage; 640 td->pages[i] = actblock << blocktopage;
551 if (td->options & NAND_BBT_VERSION) { 641 if (td->options & NAND_BBT_VERSION) {
552 td->version[i] = buf[mtd->writesize + td->veroffs]; 642 offs = bbt_get_ver_offs(mtd, td);
643 td->version[i] = buf[offs];
553 } 644 }
554 break; 645 break;
555 } 646 }
@@ -733,12 +824,26 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
733 memset(&buf[offs], 0xff, (size_t) (numblocks >> sft)); 824 memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
734 ooboffs = len + (pageoffs * mtd->oobsize); 825 ooboffs = len + (pageoffs * mtd->oobsize);
735 826
827 } else if (td->options & NAND_BBT_NO_OOB) {
828 ooboffs = 0;
829 offs = td->len;
830 /* the version byte */
831 if (td->options & NAND_BBT_VERSION)
832 offs++;
833 /* Calc length */
834 len = (size_t) (numblocks >> sft);
835 len += offs;
836 /* Make it page aligned ! */
837 len = ALIGN(len, mtd->writesize);
838 /* Preset the buffer with 0xff */
839 memset(buf, 0xff, len);
840 /* Pattern is located at the begin of first page */
841 memcpy(buf, td->pattern, td->len);
736 } else { 842 } else {
737 /* Calc length */ 843 /* Calc length */
738 len = (size_t) (numblocks >> sft); 844 len = (size_t) (numblocks >> sft);
739 /* Make it page aligned ! */ 845 /* Make it page aligned ! */
740 len = (len + (mtd->writesize - 1)) & 846 len = ALIGN(len, mtd->writesize);
741 ~(mtd->writesize - 1);
742 /* Preset the buffer with 0xff */ 847 /* Preset the buffer with 0xff */
743 memset(buf, 0xff, len + 848 memset(buf, 0xff, len +
744 (len >> this->page_shift)* mtd->oobsize); 849 (len >> this->page_shift)* mtd->oobsize);
@@ -772,7 +877,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
772 if (res < 0) 877 if (res < 0)
773 goto outerr; 878 goto outerr;
774 879
775 res = scan_write_bbt(mtd, to, len, buf, &buf[len]); 880 res = scan_write_bbt(mtd, to, len, buf,
881 td->options & NAND_BBT_NO_OOB ? NULL :
882 &buf[len]);
776 if (res < 0) 883 if (res < 0)
777 goto outerr; 884 goto outerr;
778 885
@@ -892,7 +999,8 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
892 continue; 999 continue;
893 1000
894 /* Create the table in memory by scanning the chip(s) */ 1001 /* Create the table in memory by scanning the chip(s) */
895 create_bbt(mtd, buf, bd, chipsel); 1002 if (!(this->options & NAND_CREATE_EMPTY_BBT))
1003 create_bbt(mtd, buf, bd, chipsel);
896 1004
897 td->version[i] = 1; 1005 td->version[i] = 1;
898 if (md) 1006 if (md)
@@ -983,6 +1091,49 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
983} 1091}
984 1092
985/** 1093/**
1094 * verify_bbt_descr - verify the bad block description
1095 * @bd: the table to verify
1096 *
1097 * This functions performs a few sanity checks on the bad block description
1098 * table.
1099 */
1100static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
1101{
1102 struct nand_chip *this = mtd->priv;
1103 u32 pattern_len = bd->len;
1104 u32 bits = bd->options & NAND_BBT_NRBITS_MSK;
1105 u32 table_size;
1106
1107 if (!bd)
1108 return;
1109 BUG_ON((this->options & NAND_USE_FLASH_BBT_NO_OOB) &&
1110 !(this->options & NAND_USE_FLASH_BBT));
1111 BUG_ON(!bits);
1112
1113 if (bd->options & NAND_BBT_VERSION)
1114 pattern_len++;
1115
1116 if (bd->options & NAND_BBT_NO_OOB) {
1117 BUG_ON(!(this->options & NAND_USE_FLASH_BBT));
1118 BUG_ON(!(this->options & NAND_USE_FLASH_BBT_NO_OOB));
1119 BUG_ON(bd->offs);
1120 if (bd->options & NAND_BBT_VERSION)
1121 BUG_ON(bd->veroffs != bd->len);
1122 BUG_ON(bd->options & NAND_BBT_SAVECONTENT);
1123 }
1124
1125 if (bd->options & NAND_BBT_PERCHIP)
1126 table_size = this->chipsize >> this->bbt_erase_shift;
1127 else
1128 table_size = mtd->size >> this->bbt_erase_shift;
1129 table_size >>= 3;
1130 table_size *= bits;
1131 if (bd->options & NAND_BBT_NO_OOB)
1132 table_size += pattern_len;
1133 BUG_ON(table_size > (1 << this->bbt_erase_shift));
1134}
1135
1136/**
986 * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s) 1137 * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s)
987 * @mtd: MTD device structure 1138 * @mtd: MTD device structure
988 * @bd: descriptor for the good/bad block search pattern 1139 * @bd: descriptor for the good/bad block search pattern
@@ -1023,6 +1174,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
1023 } 1174 }
1024 return res; 1175 return res;
1025 } 1176 }
1177 verify_bbt_descr(mtd, td);
1178 verify_bbt_descr(mtd, md);
1026 1179
1027 /* Allocate a temporary buffer for one eraseblock incl. oob */ 1180 /* Allocate a temporary buffer for one eraseblock incl. oob */
1028 len = (1 << this->bbt_erase_shift); 1181 len = (1 << this->bbt_erase_shift);
@@ -1166,6 +1319,26 @@ static struct nand_bbt_descr bbt_mirror_descr = {
1166 .pattern = mirror_pattern 1319 .pattern = mirror_pattern
1167}; 1320};
1168 1321
1322static struct nand_bbt_descr bbt_main_no_bbt_descr = {
1323 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1324 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
1325 | NAND_BBT_NO_OOB,
1326 .len = 4,
1327 .veroffs = 4,
1328 .maxblocks = 4,
1329 .pattern = bbt_pattern
1330};
1331
1332static struct nand_bbt_descr bbt_mirror_no_bbt_descr = {
1333 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1334 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
1335 | NAND_BBT_NO_OOB,
1336 .len = 4,
1337 .veroffs = 4,
1338 .maxblocks = 4,
1339 .pattern = mirror_pattern
1340};
1341
1169#define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \ 1342#define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \
1170 NAND_BBT_SCANBYTE1AND6) 1343 NAND_BBT_SCANBYTE1AND6)
1171/** 1344/**
@@ -1236,8 +1409,13 @@ int nand_default_bbt(struct mtd_info *mtd)
1236 if (this->options & NAND_USE_FLASH_BBT) { 1409 if (this->options & NAND_USE_FLASH_BBT) {
1237 /* Use the default pattern descriptors */ 1410 /* Use the default pattern descriptors */
1238 if (!this->bbt_td) { 1411 if (!this->bbt_td) {
1239 this->bbt_td = &bbt_main_descr; 1412 if (this->options & NAND_USE_FLASH_BBT_NO_OOB) {
1240 this->bbt_md = &bbt_mirror_descr; 1413 this->bbt_td = &bbt_main_no_bbt_descr;
1414 this->bbt_md = &bbt_mirror_no_bbt_descr;
1415 } else {
1416 this->bbt_td = &bbt_main_descr;
1417 this->bbt_md = &bbt_mirror_descr;
1418 }
1241 } 1419 }
1242 if (!this->badblock_pattern) { 1420 if (!this->badblock_pattern) {
1243 this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased; 1421 this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased;
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index c65f19074bc8..00cf1b0d6053 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -75,9 +75,13 @@ struct nand_flash_dev nand_flash_ids[] = {
75 75
76 /*512 Megabit */ 76 /*512 Megabit */
77 {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS}, 77 {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS},
78 {"NAND 64MiB 1,8V 8-bit", 0xA0, 0, 64, 0, LP_OPTIONS},
78 {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS}, 79 {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS},
80 {"NAND 64MiB 3,3V 8-bit", 0xD0, 0, 64, 0, LP_OPTIONS},
79 {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16}, 81 {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16},
82 {"NAND 64MiB 1,8V 16-bit", 0xB0, 0, 64, 0, LP_OPTIONS16},
80 {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16}, 83 {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16},
84 {"NAND 64MiB 3,3V 16-bit", 0xC0, 0, 64, 0, LP_OPTIONS16},
81 85
82 /* 1 Gigabit */ 86 /* 1 Gigabit */
83 {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS}, 87 {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS},
@@ -112,7 +116,34 @@ struct nand_flash_dev nand_flash_ids[] = {
112 {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, 116 {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16},
113 117
114 /* 32 Gigabit */ 118 /* 32 Gigabit */
119 {"NAND 4GiB 1,8V 8-bit", 0xA7, 0, 4096, 0, LP_OPTIONS},
115 {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS}, 120 {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS},
121 {"NAND 4GiB 1,8V 16-bit", 0xB7, 0, 4096, 0, LP_OPTIONS16},
122 {"NAND 4GiB 3,3V 16-bit", 0xC7, 0, 4096, 0, LP_OPTIONS16},
123
124 /* 64 Gigabit */
125 {"NAND 8GiB 1,8V 8-bit", 0xAE, 0, 8192, 0, LP_OPTIONS},
126 {"NAND 8GiB 3,3V 8-bit", 0xDE, 0, 8192, 0, LP_OPTIONS},
127 {"NAND 8GiB 1,8V 16-bit", 0xBE, 0, 8192, 0, LP_OPTIONS16},
128 {"NAND 8GiB 3,3V 16-bit", 0xCE, 0, 8192, 0, LP_OPTIONS16},
129
130 /* 128 Gigabit */
131 {"NAND 16GiB 1,8V 8-bit", 0x1A, 0, 16384, 0, LP_OPTIONS},
132 {"NAND 16GiB 3,3V 8-bit", 0x3A, 0, 16384, 0, LP_OPTIONS},
133 {"NAND 16GiB 1,8V 16-bit", 0x2A, 0, 16384, 0, LP_OPTIONS16},
134 {"NAND 16GiB 3,3V 16-bit", 0x4A, 0, 16384, 0, LP_OPTIONS16},
135
136 /* 256 Gigabit */
137 {"NAND 32GiB 1,8V 8-bit", 0x1C, 0, 32768, 0, LP_OPTIONS},
138 {"NAND 32GiB 3,3V 8-bit", 0x3C, 0, 32768, 0, LP_OPTIONS},
139 {"NAND 32GiB 1,8V 16-bit", 0x2C, 0, 32768, 0, LP_OPTIONS16},
140 {"NAND 32GiB 3,3V 16-bit", 0x4C, 0, 32768, 0, LP_OPTIONS16},
141
142 /* 512 Gigabit */
143 {"NAND 64GiB 1,8V 8-bit", 0x1E, 0, 65536, 0, LP_OPTIONS},
144 {"NAND 64GiB 3,3V 8-bit", 0x3E, 0, 65536, 0, LP_OPTIONS},
145 {"NAND 64GiB 1,8V 16-bit", 0x2E, 0, 65536, 0, LP_OPTIONS16},
146 {"NAND 64GiB 3,3V 16-bit", 0x4E, 0, 65536, 0, LP_OPTIONS16},
116 147
117 /* 148 /*
118 * Renesas AND 1 Gigabit. Those chips do not support extended id and 149 * Renesas AND 1 Gigabit. Those chips do not support extended id and
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index c25648bb5793..a6a73aab1253 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -107,6 +107,7 @@ static char *gravepages = NULL;
107static unsigned int rptwear = 0; 107static unsigned int rptwear = 0;
108static unsigned int overridesize = 0; 108static unsigned int overridesize = 0;
109static char *cache_file = NULL; 109static char *cache_file = NULL;
110static unsigned int bbt;
110 111
111module_param(first_id_byte, uint, 0400); 112module_param(first_id_byte, uint, 0400);
112module_param(second_id_byte, uint, 0400); 113module_param(second_id_byte, uint, 0400);
@@ -130,6 +131,7 @@ module_param(gravepages, charp, 0400);
130module_param(rptwear, uint, 0400); 131module_param(rptwear, uint, 0400);
131module_param(overridesize, uint, 0400); 132module_param(overridesize, uint, 0400);
132module_param(cache_file, charp, 0400); 133module_param(cache_file, charp, 0400);
134module_param(bbt, uint, 0400);
133 135
134MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)"); 136MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)");
135MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); 137MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)");
@@ -162,6 +164,7 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I
162 "The size is specified in erase blocks and as the exponent of a power of two" 164 "The size is specified in erase blocks and as the exponent of a power of two"
163 " e.g. 5 means a size of 32 erase blocks"); 165 " e.g. 5 means a size of 32 erase blocks");
164MODULE_PARM_DESC(cache_file, "File to use to cache nand pages instead of memory"); 166MODULE_PARM_DESC(cache_file, "File to use to cache nand pages instead of memory");
167MODULE_PARM_DESC(bbt, "0 OOB, 1 BBT with marker in OOB, 2 BBT with marker in data area");
165 168
166/* The largest possible page size */ 169/* The largest possible page size */
167#define NS_LARGEST_PAGE_SIZE 4096 170#define NS_LARGEST_PAGE_SIZE 4096
@@ -2264,6 +2267,18 @@ static int __init ns_init_module(void)
2264 /* and 'badblocks' parameters to work */ 2267 /* and 'badblocks' parameters to work */
2265 chip->options |= NAND_SKIP_BBTSCAN; 2268 chip->options |= NAND_SKIP_BBTSCAN;
2266 2269
2270 switch (bbt) {
2271 case 2:
2272 chip->options |= NAND_USE_FLASH_BBT_NO_OOB;
2273 case 1:
2274 chip->options |= NAND_USE_FLASH_BBT;
2275 case 0:
2276 break;
2277 default:
2278 NS_ERR("bbt has to be 0..2\n");
2279 retval = -EINVAL;
2280 goto error;
2281 }
2267 /* 2282 /*
2268 * Perform minimum nandsim structure initialization to handle 2283 * Perform minimum nandsim structure initialization to handle
2269 * the initial ID read command correctly 2284 * the initial ID read command correctly
@@ -2321,10 +2336,10 @@ static int __init ns_init_module(void)
2321 if ((retval = init_nandsim(nsmtd)) != 0) 2336 if ((retval = init_nandsim(nsmtd)) != 0)
2322 goto err_exit; 2337 goto err_exit;
2323 2338
2324 if ((retval = parse_badblocks(nand, nsmtd)) != 0) 2339 if ((retval = nand_default_bbt(nsmtd)) != 0)
2325 goto err_exit; 2340 goto err_exit;
2326 2341
2327 if ((retval = nand_default_bbt(nsmtd)) != 0) 2342 if ((retval = parse_badblocks(nand, nsmtd)) != 0)
2328 goto err_exit; 2343 goto err_exit;
2329 2344
2330 /* Register NAND partitions */ 2345 /* Register NAND partitions */
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 510554e6c115..c9ae0a5023b6 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -229,7 +229,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev,
229 const struct of_device_id *match) 229 const struct of_device_id *match)
230{ 230{
231 struct ndfc_controller *ndfc = &ndfc_ctrl; 231 struct ndfc_controller *ndfc = &ndfc_ctrl;
232 const u32 *reg; 232 const __be32 *reg;
233 u32 ccr; 233 u32 ccr;
234 int err, len; 234 int err, len;
235 235
@@ -244,7 +244,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev,
244 dev_err(&ofdev->dev, "unable read reg property (%d)\n", len); 244 dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
245 return -ENOENT; 245 return -ENOENT;
246 } 246 }
247 ndfc->chip_select = reg[0]; 247 ndfc->chip_select = be32_to_cpu(reg[0]);
248 248
249 ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0); 249 ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0);
250 if (!ndfc->ndfcbase) { 250 if (!ndfc->ndfcbase) {
@@ -257,7 +257,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev,
257 /* It is ok if ccr does not exist - just default to 0 */ 257 /* It is ok if ccr does not exist - just default to 0 */
258 reg = of_get_property(ofdev->dev.of_node, "ccr", NULL); 258 reg = of_get_property(ofdev->dev.of_node, "ccr", NULL);
259 if (reg) 259 if (reg)
260 ccr |= *reg; 260 ccr |= be32_to_cpup(reg);
261 261
262 out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); 262 out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
263 263
@@ -265,7 +265,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev,
265 reg = of_get_property(ofdev->dev.of_node, "bank-settings", NULL); 265 reg = of_get_property(ofdev->dev.of_node, "bank-settings", NULL);
266 if (reg) { 266 if (reg) {
267 int offset = NDFC_BCFG0 + (ndfc->chip_select << 2); 267 int offset = NDFC_BCFG0 + (ndfc->chip_select << 2);
268 out_be32(ndfc->ndfcbase + offset, *reg); 268 out_be32(ndfc->ndfcbase + offset, be32_to_cpup(reg));
269 } 269 }
270 270
271 err = ndfc_chip_init(ndfc, ofdev->dev.of_node); 271 err = ndfc_chip_init(ndfc, ofdev->dev.of_node);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 513e0a76a4a7..cd41c58b5bbd 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -111,11 +111,11 @@ static int use_dma = 1;
111module_param(use_dma, bool, 0); 111module_param(use_dma, bool, 0);
112MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); 112MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
113#else 113#else
114const int use_dma; 114static const int use_dma;
115#endif 115#endif
116#else 116#else
117const int use_prefetch; 117const int use_prefetch;
118const int use_dma; 118static const int use_dma;
119#endif 119#endif
120 120
121struct omap_nand_info { 121struct omap_nand_info {
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 4d01cda68844..17f8518cc5eb 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -117,7 +117,7 @@ struct pxa3xx_nand_info {
117 struct nand_chip nand_chip; 117 struct nand_chip nand_chip;
118 118
119 struct platform_device *pdev; 119 struct platform_device *pdev;
120 const struct pxa3xx_nand_flash *flash_info; 120 struct pxa3xx_nand_cmdset *cmdset;
121 121
122 struct clk *clk; 122 struct clk *clk;
123 void __iomem *mmio_base; 123 void __iomem *mmio_base;
@@ -131,6 +131,7 @@ struct pxa3xx_nand_info {
131 int drcmr_cmd; 131 int drcmr_cmd;
132 132
133 unsigned char *data_buff; 133 unsigned char *data_buff;
134 unsigned char *oob_buff;
134 dma_addr_t data_buff_phys; 135 dma_addr_t data_buff_phys;
135 size_t data_buff_size; 136 size_t data_buff_size;
136 int data_dma_ch; 137 int data_dma_ch;
@@ -149,7 +150,8 @@ struct pxa3xx_nand_info {
149 int use_ecc; /* use HW ECC ? */ 150 int use_ecc; /* use HW ECC ? */
150 int use_dma; /* use DMA ? */ 151 int use_dma; /* use DMA ? */
151 152
152 size_t data_size; /* data size in FIFO */ 153 unsigned int page_size; /* page size of attached chip */
154 unsigned int data_size; /* data size in FIFO */
153 int retcode; 155 int retcode;
154 struct completion cmd_complete; 156 struct completion cmd_complete;
155 157
@@ -158,6 +160,10 @@ struct pxa3xx_nand_info {
158 uint32_t ndcb1; 160 uint32_t ndcb1;
159 uint32_t ndcb2; 161 uint32_t ndcb2;
160 162
163 /* timing calcuted from setting */
164 uint32_t ndtr0cs0;
165 uint32_t ndtr1cs0;
166
161 /* calculated from pxa3xx_nand_flash data */ 167 /* calculated from pxa3xx_nand_flash data */
162 size_t oob_size; 168 size_t oob_size;
163 size_t read_id_bytes; 169 size_t read_id_bytes;
@@ -174,23 +180,7 @@ MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW");
174 * Default NAND flash controller configuration setup by the 180 * Default NAND flash controller configuration setup by the
175 * bootloader. This configuration is used only when pdata->keep_config is set 181 * bootloader. This configuration is used only when pdata->keep_config is set
176 */ 182 */
177static struct pxa3xx_nand_timing default_timing; 183static struct pxa3xx_nand_cmdset default_cmdset = {
178static struct pxa3xx_nand_flash default_flash;
179
180static struct pxa3xx_nand_cmdset smallpage_cmdset = {
181 .read1 = 0x0000,
182 .read2 = 0x0050,
183 .program = 0x1080,
184 .read_status = 0x0070,
185 .read_id = 0x0090,
186 .erase = 0xD060,
187 .reset = 0x00FF,
188 .lock = 0x002A,
189 .unlock = 0x2423,
190 .lock_status = 0x007A,
191};
192
193static struct pxa3xx_nand_cmdset largepage_cmdset = {
194 .read1 = 0x3000, 184 .read1 = 0x3000,
195 .read2 = 0x0050, 185 .read2 = 0x0050,
196 .program = 0x1080, 186 .program = 0x1080,
@@ -203,142 +193,27 @@ static struct pxa3xx_nand_cmdset largepage_cmdset = {
203 .lock_status = 0x007A, 193 .lock_status = 0x007A,
204}; 194};
205 195
206#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN 196static struct pxa3xx_nand_timing timing[] = {
207static struct pxa3xx_nand_timing samsung512MbX16_timing = { 197 { 40, 80, 60, 100, 80, 100, 90000, 400, 40, },
208 .tCH = 10, 198 { 10, 0, 20, 40, 30, 40, 11123, 110, 10, },
209 .tCS = 0, 199 { 10, 25, 15, 25, 15, 30, 25000, 60, 10, },
210 .tWH = 20, 200 { 10, 35, 15, 25, 15, 25, 25000, 60, 10, },
211 .tWP = 40,
212 .tRH = 30,
213 .tRP = 40,
214 .tR = 11123,
215 .tWHR = 110,
216 .tAR = 10,
217};
218
219static struct pxa3xx_nand_flash samsung512MbX16 = {
220 .timing = &samsung512MbX16_timing,
221 .cmdset = &smallpage_cmdset,
222 .page_per_block = 32,
223 .page_size = 512,
224 .flash_width = 16,
225 .dfc_width = 16,
226 .num_blocks = 4096,
227 .chip_id = 0x46ec,
228};
229
230static struct pxa3xx_nand_flash samsung2GbX8 = {
231 .timing = &samsung512MbX16_timing,
232 .cmdset = &smallpage_cmdset,
233 .page_per_block = 64,
234 .page_size = 2048,
235 .flash_width = 8,
236 .dfc_width = 8,
237 .num_blocks = 2048,
238 .chip_id = 0xdaec,
239}; 201};
240 202
241static struct pxa3xx_nand_flash samsung32GbX8 = { 203static struct pxa3xx_nand_flash builtin_flash_types[] = {
242 .timing = &samsung512MbX16_timing, 204 { 0, 0, 2048, 8, 8, 0, &default_cmdset, &timing[0] },
243 .cmdset = &smallpage_cmdset, 205 { 0x46ec, 32, 512, 16, 16, 4096, &default_cmdset, &timing[1] },
244 .page_per_block = 128, 206 { 0xdaec, 64, 2048, 8, 8, 2048, &default_cmdset, &timing[1] },
245 .page_size = 4096, 207 { 0xd7ec, 128, 4096, 8, 8, 8192, &default_cmdset, &timing[1] },
246 .flash_width = 8, 208 { 0xa12c, 64, 2048, 8, 8, 1024, &default_cmdset, &timing[2] },
247 .dfc_width = 8, 209 { 0xb12c, 64, 2048, 16, 16, 1024, &default_cmdset, &timing[2] },
248 .num_blocks = 8192, 210 { 0xdc2c, 64, 2048, 8, 8, 4096, &default_cmdset, &timing[2] },
249 .chip_id = 0xd7ec, 211 { 0xcc2c, 64, 2048, 16, 16, 4096, &default_cmdset, &timing[2] },
212 { 0xba20, 64, 2048, 16, 16, 2048, &default_cmdset, &timing[3] },
250}; 213};
251 214
252static struct pxa3xx_nand_timing micron_timing = { 215/* Define a default flash type setting serve as flash detecting only */
253 .tCH = 10, 216#define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
254 .tCS = 25,
255 .tWH = 15,
256 .tWP = 25,
257 .tRH = 15,
258 .tRP = 30,
259 .tR = 25000,
260 .tWHR = 60,
261 .tAR = 10,
262};
263
264static struct pxa3xx_nand_flash micron1GbX8 = {
265 .timing = &micron_timing,
266 .cmdset = &largepage_cmdset,
267 .page_per_block = 64,
268 .page_size = 2048,
269 .flash_width = 8,
270 .dfc_width = 8,
271 .num_blocks = 1024,
272 .chip_id = 0xa12c,
273};
274
275static struct pxa3xx_nand_flash micron1GbX16 = {
276 .timing = &micron_timing,
277 .cmdset = &largepage_cmdset,
278 .page_per_block = 64,
279 .page_size = 2048,
280 .flash_width = 16,
281 .dfc_width = 16,
282 .num_blocks = 1024,
283 .chip_id = 0xb12c,
284};
285
286static struct pxa3xx_nand_flash micron4GbX8 = {
287 .timing = &micron_timing,
288 .cmdset = &largepage_cmdset,
289 .page_per_block = 64,
290 .page_size = 2048,
291 .flash_width = 8,
292 .dfc_width = 8,
293 .num_blocks = 4096,
294 .chip_id = 0xdc2c,
295};
296
297static struct pxa3xx_nand_flash micron4GbX16 = {
298 .timing = &micron_timing,
299 .cmdset = &largepage_cmdset,
300 .page_per_block = 64,
301 .page_size = 2048,
302 .flash_width = 16,
303 .dfc_width = 16,
304 .num_blocks = 4096,
305 .chip_id = 0xcc2c,
306};
307
308static struct pxa3xx_nand_timing stm2GbX16_timing = {
309 .tCH = 10,
310 .tCS = 35,
311 .tWH = 15,
312 .tWP = 25,
313 .tRH = 15,
314 .tRP = 25,
315 .tR = 25000,
316 .tWHR = 60,
317 .tAR = 10,
318};
319
320static struct pxa3xx_nand_flash stm2GbX16 = {
321 .timing = &stm2GbX16_timing,
322 .cmdset = &largepage_cmdset,
323 .page_per_block = 64,
324 .page_size = 2048,
325 .flash_width = 16,
326 .dfc_width = 16,
327 .num_blocks = 2048,
328 .chip_id = 0xba20,
329};
330
331static struct pxa3xx_nand_flash *builtin_flash_types[] = {
332 &samsung512MbX16,
333 &samsung2GbX8,
334 &samsung32GbX8,
335 &micron1GbX8,
336 &micron1GbX16,
337 &micron4GbX8,
338 &micron4GbX16,
339 &stm2GbX16,
340};
341#endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */
342 217
343#define NDTR0_tCH(c) (min((c), 7) << 19) 218#define NDTR0_tCH(c) (min((c), 7) << 19)
344#define NDTR0_tCS(c) (min((c), 7) << 16) 219#define NDTR0_tCS(c) (min((c), 7) << 16)
@@ -351,23 +226,9 @@ static struct pxa3xx_nand_flash *builtin_flash_types[] = {
351#define NDTR1_tWHR(c) (min((c), 15) << 4) 226#define NDTR1_tWHR(c) (min((c), 15) << 4)
352#define NDTR1_tAR(c) (min((c), 15) << 0) 227#define NDTR1_tAR(c) (min((c), 15) << 0)
353 228
354#define tCH_NDTR0(r) (((r) >> 19) & 0x7)
355#define tCS_NDTR0(r) (((r) >> 16) & 0x7)
356#define tWH_NDTR0(r) (((r) >> 11) & 0x7)
357#define tWP_NDTR0(r) (((r) >> 8) & 0x7)
358#define tRH_NDTR0(r) (((r) >> 3) & 0x7)
359#define tRP_NDTR0(r) (((r) >> 0) & 0x7)
360
361#define tR_NDTR1(r) (((r) >> 16) & 0xffff)
362#define tWHR_NDTR1(r) (((r) >> 4) & 0xf)
363#define tAR_NDTR1(r) (((r) >> 0) & 0xf)
364
365/* convert nano-seconds to nand flash controller clock cycles */ 229/* convert nano-seconds to nand flash controller clock cycles */
366#define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) 230#define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000)
367 231
368/* convert nand flash controller clock cycles to nano-seconds */
369#define cycle2ns(c, clk) ((((c) + 1) * 1000000 + clk / 500) / (clk / 1000))
370
371static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, 232static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
372 const struct pxa3xx_nand_timing *t) 233 const struct pxa3xx_nand_timing *t)
373{ 234{
@@ -385,6 +246,8 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
385 NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | 246 NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) |
386 NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); 247 NDTR1_tAR(ns2cycle(t->tAR, nand_clk));
387 248
249 info->ndtr0cs0 = ndtr0;
250 info->ndtr1cs0 = ndtr1;
388 nand_writel(info, NDTR0CS0, ndtr0); 251 nand_writel(info, NDTR0CS0, ndtr0);
389 nand_writel(info, NDTR1CS0, ndtr1); 252 nand_writel(info, NDTR1CS0, ndtr1);
390} 253}
@@ -408,23 +271,31 @@ static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
408 return -ETIMEDOUT; 271 return -ETIMEDOUT;
409} 272}
410 273
411static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, 274static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
412 uint16_t cmd, int column, int page_addr)
413{ 275{
414 const struct pxa3xx_nand_flash *f = info->flash_info; 276 int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
415 const struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
416 277
417 /* calculate data size */ 278 info->data_size = info->page_size;
418 switch (f->page_size) { 279 if (!oob_enable) {
280 info->oob_size = 0;
281 return;
282 }
283
284 switch (info->page_size) {
419 case 2048: 285 case 2048:
420 info->data_size = (info->use_ecc) ? 2088 : 2112; 286 info->oob_size = (info->use_ecc) ? 40 : 64;
421 break; 287 break;
422 case 512: 288 case 512:
423 info->data_size = (info->use_ecc) ? 520 : 528; 289 info->oob_size = (info->use_ecc) ? 8 : 16;
424 break; 290 break;
425 default:
426 return -EINVAL;
427 } 291 }
292}
293
294static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
295 uint16_t cmd, int column, int page_addr)
296{
297 const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
298 pxa3xx_set_datasize(info);
428 299
429 /* generate values for NDCBx registers */ 300 /* generate values for NDCBx registers */
430 info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); 301 info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
@@ -463,12 +334,13 @@ static int prepare_erase_cmd(struct pxa3xx_nand_info *info,
463 334
464static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) 335static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
465{ 336{
466 const struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset; 337 const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
467 338
468 info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); 339 info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
469 info->ndcb1 = 0; 340 info->ndcb1 = 0;
470 info->ndcb2 = 0; 341 info->ndcb2 = 0;
471 342
343 info->oob_size = 0;
472 if (cmd == cmdset->read_id) { 344 if (cmd == cmdset->read_id) {
473 info->ndcb0 |= NDCB0_CMD_TYPE(3); 345 info->ndcb0 |= NDCB0_CMD_TYPE(3);
474 info->data_size = 8; 346 info->data_size = 8;
@@ -537,6 +409,9 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
537 case STATE_PIO_WRITING: 409 case STATE_PIO_WRITING:
538 __raw_writesl(info->mmio_base + NDDB, info->data_buff, 410 __raw_writesl(info->mmio_base + NDDB, info->data_buff,
539 DIV_ROUND_UP(info->data_size, 4)); 411 DIV_ROUND_UP(info->data_size, 4));
412 if (info->oob_size > 0)
413 __raw_writesl(info->mmio_base + NDDB, info->oob_buff,
414 DIV_ROUND_UP(info->oob_size, 4));
540 415
541 enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); 416 enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
542 417
@@ -549,6 +424,9 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
549 case STATE_PIO_READING: 424 case STATE_PIO_READING:
550 __raw_readsl(info->mmio_base + NDDB, info->data_buff, 425 __raw_readsl(info->mmio_base + NDDB, info->data_buff,
551 DIV_ROUND_UP(info->data_size, 4)); 426 DIV_ROUND_UP(info->data_size, 4));
427 if (info->oob_size > 0)
428 __raw_readsl(info->mmio_base + NDDB, info->oob_buff,
429 DIV_ROUND_UP(info->oob_size, 4));
552 break; 430 break;
553 default: 431 default:
554 printk(KERN_ERR "%s: invalid state %d\n", __func__, 432 printk(KERN_ERR "%s: invalid state %d\n", __func__,
@@ -563,7 +441,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
563static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) 441static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
564{ 442{
565 struct pxa_dma_desc *desc = info->data_desc; 443 struct pxa_dma_desc *desc = info->data_desc;
566 int dma_len = ALIGN(info->data_size, 32); 444 int dma_len = ALIGN(info->data_size + info->oob_size, 32);
567 445
568 desc->ddadr = DDADR_STOP; 446 desc->ddadr = DDADR_STOP;
569 desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; 447 desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
@@ -700,8 +578,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
700 int column, int page_addr) 578 int column, int page_addr)
701{ 579{
702 struct pxa3xx_nand_info *info = mtd->priv; 580 struct pxa3xx_nand_info *info = mtd->priv;
703 const struct pxa3xx_nand_flash *flash_info = info->flash_info; 581 const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
704 const struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset;
705 int ret; 582 int ret;
706 583
707 info->use_dma = (use_dma) ? 1 : 0; 584 info->use_dma = (use_dma) ? 1 : 0;
@@ -925,8 +802,7 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
925 802
926static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) 803static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
927{ 804{
928 const struct pxa3xx_nand_flash *f = info->flash_info; 805 const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
929 const struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
930 uint32_t ndcr; 806 uint32_t ndcr;
931 uint8_t id_buff[8]; 807 uint8_t id_buff[8];
932 808
@@ -968,7 +844,9 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
968 return -EINVAL; 844 return -EINVAL;
969 845
970 /* calculate flash information */ 846 /* calculate flash information */
971 info->oob_size = (f->page_size == 2048) ? 64 : 16; 847 info->cmdset = f->cmdset;
848 info->page_size = f->page_size;
849 info->oob_buff = info->data_buff + f->page_size;
972 info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; 850 info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
973 851
974 /* calculate addressing information */ 852 /* calculate addressing information */
@@ -992,49 +870,20 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
992 info->reg_ndcr = ndcr; 870 info->reg_ndcr = ndcr;
993 871
994 pxa3xx_nand_set_timing(info, f->timing); 872 pxa3xx_nand_set_timing(info, f->timing);
995 info->flash_info = f;
996 return 0; 873 return 0;
997} 874}
998 875
999static void pxa3xx_nand_detect_timing(struct pxa3xx_nand_info *info,
1000 struct pxa3xx_nand_timing *t)
1001{
1002 unsigned long nand_clk = clk_get_rate(info->clk);
1003 uint32_t ndtr0 = nand_readl(info, NDTR0CS0);
1004 uint32_t ndtr1 = nand_readl(info, NDTR1CS0);
1005
1006 t->tCH = cycle2ns(tCH_NDTR0(ndtr0), nand_clk);
1007 t->tCS = cycle2ns(tCS_NDTR0(ndtr0), nand_clk);
1008 t->tWH = cycle2ns(tWH_NDTR0(ndtr0), nand_clk);
1009 t->tWP = cycle2ns(tWP_NDTR0(ndtr0), nand_clk);
1010 t->tRH = cycle2ns(tRH_NDTR0(ndtr0), nand_clk);
1011 t->tRP = cycle2ns(tRP_NDTR0(ndtr0), nand_clk);
1012
1013 t->tR = cycle2ns(tR_NDTR1(ndtr1), nand_clk);
1014 t->tWHR = cycle2ns(tWHR_NDTR1(ndtr1), nand_clk);
1015 t->tAR = cycle2ns(tAR_NDTR1(ndtr1), nand_clk);
1016}
1017
1018static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) 876static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
1019{ 877{
1020 uint32_t ndcr = nand_readl(info, NDCR); 878 uint32_t ndcr = nand_readl(info, NDCR);
1021 struct nand_flash_dev *type = NULL; 879 struct nand_flash_dev *type = NULL;
1022 uint32_t id = -1; 880 uint32_t id = -1, page_per_block, num_blocks;
1023 int i; 881 int i;
1024 882
1025 default_flash.page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32; 883 page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
1026 default_flash.page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; 884 info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
1027 default_flash.flash_width = ndcr & NDCR_DWIDTH_M ? 16 : 8;
1028 default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8;
1029
1030 if (default_flash.page_size == 2048)
1031 default_flash.cmdset = &largepage_cmdset;
1032 else
1033 default_flash.cmdset = &smallpage_cmdset;
1034
1035 /* set info fields needed to __readid */ 885 /* set info fields needed to __readid */
1036 info->flash_info = &default_flash; 886 info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
1037 info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2;
1038 info->reg_ndcr = ndcr; 887 info->reg_ndcr = ndcr;
1039 888
1040 if (__readid(info, &id)) 889 if (__readid(info, &id))
@@ -1053,21 +902,20 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
1053 return -ENODEV; 902 return -ENODEV;
1054 903
1055 /* fill the missing flash information */ 904 /* fill the missing flash information */
1056 i = __ffs(default_flash.page_per_block * default_flash.page_size); 905 i = __ffs(page_per_block * info->page_size);
1057 default_flash.num_blocks = type->chipsize << (20 - i); 906 num_blocks = type->chipsize << (20 - i);
1058
1059 info->oob_size = (default_flash.page_size == 2048) ? 64 : 16;
1060 907
1061 /* calculate addressing information */ 908 /* calculate addressing information */
1062 info->col_addr_cycles = (default_flash.page_size == 2048) ? 2 : 1; 909 info->col_addr_cycles = (info->page_size == 2048) ? 2 : 1;
1063 910
1064 if (default_flash.num_blocks * default_flash.page_per_block > 65536) 911 if (num_blocks * page_per_block > 65536)
1065 info->row_addr_cycles = 3; 912 info->row_addr_cycles = 3;
1066 else 913 else
1067 info->row_addr_cycles = 2; 914 info->row_addr_cycles = 2;
1068 915
1069 pxa3xx_nand_detect_timing(info, &default_timing); 916 info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
1070 default_flash.timing = &default_timing; 917 info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
918 info->cmdset = &default_cmdset;
1071 919
1072 return 0; 920 return 0;
1073} 921}
@@ -1083,38 +931,29 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
1083 if (pxa3xx_nand_detect_config(info) == 0) 931 if (pxa3xx_nand_detect_config(info) == 0)
1084 return 0; 932 return 0;
1085 933
1086 for (i = 0; i<pdata->num_flash; ++i) { 934 /* we use default timing to detect id */
1087 f = pdata->flash + i; 935 f = DEFAULT_FLASH_TYPE;
1088 936 pxa3xx_nand_config_flash(info, f);
1089 if (pxa3xx_nand_config_flash(info, f)) 937 if (__readid(info, &id))
1090 continue; 938 goto fail_detect;
1091 939
1092 if (__readid(info, &id)) 940 for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
1093 continue; 941 /* we first choose the flash definition from platfrom */
1094 942 if (i < pdata->num_flash)
1095 if (id == f->chip_id) 943 f = pdata->flash + i;
1096 return 0; 944 else
1097 } 945 f = &builtin_flash_types[i - pdata->num_flash + 1];
1098 946 if (f->chip_id == id) {
1099#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN 947 dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
1100 for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) { 948 pxa3xx_nand_config_flash(info, f);
1101
1102 f = builtin_flash_types[i];
1103
1104 if (pxa3xx_nand_config_flash(info, f))
1105 continue;
1106
1107 if (__readid(info, &id))
1108 continue;
1109
1110 if (id == f->chip_id)
1111 return 0; 949 return 0;
950 }
1112 } 951 }
1113#endif
1114 952
1115 dev_warn(&info->pdev->dev, 953 dev_warn(&info->pdev->dev,
1116 "failed to detect configured nand flash; found %04x instead of\n", 954 "failed to detect configured nand flash; found %04x instead of\n",
1117 id); 955 id);
956fail_detect:
1118 return -ENODEV; 957 return -ENODEV;
1119} 958}
1120 959
@@ -1177,10 +1016,9 @@ static struct nand_ecclayout hw_largepage_ecclayout = {
1177static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, 1016static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
1178 struct pxa3xx_nand_info *info) 1017 struct pxa3xx_nand_info *info)
1179{ 1018{
1180 const struct pxa3xx_nand_flash *f = info->flash_info;
1181 struct nand_chip *this = &info->nand_chip; 1019 struct nand_chip *this = &info->nand_chip;
1182 1020
1183 this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0; 1021 this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;
1184 1022
1185 this->waitfunc = pxa3xx_nand_waitfunc; 1023 this->waitfunc = pxa3xx_nand_waitfunc;
1186 this->select_chip = pxa3xx_nand_select_chip; 1024 this->select_chip = pxa3xx_nand_select_chip;
@@ -1196,9 +1034,9 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
1196 this->ecc.hwctl = pxa3xx_nand_ecc_hwctl; 1034 this->ecc.hwctl = pxa3xx_nand_ecc_hwctl;
1197 this->ecc.calculate = pxa3xx_nand_ecc_calculate; 1035 this->ecc.calculate = pxa3xx_nand_ecc_calculate;
1198 this->ecc.correct = pxa3xx_nand_ecc_correct; 1036 this->ecc.correct = pxa3xx_nand_ecc_correct;
1199 this->ecc.size = f->page_size; 1037 this->ecc.size = info->page_size;
1200 1038
1201 if (f->page_size == 2048) 1039 if (info->page_size == 2048)
1202 this->ecc.layout = &hw_largepage_ecclayout; 1040 this->ecc.layout = &hw_largepage_ecclayout;
1203 else 1041 else
1204 this->ecc.layout = &hw_smallpage_ecclayout; 1042 this->ecc.layout = &hw_smallpage_ecclayout;
@@ -1411,9 +1249,11 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
1411 struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); 1249 struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
1412 struct pxa3xx_nand_info *info = mtd->priv; 1250 struct pxa3xx_nand_info *info = mtd->priv;
1413 1251
1252 nand_writel(info, NDTR0CS0, info->ndtr0cs0);
1253 nand_writel(info, NDTR1CS0, info->ndtr1cs0);
1414 clk_enable(info->clk); 1254 clk_enable(info->clk);
1415 1255
1416 return pxa3xx_nand_config_flash(info, info->flash_info); 1256 return 0;
1417} 1257}
1418#else 1258#else
1419#define pxa3xx_nand_suspend NULL 1259#define pxa3xx_nand_suspend NULL
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 5169ca6a66bc..d9d7efbc77cc 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -757,11 +757,6 @@ static irqreturn_t r852_irq(int irq, void *data)
757 757
758 spin_lock_irqsave(&dev->irqlock, flags); 758 spin_lock_irqsave(&dev->irqlock, flags);
759 759
760 /* We can recieve shared interrupt while pci is suspended
761 in that case reads will return 0xFFFFFFFF.... */
762 if (dev->insuspend)
763 goto out;
764
765 /* handle card detection interrupts first */ 760 /* handle card detection interrupts first */
766 card_status = r852_read_reg(dev, R852_CARD_IRQ_STA); 761 card_status = r852_read_reg(dev, R852_CARD_IRQ_STA);
767 r852_write_reg(dev, R852_CARD_IRQ_STA, card_status); 762 r852_write_reg(dev, R852_CARD_IRQ_STA, card_status);
@@ -1035,7 +1030,6 @@ void r852_shutdown(struct pci_dev *pci_dev)
1035int r852_suspend(struct device *device) 1030int r852_suspend(struct device *device)
1036{ 1031{
1037 struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); 1032 struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
1038 unsigned long flags;
1039 1033
1040 if (dev->ctlreg & R852_CTL_CARDENABLE) 1034 if (dev->ctlreg & R852_CTL_CARDENABLE)
1041 return -EBUSY; 1035 return -EBUSY;
@@ -1047,43 +1041,22 @@ int r852_suspend(struct device *device)
1047 r852_disable_irqs(dev); 1041 r852_disable_irqs(dev);
1048 r852_engine_disable(dev); 1042 r852_engine_disable(dev);
1049 1043
1050 spin_lock_irqsave(&dev->irqlock, flags);
1051 dev->insuspend = 1;
1052 spin_unlock_irqrestore(&dev->irqlock, flags);
1053
1054 /* At that point, even if interrupt handler is running, it will quit */
1055 /* So wait for this to happen explictly */
1056 synchronize_irq(dev->irq);
1057
1058 /* If card was pulled off just during the suspend, which is very 1044 /* If card was pulled off just during the suspend, which is very
1059 unlikely, we will remove it on resume, it too late now 1045 unlikely, we will remove it on resume, it too late now
1060 anyway... */ 1046 anyway... */
1061 dev->card_unstable = 0; 1047 dev->card_unstable = 0;
1062 1048 return 0;
1063 pci_save_state(to_pci_dev(device));
1064 return pci_prepare_to_sleep(to_pci_dev(device));
1065} 1049}
1066 1050
1067int r852_resume(struct device *device) 1051int r852_resume(struct device *device)
1068{ 1052{
1069 struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); 1053 struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
1070 unsigned long flags;
1071
1072 /* Turn on the hardware */
1073 pci_back_from_sleep(to_pci_dev(device));
1074 pci_restore_state(to_pci_dev(device));
1075 1054
1076 r852_disable_irqs(dev); 1055 r852_disable_irqs(dev);
1077 r852_card_update_present(dev); 1056 r852_card_update_present(dev);
1078 r852_engine_disable(dev); 1057 r852_engine_disable(dev);
1079 1058
1080 1059
1081 /* Now its safe for IRQ to run */
1082 spin_lock_irqsave(&dev->irqlock, flags);
1083 dev->insuspend = 0;
1084 spin_unlock_irqrestore(&dev->irqlock, flags);
1085
1086
1087 /* If card status changed, just do the work */ 1060 /* If card status changed, just do the work */
1088 if (dev->card_detected != dev->card_registred) { 1061 if (dev->card_detected != dev->card_registred) {
1089 dbg("card was %s during low power state", 1062 dbg("card was %s during low power state",
@@ -1121,7 +1094,6 @@ MODULE_DEVICE_TABLE(pci, r852_pci_id_tbl);
1121 1094
1122SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume); 1095SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume);
1123 1096
1124
1125static struct pci_driver r852_pci_driver = { 1097static struct pci_driver r852_pci_driver = {
1126 .name = DRV_NAME, 1098 .name = DRV_NAME,
1127 .id_table = r852_pci_id_tbl, 1099 .id_table = r852_pci_id_tbl,
diff --git a/drivers/mtd/nand/r852.h b/drivers/mtd/nand/r852.h
index 8096cc280c73..e6a21d9d22c6 100644
--- a/drivers/mtd/nand/r852.h
+++ b/drivers/mtd/nand/r852.h
@@ -140,8 +140,6 @@ struct r852_device {
140 /* interrupt handling */ 140 /* interrupt handling */
141 spinlock_t irqlock; /* IRQ protecting lock */ 141 spinlock_t irqlock; /* IRQ protecting lock */
142 int irq; /* irq num */ 142 int irq; /* irq num */
143 int insuspend; /* device is suspended */
144
145 /* misc */ 143 /* misc */
146 void *tmp_buffer; /* temporary buffer */ 144 void *tmp_buffer; /* temporary buffer */
147 uint8_t ctlreg; /* cached contents of control reg */ 145 uint8_t ctlreg; /* cached contents of control reg */
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 7bd171eefd21..a996718fa6b0 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -44,7 +44,7 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
44 pp = NULL; 44 pp = NULL;
45 i = 0; 45 i = 0;
46 while ((pp = of_get_next_child(node, pp))) { 46 while ((pp = of_get_next_child(node, pp))) {
47 const u32 *reg; 47 const __be32 *reg;
48 int len; 48 int len;
49 49
50 reg = of_get_property(pp, "reg", &len); 50 reg = of_get_property(pp, "reg", &len);
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index 3f32289fdbb5..4dbd0f58eebf 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -32,10 +32,11 @@ config MTD_ONENAND_OMAP2
32 32
33config MTD_ONENAND_SAMSUNG 33config MTD_ONENAND_SAMSUNG
34 tristate "OneNAND on Samsung SOC controller support" 34 tristate "OneNAND on Samsung SOC controller support"
35 depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 35 depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310
36 help 36 help
37 Support for a OneNAND flash device connected to an Samsung SOC 37 Support for a OneNAND flash device connected to an Samsung SOC.
38 S3C64XX/S5PC1XX controller. 38 S3C64XX/S5PC100 use command mapping method.
39 S5PC110/S5PC210 use generic OneNAND method.
39 40
40config MTD_ONENAND_OTP 41config MTD_ONENAND_OTP
41 bool "OneNAND OTP Support" 42 bool "OneNAND OTP Support"
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index a2bb520286f8..6b3a875647c9 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -3365,18 +3365,19 @@ static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
3365static void onenand_check_features(struct mtd_info *mtd) 3365static void onenand_check_features(struct mtd_info *mtd)
3366{ 3366{
3367 struct onenand_chip *this = mtd->priv; 3367 struct onenand_chip *this = mtd->priv;
3368 unsigned int density, process; 3368 unsigned int density, process, numbufs;
3369 3369
3370 /* Lock scheme depends on density and process */ 3370 /* Lock scheme depends on density and process */
3371 density = onenand_get_density(this->device_id); 3371 density = onenand_get_density(this->device_id);
3372 process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT; 3372 process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
3373 numbufs = this->read_word(this->base + ONENAND_REG_NUM_BUFFERS) >> 8;
3373 3374
3374 /* Lock scheme */ 3375 /* Lock scheme */
3375 switch (density) { 3376 switch (density) {
3376 case ONENAND_DEVICE_DENSITY_4Gb: 3377 case ONENAND_DEVICE_DENSITY_4Gb:
3377 if (ONENAND_IS_DDP(this)) 3378 if (ONENAND_IS_DDP(this))
3378 this->options |= ONENAND_HAS_2PLANE; 3379 this->options |= ONENAND_HAS_2PLANE;
3379 else 3380 else if (numbufs == 1)
3380 this->options |= ONENAND_HAS_4KB_PAGE; 3381 this->options |= ONENAND_HAS_4KB_PAGE;
3381 3382
3382 case ONENAND_DEVICE_DENSITY_2Gb: 3383 case ONENAND_DEVICE_DENSITY_2Gb:
@@ -4027,7 +4028,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
4027 mtd->ecclayout = this->ecclayout; 4028 mtd->ecclayout = this->ecclayout;
4028 4029
4029 /* Fill in remaining MTD driver data */ 4030 /* Fill in remaining MTD driver data */
4030 mtd->type = MTD_NANDFLASH; 4031 mtd->type = ONENAND_IS_MLC(this) ? MTD_MLCNANDFLASH : MTD_NANDFLASH;
4031 mtd->flags = MTD_CAP_NANDFLASH; 4032 mtd->flags = MTD_CAP_NANDFLASH;
4032 mtd->erase = onenand_erase; 4033 mtd->erase = onenand_erase;
4033 mtd->point = NULL; 4034 mtd->point = NULL;
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index a460f1b748c2..0de7a05e6de0 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -22,6 +22,7 @@
22#include <linux/mtd/onenand.h> 22#include <linux/mtd/onenand.h>
23#include <linux/mtd/partitions.h> 23#include <linux/mtd/partitions.h>
24#include <linux/dma-mapping.h> 24#include <linux/dma-mapping.h>
25#include <linux/interrupt.h>
25 26
26#include <asm/mach/flash.h> 27#include <asm/mach/flash.h>
27#include <plat/regs-onenand.h> 28#include <plat/regs-onenand.h>
@@ -58,7 +59,7 @@ enum soc_type {
58#define MAP_11 (0x3) 59#define MAP_11 (0x3)
59 60
60#define S3C64XX_CMD_MAP_SHIFT 24 61#define S3C64XX_CMD_MAP_SHIFT 24
61#define S5PC1XX_CMD_MAP_SHIFT 26 62#define S5PC100_CMD_MAP_SHIFT 26
62 63
63#define S3C6400_FBA_SHIFT 10 64#define S3C6400_FBA_SHIFT 10
64#define S3C6400_FPA_SHIFT 4 65#define S3C6400_FPA_SHIFT 4
@@ -81,6 +82,17 @@ enum soc_type {
81#define S5PC110_DMA_TRANS_CMD 0x418 82#define S5PC110_DMA_TRANS_CMD 0x418
82#define S5PC110_DMA_TRANS_STATUS 0x41C 83#define S5PC110_DMA_TRANS_STATUS 0x41C
83#define S5PC110_DMA_TRANS_DIR 0x420 84#define S5PC110_DMA_TRANS_DIR 0x420
85#define S5PC110_INTC_DMA_CLR 0x1004
86#define S5PC110_INTC_ONENAND_CLR 0x1008
87#define S5PC110_INTC_DMA_MASK 0x1024
88#define S5PC110_INTC_ONENAND_MASK 0x1028
89#define S5PC110_INTC_DMA_PEND 0x1044
90#define S5PC110_INTC_ONENAND_PEND 0x1048
91#define S5PC110_INTC_DMA_STATUS 0x1064
92#define S5PC110_INTC_ONENAND_STATUS 0x1068
93
94#define S5PC110_INTC_DMA_TD (1 << 24)
95#define S5PC110_INTC_DMA_TE (1 << 16)
84 96
85#define S5PC110_DMA_CFG_SINGLE (0x0 << 16) 97#define S5PC110_DMA_CFG_SINGLE (0x0 << 16)
86#define S5PC110_DMA_CFG_4BURST (0x2 << 16) 98#define S5PC110_DMA_CFG_4BURST (0x2 << 16)
@@ -134,6 +146,7 @@ struct s3c_onenand {
134 void __iomem *dma_addr; 146 void __iomem *dma_addr;
135 struct resource *dma_res; 147 struct resource *dma_res;
136 unsigned long phys_base; 148 unsigned long phys_base;
149 struct completion complete;
137#ifdef CONFIG_MTD_PARTITIONS 150#ifdef CONFIG_MTD_PARTITIONS
138 struct mtd_partition *parts; 151 struct mtd_partition *parts;
139#endif 152#endif
@@ -191,7 +204,7 @@ static unsigned int s3c64xx_cmd_map(unsigned type, unsigned val)
191 204
192static unsigned int s5pc1xx_cmd_map(unsigned type, unsigned val) 205static unsigned int s5pc1xx_cmd_map(unsigned type, unsigned val)
193{ 206{
194 return (type << S5PC1XX_CMD_MAP_SHIFT) | val; 207 return (type << S5PC100_CMD_MAP_SHIFT) | val;
195} 208}
196 209
197static unsigned int s3c6400_mem_addr(int fba, int fpa, int fsa) 210static unsigned int s3c6400_mem_addr(int fba, int fpa, int fsa)
@@ -531,10 +544,13 @@ static int onenand_write_bufferram(struct mtd_info *mtd, int area,
531 return 0; 544 return 0;
532} 545}
533 546
534static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction) 547static int (*s5pc110_dma_ops)(void *dst, void *src, size_t count, int direction);
548
549static int s5pc110_dma_poll(void *dst, void *src, size_t count, int direction)
535{ 550{
536 void __iomem *base = onenand->dma_addr; 551 void __iomem *base = onenand->dma_addr;
537 int status; 552 int status;
553 unsigned long timeout;
538 554
539 writel(src, base + S5PC110_DMA_SRC_ADDR); 555 writel(src, base + S5PC110_DMA_SRC_ADDR);
540 writel(dst, base + S5PC110_DMA_DST_ADDR); 556 writel(dst, base + S5PC110_DMA_DST_ADDR);
@@ -552,6 +568,13 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction)
552 568
553 writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD); 569 writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD);
554 570
571 /*
572 * There's no exact timeout values at Spec.
573 * In real case it takes under 1 msec.
574 * So 20 msecs are enough.
575 */
576 timeout = jiffies + msecs_to_jiffies(20);
577
555 do { 578 do {
556 status = readl(base + S5PC110_DMA_TRANS_STATUS); 579 status = readl(base + S5PC110_DMA_TRANS_STATUS);
557 if (status & S5PC110_DMA_TRANS_STATUS_TE) { 580 if (status & S5PC110_DMA_TRANS_STATUS_TE) {
@@ -559,13 +582,68 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction)
559 base + S5PC110_DMA_TRANS_CMD); 582 base + S5PC110_DMA_TRANS_CMD);
560 return -EIO; 583 return -EIO;
561 } 584 }
562 } while (!(status & S5PC110_DMA_TRANS_STATUS_TD)); 585 } while (!(status & S5PC110_DMA_TRANS_STATUS_TD) &&
586 time_before(jiffies, timeout));
563 587
564 writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); 588 writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD);
565 589
566 return 0; 590 return 0;
567} 591}
568 592
593static irqreturn_t s5pc110_onenand_irq(int irq, void *data)
594{
595 void __iomem *base = onenand->dma_addr;
596 int status, cmd = 0;
597
598 status = readl(base + S5PC110_INTC_DMA_STATUS);
599
600 if (likely(status & S5PC110_INTC_DMA_TD))
601 cmd = S5PC110_DMA_TRANS_CMD_TDC;
602
603 if (unlikely(status & S5PC110_INTC_DMA_TE))
604 cmd = S5PC110_DMA_TRANS_CMD_TEC;
605
606 writel(cmd, base + S5PC110_DMA_TRANS_CMD);
607 writel(status, base + S5PC110_INTC_DMA_CLR);
608
609 if (!onenand->complete.done)
610 complete(&onenand->complete);
611
612 return IRQ_HANDLED;
613}
614
615static int s5pc110_dma_irq(void *dst, void *src, size_t count, int direction)
616{
617 void __iomem *base = onenand->dma_addr;
618 int status;
619
620 status = readl(base + S5PC110_INTC_DMA_MASK);
621 if (status) {
622 status &= ~(S5PC110_INTC_DMA_TD | S5PC110_INTC_DMA_TE);
623 writel(status, base + S5PC110_INTC_DMA_MASK);
624 }
625
626 writel(src, base + S5PC110_DMA_SRC_ADDR);
627 writel(dst, base + S5PC110_DMA_DST_ADDR);
628
629 if (direction == S5PC110_DMA_DIR_READ) {
630 writel(S5PC110_DMA_SRC_CFG_READ, base + S5PC110_DMA_SRC_CFG);
631 writel(S5PC110_DMA_DST_CFG_READ, base + S5PC110_DMA_DST_CFG);
632 } else {
633 writel(S5PC110_DMA_SRC_CFG_WRITE, base + S5PC110_DMA_SRC_CFG);
634 writel(S5PC110_DMA_DST_CFG_WRITE, base + S5PC110_DMA_DST_CFG);
635 }
636
637 writel(count, base + S5PC110_DMA_TRANS_SIZE);
638 writel(direction, base + S5PC110_DMA_TRANS_DIR);
639
640 writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD);
641
642 wait_for_completion_timeout(&onenand->complete, msecs_to_jiffies(20));
643
644 return 0;
645}
646
569static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, 647static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
570 unsigned char *buffer, int offset, size_t count) 648 unsigned char *buffer, int offset, size_t count)
571{ 649{
@@ -573,7 +651,8 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
573 void __iomem *p; 651 void __iomem *p;
574 void *buf = (void *) buffer; 652 void *buf = (void *) buffer;
575 dma_addr_t dma_src, dma_dst; 653 dma_addr_t dma_src, dma_dst;
576 int err; 654 int err, page_dma = 0;
655 struct device *dev = &onenand->pdev->dev;
577 656
578 p = this->base + area; 657 p = this->base + area;
579 if (ONENAND_CURRENT_BUFFERRAM(this)) { 658 if (ONENAND_CURRENT_BUFFERRAM(this)) {
@@ -597,21 +676,27 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
597 page = vmalloc_to_page(buf); 676 page = vmalloc_to_page(buf);
598 if (!page) 677 if (!page)
599 goto normal; 678 goto normal;
600 buf = page_address(page) + ((size_t) buf & ~PAGE_MASK);
601 }
602 679
603 /* DMA routine */ 680 page_dma = 1;
604 dma_src = onenand->phys_base + (p - this->base); 681 /* DMA routine */
605 dma_dst = dma_map_single(&onenand->pdev->dev, 682 dma_src = onenand->phys_base + (p - this->base);
606 buf, count, DMA_FROM_DEVICE); 683 dma_dst = dma_map_page(dev, page, 0, count, DMA_FROM_DEVICE);
607 if (dma_mapping_error(&onenand->pdev->dev, dma_dst)) { 684 } else {
608 dev_err(&onenand->pdev->dev, 685 /* DMA routine */
609 "Couldn't map a %d byte buffer for DMA\n", count); 686 dma_src = onenand->phys_base + (p - this->base);
687 dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE);
688 }
689 if (dma_mapping_error(dev, dma_dst)) {
690 dev_err(dev, "Couldn't map a %d byte buffer for DMA\n", count);
610 goto normal; 691 goto normal;
611 } 692 }
612 err = s5pc110_dma_ops((void *) dma_dst, (void *) dma_src, 693 err = s5pc110_dma_ops((void *) dma_dst, (void *) dma_src,
613 count, S5PC110_DMA_DIR_READ); 694 count, S5PC110_DMA_DIR_READ);
614 dma_unmap_single(&onenand->pdev->dev, dma_dst, count, DMA_FROM_DEVICE); 695
696 if (page_dma)
697 dma_unmap_page(dev, dma_dst, count, DMA_FROM_DEVICE);
698 else
699 dma_unmap_single(dev, dma_dst, count, DMA_FROM_DEVICE);
615 700
616 if (!err) 701 if (!err)
617 return 0; 702 return 0;
@@ -759,7 +844,6 @@ static void s3c_onenand_setup(struct mtd_info *mtd)
759 onenand->cmd_map = s5pc1xx_cmd_map; 844 onenand->cmd_map = s5pc1xx_cmd_map;
760 } else if (onenand->type == TYPE_S5PC110) { 845 } else if (onenand->type == TYPE_S5PC110) {
761 /* Use generic onenand functions */ 846 /* Use generic onenand functions */
762 onenand->cmd_map = s5pc1xx_cmd_map;
763 this->read_bufferram = s5pc110_read_bufferram; 847 this->read_bufferram = s5pc110_read_bufferram;
764 this->chip_probe = s5pc110_chip_probe; 848 this->chip_probe = s5pc110_chip_probe;
765 return; 849 return;
@@ -904,6 +988,20 @@ static int s3c_onenand_probe(struct platform_device *pdev)
904 } 988 }
905 989
906 onenand->phys_base = onenand->base_res->start; 990 onenand->phys_base = onenand->base_res->start;
991
992 s5pc110_dma_ops = s5pc110_dma_poll;
993 /* Interrupt support */
994 r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
995 if (r) {
996 init_completion(&onenand->complete);
997 s5pc110_dma_ops = s5pc110_dma_irq;
998 err = request_irq(r->start, s5pc110_onenand_irq,
999 IRQF_SHARED, "onenand", &onenand);
1000 if (err) {
1001 dev_err(&pdev->dev, "failed to get irq\n");
1002 goto scan_failed;
1003 }
1004 }
907 } 1005 }
908 1006
909 if (onenand_scan(mtd, 1)) { 1007 if (onenand_scan(mtd, 1)) {
@@ -1000,7 +1098,7 @@ static int s3c_pm_ops_suspend(struct device *dev)
1000 struct onenand_chip *this = mtd->priv; 1098 struct onenand_chip *this = mtd->priv;
1001 1099
1002 this->wait(mtd, FL_PM_SUSPENDED); 1100 this->wait(mtd, FL_PM_SUSPENDED);
1003 return mtd->suspend(mtd); 1101 return 0;
1004} 1102}
1005 1103
1006static int s3c_pm_ops_resume(struct device *dev) 1104static int s3c_pm_ops_resume(struct device *dev)
@@ -1009,7 +1107,6 @@ static int s3c_pm_ops_resume(struct device *dev)
1009 struct mtd_info *mtd = platform_get_drvdata(pdev); 1107 struct mtd_info *mtd = platform_get_drvdata(pdev);
1010 struct onenand_chip *this = mtd->priv; 1108 struct onenand_chip *this = mtd->priv;
1011 1109
1012 mtd->resume(mtd);
1013 this->unlock_all(mtd); 1110 this->unlock_all(mtd);
1014 return 0; 1111 return 0;
1015} 1112}
diff --git a/drivers/mtd/sm_ftl.h b/drivers/mtd/sm_ftl.h
index e30e48e7f63d..43bb7300785b 100644
--- a/drivers/mtd/sm_ftl.h
+++ b/drivers/mtd/sm_ftl.h
@@ -20,7 +20,7 @@
20 20
21 21
22struct ftl_zone { 22struct ftl_zone {
23 int initialized; 23 bool initialized;
24 int16_t *lba_to_phys_table; /* LBA to physical table */ 24 int16_t *lba_to_phys_table; /* LBA to physical table */
25 struct kfifo free_sectors; /* queue of free sectors */ 25 struct kfifo free_sectors; /* queue of free sectors */
26}; 26};
@@ -37,8 +37,8 @@ struct sm_ftl {
37 int zone_count; /* number of zones */ 37 int zone_count; /* number of zones */
38 int max_lba; /* maximum lba in a zone */ 38 int max_lba; /* maximum lba in a zone */
39 int smallpagenand; /* 256 bytes/page nand */ 39 int smallpagenand; /* 256 bytes/page nand */
40 int readonly; /* is FS readonly */ 40 bool readonly; /* is FS readonly */
41 int unstable; 41 bool unstable;
42 int cis_block; /* CIS block location */ 42 int cis_block; /* CIS block location */
43 int cis_boffset; /* CIS offset in the block */ 43 int cis_boffset; /* CIS offset in the block */
44 int cis_page_offset; /* CIS offset in the page */ 44 int cis_page_offset; /* CIS offset in the page */
@@ -49,7 +49,7 @@ struct sm_ftl {
49 int cache_zone; /* zone of cached block */ 49 int cache_zone; /* zone of cached block */
50 unsigned char *cache_data; /* cached block data */ 50 unsigned char *cache_data; /* cached block data */
51 long unsigned int cache_data_invalid_bitmap; 51 long unsigned int cache_data_invalid_bitmap;
52 int cache_clean; 52 bool cache_clean;
53 struct work_struct flush_work; 53 struct work_struct flush_work;
54 struct timer_list timer; 54 struct timer_list timer;
55 55
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 5699ce0c1780..3f3d431033ca 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -123,83 +123,87 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
123 u32 linelength; 123 u32 linelength;
124 bool yuv; 124 bool yuv;
125 125
126 /* Select data format */ 126 /*
127 * Select data format. MIPI DSI is not hot-pluggable, so, we just use
128 * the default videomode. If this ever becomes a problem, We'll have to
129 * move this to mipi_display_on() above and use info->var.xres
130 */
127 switch (pdata->data_format) { 131 switch (pdata->data_format) {
128 case MIPI_RGB888: 132 case MIPI_RGB888:
129 pctype = 0; 133 pctype = 0;
130 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; 134 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
131 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 135 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
132 linelength = ch->lcd_cfg.xres * 3; 136 linelength = ch->lcd_cfg[0].xres * 3;
133 yuv = false; 137 yuv = false;
134 break; 138 break;
135 case MIPI_RGB565: 139 case MIPI_RGB565:
136 pctype = 1; 140 pctype = 1;
137 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; 141 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
138 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 142 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
139 linelength = ch->lcd_cfg.xres * 2; 143 linelength = ch->lcd_cfg[0].xres * 2;
140 yuv = false; 144 yuv = false;
141 break; 145 break;
142 case MIPI_RGB666_LP: 146 case MIPI_RGB666_LP:
143 pctype = 2; 147 pctype = 2;
144 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 148 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
145 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 149 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
146 linelength = ch->lcd_cfg.xres * 3; 150 linelength = ch->lcd_cfg[0].xres * 3;
147 yuv = false; 151 yuv = false;
148 break; 152 break;
149 case MIPI_RGB666: 153 case MIPI_RGB666:
150 pctype = 3; 154 pctype = 3;
151 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; 155 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
152 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; 156 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
153 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; 157 linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8;
154 yuv = false; 158 yuv = false;
155 break; 159 break;
156 case MIPI_BGR888: 160 case MIPI_BGR888:
157 pctype = 8; 161 pctype = 8;
158 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; 162 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
159 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 163 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
160 linelength = ch->lcd_cfg.xres * 3; 164 linelength = ch->lcd_cfg[0].xres * 3;
161 yuv = false; 165 yuv = false;
162 break; 166 break;
163 case MIPI_BGR565: 167 case MIPI_BGR565:
164 pctype = 9; 168 pctype = 9;
165 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; 169 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
166 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 170 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
167 linelength = ch->lcd_cfg.xres * 2; 171 linelength = ch->lcd_cfg[0].xres * 2;
168 yuv = false; 172 yuv = false;
169 break; 173 break;
170 case MIPI_BGR666_LP: 174 case MIPI_BGR666_LP:
171 pctype = 0xa; 175 pctype = 0xa;
172 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 176 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
173 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 177 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
174 linelength = ch->lcd_cfg.xres * 3; 178 linelength = ch->lcd_cfg[0].xres * 3;
175 yuv = false; 179 yuv = false;
176 break; 180 break;
177 case MIPI_BGR666: 181 case MIPI_BGR666:
178 pctype = 0xb; 182 pctype = 0xb;
179 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; 183 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
180 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; 184 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
181 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; 185 linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8;
182 yuv = false; 186 yuv = false;
183 break; 187 break;
184 case MIPI_YUYV: 188 case MIPI_YUYV:
185 pctype = 4; 189 pctype = 4;
186 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; 190 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
187 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 191 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
188 linelength = ch->lcd_cfg.xres * 2; 192 linelength = ch->lcd_cfg[0].xres * 2;
189 yuv = true; 193 yuv = true;
190 break; 194 break;
191 case MIPI_UYVY: 195 case MIPI_UYVY:
192 pctype = 5; 196 pctype = 5;
193 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; 197 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
194 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 198 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
195 linelength = ch->lcd_cfg.xres * 2; 199 linelength = ch->lcd_cfg[0].xres * 2;
196 yuv = true; 200 yuv = true;
197 break; 201 break;
198 case MIPI_YUV420_L: 202 case MIPI_YUV420_L:
199 pctype = 6; 203 pctype = 6;
200 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; 204 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
201 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; 205 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
202 linelength = (ch->lcd_cfg.xres * 12 + 7) / 8; 206 linelength = (ch->lcd_cfg[0].xres * 12 + 7) / 8;
203 yuv = true; 207 yuv = true;
204 break; 208 break;
205 case MIPI_YUV420: 209 case MIPI_YUV420:
@@ -207,7 +211,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
207 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; 211 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
208 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; 212 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
209 /* Length of U/V line */ 213 /* Length of U/V line */
210 linelength = (ch->lcd_cfg.xres + 1) / 2; 214 linelength = (ch->lcd_cfg[0].xres + 1) / 2;
211 yuv = true; 215 yuv = true;
212 break; 216 break;
213 default: 217 default:
@@ -281,7 +285,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
281 iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */ 285 iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */
282 /* 286 /*
283 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see 287 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see
284 * sh_mobile_lcdc_info.ch[0].lcd_cfg.xres), HSALEN = 1 - default 288 * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default
285 * (unused, since VMCTR2[HSABM] = 0) 289 * (unused, since VMCTR2[HSABM] = 0)
286 */ 290 */
287 iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */ 291 iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index ef989d94511c..55b3077ff6ff 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -28,6 +28,8 @@
28#include <video/sh_mobile_hdmi.h> 28#include <video/sh_mobile_hdmi.h>
29#include <video/sh_mobile_lcdc.h> 29#include <video/sh_mobile_lcdc.h>
30 30
31#include "sh_mobile_lcdcfb.h"
32
31#define HDMI_SYSTEM_CTRL 0x00 /* System control */ 33#define HDMI_SYSTEM_CTRL 0x00 /* System control */
32#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control, 34#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control,
33 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */ 35 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
@@ -206,12 +208,15 @@ enum hotplug_state {
206 208
207struct sh_hdmi { 209struct sh_hdmi {
208 void __iomem *base; 210 void __iomem *base;
209 enum hotplug_state hp_state; 211 enum hotplug_state hp_state; /* hot-plug status */
212 bool preprogrammed_mode; /* use a pre-programmed VIC or the external mode */
210 struct clk *hdmi_clk; 213 struct clk *hdmi_clk;
211 struct device *dev; 214 struct device *dev;
212 struct fb_info *info; 215 struct fb_info *info;
216 struct mutex mutex; /* Protect the info pointer */
213 struct delayed_work edid_work; 217 struct delayed_work edid_work;
214 struct fb_var_screeninfo var; 218 struct fb_var_screeninfo var;
219 struct fb_monspecs monspec;
215}; 220};
216 221
217static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) 222static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
@@ -277,7 +282,7 @@ static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = {
277 */ 282 */
278 283
279/* External video parameter settings */ 284/* External video parameter settings */
280static void hdmi_external_video_param(struct sh_hdmi *hdmi) 285static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
281{ 286{
282 struct fb_var_screeninfo *var = &hdmi->var; 287 struct fb_var_screeninfo *var = &hdmi->var;
283 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset; 288 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset;
@@ -309,9 +314,9 @@ static void hdmi_external_video_param(struct sh_hdmi *hdmi)
309 if (var->sync & FB_SYNC_VERT_HIGH_ACT) 314 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
310 sync |= 8; 315 sync |= 8;
311 316
312 pr_debug("H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n", 317 dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n",
313 htotal, hblank, hdelay, var->hsync_len, 318 htotal, hblank, hdelay, var->hsync_len,
314 vtotal, vblank, vdelay, var->vsync_len, sync); 319 vtotal, vblank, vdelay, var->vsync_len, sync);
315 320
316 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); 321 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
317 322
@@ -336,7 +341,10 @@ static void hdmi_external_video_param(struct sh_hdmi *hdmi)
336 341
337 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION); 342 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION);
338 343
339 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for manual mode */ 344 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
345 if (!hdmi->preprogrammed_mode)
346 hdmi_write(hdmi, sync | 1 | (voffset << 4),
347 HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
340} 348}
341 349
342/** 350/**
@@ -454,21 +462,61 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
454} 462}
455 463
456/** 464/**
457 * sh_hdmi_phy_config() 465 * sh_hdmi_phy_config() - configure the HDMI PHY for the used video mode
458 */ 466 */
459static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) 467static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
460{ 468{
461 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ 469 if (hdmi->var.yres > 480) {
462 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); 470 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
463 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); 471 /*
464 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3); 472 * [1:0] Speed_A
465 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */ 473 * [3:2] Speed_B
466 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5); 474 * [4] PLLA_Bypass
467 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6); 475 * [6] DRV_TEST_EN
468 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7); 476 * [7] DRV_TEST_IN
469 hdmi_write(hdmi, 0x0E, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); 477 */
470 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); 478 hdmi_write(hdmi, 0x0f, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
471 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); 479 /* PLLB_CONFIG[17], PLLA_CONFIG[17] - not in PHY datasheet */
480 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
481 /*
482 * [2:0] BGR_I_OFFSET
483 * [6:4] BGR_V_OFFSET
484 */
485 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
486 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */
487 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
488 /*
489 * PLLA_CONFIG[15:8]: regulator voltage[0], CP current,
490 * LPF capacitance, LPF resistance[1]
491 */
492 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
493 /* PLLB_CONFIG[7:0]: LPF resistance[0], VCO offset, VCO gain */
494 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
495 /*
496 * PLLB_CONFIG[15:8]: regulator voltage[0], CP current,
497 * LPF capacitance, LPF resistance[1]
498 */
499 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
500 /* DRV_CONFIG, PE_CONFIG */
501 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
502 /*
503 * [2:0] AMON_SEL (4 == LPF voltage)
504 * [4] PLLA_CONFIG[16]
505 * [5] PLLB_CONFIG[16]
506 */
507 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
508 } else {
509 /* for 480p8bit 27MHz */
510 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
511 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
512 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
513 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
514 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
515 hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
516 hdmi_write(hdmi, 0x0F, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
517 hdmi_write(hdmi, 0x20, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
518 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
519 }
472} 520}
473 521
474/** 522/**
@@ -476,6 +524,8 @@ static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
476 */ 524 */
477static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi) 525static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
478{ 526{
527 u8 vic;
528
479 /* AVI InfoFrame */ 529 /* AVI InfoFrame */
480 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX); 530 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX);
481 531
@@ -500,9 +550,9 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
500 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1); 550 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
501 551
502 /* 552 /*
503 * C = No Data 553 * [7:6] C = Colorimetry: no data
504 * M = 16:9 Picture Aspect Ratio 554 * [5:4] M = 2: 16:9, 1: 4:3 Picture Aspect Ratio
505 * R = Same as picture aspect ratio 555 * [3:0] R = 8: Active Frame Aspect Ratio: same as picture aspect ratio
506 */ 556 */
507 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2); 557 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
508 558
@@ -516,9 +566,15 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
516 566
517 /* 567 /*
518 * VIC = 1280 x 720p: ignored if external config is used 568 * VIC = 1280 x 720p: ignored if external config is used
519 * Send 2 for 720 x 480p, 16 for 1080p 569 * Send 2 for 720 x 480p, 16 for 1080p, ignored in external mode
520 */ 570 */
521 hdmi_write(hdmi, 4, HDMI_CTRL_PKT_BUF_ACCESS_PB4); 571 if (hdmi->var.yres == 1080 && hdmi->var.xres == 1920)
572 vic = 16;
573 else if (hdmi->var.yres == 480 && hdmi->var.xres == 720)
574 vic = 2;
575 else
576 vic = 4;
577 hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
522 578
523 /* PR = No Repetition */ 579 /* PR = No Repetition */
524 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5); 580 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
@@ -592,100 +648,6 @@ static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi)
592} 648}
593 649
594/** 650/**
595 * sh_hdmi_gamut_metadata_setup() - Gamut Metadata Packet of CONTROL PACKET
596 */
597static void sh_hdmi_gamut_metadata_setup(struct sh_hdmi *hdmi)
598{
599 int i;
600
601 /* Gamut Metadata Packet */
602 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_INDEX);
603
604 /* Packet Type = 0x0A */
605 hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
606 /* Gamut Packet is not used, so default value */
607 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
608 /* Gamut Packet is not used, so default value */
609 hdmi_write(hdmi, 0x10, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
610
611 /* GBD bytes 0 through 27 */
612 for (i = 0; i <= 27; i++)
613 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0_63H - PB27_7EH */
614 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
615}
616
617/**
618 * sh_hdmi_acp_setup() - Audio Content Protection Packet (ACP)
619 */
620static void sh_hdmi_acp_setup(struct sh_hdmi *hdmi)
621{
622 int i;
623
624 /* Audio Content Protection Packet (ACP) */
625 hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_INDEX);
626
627 /* Packet Type = 0x04 */
628 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
629 /* ACP_Type */
630 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
631 /* Reserved (0) */
632 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
633
634 /* GBD bytes 0 through 27 */
635 for (i = 0; i <= 27; i++)
636 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
637 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
638}
639
640/**
641 * sh_hdmi_isrc1_setup() - ISRC1 Packet
642 */
643static void sh_hdmi_isrc1_setup(struct sh_hdmi *hdmi)
644{
645 int i;
646
647 /* ISRC1 Packet */
648 hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_INDEX);
649
650 /* Packet Type = 0x05 */
651 hdmi_write(hdmi, 0x05, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
652 /* ISRC_Cont, ISRC_Valid, Reserved (0), ISRC_Status */
653 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
654 /* Reserved (0) */
655 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
656
657 /* PB0 UPC_EAN_ISRC_0-15 */
658 /* Bytes PB16-PB27 shall be set to a value of 0. */
659 for (i = 0; i <= 27; i++)
660 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
661 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
662}
663
664/**
665 * sh_hdmi_isrc2_setup() - ISRC2 Packet
666 */
667static void sh_hdmi_isrc2_setup(struct sh_hdmi *hdmi)
668{
669 int i;
670
671 /* ISRC2 Packet */
672 hdmi_write(hdmi, 0x03, HDMI_CTRL_PKT_BUF_INDEX);
673
674 /* HB0 Packet Type = 0x06 */
675 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
676 /* Reserved (0) */
677 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
678 /* Reserved (0) */
679 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
680
681 /* PB0 UPC_EAN_ISRC_16-31 */
682 /* Bytes PB16-PB27 shall be set to a value of 0. */
683 for (i = 0; i <= 27; i++)
684 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
685 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
686}
687
688/**
689 * sh_hdmi_configure() - Initialise HDMI for output 651 * sh_hdmi_configure() - Initialise HDMI for output
690 */ 652 */
691static void sh_hdmi_configure(struct sh_hdmi *hdmi) 653static void sh_hdmi_configure(struct sh_hdmi *hdmi)
@@ -705,18 +667,6 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
705 /* Audio InfoFrame */ 667 /* Audio InfoFrame */
706 sh_hdmi_audio_infoframe_setup(hdmi); 668 sh_hdmi_audio_infoframe_setup(hdmi);
707 669
708 /* Gamut Metadata packet */
709 sh_hdmi_gamut_metadata_setup(hdmi);
710
711 /* Audio Content Protection (ACP) Packet */
712 sh_hdmi_acp_setup(hdmi);
713
714 /* ISRC1 Packet */
715 sh_hdmi_isrc1_setup(hdmi);
716
717 /* ISRC2 Packet */
718 sh_hdmi_isrc2_setup(hdmi);
719
720 /* 670 /*
721 * Control packet auto send with VSYNC control: auto send 671 * Control packet auto send with VSYNC control: auto send
722 * General control, Gamut metadata, ISRC, and ACP packets 672 * General control, Gamut metadata, ISRC, and ACP packets
@@ -734,17 +684,42 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
734 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL); 684 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL);
735} 685}
736 686
737static void sh_hdmi_read_edid(struct sh_hdmi *hdmi) 687static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
688 const struct fb_videomode *mode)
738{ 689{
739 struct fb_var_screeninfo *var = &hdmi->var; 690 long target = PICOS2KHZ(mode->pixclock) * 1000,
740 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 691 rate = clk_round_rate(hdmi->hdmi_clk, target);
741 struct fb_videomode *lcd_cfg = &pdata->lcd_chan->lcd_cfg; 692 unsigned long rate_error = rate > 0 ? abs(rate - target) : ULONG_MAX;
742 unsigned long height = var->height, width = var->width; 693
743 int i; 694 dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n",
695 mode->left_margin, mode->xres,
696 mode->right_margin, mode->hsync_len,
697 mode->upper_margin, mode->yres,
698 mode->lower_margin, mode->vsync_len);
699
700 dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz\n", target,
701 rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
702 mode->refresh);
703
704 return rate_error;
705}
706
707static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
708{
709 struct fb_var_screeninfo tmpvar;
710 struct fb_var_screeninfo *var = &tmpvar;
711 const struct fb_videomode *mode, *found = NULL;
712 struct fb_info *info = hdmi->info;
713 struct fb_modelist *modelist = NULL;
714 unsigned int f_width = 0, f_height = 0, f_refresh = 0;
715 unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */
716 bool exact_match = false;
744 u8 edid[128]; 717 u8 edid[128];
718 char *forced;
719 int i;
745 720
746 /* Read EDID */ 721 /* Read EDID */
747 pr_debug("Read back EDID code:"); 722 dev_dbg(hdmi->dev, "Read back EDID code:");
748 for (i = 0; i < 128; i++) { 723 for (i = 0; i < 128; i++) {
749 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); 724 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
750#ifdef DEBUG 725#ifdef DEBUG
@@ -759,29 +734,97 @@ static void sh_hdmi_read_edid(struct sh_hdmi *hdmi)
759#ifdef DEBUG 734#ifdef DEBUG
760 printk(KERN_CONT "\n"); 735 printk(KERN_CONT "\n");
761#endif 736#endif
762 fb_parse_edid(edid, var); 737
763 pr_debug("%u-%u-%u-%u x %u-%u-%u-%u @ %lu kHz monitor detected\n", 738 fb_edid_to_monspecs(edid, &hdmi->monspec);
764 var->left_margin, var->xres, var->right_margin, var->hsync_len, 739
765 var->upper_margin, var->yres, var->lower_margin, var->vsync_len, 740 fb_get_options("sh_mobile_lcdc", &forced);
766 PICOS2KHZ(var->pixclock)); 741 if (forced && *forced) {
767 742 /* Only primitive parsing so far */
768 /* FIXME: Use user-provided configuration instead of EDID */ 743 i = sscanf(forced, "%ux%u@%u",
769 var->width = width; 744 &f_width, &f_height, &f_refresh);
770 var->xres = lcd_cfg->xres; 745 if (i < 2) {
771 var->xres_virtual = lcd_cfg->xres; 746 f_width = 0;
772 var->left_margin = lcd_cfg->left_margin; 747 f_height = 0;
773 var->right_margin = lcd_cfg->right_margin; 748 }
774 var->hsync_len = lcd_cfg->hsync_len; 749 dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n",
775 var->height = height; 750 f_width, f_height, f_refresh);
776 var->yres = lcd_cfg->yres; 751 }
777 var->yres_virtual = lcd_cfg->yres * 2; 752
778 var->upper_margin = lcd_cfg->upper_margin; 753 /* Walk monitor modes to find the best or the exact match */
779 var->lower_margin = lcd_cfg->lower_margin; 754 for (i = 0, mode = hdmi->monspec.modedb;
780 var->vsync_len = lcd_cfg->vsync_len; 755 f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match;
781 var->sync = lcd_cfg->sync; 756 i++, mode++) {
782 var->pixclock = lcd_cfg->pixclock; 757 unsigned long rate_error = sh_hdmi_rate_error(hdmi, mode);
783 758
784 hdmi_external_video_param(hdmi); 759 /* No interest in unmatching modes */
760 if (f_width != mode->xres || f_height != mode->yres)
761 continue;
762 if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
763 /*
764 * Exact match if either the refresh rate matches or it
765 * hasn't been specified and we've found a mode, for
766 * which we can configure the clock precisely
767 */
768 exact_match = true;
769 else if (found && found_rate_error <= rate_error)
770 /*
771 * We otherwise search for the closest matching clock
772 * rate - either if no refresh rate has been specified
773 * or we cannot find an exactly matching one
774 */
775 continue;
776
777 /* Check if supported: sufficient fb memory, supported clock-rate */
778 fb_videomode_to_var(var, mode);
779
780 if (info && info->fbops->fb_check_var &&
781 info->fbops->fb_check_var(var, info)) {
782 exact_match = false;
783 continue;
784 }
785
786 found = mode;
787 found_rate_error = rate_error;
788 }
789
790 /*
791 * TODO 1: if no ->info is present, postpone running the config until
792 * after ->info first gets registered.
793 * TODO 2: consider registering the HDMI platform device from the LCDC
794 * driver, and passing ->info with HDMI platform data.
795 */
796 if (info && !found) {
797 modelist = hdmi->info->modelist.next &&
798 !list_empty(&hdmi->info->modelist) ?
799 list_entry(hdmi->info->modelist.next,
800 struct fb_modelist, list) :
801 NULL;
802
803 if (modelist) {
804 found = &modelist->mode;
805 found_rate_error = sh_hdmi_rate_error(hdmi, found);
806 }
807 }
808
809 /* No cookie today */
810 if (!found)
811 return -ENXIO;
812
813 dev_info(hdmi->dev, "Using %s mode %ux%u@%uHz (%luHz), clock error %luHz\n",
814 modelist ? "default" : "EDID", found->xres, found->yres,
815 found->refresh, PICOS2KHZ(found->pixclock) * 1000, found_rate_error);
816
817 if ((found->xres == 720 && found->yres == 480) ||
818 (found->xres == 1280 && found->yres == 720) ||
819 (found->xres == 1920 && found->yres == 1080))
820 hdmi->preprogrammed_mode = true;
821 else
822 hdmi->preprogrammed_mode = false;
823
824 fb_videomode_to_var(&hdmi->var, found);
825 sh_hdmi_external_video_param(hdmi);
826
827 return 0;
785} 828}
786 829
787static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) 830static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
@@ -809,8 +852,8 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
809 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2); 852 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2);
810 853
811 if (printk_ratelimit()) 854 if (printk_ratelimit())
812 pr_debug("IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n", 855 dev_dbg(hdmi->dev, "IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n",
813 irq, status1, mask1, status2, mask2); 856 irq, status1, mask1, status2, mask2);
814 857
815 if (!((status1 & mask1) | (status2 & mask2))) { 858 if (!((status1 & mask1) | (status2 & mask2))) {
816 return IRQ_NONE; 859 return IRQ_NONE;
@@ -821,7 +864,7 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
821 udelay(500); 864 udelay(500);
822 865
823 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS); 866 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS);
824 pr_debug("MSENS 0x%x\n", msens); 867 dev_dbg(hdmi->dev, "MSENS 0x%x\n", msens);
825 /* Check, if hot plug & MSENS pin status are both high */ 868 /* Check, if hot plug & MSENS pin status are both high */
826 if ((msens & 0xC0) == 0xC0) { 869 if ((msens & 0xC0) == 0xC0) {
827 /* Display plug in */ 870 /* Display plug in */
@@ -857,83 +900,176 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
857 return IRQ_HANDLED; 900 return IRQ_HANDLED;
858} 901}
859 902
860static void hdmi_display_on(void *arg, struct fb_info *info) 903/* locking: called with info->lock held, or before register_framebuffer() */
904static void sh_hdmi_display_on(void *arg, struct fb_info *info)
861{ 905{
906 /*
907 * info is guaranteed to be valid, when we are called, because our
908 * FB_EVENT_FB_UNBIND notify is also called with info->lock held
909 */
862 struct sh_hdmi *hdmi = arg; 910 struct sh_hdmi *hdmi = arg;
863 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 911 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
912 struct sh_mobile_lcdc_chan *ch = info->par;
864 913
865 if (info->var.xres != 1280 || info->var.yres != 720) { 914 dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__,
866 dev_warn(info->device, "Unsupported framebuffer geometry %ux%u\n", 915 pdata->lcd_dev, info->state);
867 info->var.xres, info->var.yres); 916
868 return; 917 /* No need to lock */
869 } 918 hdmi->info = info;
870 919
871 pr_debug("%s(%p): state %x\n", __func__, pdata->lcd_dev, info->state);
872 /* 920 /*
873 * FIXME: not a good place to store fb_info. And we cannot nullify it 921 * hp_state can be set to
874 * even on monitor disconnect. What should the lifecycle be? 922 * HDMI_HOTPLUG_DISCONNECTED: on monitor unplug
923 * HDMI_HOTPLUG_CONNECTED: on monitor plug-in
924 * HDMI_HOTPLUG_EDID_DONE: on EDID read completion
875 */ 925 */
876 hdmi->info = info;
877 switch (hdmi->hp_state) { 926 switch (hdmi->hp_state) {
878 case HDMI_HOTPLUG_EDID_DONE: 927 case HDMI_HOTPLUG_EDID_DONE:
879 /* PS mode d->e. All functions are active */ 928 /* PS mode d->e. All functions are active */
880 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL); 929 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
881 pr_debug("HDMI running\n"); 930 dev_dbg(hdmi->dev, "HDMI running\n");
882 break; 931 break;
883 case HDMI_HOTPLUG_DISCONNECTED: 932 case HDMI_HOTPLUG_DISCONNECTED:
884 info->state = FBINFO_STATE_SUSPENDED; 933 info->state = FBINFO_STATE_SUSPENDED;
885 default: 934 default:
886 hdmi->var = info->var; 935 hdmi->var = ch->display_var;
887 } 936 }
888} 937}
889 938
890static void hdmi_display_off(void *arg) 939/* locking: called with info->lock held */
940static void sh_hdmi_display_off(void *arg)
891{ 941{
892 struct sh_hdmi *hdmi = arg; 942 struct sh_hdmi *hdmi = arg;
893 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 943 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
894 944
895 pr_debug("%s(%p)\n", __func__, pdata->lcd_dev); 945 dev_dbg(hdmi->dev, "%s(%p)\n", __func__, pdata->lcd_dev);
896 /* PS mode e->a */ 946 /* PS mode e->a */
897 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL); 947 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
898} 948}
899 949
950static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi)
951{
952 struct fb_info *info = hdmi->info;
953 struct sh_mobile_lcdc_chan *ch = info->par;
954 struct fb_var_screeninfo *new_var = &hdmi->var, *old_var = &ch->display_var;
955 struct fb_videomode mode1, mode2;
956
957 fb_var_to_videomode(&mode1, old_var);
958 fb_var_to_videomode(&mode2, new_var);
959
960 dev_dbg(info->dev, "Old %ux%u, new %ux%u\n",
961 mode1.xres, mode1.yres, mode2.xres, mode2.yres);
962
963 if (fb_mode_is_equal(&mode1, &mode2))
964 return false;
965
966 dev_dbg(info->dev, "Switching %u -> %u lines\n",
967 mode1.yres, mode2.yres);
968 *old_var = *new_var;
969
970 return true;
971}
972
973/**
974 * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
975 * @hdmi: driver context
976 * @pixclock: pixel clock period in picoseconds
977 * return: configured positive rate if successful
978 * 0 if couldn't set the rate, but managed to enable the clock
979 * negative error, if couldn't enable the clock
980 */
981static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long pixclock)
982{
983 long rate;
984 int ret;
985
986 rate = PICOS2KHZ(pixclock) * 1000;
987 rate = clk_round_rate(hdmi->hdmi_clk, rate);
988 if (rate > 0) {
989 ret = clk_set_rate(hdmi->hdmi_clk, rate);
990 if (ret < 0) {
991 dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", rate, ret);
992 rate = 0;
993 } else {
994 dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", rate);
995 }
996 } else {
997 rate = 0;
998 dev_warn(hdmi->dev, "Cannot get suitable rate: %ld\n", rate);
999 }
1000
1001 ret = clk_enable(hdmi->hdmi_clk);
1002 if (ret < 0) {
1003 dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
1004 return ret;
1005 }
1006
1007 return rate;
1008}
1009
900/* Hotplug interrupt occurred, read EDID */ 1010/* Hotplug interrupt occurred, read EDID */
901static void edid_work_fn(struct work_struct *work) 1011static void sh_hdmi_edid_work_fn(struct work_struct *work)
902{ 1012{
903 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); 1013 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
904 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 1014 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1015 struct sh_mobile_lcdc_chan *ch;
1016 int ret;
905 1017
906 pr_debug("%s(%p): begin, hotplug status %d\n", __func__, 1018 dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__,
907 pdata->lcd_dev, hdmi->hp_state); 1019 pdata->lcd_dev, hdmi->hp_state);
908 1020
909 if (!pdata->lcd_dev) 1021 if (!pdata->lcd_dev)
910 return; 1022 return;
911 1023
1024 mutex_lock(&hdmi->mutex);
1025
912 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { 1026 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
913 pm_runtime_get_sync(hdmi->dev);
914 /* A device has been plugged in */ 1027 /* A device has been plugged in */
915 sh_hdmi_read_edid(hdmi); 1028 pm_runtime_get_sync(hdmi->dev);
1029
1030 ret = sh_hdmi_read_edid(hdmi);
1031 if (ret < 0)
1032 goto out;
1033
1034 /* Reconfigure the clock */
1035 clk_disable(hdmi->hdmi_clk);
1036 ret = sh_hdmi_clk_configure(hdmi, hdmi->var.pixclock);
1037 if (ret < 0)
1038 goto out;
1039
916 msleep(10); 1040 msleep(10);
917 sh_hdmi_configure(hdmi); 1041 sh_hdmi_configure(hdmi);
918 /* Switched to another (d) power-save mode */ 1042 /* Switched to another (d) power-save mode */
919 msleep(10); 1043 msleep(10);
920 1044
921 if (!hdmi->info) 1045 if (!hdmi->info)
922 return; 1046 goto out;
1047
1048 ch = hdmi->info->par;
923 1049
924 acquire_console_sem(); 1050 acquire_console_sem();
925 1051
926 /* HDMI plug in */ 1052 /* HDMI plug in */
927 hdmi->info->var = hdmi->var; 1053 if (!sh_hdmi_must_reconfigure(hdmi) &&
928 if (hdmi->info->state != FBINFO_STATE_RUNNING) 1054 hdmi->info->state == FBINFO_STATE_RUNNING) {
1055 /*
1056 * First activation with the default monitor - just turn
1057 * on, if we run a resume here, the logo disappears
1058 */
1059 if (lock_fb_info(hdmi->info)) {
1060 sh_hdmi_display_on(hdmi, hdmi->info);
1061 unlock_fb_info(hdmi->info);
1062 }
1063 } else {
1064 /* New monitor or have to wake up */
929 fb_set_suspend(hdmi->info, 0); 1065 fb_set_suspend(hdmi->info, 0);
930 else 1066 }
931 hdmi_display_on(hdmi, hdmi->info);
932 1067
933 release_console_sem(); 1068 release_console_sem();
934 } else { 1069 } else {
1070 ret = 0;
935 if (!hdmi->info) 1071 if (!hdmi->info)
936 return; 1072 goto out;
937 1073
938 acquire_console_sem(); 1074 acquire_console_sem();
939 1075
@@ -942,15 +1078,67 @@ static void edid_work_fn(struct work_struct *work)
942 1078
943 release_console_sem(); 1079 release_console_sem();
944 pm_runtime_put(hdmi->dev); 1080 pm_runtime_put(hdmi->dev);
1081 fb_destroy_modedb(hdmi->monspec.modedb);
945 } 1082 }
946 1083
947 pr_debug("%s(%p): end\n", __func__, pdata->lcd_dev); 1084out:
1085 if (ret < 0)
1086 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
1087 mutex_unlock(&hdmi->mutex);
1088
1089 dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, pdata->lcd_dev);
1090}
1091
1092static int sh_hdmi_notify(struct notifier_block *nb,
1093 unsigned long action, void *data);
1094
1095static struct notifier_block sh_hdmi_notifier = {
1096 .notifier_call = sh_hdmi_notify,
1097};
1098
1099static int sh_hdmi_notify(struct notifier_block *nb,
1100 unsigned long action, void *data)
1101{
1102 struct fb_event *event = data;
1103 struct fb_info *info = event->info;
1104 struct sh_mobile_lcdc_chan *ch = info->par;
1105 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
1106 struct sh_hdmi *hdmi = board_cfg->board_data;
1107
1108 if (nb != &sh_hdmi_notifier || !hdmi || hdmi->info != info)
1109 return NOTIFY_DONE;
1110
1111 switch(action) {
1112 case FB_EVENT_FB_REGISTERED:
1113 /* Unneeded, activation taken care by sh_hdmi_display_on() */
1114 break;
1115 case FB_EVENT_FB_UNREGISTERED:
1116 /*
1117 * We are called from unregister_framebuffer() with the
1118 * info->lock held. This is bad for us, because we can race with
1119 * the scheduled work, which has to call fb_set_suspend(), which
1120 * takes info->lock internally, so, sh_hdmi_edid_work_fn()
1121 * cannot take and hold info->lock for the whole function
1122 * duration. Using an additional lock creates a classical AB-BA
1123 * lock up. Therefore, we have to release the info->lock
1124 * temporarily, synchronise with the work queue and re-acquire
1125 * the info->lock.
1126 */
1127 unlock_fb_info(hdmi->info);
1128 mutex_lock(&hdmi->mutex);
1129 hdmi->info = NULL;
1130 mutex_unlock(&hdmi->mutex);
1131 lock_fb_info(hdmi->info);
1132 return NOTIFY_OK;
1133 }
1134 return NOTIFY_DONE;
948} 1135}
949 1136
950static int __init sh_hdmi_probe(struct platform_device *pdev) 1137static int __init sh_hdmi_probe(struct platform_device *pdev)
951{ 1138{
952 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1139 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
953 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1140 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1141 struct sh_mobile_lcdc_board_cfg *board_cfg;
954 int irq = platform_get_irq(pdev, 0), ret; 1142 int irq = platform_get_irq(pdev, 0), ret;
955 struct sh_hdmi *hdmi; 1143 struct sh_hdmi *hdmi;
956 long rate; 1144 long rate;
@@ -964,10 +1152,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
964 return -ENOMEM; 1152 return -ENOMEM;
965 } 1153 }
966 1154
967 ret = snd_soc_register_codec(&pdev->dev, 1155 mutex_init(&hdmi->mutex);
968 &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
969 if (ret < 0)
970 goto esndreg;
971 1156
972 hdmi->dev = &pdev->dev; 1157 hdmi->dev = &pdev->dev;
973 1158
@@ -978,30 +1163,14 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
978 goto egetclk; 1163 goto egetclk;
979 } 1164 }
980 1165
981 rate = PICOS2KHZ(pdata->lcd_chan->lcd_cfg.pixclock) * 1000; 1166 /* Some arbitrary relaxed pixclock just to get things started */
982 1167 rate = sh_hdmi_clk_configure(hdmi, 37037);
983 rate = clk_round_rate(hdmi->hdmi_clk, rate);
984 if (rate < 0) { 1168 if (rate < 0) {
985 ret = rate; 1169 ret = rate;
986 dev_err(&pdev->dev, "Cannot get suitable rate: %ld\n", rate);
987 goto erate; 1170 goto erate;
988 } 1171 }
989 1172
990 ret = clk_set_rate(hdmi->hdmi_clk, rate); 1173 dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
991 if (ret < 0) {
992 dev_err(&pdev->dev, "Cannot set rate %ld: %d\n", rate, ret);
993 goto erate;
994 }
995
996 pr_debug("HDMI set frequency %lu\n", rate);
997
998 ret = clk_enable(hdmi->hdmi_clk);
999 if (ret < 0) {
1000 dev_err(&pdev->dev, "Cannot enable clock: %d\n", ret);
1001 goto eclkenable;
1002 }
1003
1004 dev_info(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
1005 1174
1006 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { 1175 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
1007 dev_err(&pdev->dev, "HDMI register region already claimed\n"); 1176 dev_err(&pdev->dev, "HDMI register region already claimed\n");
@@ -1018,18 +1187,18 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1018 1187
1019 platform_set_drvdata(pdev, hdmi); 1188 platform_set_drvdata(pdev, hdmi);
1020 1189
1021#if 1
1022 /* Product and revision IDs are 0 in sh-mobile version */ 1190 /* Product and revision IDs are 0 in sh-mobile version */
1023 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", 1191 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
1024 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); 1192 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
1025#endif
1026 1193
1027 /* Set up LCDC callbacks */ 1194 /* Set up LCDC callbacks */
1028 pdata->lcd_chan->board_cfg.board_data = hdmi; 1195 board_cfg = &pdata->lcd_chan->board_cfg;
1029 pdata->lcd_chan->board_cfg.display_on = hdmi_display_on; 1196 board_cfg->owner = THIS_MODULE;
1030 pdata->lcd_chan->board_cfg.display_off = hdmi_display_off; 1197 board_cfg->board_data = hdmi;
1198 board_cfg->display_on = sh_hdmi_display_on;
1199 board_cfg->display_off = sh_hdmi_display_off;
1031 1200
1032 INIT_DELAYED_WORK(&hdmi->edid_work, edid_work_fn); 1201 INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn);
1033 1202
1034 pm_runtime_enable(&pdev->dev); 1203 pm_runtime_enable(&pdev->dev);
1035 pm_runtime_resume(&pdev->dev); 1204 pm_runtime_resume(&pdev->dev);
@@ -1041,8 +1210,17 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1041 goto ereqirq; 1210 goto ereqirq;
1042 } 1211 }
1043 1212
1213 ret = snd_soc_register_codec(&pdev->dev,
1214 &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
1215 if (ret < 0) {
1216 dev_err(&pdev->dev, "codec registration failed\n");
1217 goto ecodec;
1218 }
1219
1044 return 0; 1220 return 0;
1045 1221
1222ecodec:
1223 free_irq(irq, hdmi);
1046ereqirq: 1224ereqirq:
1047 pm_runtime_disable(&pdev->dev); 1225 pm_runtime_disable(&pdev->dev);
1048 iounmap(hdmi->base); 1226 iounmap(hdmi->base);
@@ -1050,12 +1228,10 @@ emap:
1050 release_mem_region(res->start, resource_size(res)); 1228 release_mem_region(res->start, resource_size(res));
1051ereqreg: 1229ereqreg:
1052 clk_disable(hdmi->hdmi_clk); 1230 clk_disable(hdmi->hdmi_clk);
1053eclkenable:
1054erate: 1231erate:
1055 clk_put(hdmi->hdmi_clk); 1232 clk_put(hdmi->hdmi_clk);
1056egetclk: 1233egetclk:
1057 snd_soc_unregister_codec(&pdev->dev); 1234 mutex_destroy(&hdmi->mutex);
1058esndreg:
1059 kfree(hdmi); 1235 kfree(hdmi);
1060 1236
1061 return ret; 1237 return ret;
@@ -1066,21 +1242,26 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
1066 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1242 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
1067 struct sh_hdmi *hdmi = platform_get_drvdata(pdev); 1243 struct sh_hdmi *hdmi = platform_get_drvdata(pdev);
1068 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1244 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1245 struct sh_mobile_lcdc_board_cfg *board_cfg = &pdata->lcd_chan->board_cfg;
1069 int irq = platform_get_irq(pdev, 0); 1246 int irq = platform_get_irq(pdev, 0);
1070 1247
1071 snd_soc_unregister_codec(&pdev->dev); 1248 snd_soc_unregister_codec(&pdev->dev);
1072 1249
1073 pdata->lcd_chan->board_cfg.display_on = NULL; 1250 board_cfg->display_on = NULL;
1074 pdata->lcd_chan->board_cfg.display_off = NULL; 1251 board_cfg->display_off = NULL;
1075 pdata->lcd_chan->board_cfg.board_data = NULL; 1252 board_cfg->board_data = NULL;
1253 board_cfg->owner = NULL;
1076 1254
1255 /* No new work will be scheduled, wait for running ISR */
1077 free_irq(irq, hdmi); 1256 free_irq(irq, hdmi);
1078 pm_runtime_disable(&pdev->dev); 1257 /* Wait for already scheduled work */
1079 cancel_delayed_work_sync(&hdmi->edid_work); 1258 cancel_delayed_work_sync(&hdmi->edid_work);
1259 pm_runtime_disable(&pdev->dev);
1080 clk_disable(hdmi->hdmi_clk); 1260 clk_disable(hdmi->hdmi_clk);
1081 clk_put(hdmi->hdmi_clk); 1261 clk_put(hdmi->hdmi_clk);
1082 iounmap(hdmi->base); 1262 iounmap(hdmi->base);
1083 release_mem_region(res->start, resource_size(res)); 1263 release_mem_region(res->start, resource_size(res));
1264 mutex_destroy(&hdmi->mutex);
1084 kfree(hdmi); 1265 kfree(hdmi);
1085 1266
1086 return 0; 1267 return 0;
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 7a1419279c8f..50963739a409 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -12,7 +12,6 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/mm.h> 14#include <linux/mm.h>
15#include <linux/fb.h>
16#include <linux/clk.h> 15#include <linux/clk.h>
17#include <linux/pm_runtime.h> 16#include <linux/pm_runtime.h>
18#include <linux/platform_device.h> 17#include <linux/platform_device.h>
@@ -21,10 +20,12 @@
21#include <linux/vmalloc.h> 20#include <linux/vmalloc.h>
22#include <linux/ioctl.h> 21#include <linux/ioctl.h>
23#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/console.h>
24#include <video/sh_mobile_lcdc.h> 24#include <video/sh_mobile_lcdc.h>
25#include <asm/atomic.h> 25#include <asm/atomic.h>
26 26
27#define PALETTE_NR 16 27#include "sh_mobile_lcdcfb.h"
28
28#define SIDE_B_OFFSET 0x1000 29#define SIDE_B_OFFSET 0x1000
29#define MIRROR_OFFSET 0x2000 30#define MIRROR_OFFSET 0x2000
30 31
@@ -53,11 +54,8 @@ static int lcdc_shared_regs[] = {
53}; 54};
54#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) 55#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
55 56
56/* per-channel registers */ 57#define DEFAULT_XRES 1280
57enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, 58#define DEFAULT_YRES 1024
58 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
59 LDHAJR,
60 NR_CH_REGS };
61 59
62static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 60static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
63 [LDDCKPAT1R] = 0x400, 61 [LDDCKPAT1R] = 0x400,
@@ -112,23 +110,21 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
112#define LDRCNTR_MRC 0x00000001 110#define LDRCNTR_MRC 0x00000001
113#define LDSR_MRS 0x00000100 111#define LDSR_MRS 0x00000100
114 112
115struct sh_mobile_lcdc_priv; 113static const struct fb_videomode default_720p = {
116struct sh_mobile_lcdc_chan { 114 .name = "HDMI 720p",
117 struct sh_mobile_lcdc_priv *lcdc; 115 .xres = 1280,
118 unsigned long *reg_offs; 116 .yres = 720,
119 unsigned long ldmt1r_value; 117
120 unsigned long enabled; /* ME and SE in LDCNT2R */ 118 .left_margin = 200,
121 struct sh_mobile_lcdc_chan_cfg cfg; 119 .right_margin = 88,
122 u32 pseudo_palette[PALETTE_NR]; 120 .hsync_len = 48,
123 unsigned long saved_ch_regs[NR_CH_REGS]; 121
124 struct fb_info *info; 122 .upper_margin = 20,
125 dma_addr_t dma_handle; 123 .lower_margin = 5,
126 struct fb_deferred_io defio; 124 .vsync_len = 5,
127 struct scatterlist *sglist; 125
128 unsigned long frame_end; 126 .pixclock = 13468,
129 unsigned long pan_offset; 127 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
130 wait_queue_head_t frame_end_wait;
131 struct completion vsync_completion;
132}; 128};
133 129
134struct sh_mobile_lcdc_priv { 130struct sh_mobile_lcdc_priv {
@@ -409,8 +405,8 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
409 405
410static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) 406static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
411{ 407{
412 struct fb_var_screeninfo *var = &ch->info->var; 408 struct fb_var_screeninfo *var = &ch->info->var, *display_var = &ch->display_var;
413 unsigned long h_total, hsync_pos; 409 unsigned long h_total, hsync_pos, display_h_total;
414 u32 tmp; 410 u32 tmp;
415 411
416 tmp = ch->ldmt1r_value; 412 tmp = ch->ldmt1r_value;
@@ -428,31 +424,33 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
428 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r); 424 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
429 425
430 /* horizontal configuration */ 426 /* horizontal configuration */
431 h_total = var->xres + var->hsync_len + 427 h_total = display_var->xres + display_var->hsync_len +
432 var->left_margin + var->right_margin; 428 display_var->left_margin + display_var->right_margin;
433 tmp = h_total / 8; /* HTCN */ 429 tmp = h_total / 8; /* HTCN */
434 tmp |= (var->xres / 8) << 16; /* HDCN */ 430 tmp |= (min(display_var->xres, var->xres) / 8) << 16; /* HDCN */
435 lcdc_write_chan(ch, LDHCNR, tmp); 431 lcdc_write_chan(ch, LDHCNR, tmp);
436 432
437 hsync_pos = var->xres + var->right_margin; 433 hsync_pos = display_var->xres + display_var->right_margin;
438 tmp = hsync_pos / 8; /* HSYNP */ 434 tmp = hsync_pos / 8; /* HSYNP */
439 tmp |= (var->hsync_len / 8) << 16; /* HSYNW */ 435 tmp |= (display_var->hsync_len / 8) << 16; /* HSYNW */
440 lcdc_write_chan(ch, LDHSYNR, tmp); 436 lcdc_write_chan(ch, LDHSYNR, tmp);
441 437
442 /* vertical configuration */ 438 /* vertical configuration */
443 tmp = var->yres + var->vsync_len + 439 tmp = display_var->yres + display_var->vsync_len +
444 var->upper_margin + var->lower_margin; /* VTLN */ 440 display_var->upper_margin + display_var->lower_margin; /* VTLN */
445 tmp |= var->yres << 16; /* VDLN */ 441 tmp |= min(display_var->yres, var->yres) << 16; /* VDLN */
446 lcdc_write_chan(ch, LDVLNR, tmp); 442 lcdc_write_chan(ch, LDVLNR, tmp);
447 443
448 tmp = var->yres + var->lower_margin; /* VSYNP */ 444 tmp = display_var->yres + display_var->lower_margin; /* VSYNP */
449 tmp |= var->vsync_len << 16; /* VSYNW */ 445 tmp |= display_var->vsync_len << 16; /* VSYNW */
450 lcdc_write_chan(ch, LDVSYNR, tmp); 446 lcdc_write_chan(ch, LDVSYNR, tmp);
451 447
452 /* Adjust horizontal synchronisation for HDMI */ 448 /* Adjust horizontal synchronisation for HDMI */
453 tmp = ((var->xres & 7) << 24) | 449 display_h_total = display_var->xres + display_var->hsync_len +
454 ((h_total & 7) << 16) | 450 display_var->left_margin + display_var->right_margin;
455 ((var->hsync_len & 7) << 8) | 451 tmp = ((display_var->xres & 7) << 24) |
452 ((display_h_total & 7) << 16) |
453 ((display_var->hsync_len & 7) << 8) |
456 hsync_pos; 454 hsync_pos;
457 lcdc_write_chan(ch, LDHAJR, tmp); 455 lcdc_write_chan(ch, LDHAJR, tmp);
458} 456}
@@ -460,7 +458,6 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
460static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 458static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
461{ 459{
462 struct sh_mobile_lcdc_chan *ch; 460 struct sh_mobile_lcdc_chan *ch;
463 struct fb_videomode *lcd_cfg;
464 struct sh_mobile_lcdc_board_cfg *board_cfg; 461 struct sh_mobile_lcdc_board_cfg *board_cfg;
465 unsigned long tmp; 462 unsigned long tmp;
466 int k, m; 463 int k, m;
@@ -503,7 +500,8 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
503 m = 1 << 6; 500 m = 1 << 6;
504 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); 501 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
505 502
506 lcdc_write_chan(ch, LDDCKPAT1R, 0x00000000); 503 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider denominator */
504 lcdc_write_chan(ch, LDDCKPAT1R, 0);
507 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); 505 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
508 } 506 }
509 507
@@ -518,7 +516,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
518 516
519 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 517 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
520 ch = &priv->ch[k]; 518 ch = &priv->ch[k];
521 lcd_cfg = &ch->cfg.lcd_cfg;
522 519
523 if (!ch->enabled) 520 if (!ch->enabled)
524 continue; 521 continue;
@@ -547,7 +544,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
547 544
548 /* set bpp format in PKF[4:0] */ 545 /* set bpp format in PKF[4:0] */
549 tmp = lcdc_read_chan(ch, LDDFR); 546 tmp = lcdc_read_chan(ch, LDDFR);
550 tmp &= ~(0x0001001f); 547 tmp &= ~0x0001001f;
551 tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0; 548 tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0;
552 lcdc_write_chan(ch, LDDFR, tmp); 549 lcdc_write_chan(ch, LDDFR, tmp);
553 550
@@ -591,8 +588,10 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
591 continue; 588 continue;
592 589
593 board_cfg = &ch->cfg.board_cfg; 590 board_cfg = &ch->cfg.board_cfg;
594 if (board_cfg->display_on) 591 if (try_module_get(board_cfg->owner) && board_cfg->display_on) {
595 board_cfg->display_on(board_cfg->board_data, ch->info); 592 board_cfg->display_on(board_cfg->board_data, ch->info);
593 module_put(board_cfg->owner);
594 }
596 } 595 }
597 596
598 return 0; 597 return 0;
@@ -614,7 +613,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
614 * flush frame, and wait for frame end interrupt 613 * flush frame, and wait for frame end interrupt
615 * clean up deferred io and enable clock 614 * clean up deferred io and enable clock
616 */ 615 */
617 if (ch->info->fbdefio) { 616 if (ch->info && ch->info->fbdefio) {
618 ch->frame_end = 0; 617 ch->frame_end = 0;
619 schedule_delayed_work(&ch->info->deferred_work, 0); 618 schedule_delayed_work(&ch->info->deferred_work, 0);
620 wait_event(ch->frame_end_wait, ch->frame_end); 619 wait_event(ch->frame_end_wait, ch->frame_end);
@@ -624,8 +623,10 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
624 } 623 }
625 624
626 board_cfg = &ch->cfg.board_cfg; 625 board_cfg = &ch->cfg.board_cfg;
627 if (board_cfg->display_off) 626 if (try_module_get(board_cfg->owner) && board_cfg->display_off) {
628 board_cfg->display_off(board_cfg->board_data); 627 board_cfg->display_off(board_cfg->board_data);
628 module_put(board_cfg->owner);
629 }
629 } 630 }
630 631
631 /* stop the lcdc */ 632 /* stop the lcdc */
@@ -704,7 +705,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
704 return PTR_ERR(priv->dot_clk); 705 return PTR_ERR(priv->dot_clk);
705 } 706 }
706 } 707 }
707 atomic_set(&priv->hw_usecnt, -1);
708 708
709 /* Runtime PM support involves two step for this driver: 709 /* Runtime PM support involves two step for this driver:
710 * 1) Enable Runtime PM 710 * 1) Enable Runtime PM
@@ -837,6 +837,102 @@ static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
837 return retval; 837 return retval;
838} 838}
839 839
840static void sh_mobile_fb_reconfig(struct fb_info *info)
841{
842 struct sh_mobile_lcdc_chan *ch = info->par;
843 struct fb_videomode mode1, mode2;
844 struct fb_event event;
845 int evnt = FB_EVENT_MODE_CHANGE_ALL;
846
847 if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par))
848 /* More framebuffer users are active */
849 return;
850
851 fb_var_to_videomode(&mode1, &ch->display_var);
852 fb_var_to_videomode(&mode2, &info->var);
853
854 if (fb_mode_is_equal(&mode1, &mode2))
855 return;
856
857 /* Display has been re-plugged, framebuffer is free now, reconfigure */
858 if (fb_set_var(info, &ch->display_var) < 0)
859 /* Couldn't reconfigure, hopefully, can continue as before */
860 return;
861
862 info->fix.line_length = mode2.xres * (ch->cfg.bpp / 8);
863
864 /*
865 * fb_set_var() calls the notifier change internally, only if
866 * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a
867 * user event, we have to call the chain ourselves.
868 */
869 event.info = info;
870 event.data = &mode2;
871 fb_notifier_call_chain(evnt, &event);
872}
873
874/*
875 * Locking: both .fb_release() and .fb_open() are called with info->lock held if
876 * user == 1, or with console sem held, if user == 0.
877 */
878static int sh_mobile_release(struct fb_info *info, int user)
879{
880 struct sh_mobile_lcdc_chan *ch = info->par;
881
882 mutex_lock(&ch->open_lock);
883 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
884
885 ch->use_count--;
886
887 /* Nothing to reconfigure, when called from fbcon */
888 if (user) {
889 acquire_console_sem();
890 sh_mobile_fb_reconfig(info);
891 release_console_sem();
892 }
893
894 mutex_unlock(&ch->open_lock);
895
896 return 0;
897}
898
899static int sh_mobile_open(struct fb_info *info, int user)
900{
901 struct sh_mobile_lcdc_chan *ch = info->par;
902
903 mutex_lock(&ch->open_lock);
904 ch->use_count++;
905
906 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
907 mutex_unlock(&ch->open_lock);
908
909 return 0;
910}
911
912static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
913{
914 struct sh_mobile_lcdc_chan *ch = info->par;
915
916 if (var->xres < 160 || var->xres > 1920 ||
917 var->yres < 120 || var->yres > 1080 ||
918 var->left_margin < 32 || var->left_margin > 320 ||
919 var->right_margin < 12 || var->right_margin > 240 ||
920 var->upper_margin < 12 || var->upper_margin > 120 ||
921 var->lower_margin < 1 || var->lower_margin > 64 ||
922 var->hsync_len < 32 || var->hsync_len > 240 ||
923 var->vsync_len < 2 || var->vsync_len > 64 ||
924 var->pixclock < 6000 || var->pixclock > 40000 ||
925 var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) {
926 dev_warn(info->dev, "Invalid info: %u %u %u %u %u %u %u %u %u!\n",
927 var->xres, var->yres,
928 var->left_margin, var->right_margin,
929 var->upper_margin, var->lower_margin,
930 var->hsync_len, var->vsync_len,
931 var->pixclock);
932 return -EINVAL;
933 }
934 return 0;
935}
840 936
841static struct fb_ops sh_mobile_lcdc_ops = { 937static struct fb_ops sh_mobile_lcdc_ops = {
842 .owner = THIS_MODULE, 938 .owner = THIS_MODULE,
@@ -848,6 +944,9 @@ static struct fb_ops sh_mobile_lcdc_ops = {
848 .fb_imageblit = sh_mobile_lcdc_imageblit, 944 .fb_imageblit = sh_mobile_lcdc_imageblit,
849 .fb_pan_display = sh_mobile_fb_pan_display, 945 .fb_pan_display = sh_mobile_fb_pan_display,
850 .fb_ioctl = sh_mobile_ioctl, 946 .fb_ioctl = sh_mobile_ioctl,
947 .fb_open = sh_mobile_open,
948 .fb_release = sh_mobile_release,
949 .fb_check_var = sh_mobile_check_var,
851}; 950};
852 951
853static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) 952static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
@@ -958,6 +1057,7 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
958 .runtime_resume = sh_mobile_lcdc_runtime_resume, 1057 .runtime_resume = sh_mobile_lcdc_runtime_resume,
959}; 1058};
960 1059
1060/* locking: called with info->lock held */
961static int sh_mobile_lcdc_notify(struct notifier_block *nb, 1061static int sh_mobile_lcdc_notify(struct notifier_block *nb,
962 unsigned long action, void *data) 1062 unsigned long action, void *data)
963{ 1063{
@@ -965,53 +1065,40 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
965 struct fb_info *info = event->info; 1065 struct fb_info *info = event->info;
966 struct sh_mobile_lcdc_chan *ch = info->par; 1066 struct sh_mobile_lcdc_chan *ch = info->par;
967 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; 1067 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
968 struct fb_var_screeninfo *var; 1068 int ret;
969 1069
970 if (&ch->lcdc->notifier != nb) 1070 if (&ch->lcdc->notifier != nb)
971 return 0; 1071 return NOTIFY_DONE;
972 1072
973 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n", 1073 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
974 __func__, action, event->data); 1074 __func__, action, event->data);
975 1075
976 switch(action) { 1076 switch(action) {
977 case FB_EVENT_SUSPEND: 1077 case FB_EVENT_SUSPEND:
978 if (board_cfg->display_off) 1078 if (try_module_get(board_cfg->owner) && board_cfg->display_off) {
979 board_cfg->display_off(board_cfg->board_data); 1079 board_cfg->display_off(board_cfg->board_data);
1080 module_put(board_cfg->owner);
1081 }
980 pm_runtime_put(info->device); 1082 pm_runtime_put(info->device);
1083 sh_mobile_lcdc_stop(ch->lcdc);
981 break; 1084 break;
982 case FB_EVENT_RESUME: 1085 case FB_EVENT_RESUME:
983 var = &info->var; 1086 mutex_lock(&ch->open_lock);
1087 sh_mobile_fb_reconfig(info);
1088 mutex_unlock(&ch->open_lock);
984 1089
985 /* HDMI must be enabled before LCDC configuration */ 1090 /* HDMI must be enabled before LCDC configuration */
986 if (board_cfg->display_on) 1091 if (try_module_get(board_cfg->owner) && board_cfg->display_on) {
987 board_cfg->display_on(board_cfg->board_data, ch->info); 1092 board_cfg->display_on(board_cfg->board_data, info);
988 1093 module_put(board_cfg->owner);
989 /* Check if the new display is not in our modelist */
990 if (ch->info->modelist.next &&
991 !fb_match_mode(var, &ch->info->modelist)) {
992 struct fb_videomode mode;
993 int ret;
994
995 /* Can we handle this display? */
996 if (var->xres > ch->cfg.lcd_cfg.xres ||
997 var->yres > ch->cfg.lcd_cfg.yres)
998 return -ENOMEM;
999
1000 /* Add to the modelist */
1001 fb_var_to_videomode(&mode, var);
1002 ret = fb_add_videomode(&mode, &ch->info->modelist);
1003 if (ret < 0)
1004 return ret;
1005 } 1094 }
1006 1095
1007 pm_runtime_get_sync(info->device); 1096 ret = sh_mobile_lcdc_start(ch->lcdc);
1008 1097 if (!ret)
1009 sh_mobile_lcdc_geometry(ch); 1098 pm_runtime_get_sync(info->device);
1010
1011 break;
1012 } 1099 }
1013 1100
1014 return 0; 1101 return NOTIFY_OK;
1015} 1102}
1016 1103
1017static int sh_mobile_lcdc_remove(struct platform_device *pdev); 1104static int sh_mobile_lcdc_remove(struct platform_device *pdev);
@@ -1020,14 +1107,13 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1020{ 1107{
1021 struct fb_info *info; 1108 struct fb_info *info;
1022 struct sh_mobile_lcdc_priv *priv; 1109 struct sh_mobile_lcdc_priv *priv;
1023 struct sh_mobile_lcdc_info *pdata; 1110 struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data;
1024 struct sh_mobile_lcdc_chan_cfg *cfg;
1025 struct resource *res; 1111 struct resource *res;
1026 int error; 1112 int error;
1027 void *buf; 1113 void *buf;
1028 int i, j; 1114 int i, j;
1029 1115
1030 if (!pdev->dev.platform_data) { 1116 if (!pdata) {
1031 dev_err(&pdev->dev, "no platform data defined\n"); 1117 dev_err(&pdev->dev, "no platform data defined\n");
1032 return -EINVAL; 1118 return -EINVAL;
1033 } 1119 }
@@ -1055,31 +1141,33 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1055 } 1141 }
1056 1142
1057 priv->irq = i; 1143 priv->irq = i;
1058 pdata = pdev->dev.platform_data; 1144 atomic_set(&priv->hw_usecnt, -1);
1059 1145
1060 j = 0; 1146 j = 0;
1061 for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) { 1147 for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) {
1062 priv->ch[j].lcdc = priv; 1148 struct sh_mobile_lcdc_chan *ch = priv->ch + j;
1063 memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i])); 1149
1150 ch->lcdc = priv;
1151 memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
1064 1152
1065 error = sh_mobile_lcdc_check_interface(&priv->ch[j]); 1153 error = sh_mobile_lcdc_check_interface(ch);
1066 if (error) { 1154 if (error) {
1067 dev_err(&pdev->dev, "unsupported interface type\n"); 1155 dev_err(&pdev->dev, "unsupported interface type\n");
1068 goto err1; 1156 goto err1;
1069 } 1157 }
1070 init_waitqueue_head(&priv->ch[j].frame_end_wait); 1158 init_waitqueue_head(&ch->frame_end_wait);
1071 init_completion(&priv->ch[j].vsync_completion); 1159 init_completion(&ch->vsync_completion);
1072 priv->ch[j].pan_offset = 0; 1160 ch->pan_offset = 0;
1073 1161
1074 switch (pdata->ch[i].chan) { 1162 switch (pdata->ch[i].chan) {
1075 case LCDC_CHAN_MAINLCD: 1163 case LCDC_CHAN_MAINLCD:
1076 priv->ch[j].enabled = 1 << 1; 1164 ch->enabled = 1 << 1;
1077 priv->ch[j].reg_offs = lcdc_offs_mainlcd; 1165 ch->reg_offs = lcdc_offs_mainlcd;
1078 j++; 1166 j++;
1079 break; 1167 break;
1080 case LCDC_CHAN_SUBLCD: 1168 case LCDC_CHAN_SUBLCD:
1081 priv->ch[j].enabled = 1 << 2; 1169 ch->enabled = 1 << 2;
1082 priv->ch[j].reg_offs = lcdc_offs_sublcd; 1170 ch->reg_offs = lcdc_offs_sublcd;
1083 j++; 1171 j++;
1084 break; 1172 break;
1085 } 1173 }
@@ -1103,69 +1191,83 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1103 1191
1104 for (i = 0; i < j; i++) { 1192 for (i = 0; i < j; i++) {
1105 struct fb_var_screeninfo *var; 1193 struct fb_var_screeninfo *var;
1106 struct fb_videomode *lcd_cfg; 1194 const struct fb_videomode *lcd_cfg, *max_cfg = NULL;
1107 cfg = &priv->ch[i].cfg; 1195 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1196 struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg;
1197 const struct fb_videomode *mode = cfg->lcd_cfg;
1198 unsigned long max_size = 0;
1199 int k;
1108 1200
1109 priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); 1201 ch->info = framebuffer_alloc(0, &pdev->dev);
1110 if (!priv->ch[i].info) { 1202 if (!ch->info) {
1111 dev_err(&pdev->dev, "unable to allocate fb_info\n"); 1203 dev_err(&pdev->dev, "unable to allocate fb_info\n");
1112 error = -ENOMEM; 1204 error = -ENOMEM;
1113 break; 1205 break;
1114 } 1206 }
1115 1207
1116 info = priv->ch[i].info; 1208 info = ch->info;
1117 var = &info->var; 1209 var = &info->var;
1118 lcd_cfg = &cfg->lcd_cfg;
1119 info->fbops = &sh_mobile_lcdc_ops; 1210 info->fbops = &sh_mobile_lcdc_ops;
1120 var->xres = var->xres_virtual = lcd_cfg->xres; 1211 info->par = ch;
1121 var->yres = lcd_cfg->yres; 1212
1213 mutex_init(&ch->open_lock);
1214
1215 for (k = 0, lcd_cfg = mode;
1216 k < cfg->num_cfg && lcd_cfg;
1217 k++, lcd_cfg++) {
1218 unsigned long size = lcd_cfg->yres * lcd_cfg->xres;
1219
1220 if (size > max_size) {
1221 max_cfg = lcd_cfg;
1222 max_size = size;
1223 }
1224 }
1225
1226 if (!mode)
1227 max_size = DEFAULT_XRES * DEFAULT_YRES;
1228 else if (max_cfg)
1229 dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",
1230 max_cfg->xres, max_cfg->yres);
1231
1232 info->fix = sh_mobile_lcdc_fix;
1233 info->fix.smem_len = max_size * (cfg->bpp / 8) * 2;
1234
1235 if (!mode)
1236 mode = &default_720p;
1237
1238 fb_videomode_to_var(var, mode);
1122 /* Default Y virtual resolution is 2x panel size */ 1239 /* Default Y virtual resolution is 2x panel size */
1123 var->yres_virtual = var->yres * 2; 1240 var->yres_virtual = var->yres * 2;
1124 var->width = cfg->lcd_size_cfg.width;
1125 var->height = cfg->lcd_size_cfg.height;
1126 var->activate = FB_ACTIVATE_NOW; 1241 var->activate = FB_ACTIVATE_NOW;
1127 var->left_margin = lcd_cfg->left_margin;
1128 var->right_margin = lcd_cfg->right_margin;
1129 var->upper_margin = lcd_cfg->upper_margin;
1130 var->lower_margin = lcd_cfg->lower_margin;
1131 var->hsync_len = lcd_cfg->hsync_len;
1132 var->vsync_len = lcd_cfg->vsync_len;
1133 var->sync = lcd_cfg->sync;
1134 var->pixclock = lcd_cfg->pixclock;
1135 1242
1136 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp); 1243 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp);
1137 if (error) 1244 if (error)
1138 break; 1245 break;
1139 1246
1140 info->fix = sh_mobile_lcdc_fix;
1141 info->fix.line_length = lcd_cfg->xres * (cfg->bpp / 8);
1142 info->fix.smem_len = info->fix.line_length *
1143 var->yres_virtual;
1144
1145 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, 1247 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
1146 &priv->ch[i].dma_handle, GFP_KERNEL); 1248 &ch->dma_handle, GFP_KERNEL);
1147 if (!buf) { 1249 if (!buf) {
1148 dev_err(&pdev->dev, "unable to allocate buffer\n"); 1250 dev_err(&pdev->dev, "unable to allocate buffer\n");
1149 error = -ENOMEM; 1251 error = -ENOMEM;
1150 break; 1252 break;
1151 } 1253 }
1152 1254
1153 info->pseudo_palette = &priv->ch[i].pseudo_palette; 1255 info->pseudo_palette = &ch->pseudo_palette;
1154 info->flags = FBINFO_FLAG_DEFAULT; 1256 info->flags = FBINFO_FLAG_DEFAULT;
1155 1257
1156 error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); 1258 error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
1157 if (error < 0) { 1259 if (error < 0) {
1158 dev_err(&pdev->dev, "unable to allocate cmap\n"); 1260 dev_err(&pdev->dev, "unable to allocate cmap\n");
1159 dma_free_coherent(&pdev->dev, info->fix.smem_len, 1261 dma_free_coherent(&pdev->dev, info->fix.smem_len,
1160 buf, priv->ch[i].dma_handle); 1262 buf, ch->dma_handle);
1161 break; 1263 break;
1162 } 1264 }
1163 1265
1164 memset(buf, 0, info->fix.smem_len); 1266 info->fix.smem_start = ch->dma_handle;
1165 info->fix.smem_start = priv->ch[i].dma_handle; 1267 info->fix.line_length = var->xres * (cfg->bpp / 8);
1166 info->screen_base = buf; 1268 info->screen_base = buf;
1167 info->device = &pdev->dev; 1269 info->device = &pdev->dev;
1168 info->par = &priv->ch[i]; 1270 ch->display_var = *var;
1169 } 1271 }
1170 1272
1171 if (error) 1273 if (error)
@@ -1179,6 +1281,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1179 1281
1180 for (i = 0; i < j; i++) { 1282 for (i = 0; i < j; i++) {
1181 struct sh_mobile_lcdc_chan *ch = priv->ch + i; 1283 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1284 const struct fb_videomode *mode = ch->cfg.lcd_cfg;
1285
1286 if (!mode)
1287 mode = &default_720p;
1182 1288
1183 info = ch->info; 1289 info = ch->info;
1184 1290
@@ -1191,6 +1297,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1191 } 1297 }
1192 } 1298 }
1193 1299
1300 fb_videomode_to_modelist(mode, ch->cfg.num_cfg, &info->modelist);
1194 error = register_framebuffer(info); 1301 error = register_framebuffer(info);
1195 if (error < 0) 1302 if (error < 0)
1196 goto err1; 1303 goto err1;
@@ -1200,8 +1307,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1200 pdev->name, 1307 pdev->name,
1201 (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? 1308 (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
1202 "mainlcd" : "sublcd", 1309 "mainlcd" : "sublcd",
1203 (int) ch->cfg.lcd_cfg.xres, 1310 info->var.xres, info->var.yres,
1204 (int) ch->cfg.lcd_cfg.yres,
1205 ch->cfg.bpp); 1311 ch->cfg.bpp);
1206 1312
1207 /* deferred io mode: disable clock to save power */ 1313 /* deferred io mode: disable clock to save power */
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
new file mode 100644
index 000000000000..9ecee2fba1d7
--- /dev/null
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -0,0 +1,41 @@
1#ifndef SH_MOBILE_LCDCFB_H
2#define SH_MOBILE_LCDCFB_H
3
4#include <linux/completion.h>
5#include <linux/fb.h>
6#include <linux/mutex.h>
7#include <linux/wait.h>
8
9/* per-channel registers */
10enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
11 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
12 LDHAJR,
13 NR_CH_REGS };
14
15#define PALETTE_NR 16
16
17struct sh_mobile_lcdc_priv;
18struct fb_info;
19
20struct sh_mobile_lcdc_chan {
21 struct sh_mobile_lcdc_priv *lcdc;
22 unsigned long *reg_offs;
23 unsigned long ldmt1r_value;
24 unsigned long enabled; /* ME and SE in LDCNT2R */
25 struct sh_mobile_lcdc_chan_cfg cfg;
26 u32 pseudo_palette[PALETTE_NR];
27 unsigned long saved_ch_regs[NR_CH_REGS];
28 struct fb_info *info;
29 dma_addr_t dma_handle;
30 struct fb_deferred_io defio;
31 struct scatterlist *sglist;
32 unsigned long frame_end;
33 unsigned long pan_offset;
34 wait_queue_head_t frame_end_wait;
35 struct completion vsync_completion;
36 struct fb_var_screeninfo display_var;
37 int use_count;
38 struct mutex open_lock; /* protects the use counter */
39};
40
41#endif
diff --git a/fs/compat.c b/fs/compat.c
index ff66c0d7583d..c580c322fa6b 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -49,6 +49,7 @@
49#include <linux/eventpoll.h> 49#include <linux/eventpoll.h>
50#include <linux/fs_struct.h> 50#include <linux/fs_struct.h>
51#include <linux/slab.h> 51#include <linux/slab.h>
52#include <linux/pagemap.h>
52 53
53#include <asm/uaccess.h> 54#include <asm/uaccess.h>
54#include <asm/mmu_context.h> 55#include <asm/mmu_context.h>
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index a906f538d11c..85c6be2db02f 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -23,7 +23,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *,
23static inline struct jffs2_inode_cache * 23static inline struct jffs2_inode_cache *
24first_inode_chain(int *i, struct jffs2_sb_info *c) 24first_inode_chain(int *i, struct jffs2_sb_info *c)
25{ 25{
26 for (; *i < INOCACHE_HASHSIZE; (*i)++) { 26 for (; *i < c->inocache_hashsize; (*i)++) {
27 if (c->inocache_list[*i]) 27 if (c->inocache_list[*i])
28 return c->inocache_list[*i]; 28 return c->inocache_list[*i];
29 } 29 }
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c
index 617a1e5694c1..de4247021d25 100644
--- a/fs/jffs2/compr.c
+++ b/fs/jffs2/compr.c
@@ -103,7 +103,7 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
103 spin_unlock(&jffs2_compressor_list_lock); 103 spin_unlock(&jffs2_compressor_list_lock);
104 *datalen = orig_slen; 104 *datalen = orig_slen;
105 *cdatalen = orig_dlen; 105 *cdatalen = orig_dlen;
106 compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL); 106 compr_ret = this->compress(data_in, output_buf, datalen, cdatalen);
107 spin_lock(&jffs2_compressor_list_lock); 107 spin_lock(&jffs2_compressor_list_lock);
108 this->usecount--; 108 this->usecount--;
109 if (!compr_ret) { 109 if (!compr_ret) {
@@ -152,7 +152,7 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
152 spin_unlock(&jffs2_compressor_list_lock); 152 spin_unlock(&jffs2_compressor_list_lock);
153 *datalen = orig_slen; 153 *datalen = orig_slen;
154 *cdatalen = orig_dlen; 154 *cdatalen = orig_dlen;
155 compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL); 155 compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen);
156 spin_lock(&jffs2_compressor_list_lock); 156 spin_lock(&jffs2_compressor_list_lock);
157 this->usecount--; 157 this->usecount--;
158 if (!compr_ret) { 158 if (!compr_ret) {
@@ -220,7 +220,7 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
220 if (comprtype == this->compr) { 220 if (comprtype == this->compr) {
221 this->usecount++; 221 this->usecount++;
222 spin_unlock(&jffs2_compressor_list_lock); 222 spin_unlock(&jffs2_compressor_list_lock);
223 ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL); 223 ret = this->decompress(cdata_in, data_out, cdatalen, datalen);
224 spin_lock(&jffs2_compressor_list_lock); 224 spin_lock(&jffs2_compressor_list_lock);
225 if (ret) { 225 if (ret) {
226 printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret); 226 printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h
index e471a9106fd9..13bb7597ab39 100644
--- a/fs/jffs2/compr.h
+++ b/fs/jffs2/compr.h
@@ -49,9 +49,9 @@ struct jffs2_compressor {
49 char *name; 49 char *name;
50 char compr; /* JFFS2_COMPR_XXX */ 50 char compr; /* JFFS2_COMPR_XXX */
51 int (*compress)(unsigned char *data_in, unsigned char *cpage_out, 51 int (*compress)(unsigned char *data_in, unsigned char *cpage_out,
52 uint32_t *srclen, uint32_t *destlen, void *model); 52 uint32_t *srclen, uint32_t *destlen);
53 int (*decompress)(unsigned char *cdata_in, unsigned char *data_out, 53 int (*decompress)(unsigned char *cdata_in, unsigned char *data_out,
54 uint32_t cdatalen, uint32_t datalen, void *model); 54 uint32_t cdatalen, uint32_t datalen);
55 int usecount; 55 int usecount;
56 int disabled; /* if set the compressor won't compress */ 56 int disabled; /* if set the compressor won't compress */
57 unsigned char *compr_buf; /* used by size compr. mode */ 57 unsigned char *compr_buf; /* used by size compr. mode */
diff --git a/fs/jffs2/compr_lzo.c b/fs/jffs2/compr_lzo.c
index ed25ae7c98eb..af186ee674d8 100644
--- a/fs/jffs2/compr_lzo.c
+++ b/fs/jffs2/compr_lzo.c
@@ -42,7 +42,7 @@ static int __init alloc_workspace(void)
42} 42}
43 43
44static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out, 44static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out,
45 uint32_t *sourcelen, uint32_t *dstlen, void *model) 45 uint32_t *sourcelen, uint32_t *dstlen)
46{ 46{
47 size_t compress_size; 47 size_t compress_size;
48 int ret; 48 int ret;
@@ -67,7 +67,7 @@ static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out,
67} 67}
68 68
69static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, 69static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out,
70 uint32_t srclen, uint32_t destlen, void *model) 70 uint32_t srclen, uint32_t destlen)
71{ 71{
72 size_t dl = destlen; 72 size_t dl = destlen;
73 int ret; 73 int ret;
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c
index 9696ad9ef5f7..16a5047903a6 100644
--- a/fs/jffs2/compr_rtime.c
+++ b/fs/jffs2/compr_rtime.c
@@ -31,8 +31,7 @@
31/* _compress returns the compressed size, -1 if bigger */ 31/* _compress returns the compressed size, -1 if bigger */
32static int jffs2_rtime_compress(unsigned char *data_in, 32static int jffs2_rtime_compress(unsigned char *data_in,
33 unsigned char *cpage_out, 33 unsigned char *cpage_out,
34 uint32_t *sourcelen, uint32_t *dstlen, 34 uint32_t *sourcelen, uint32_t *dstlen)
35 void *model)
36{ 35{
37 short positions[256]; 36 short positions[256];
38 int outpos = 0; 37 int outpos = 0;
@@ -73,8 +72,7 @@ static int jffs2_rtime_compress(unsigned char *data_in,
73 72
74static int jffs2_rtime_decompress(unsigned char *data_in, 73static int jffs2_rtime_decompress(unsigned char *data_in,
75 unsigned char *cpage_out, 74 unsigned char *cpage_out,
76 uint32_t srclen, uint32_t destlen, 75 uint32_t srclen, uint32_t destlen)
77 void *model)
78{ 76{
79 short positions[256]; 77 short positions[256];
80 int outpos = 0; 78 int outpos = 0;
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c
index a12b4f763373..9e7cec808c4c 100644
--- a/fs/jffs2/compr_rubin.c
+++ b/fs/jffs2/compr_rubin.c
@@ -298,7 +298,7 @@ static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in,
298#if 0 298#if 0
299/* _compress returns the compressed size, -1 if bigger */ 299/* _compress returns the compressed size, -1 if bigger */
300int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, 300int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out,
301 uint32_t *sourcelen, uint32_t *dstlen, void *model) 301 uint32_t *sourcelen, uint32_t *dstlen)
302{ 302{
303 return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, 303 return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in,
304 cpage_out, sourcelen, dstlen); 304 cpage_out, sourcelen, dstlen);
@@ -306,8 +306,7 @@ int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out,
306#endif 306#endif
307static int jffs2_dynrubin_compress(unsigned char *data_in, 307static int jffs2_dynrubin_compress(unsigned char *data_in,
308 unsigned char *cpage_out, 308 unsigned char *cpage_out,
309 uint32_t *sourcelen, uint32_t *dstlen, 309 uint32_t *sourcelen, uint32_t *dstlen)
310 void *model)
311{ 310{
312 int bits[8]; 311 int bits[8];
313 unsigned char histo[256]; 312 unsigned char histo[256];
@@ -387,8 +386,7 @@ static void rubin_do_decompress(int bit_divider, int *bits,
387 386
388static int jffs2_rubinmips_decompress(unsigned char *data_in, 387static int jffs2_rubinmips_decompress(unsigned char *data_in,
389 unsigned char *cpage_out, 388 unsigned char *cpage_out,
390 uint32_t sourcelen, uint32_t dstlen, 389 uint32_t sourcelen, uint32_t dstlen)
391 void *model)
392{ 390{
393 rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, 391 rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in,
394 cpage_out, sourcelen, dstlen); 392 cpage_out, sourcelen, dstlen);
@@ -397,8 +395,7 @@ static int jffs2_rubinmips_decompress(unsigned char *data_in,
397 395
398static int jffs2_dynrubin_decompress(unsigned char *data_in, 396static int jffs2_dynrubin_decompress(unsigned char *data_in,
399 unsigned char *cpage_out, 397 unsigned char *cpage_out,
400 uint32_t sourcelen, uint32_t dstlen, 398 uint32_t sourcelen, uint32_t dstlen)
401 void *model)
402{ 399{
403 int bits[8]; 400 int bits[8];
404 int c; 401 int c;
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c
index 97fc45de6f81..fd05a0b9431d 100644
--- a/fs/jffs2/compr_zlib.c
+++ b/fs/jffs2/compr_zlib.c
@@ -68,8 +68,7 @@ static void free_workspaces(void)
68 68
69static int jffs2_zlib_compress(unsigned char *data_in, 69static int jffs2_zlib_compress(unsigned char *data_in,
70 unsigned char *cpage_out, 70 unsigned char *cpage_out,
71 uint32_t *sourcelen, uint32_t *dstlen, 71 uint32_t *sourcelen, uint32_t *dstlen)
72 void *model)
73{ 72{
74 int ret; 73 int ret;
75 74
@@ -136,8 +135,7 @@ static int jffs2_zlib_compress(unsigned char *data_in,
136 135
137static int jffs2_zlib_decompress(unsigned char *data_in, 136static int jffs2_zlib_decompress(unsigned char *data_in,
138 unsigned char *cpage_out, 137 unsigned char *cpage_out,
139 uint32_t srclen, uint32_t destlen, 138 uint32_t srclen, uint32_t destlen)
140 void *model)
141{ 139{
142 int ret; 140 int ret;
143 int wbits = MAX_WBITS; 141 int wbits = MAX_WBITS;
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 79121aa5858b..92978658ed18 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -367,7 +367,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
367 } 367 }
368 368
369 /* We use f->target field to store the target path. */ 369 /* We use f->target field to store the target path. */
370 f->target = kmalloc(targetlen + 1, GFP_KERNEL); 370 f->target = kmemdup(target, targetlen + 1, GFP_KERNEL);
371 if (!f->target) { 371 if (!f->target) {
372 printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); 372 printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1);
373 mutex_unlock(&f->sem); 373 mutex_unlock(&f->sem);
@@ -376,7 +376,6 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
376 goto fail; 376 goto fail;
377 } 377 }
378 378
379 memcpy(f->target, target, targetlen + 1);
380 D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target)); 379 D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target));
381 380
382 /* No data here. Only a metadata node, which will be 381 /* No data here. Only a metadata node, which will be
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index abac961f617b..e513f1913c15 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -151,7 +151,7 @@ int jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
151 } 151 }
152 152
153 /* Be nice */ 153 /* Be nice */
154 yield(); 154 cond_resched();
155 mutex_lock(&c->erase_free_sem); 155 mutex_lock(&c->erase_free_sem);
156 spin_lock(&c->erase_completion_lock); 156 spin_lock(&c->erase_completion_lock);
157 } 157 }
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index d9beb06e6fca..e896e67767eb 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -474,6 +474,25 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
474 return inode; 474 return inode;
475} 475}
476 476
477static int calculate_inocache_hashsize(uint32_t flash_size)
478{
479 /*
480 * Pick a inocache hash size based on the size of the medium.
481 * Count how many megabytes we're dealing with, apply a hashsize twice
482 * that size, but rounding down to the usual big powers of 2. And keep
483 * to sensible bounds.
484 */
485
486 int size_mb = flash_size / 1024 / 1024;
487 int hashsize = (size_mb * 2) & ~0x3f;
488
489 if (hashsize < INOCACHE_HASHSIZE_MIN)
490 return INOCACHE_HASHSIZE_MIN;
491 if (hashsize > INOCACHE_HASHSIZE_MAX)
492 return INOCACHE_HASHSIZE_MAX;
493
494 return hashsize;
495}
477 496
478int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) 497int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
479{ 498{
@@ -520,7 +539,8 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
520 if (ret) 539 if (ret)
521 return ret; 540 return ret;
522 541
523 c->inocache_list = kcalloc(INOCACHE_HASHSIZE, sizeof(struct jffs2_inode_cache *), GFP_KERNEL); 542 c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size);
543 c->inocache_list = kcalloc(c->inocache_hashsize, sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
524 if (!c->inocache_list) { 544 if (!c->inocache_list) {
525 ret = -ENOMEM; 545 ret = -ENOMEM;
526 goto out_wbuf; 546 goto out_wbuf;
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 846a79452497..31dce611337c 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -219,13 +219,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
219 if (!list_empty(&c->erase_complete_list) || 219 if (!list_empty(&c->erase_complete_list) ||
220 !list_empty(&c->erase_pending_list)) { 220 !list_empty(&c->erase_pending_list)) {
221 spin_unlock(&c->erase_completion_lock); 221 spin_unlock(&c->erase_completion_lock);
222 mutex_unlock(&c->alloc_sem);
222 D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n")); 223 D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n"));
223 if (jffs2_erase_pending_blocks(c, 1)) { 224 if (jffs2_erase_pending_blocks(c, 1))
224 mutex_unlock(&c->alloc_sem);
225 return 0; 225 return 0;
226 } 226
227 D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n")); 227 D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n"));
228 spin_lock(&c->erase_completion_lock); 228 spin_lock(&c->erase_completion_lock);
229 mutex_lock(&c->alloc_sem);
229 } 230 }
230 231
231 /* First, work out which block we're garbage-collecting */ 232 /* First, work out which block we're garbage-collecting */
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 6784bc89add1..f864005de64c 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -100,6 +100,7 @@ struct jffs2_sb_info {
100 wait_queue_head_t erase_wait; /* For waiting for erases to complete */ 100 wait_queue_head_t erase_wait; /* For waiting for erases to complete */
101 101
102 wait_queue_head_t inocache_wq; 102 wait_queue_head_t inocache_wq;
103 int inocache_hashsize;
103 struct jffs2_inode_cache **inocache_list; 104 struct jffs2_inode_cache **inocache_list;
104 spinlock_t inocache_lock; 105 spinlock_t inocache_lock;
105 106
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index af02bd138469..5e03233c2363 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -420,7 +420,7 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t
420{ 420{
421 struct jffs2_inode_cache *ret; 421 struct jffs2_inode_cache *ret;
422 422
423 ret = c->inocache_list[ino % INOCACHE_HASHSIZE]; 423 ret = c->inocache_list[ino % c->inocache_hashsize];
424 while (ret && ret->ino < ino) { 424 while (ret && ret->ino < ino) {
425 ret = ret->next; 425 ret = ret->next;
426 } 426 }
@@ -441,7 +441,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new
441 441
442 dbg_inocache("add %p (ino #%u)\n", new, new->ino); 442 dbg_inocache("add %p (ino #%u)\n", new, new->ino);
443 443
444 prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE]; 444 prev = &c->inocache_list[new->ino % c->inocache_hashsize];
445 445
446 while ((*prev) && (*prev)->ino < new->ino) { 446 while ((*prev) && (*prev)->ino < new->ino) {
447 prev = &(*prev)->next; 447 prev = &(*prev)->next;
@@ -462,7 +462,7 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
462 dbg_inocache("del %p (ino #%u)\n", old, old->ino); 462 dbg_inocache("del %p (ino #%u)\n", old, old->ino);
463 spin_lock(&c->inocache_lock); 463 spin_lock(&c->inocache_lock);
464 464
465 prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE]; 465 prev = &c->inocache_list[old->ino % c->inocache_hashsize];
466 466
467 while ((*prev) && (*prev)->ino < old->ino) { 467 while ((*prev) && (*prev)->ino < old->ino) {
468 prev = &(*prev)->next; 468 prev = &(*prev)->next;
@@ -487,7 +487,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c)
487 int i; 487 int i;
488 struct jffs2_inode_cache *this, *next; 488 struct jffs2_inode_cache *this, *next;
489 489
490 for (i=0; i<INOCACHE_HASHSIZE; i++) { 490 for (i=0; i < c->inocache_hashsize; i++) {
491 this = c->inocache_list[i]; 491 this = c->inocache_list[i];
492 while (this) { 492 while (this) {
493 next = this->next; 493 next = this->next;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 523a91691052..5a53d9bdb2b5 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -199,7 +199,8 @@ struct jffs2_inode_cache {
199#define RAWNODE_CLASS_XATTR_DATUM 1 199#define RAWNODE_CLASS_XATTR_DATUM 1
200#define RAWNODE_CLASS_XATTR_REF 2 200#define RAWNODE_CLASS_XATTR_REF 2
201 201
202#define INOCACHE_HASHSIZE 128 202#define INOCACHE_HASHSIZE_MIN 128
203#define INOCACHE_HASHSIZE_MAX 1024
203 204
204#define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size) 205#define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
205 206
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 46f870d1cc36..b632dddcb482 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -20,7 +20,7 @@
20#include "summary.h" 20#include "summary.h"
21#include "debug.h" 21#include "debug.h"
22 22
23#define DEFAULT_EMPTY_SCAN_SIZE 1024 23#define DEFAULT_EMPTY_SCAN_SIZE 256
24 24
25#define noisy_printk(noise, args...) do { \ 25#define noisy_printk(noise, args...) do { \
26 if (*(noise)) { \ 26 if (*(noise)) { \
@@ -435,7 +435,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
435 unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { 435 unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
436 struct jffs2_unknown_node *node; 436 struct jffs2_unknown_node *node;
437 struct jffs2_unknown_node crcnode; 437 struct jffs2_unknown_node crcnode;
438 uint32_t ofs, prevofs; 438 uint32_t ofs, prevofs, max_ofs;
439 uint32_t hdr_crc, buf_ofs, buf_len; 439 uint32_t hdr_crc, buf_ofs, buf_len;
440 int err; 440 int err;
441 int noise = 0; 441 int noise = 0;
@@ -550,12 +550,12 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
550 550
551 /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ 551 /* We temporarily use 'ofs' as a pointer into the buffer/jeb */
552 ofs = 0; 552 ofs = 0;
553 553 max_ofs = EMPTY_SCAN_SIZE(c->sector_size);
554 /* Scan only 4KiB of 0xFF before declaring it's empty */ 554 /* Scan only EMPTY_SCAN_SIZE of 0xFF before declaring it's empty */
555 while(ofs < EMPTY_SCAN_SIZE(c->sector_size) && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF) 555 while(ofs < max_ofs && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
556 ofs += 4; 556 ofs += 4;
557 557
558 if (ofs == EMPTY_SCAN_SIZE(c->sector_size)) { 558 if (ofs == max_ofs) {
559#ifdef CONFIG_JFFS2_FS_WRITEBUFFER 559#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
560 if (jffs2_cleanmarker_oob(c)) { 560 if (jffs2_cleanmarker_oob(c)) {
561 /* scan oob, take care of cleanmarker */ 561 /* scan oob, take care of cleanmarker */
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 7fa20beb2ab9..57cc0e63714f 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -84,7 +84,7 @@ struct nand_bbt_descr {
84#define NAND_BBT_PERCHIP 0x00000080 84#define NAND_BBT_PERCHIP 0x00000080
85/* bbt has a version counter at offset veroffs */ 85/* bbt has a version counter at offset veroffs */
86#define NAND_BBT_VERSION 0x00000100 86#define NAND_BBT_VERSION 0x00000100
87/* Create a bbt if none axists */ 87/* Create a bbt if none exists */
88#define NAND_BBT_CREATE 0x00000200 88#define NAND_BBT_CREATE 0x00000200
89/* Search good / bad pattern through all pages of a block */ 89/* Search good / bad pattern through all pages of a block */
90#define NAND_BBT_SCANALLPAGES 0x00000400 90#define NAND_BBT_SCANALLPAGES 0x00000400
@@ -102,6 +102,8 @@ struct nand_bbt_descr {
102#define NAND_BBT_SCANBYTE1AND6 0x00100000 102#define NAND_BBT_SCANBYTE1AND6 0x00100000
103/* The nand_bbt_descr was created dynamicaly and must be freed */ 103/* The nand_bbt_descr was created dynamicaly and must be freed */
104#define NAND_BBT_DYNAMICSTRUCT 0x00200000 104#define NAND_BBT_DYNAMICSTRUCT 0x00200000
105/* The bad block table does not OOB for marker */
106#define NAND_BBT_NO_OOB 0x00400000
105 107
106/* The maximum number of blocks to scan for a bbt */ 108/* The maximum number of blocks to scan for a bbt */
107#define NAND_BBT_SCAN_MAXBLOCKS 4 109#define NAND_BBT_SCAN_MAXBLOCKS 4
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
index d2118b0eac9a..4dd0c2cd7659 100644
--- a/include/linux/mtd/cfi.h
+++ b/include/linux/mtd/cfi.h
@@ -289,6 +289,7 @@ struct cfi_private {
289 must be of the same type. */ 289 must be of the same type. */
290 int mfr, id; 290 int mfr, id;
291 int numchips; 291 int numchips;
292 map_word sector_erase_cmd;
292 unsigned long chipshift; /* Because they're of the same type */ 293 unsigned long chipshift; /* Because they're of the same type */
293 const char *im_name; /* inter_module name for cmdset_setup */ 294 const char *im_name; /* inter_module name for cmdset_setup */
294 struct flchip chips[0]; /* per-chip data structure for each chip */ 295 struct flchip chips[0]; /* per-chip data structure for each chip */
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h
new file mode 100644
index 000000000000..5d2556700ec2
--- /dev/null
+++ b/include/linux/mtd/fsmc.h
@@ -0,0 +1,181 @@
1/*
2 * incude/mtd/fsmc.h
3 *
4 * ST Microelectronics
5 * Flexible Static Memory Controller (FSMC)
6 * platform data interface and header file
7 *
8 * Copyright © 2010 ST Microelectronics
9 * Vipin Kumar <vipin.kumar@st.com>
10 *
11 * This file is licensed under the terms of the GNU General Public
12 * License version 2. This program is licensed "as is" without any
13 * warranty of any kind, whether express or implied.
14 */
15
16#ifndef __MTD_FSMC_H
17#define __MTD_FSMC_H
18
19#include <linux/platform_device.h>
20#include <linux/mtd/physmap.h>
21#include <linux/types.h>
22#include <linux/mtd/partitions.h>
23#include <asm/param.h>
24
25#define FSMC_NAND_BW8 1
26#define FSMC_NAND_BW16 2
27
28/*
29 * The placement of the Command Latch Enable (CLE) and
30 * Address Latch Enable (ALE) is twised around in the
31 * SPEAR310 implementation.
32 */
33#if defined(CONFIG_MACH_SPEAR310)
34#define PLAT_NAND_CLE (1 << 17)
35#define PLAT_NAND_ALE (1 << 16)
36#else
37#define PLAT_NAND_CLE (1 << 16)
38#define PLAT_NAND_ALE (1 << 17)
39#endif
40
41#define FSMC_MAX_NOR_BANKS 4
42#define FSMC_MAX_NAND_BANKS 4
43
44#define FSMC_FLASH_WIDTH8 1
45#define FSMC_FLASH_WIDTH16 2
46
47struct fsmc_nor_bank_regs {
48 uint32_t ctrl;
49 uint32_t ctrl_tim;
50};
51
52/* ctrl register definitions */
53#define BANK_ENABLE (1 << 0)
54#define MUXED (1 << 1)
55#define NOR_DEV (2 << 2)
56#define WIDTH_8 (0 << 4)
57#define WIDTH_16 (1 << 4)
58#define RSTPWRDWN (1 << 6)
59#define WPROT (1 << 7)
60#define WRT_ENABLE (1 << 12)
61#define WAIT_ENB (1 << 13)
62
63/* ctrl_tim register definitions */
64
65struct fsms_nand_bank_regs {
66 uint32_t pc;
67 uint32_t sts;
68 uint32_t comm;
69 uint32_t attrib;
70 uint32_t ioata;
71 uint32_t ecc1;
72 uint32_t ecc2;
73 uint32_t ecc3;
74};
75
76#define FSMC_NOR_REG_SIZE 0x40
77
78struct fsmc_regs {
79 struct fsmc_nor_bank_regs nor_bank_regs[FSMC_MAX_NOR_BANKS];
80 uint8_t reserved_1[0x40 - 0x20];
81 struct fsms_nand_bank_regs bank_regs[FSMC_MAX_NAND_BANKS];
82 uint8_t reserved_2[0xfe0 - 0xc0];
83 uint32_t peripid0; /* 0xfe0 */
84 uint32_t peripid1; /* 0xfe4 */
85 uint32_t peripid2; /* 0xfe8 */
86 uint32_t peripid3; /* 0xfec */
87 uint32_t pcellid0; /* 0xff0 */
88 uint32_t pcellid1; /* 0xff4 */
89 uint32_t pcellid2; /* 0xff8 */
90 uint32_t pcellid3; /* 0xffc */
91};
92
93#define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ)
94
95/* pc register definitions */
96#define FSMC_RESET (1 << 0)
97#define FSMC_WAITON (1 << 1)
98#define FSMC_ENABLE (1 << 2)
99#define FSMC_DEVTYPE_NAND (1 << 3)
100#define FSMC_DEVWID_8 (0 << 4)
101#define FSMC_DEVWID_16 (1 << 4)
102#define FSMC_ECCEN (1 << 6)
103#define FSMC_ECCPLEN_512 (0 << 7)
104#define FSMC_ECCPLEN_256 (1 << 7)
105#define FSMC_TCLR_1 (1 << 9)
106#define FSMC_TAR_1 (1 << 13)
107
108/* sts register definitions */
109#define FSMC_CODE_RDY (1 << 15)
110
111/* comm register definitions */
112#define FSMC_TSET_0 (0 << 0)
113#define FSMC_TWAIT_6 (6 << 8)
114#define FSMC_THOLD_4 (4 << 16)
115#define FSMC_THIZ_1 (1 << 24)
116
117/* peripid2 register definitions */
118#define FSMC_REVISION_MSK (0xf)
119#define FSMC_REVISION_SHFT (0x4)
120
121#define FSMC_VER1 1
122#define FSMC_VER2 2
123#define FSMC_VER3 3
124#define FSMC_VER4 4
125#define FSMC_VER5 5
126#define FSMC_VER6 6
127#define FSMC_VER7 7
128#define FSMC_VER8 8
129
130static inline uint32_t get_fsmc_version(struct fsmc_regs *regs)
131{
132 return (readl(&regs->peripid2) >> FSMC_REVISION_SHFT) &
133 FSMC_REVISION_MSK;
134}
135
136/*
137 * There are 13 bytes of ecc for every 512 byte block in FSMC version 8
138 * and it has to be read consecutively and immediately after the 512
139 * byte data block for hardware to generate the error bit offsets
140 * Managing the ecc bytes in the following way is easier. This way is
141 * similar to oobfree structure maintained already in u-boot nand driver
142 */
143#define MAX_ECCPLACE_ENTRIES 32
144
145struct fsmc_nand_eccplace {
146 uint8_t offset;
147 uint8_t length;
148};
149
150struct fsmc_eccplace {
151 struct fsmc_nand_eccplace eccplace[MAX_ECCPLACE_ENTRIES];
152};
153
154/**
155 * fsmc_nand_platform_data - platform specific NAND controller config
156 * @partitions: partition table for the platform, use a default fallback
157 * if this is NULL
158 * @nr_partitions: the number of partitions in the previous entry
159 * @options: different options for the driver
160 * @width: bus width
161 * @bank: default bank
162 * @select_bank: callback to select a certain bank, this is
163 * platform-specific. If the controller only supports one bank
164 * this may be set to NULL
165 */
166struct fsmc_nand_platform_data {
167 struct mtd_partition *partitions;
168 unsigned int nr_partitions;
169 unsigned int options;
170 unsigned int width;
171 unsigned int bank;
172 void (*select_bank)(uint32_t bank, uint32_t busw);
173};
174
175extern int __init fsmc_nor_init(struct platform_device *pdev,
176 unsigned long base, uint32_t bank, uint32_t width);
177extern void __init fsmc_init_board_info(struct platform_device *pdev,
178 struct mtd_partition *partitions, unsigned int nr_partitions,
179 unsigned int width);
180
181#endif /* __MTD_FSMC_H */
diff --git a/include/linux/mtd/inftl.h b/include/linux/mtd/inftl.h
index 64ee53ce95a9..02cd5f9b79b8 100644
--- a/include/linux/mtd/inftl.h
+++ b/include/linux/mtd/inftl.h
@@ -37,14 +37,14 @@ struct INFTLrecord {
37 __u16 firstEUN; 37 __u16 firstEUN;
38 __u16 lastEUN; 38 __u16 lastEUN;
39 __u16 numfreeEUNs; 39 __u16 numfreeEUNs;
40 __u16 LastFreeEUN; /* To speed up finding a free EUN */ 40 __u16 LastFreeEUN; /* To speed up finding a free EUN */
41 int head,sect,cyl; 41 int head,sect,cyl;
42 __u16 *PUtable; /* Physical Unit Table */ 42 __u16 *PUtable; /* Physical Unit Table */
43 __u16 *VUtable; /* Virtual Unit Table */ 43 __u16 *VUtable; /* Virtual Unit Table */
44 unsigned int nb_blocks; /* number of physical blocks */ 44 unsigned int nb_blocks; /* number of physical blocks */
45 unsigned int nb_boot_blocks; /* number of blocks used by the bios */ 45 unsigned int nb_boot_blocks; /* number of blocks used by the bios */
46 struct erase_info instr; 46 struct erase_info instr;
47 struct nand_ecclayout oobinfo; 47 struct nand_ecclayout oobinfo;
48}; 48};
49 49
50int INFTL_mount(struct INFTLrecord *s); 50int INFTL_mount(struct INFTLrecord *s);
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 8485e42a9b09..fe8d77ebec13 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -110,6 +110,21 @@ struct mtd_oob_ops {
110 uint8_t *oobbuf; 110 uint8_t *oobbuf;
111}; 111};
112 112
113#define MTD_MAX_OOBFREE_ENTRIES_LARGE 32
114#define MTD_MAX_ECCPOS_ENTRIES_LARGE 448
115/*
116 * Internal ECC layout control structure. For historical reasons, there is a
117 * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained
118 * for export to user-space via the ECCGETLAYOUT ioctl.
119 * nand_ecclayout should be expandable in the future simply by the above macros.
120 */
121struct nand_ecclayout {
122 __u32 eccbytes;
123 __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE];
124 __u32 oobavail;
125 struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE];
126};
127
113struct mtd_info { 128struct mtd_info {
114 u_char type; 129 u_char type;
115 uint32_t flags; 130 uint32_t flags;
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 102e12c58cb3..63e17d01fde9 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -27,15 +27,17 @@
27struct mtd_info; 27struct mtd_info;
28struct nand_flash_dev; 28struct nand_flash_dev;
29/* Scan and identify a NAND device */ 29/* Scan and identify a NAND device */
30extern int nand_scan (struct mtd_info *mtd, int max_chips); 30extern int nand_scan(struct mtd_info *mtd, int max_chips);
31/* Separate phases of nand_scan(), allowing board driver to intervene 31/*
32 * and override command or ECC setup according to flash type */ 32 * Separate phases of nand_scan(), allowing board driver to intervene
33 * and override command or ECC setup according to flash type.
34 */
33extern int nand_scan_ident(struct mtd_info *mtd, int max_chips, 35extern int nand_scan_ident(struct mtd_info *mtd, int max_chips,
34 struct nand_flash_dev *table); 36 struct nand_flash_dev *table);
35extern int nand_scan_tail(struct mtd_info *mtd); 37extern int nand_scan_tail(struct mtd_info *mtd);
36 38
37/* Free resources held by the NAND device */ 39/* Free resources held by the NAND device */
38extern void nand_release (struct mtd_info *mtd); 40extern void nand_release(struct mtd_info *mtd);
39 41
40/* Internal helper for board drivers which need to override command function */ 42/* Internal helper for board drivers which need to override command function */
41extern void nand_wait_ready(struct mtd_info *mtd); 43extern void nand_wait_ready(struct mtd_info *mtd);
@@ -49,12 +51,13 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
49/* The maximum number of NAND chips in an array */ 51/* The maximum number of NAND chips in an array */
50#define NAND_MAX_CHIPS 8 52#define NAND_MAX_CHIPS 8
51 53
52/* This constant declares the max. oobsize / page, which 54/*
55 * This constant declares the max. oobsize / page, which
53 * is supported now. If you add a chip with bigger oobsize/page 56 * is supported now. If you add a chip with bigger oobsize/page
54 * adjust this accordingly. 57 * adjust this accordingly.
55 */ 58 */
56#define NAND_MAX_OOBSIZE 256 59#define NAND_MAX_OOBSIZE 576
57#define NAND_MAX_PAGESIZE 4096 60#define NAND_MAX_PAGESIZE 8192
58 61
59/* 62/*
60 * Constants for hardware specific CLE/ALE/NCE function 63 * Constants for hardware specific CLE/ALE/NCE function
@@ -88,6 +91,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
88#define NAND_CMD_RNDIN 0x85 91#define NAND_CMD_RNDIN 0x85
89#define NAND_CMD_READID 0x90 92#define NAND_CMD_READID 0x90
90#define NAND_CMD_ERASE2 0xd0 93#define NAND_CMD_ERASE2 0xd0
94#define NAND_CMD_PARAM 0xec
91#define NAND_CMD_RESET 0xff 95#define NAND_CMD_RESET 0xff
92 96
93#define NAND_CMD_LOCK 0x2a 97#define NAND_CMD_LOCK 0x2a
@@ -152,9 +156,10 @@ typedef enum {
152#define NAND_GET_DEVICE 0x80 156#define NAND_GET_DEVICE 0x80
153 157
154 158
155/* Option constants for bizarre disfunctionality and real 159/*
156* features 160 * Option constants for bizarre disfunctionality and real
157*/ 161 * features.
162 */
158/* Chip can not auto increment pages */ 163/* Chip can not auto increment pages */
159#define NAND_NO_AUTOINCR 0x00000001 164#define NAND_NO_AUTOINCR 0x00000001
160/* Buswitdh is 16 bit */ 165/* Buswitdh is 16 bit */
@@ -165,19 +170,27 @@ typedef enum {
165#define NAND_CACHEPRG 0x00000008 170#define NAND_CACHEPRG 0x00000008
166/* Chip has copy back function */ 171/* Chip has copy back function */
167#define NAND_COPYBACK 0x00000010 172#define NAND_COPYBACK 0x00000010
168/* AND Chip which has 4 banks and a confusing page / block 173/*
169 * assignment. See Renesas datasheet for further information */ 174 * AND Chip which has 4 banks and a confusing page / block
175 * assignment. See Renesas datasheet for further information.
176 */
170#define NAND_IS_AND 0x00000020 177#define NAND_IS_AND 0x00000020
171/* Chip has a array of 4 pages which can be read without 178/*
172 * additional ready /busy waits */ 179 * Chip has a array of 4 pages which can be read without
180 * additional ready /busy waits.
181 */
173#define NAND_4PAGE_ARRAY 0x00000040 182#define NAND_4PAGE_ARRAY 0x00000040
174/* Chip requires that BBT is periodically rewritten to prevent 183/*
184 * Chip requires that BBT is periodically rewritten to prevent
175 * bits from adjacent blocks from 'leaking' in altering data. 185 * bits from adjacent blocks from 'leaking' in altering data.
176 * This happens with the Renesas AG-AND chips, possibly others. */ 186 * This happens with the Renesas AG-AND chips, possibly others.
187 */
177#define BBT_AUTO_REFRESH 0x00000080 188#define BBT_AUTO_REFRESH 0x00000080
178/* Chip does not require ready check on read. True 189/*
190 * Chip does not require ready check on read. True
179 * for all large page devices, as they do not support 191 * for all large page devices, as they do not support
180 * autoincrement.*/ 192 * autoincrement.
193 */
181#define NAND_NO_READRDY 0x00000100 194#define NAND_NO_READRDY 0x00000100
182/* Chip does not allow subpage writes */ 195/* Chip does not allow subpage writes */
183#define NAND_NO_SUBPAGE_WRITE 0x00000200 196#define NAND_NO_SUBPAGE_WRITE 0x00000200
@@ -205,16 +218,27 @@ typedef enum {
205#define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR) 218#define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR)
206 219
207/* Non chip related options */ 220/* Non chip related options */
208/* Use a flash based bad block table. This option is passed to the 221/*
209 * default bad block table function. */ 222 * Use a flash based bad block table. OOB identifier is saved in OOB area.
223 * This option is passed to the default bad block table function.
224 */
210#define NAND_USE_FLASH_BBT 0x00010000 225#define NAND_USE_FLASH_BBT 0x00010000
211/* This option skips the bbt scan during initialization. */ 226/* This option skips the bbt scan during initialization. */
212#define NAND_SKIP_BBTSCAN 0x00020000 227#define NAND_SKIP_BBTSCAN 0x00020000
213/* This option is defined if the board driver allocates its own buffers 228/*
214 (e.g. because it needs them DMA-coherent */ 229 * This option is defined if the board driver allocates its own buffers
230 * (e.g. because it needs them DMA-coherent).
231 */
215#define NAND_OWN_BUFFERS 0x00040000 232#define NAND_OWN_BUFFERS 0x00040000
216/* Chip may not exist, so silence any errors in scan */ 233/* Chip may not exist, so silence any errors in scan */
217#define NAND_SCAN_SILENT_NODEV 0x00080000 234#define NAND_SCAN_SILENT_NODEV 0x00080000
235/*
236 * If passed additionally to NAND_USE_FLASH_BBT then BBT code will not touch
237 * the OOB area.
238 */
239#define NAND_USE_FLASH_BBT_NO_OOB 0x00100000
240/* Create an empty BBT with no vendor information if the BBT is available */
241#define NAND_CREATE_EMPTY_BBT 0x00200000
218 242
219/* Options set by nand scan */ 243/* Options set by nand scan */
220/* Nand scan has allocated controller struct */ 244/* Nand scan has allocated controller struct */
@@ -227,15 +251,80 @@ typedef enum {
227/* Keep gcc happy */ 251/* Keep gcc happy */
228struct nand_chip; 252struct nand_chip;
229 253
254struct nand_onfi_params {
255 /* rev info and features block */
256 /* 'O' 'N' 'F' 'I' */
257 u8 sig[4];
258 __le16 revision;
259 __le16 features;
260 __le16 opt_cmd;
261 u8 reserved[22];
262
263 /* manufacturer information block */
264 char manufacturer[12];
265 char model[20];
266 u8 jedec_id;
267 __le16 date_code;
268 u8 reserved2[13];
269
270 /* memory organization block */
271 __le32 byte_per_page;
272 __le16 spare_bytes_per_page;
273 __le32 data_bytes_per_ppage;
274 __le16 spare_bytes_per_ppage;
275 __le32 pages_per_block;
276 __le32 blocks_per_lun;
277 u8 lun_count;
278 u8 addr_cycles;
279 u8 bits_per_cell;
280 __le16 bb_per_lun;
281 __le16 block_endurance;
282 u8 guaranteed_good_blocks;
283 __le16 guaranteed_block_endurance;
284 u8 programs_per_page;
285 u8 ppage_attr;
286 u8 ecc_bits;
287 u8 interleaved_bits;
288 u8 interleaved_ops;
289 u8 reserved3[13];
290
291 /* electrical parameter block */
292 u8 io_pin_capacitance_max;
293 __le16 async_timing_mode;
294 __le16 program_cache_timing_mode;
295 __le16 t_prog;
296 __le16 t_bers;
297 __le16 t_r;
298 __le16 t_ccs;
299 __le16 src_sync_timing_mode;
300 __le16 src_ssync_features;
301 __le16 clk_pin_capacitance_typ;
302 __le16 io_pin_capacitance_typ;
303 __le16 input_pin_capacitance_typ;
304 u8 input_pin_capacitance_max;
305 u8 driver_strenght_support;
306 __le16 t_int_r;
307 __le16 t_ald;
308 u8 reserved4[7];
309
310 /* vendor */
311 u8 reserved5[90];
312
313 __le16 crc;
314} __attribute__((packed));
315
316#define ONFI_CRC_BASE 0x4F4E
317
230/** 318/**
231 * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices 319 * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
232 * @lock: protection lock 320 * @lock: protection lock
233 * @active: the mtd device which holds the controller currently 321 * @active: the mtd device which holds the controller currently
234 * @wq: wait queue to sleep on if a NAND operation is in progress 322 * @wq: wait queue to sleep on if a NAND operation is in
235 * used instead of the per chip wait queue when a hw controller is available 323 * progress used instead of the per chip wait queue
324 * when a hw controller is available.
236 */ 325 */
237struct nand_hw_control { 326struct nand_hw_control {
238 spinlock_t lock; 327 spinlock_t lock;
239 struct nand_chip *active; 328 struct nand_chip *active;
240 wait_queue_head_t wq; 329 wait_queue_head_t wq;
241}; 330};
@@ -256,51 +345,42 @@ struct nand_hw_control {
256 * @correct: function for ecc correction, matching to ecc generator (sw/hw) 345 * @correct: function for ecc correction, matching to ecc generator (sw/hw)
257 * @read_page_raw: function to read a raw page without ECC 346 * @read_page_raw: function to read a raw page without ECC
258 * @write_page_raw: function to write a raw page without ECC 347 * @write_page_raw: function to write a raw page without ECC
259 * @read_page: function to read a page according to the ecc generator requirements 348 * @read_page: function to read a page according to the ecc generator
349 * requirements.
260 * @read_subpage: function to read parts of the page covered by ECC. 350 * @read_subpage: function to read parts of the page covered by ECC.
261 * @write_page: function to write a page according to the ecc generator requirements 351 * @write_page: function to write a page according to the ecc generator
352 * requirements.
262 * @read_oob: function to read chip OOB data 353 * @read_oob: function to read chip OOB data
263 * @write_oob: function to write chip OOB data 354 * @write_oob: function to write chip OOB data
264 */ 355 */
265struct nand_ecc_ctrl { 356struct nand_ecc_ctrl {
266 nand_ecc_modes_t mode; 357 nand_ecc_modes_t mode;
267 int steps; 358 int steps;
268 int size; 359 int size;
269 int bytes; 360 int bytes;
270 int total; 361 int total;
271 int prepad; 362 int prepad;
272 int postpad; 363 int postpad;
273 struct nand_ecclayout *layout; 364 struct nand_ecclayout *layout;
274 void (*hwctl)(struct mtd_info *mtd, int mode); 365 void (*hwctl)(struct mtd_info *mtd, int mode);
275 int (*calculate)(struct mtd_info *mtd, 366 int (*calculate)(struct mtd_info *mtd, const uint8_t *dat,
276 const uint8_t *dat, 367 uint8_t *ecc_code);
277 uint8_t *ecc_code); 368 int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc,
278 int (*correct)(struct mtd_info *mtd, uint8_t *dat, 369 uint8_t *calc_ecc);
279 uint8_t *read_ecc, 370 int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
280 uint8_t *calc_ecc); 371 uint8_t *buf, int page);
281 int (*read_page_raw)(struct mtd_info *mtd, 372 void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
282 struct nand_chip *chip, 373 const uint8_t *buf);
283 uint8_t *buf, int page); 374 int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
284 void (*write_page_raw)(struct mtd_info *mtd, 375 uint8_t *buf, int page);
285 struct nand_chip *chip, 376 int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
286 const uint8_t *buf); 377 uint32_t offs, uint32_t len, uint8_t *buf);
287 int (*read_page)(struct mtd_info *mtd, 378 void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
288 struct nand_chip *chip, 379 const uint8_t *buf);
289 uint8_t *buf, int page); 380 int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page,
290 int (*read_subpage)(struct mtd_info *mtd, 381 int sndcmd);
291 struct nand_chip *chip, 382 int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip,
292 uint32_t offs, uint32_t len, 383 int page);
293 uint8_t *buf);
294 void (*write_page)(struct mtd_info *mtd,
295 struct nand_chip *chip,
296 const uint8_t *buf);
297 int (*read_oob)(struct mtd_info *mtd,
298 struct nand_chip *chip,
299 int page,
300 int sndcmd);
301 int (*write_oob)(struct mtd_info *mtd,
302 struct nand_chip *chip,
303 int page);
304}; 384};
305 385
306/** 386/**
@@ -320,102 +400,132 @@ struct nand_buffers {
320 400
321/** 401/**
322 * struct nand_chip - NAND Private Flash Chip Data 402 * struct nand_chip - NAND Private Flash Chip Data
323 * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device 403 * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the
324 * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device 404 * flash device
405 * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the
406 * flash device.
325 * @read_byte: [REPLACEABLE] read one byte from the chip 407 * @read_byte: [REPLACEABLE] read one byte from the chip
326 * @read_word: [REPLACEABLE] read one word from the chip 408 * @read_word: [REPLACEABLE] read one word from the chip
327 * @write_buf: [REPLACEABLE] write data from the buffer to the chip 409 * @write_buf: [REPLACEABLE] write data from the buffer to the chip
328 * @read_buf: [REPLACEABLE] read data from the chip into the buffer 410 * @read_buf: [REPLACEABLE] read data from the chip into the buffer
329 * @verify_buf: [REPLACEABLE] verify buffer contents against the chip data 411 * @verify_buf: [REPLACEABLE] verify buffer contents against the chip
412 * data.
330 * @select_chip: [REPLACEABLE] select chip nr 413 * @select_chip: [REPLACEABLE] select chip nr
331 * @block_bad: [REPLACEABLE] check, if the block is bad 414 * @block_bad: [REPLACEABLE] check, if the block is bad
332 * @block_markbad: [REPLACEABLE] mark the block bad 415 * @block_markbad: [REPLACEABLE] mark the block bad
333 * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific funtion for controlling 416 * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific funtion for controlling
334 * ALE/CLE/nCE. Also used to write command and address 417 * ALE/CLE/nCE. Also used to write command and address
335 * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line 418 * @init_size: [BOARDSPECIFIC] hardwarespecific funtion for setting
336 * If set to NULL no access to ready/busy is available and the ready/busy information 419 * mtd->oobsize, mtd->writesize and so on.
337 * is read from the chip status register 420 * @id_data contains the 8 bytes values of NAND_CMD_READID.
338 * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing commands to the chip 421 * Return with the bus width.
339 * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on ready 422 * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing
423 * device ready/busy line. If set to NULL no access to
424 * ready/busy is available and the ready/busy information
425 * is read from the chip status register.
426 * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing
427 * commands to the chip.
428 * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on
429 * ready.
340 * @ecc: [BOARDSPECIFIC] ecc control ctructure 430 * @ecc: [BOARDSPECIFIC] ecc control ctructure
341 * @buffers: buffer structure for read/write 431 * @buffers: buffer structure for read/write
342 * @hwcontrol: platform-specific hardware control structure 432 * @hwcontrol: platform-specific hardware control structure
343 * @ops: oob operation operands 433 * @ops: oob operation operands
344 * @erase_cmd: [INTERN] erase command write function, selectable due to AND support 434 * @erase_cmd: [INTERN] erase command write function, selectable due
435 * to AND support.
345 * @scan_bbt: [REPLACEABLE] function to scan bad block table 436 * @scan_bbt: [REPLACEABLE] function to scan bad block table
346 * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR) 437 * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering
438 * data from array to read regs (tR).
347 * @state: [INTERN] the current state of the NAND device 439 * @state: [INTERN] the current state of the NAND device
348 * @oob_poi: poison value buffer 440 * @oob_poi: poison value buffer
349 * @page_shift: [INTERN] number of address bits in a page (column address bits) 441 * @page_shift: [INTERN] number of address bits in a page (column
442 * address bits).
350 * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock 443 * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock
351 * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry 444 * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry
352 * @chip_shift: [INTERN] number of address bits in one chip 445 * @chip_shift: [INTERN] number of address bits in one chip
353 * @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about 446 * @options: [BOARDSPECIFIC] various chip options. They can partly
354 * special functionality. See the defines for further explanation 447 * be set to inform nand_scan about special functionality.
355 * @badblockpos: [INTERN] position of the bad block marker in the oob area 448 * See the defines for further explanation.
449 * @badblockpos: [INTERN] position of the bad block marker in the oob
450 * area.
356 * @cellinfo: [INTERN] MLC/multichip data from chip ident 451 * @cellinfo: [INTERN] MLC/multichip data from chip ident
357 * @numchips: [INTERN] number of physical chips 452 * @numchips: [INTERN] number of physical chips
358 * @chipsize: [INTERN] the size of one chip for multichip arrays 453 * @chipsize: [INTERN] the size of one chip for multichip arrays
359 * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 454 * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1
360 * @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf 455 * @pagebuf: [INTERN] holds the pagenumber which is currently in
456 * data_buf.
361 * @subpagesize: [INTERN] holds the subpagesize 457 * @subpagesize: [INTERN] holds the subpagesize
458 * @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded),
459 * non 0 if ONFI supported.
460 * @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is
461 * supported, 0 otherwise.
362 * @ecclayout: [REPLACEABLE] the default ecc placement scheme 462 * @ecclayout: [REPLACEABLE] the default ecc placement scheme
363 * @bbt: [INTERN] bad block table pointer 463 * @bbt: [INTERN] bad block table pointer
364 * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup 464 * @bbt_td: [REPLACEABLE] bad block table descriptor for flash
465 * lookup.
365 * @bbt_md: [REPLACEABLE] bad block table mirror descriptor 466 * @bbt_md: [REPLACEABLE] bad block table mirror descriptor
366 * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan 467 * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial
367 * @controller: [REPLACEABLE] a pointer to a hardware controller structure 468 * bad block scan.
368 * which is shared among multiple independend devices 469 * @controller: [REPLACEABLE] a pointer to a hardware controller
470 * structure which is shared among multiple independend
471 * devices.
369 * @priv: [OPTIONAL] pointer to private chip date 472 * @priv: [OPTIONAL] pointer to private chip date
370 * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks 473 * @errstat: [OPTIONAL] hardware specific function to perform
371 * (determine if errors are correctable) 474 * additional error status checks (determine if errors are
475 * correctable).
372 * @write_page: [REPLACEABLE] High-level page write function 476 * @write_page: [REPLACEABLE] High-level page write function
373 */ 477 */
374 478
375struct nand_chip { 479struct nand_chip {
376 void __iomem *IO_ADDR_R; 480 void __iomem *IO_ADDR_R;
377 void __iomem *IO_ADDR_W; 481 void __iomem *IO_ADDR_W;
378 482
379 uint8_t (*read_byte)(struct mtd_info *mtd); 483 uint8_t (*read_byte)(struct mtd_info *mtd);
380 u16 (*read_word)(struct mtd_info *mtd); 484 u16 (*read_word)(struct mtd_info *mtd);
381 void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); 485 void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
382 void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); 486 void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
383 int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); 487 int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
384 void (*select_chip)(struct mtd_info *mtd, int chip); 488 void (*select_chip)(struct mtd_info *mtd, int chip);
385 int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); 489 int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
386 int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); 490 int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
387 void (*cmd_ctrl)(struct mtd_info *mtd, int dat, 491 void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
388 unsigned int ctrl); 492 int (*init_size)(struct mtd_info *mtd, struct nand_chip *this,
389 int (*dev_ready)(struct mtd_info *mtd); 493 u8 *id_data);
390 void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr); 494 int (*dev_ready)(struct mtd_info *mtd);
391 int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this); 495 void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column,
392 void (*erase_cmd)(struct mtd_info *mtd, int page); 496 int page_addr);
393 int (*scan_bbt)(struct mtd_info *mtd); 497 int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
394 int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page); 498 void (*erase_cmd)(struct mtd_info *mtd, int page);
395 int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, 499 int (*scan_bbt)(struct mtd_info *mtd);
396 const uint8_t *buf, int page, int cached, int raw); 500 int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state,
397 501 int status, int page);
398 int chip_delay; 502 int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
399 unsigned int options; 503 const uint8_t *buf, int page, int cached, int raw);
400 504
401 int page_shift; 505 int chip_delay;
402 int phys_erase_shift; 506 unsigned int options;
403 int bbt_erase_shift; 507
404 int chip_shift; 508 int page_shift;
405 int numchips; 509 int phys_erase_shift;
406 uint64_t chipsize; 510 int bbt_erase_shift;
407 int pagemask; 511 int chip_shift;
408 int pagebuf; 512 int numchips;
409 int subpagesize; 513 uint64_t chipsize;
410 uint8_t cellinfo; 514 int pagemask;
411 int badblockpos; 515 int pagebuf;
412 int badblockbits; 516 int subpagesize;
413 517 uint8_t cellinfo;
414 flstate_t state; 518 int badblockpos;
415 519 int badblockbits;
416 uint8_t *oob_poi; 520
417 struct nand_hw_control *controller; 521 int onfi_version;
418 struct nand_ecclayout *ecclayout; 522 struct nand_onfi_params onfi_params;
523
524 flstate_t state;
525
526 uint8_t *oob_poi;
527 struct nand_hw_control *controller;
528 struct nand_ecclayout *ecclayout;
419 529
420 struct nand_ecc_ctrl ecc; 530 struct nand_ecc_ctrl ecc;
421 struct nand_buffers *buffers; 531 struct nand_buffers *buffers;
@@ -423,13 +533,13 @@ struct nand_chip {
423 533
424 struct mtd_oob_ops ops; 534 struct mtd_oob_ops ops;
425 535
426 uint8_t *bbt; 536 uint8_t *bbt;
427 struct nand_bbt_descr *bbt_td; 537 struct nand_bbt_descr *bbt_td;
428 struct nand_bbt_descr *bbt_md; 538 struct nand_bbt_descr *bbt_md;
429 539
430 struct nand_bbt_descr *badblock_pattern; 540 struct nand_bbt_descr *badblock_pattern;
431 541
432 void *priv; 542 void *priv;
433}; 543};
434 544
435/* 545/*
@@ -473,7 +583,7 @@ struct nand_flash_dev {
473*/ 583*/
474struct nand_manufacturers { 584struct nand_manufacturers {
475 int id; 585 int id;
476 char * name; 586 char *name;
477}; 587};
478 588
479extern struct nand_flash_dev nand_flash_ids[]; 589extern struct nand_flash_dev nand_flash_ids[];
@@ -486,7 +596,7 @@ extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
486extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, 596extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
487 int allowbbt); 597 int allowbbt);
488extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, 598extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
489 size_t * retlen, uint8_t * buf); 599 size_t *retlen, uint8_t *buf);
490 600
491/** 601/**
492 * struct platform_nand_chip - chip level device structure 602 * struct platform_nand_chip - chip level device structure
@@ -502,17 +612,16 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
502 * @priv: hardware controller specific settings 612 * @priv: hardware controller specific settings
503 */ 613 */
504struct platform_nand_chip { 614struct platform_nand_chip {
505 int nr_chips; 615 int nr_chips;
506 int chip_offset; 616 int chip_offset;
507 int nr_partitions; 617 int nr_partitions;
508 struct mtd_partition *partitions; 618 struct mtd_partition *partitions;
509 struct nand_ecclayout *ecclayout; 619 struct nand_ecclayout *ecclayout;
510 int chip_delay; 620 int chip_delay;
511 unsigned int options; 621 unsigned int options;
512 const char **part_probe_types; 622 const char **part_probe_types;
513 void (*set_parts)(uint64_t size, 623 void (*set_parts)(uint64_t size, struct platform_nand_chip *chip);
514 struct platform_nand_chip *chip); 624 void *priv;
515 void *priv;
516}; 625};
517 626
518/* Keep gcc happy */ 627/* Keep gcc happy */
@@ -534,18 +643,15 @@ struct platform_device;
534 * All fields are optional and depend on the hardware driver requirements 643 * All fields are optional and depend on the hardware driver requirements
535 */ 644 */
536struct platform_nand_ctrl { 645struct platform_nand_ctrl {
537 int (*probe)(struct platform_device *pdev); 646 int (*probe)(struct platform_device *pdev);
538 void (*remove)(struct platform_device *pdev); 647 void (*remove)(struct platform_device *pdev);
539 void (*hwcontrol)(struct mtd_info *mtd, int cmd); 648 void (*hwcontrol)(struct mtd_info *mtd, int cmd);
540 int (*dev_ready)(struct mtd_info *mtd); 649 int (*dev_ready)(struct mtd_info *mtd);
541 void (*select_chip)(struct mtd_info *mtd, int chip); 650 void (*select_chip)(struct mtd_info *mtd, int chip);
542 void (*cmd_ctrl)(struct mtd_info *mtd, int dat, 651 void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
543 unsigned int ctrl); 652 void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
544 void (*write_buf)(struct mtd_info *mtd, 653 void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
545 const uint8_t *buf, int len); 654 void *priv;
546 void (*read_buf)(struct mtd_info *mtd,
547 uint8_t *buf, int len);
548 void *priv;
549}; 655};
550 656
551/** 657/**
@@ -554,8 +660,8 @@ struct platform_nand_ctrl {
554 * @ctrl: controller level device structure 660 * @ctrl: controller level device structure
555 */ 661 */
556struct platform_nand_data { 662struct platform_nand_data {
557 struct platform_nand_chip chip; 663 struct platform_nand_chip chip;
558 struct platform_nand_ctrl ctrl; 664 struct platform_nand_ctrl ctrl;
559}; 665};
560 666
561/* Some helpers to access the data structures */ 667/* Some helpers to access the data structures */
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 274b6196091d..2b54316591d2 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -39,7 +39,7 @@ struct mtd_partition {
39 uint64_t size; /* partition size */ 39 uint64_t size; /* partition size */
40 uint64_t offset; /* offset within the master MTD space */ 40 uint64_t offset; /* offset within the master MTD space */
41 uint32_t mask_flags; /* master MTD flags to mask out for this partition */ 41 uint32_t mask_flags; /* master MTD flags to mask out for this partition */
42 struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/ 42 struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only) */
43}; 43};
44 44
45#define MTDPART_OFS_NXTBLK (-2) 45#define MTDPART_OFS_NXTBLK (-2)
@@ -89,4 +89,9 @@ static inline int mtd_has_cmdlinepart(void) { return 1; }
89static inline int mtd_has_cmdlinepart(void) { return 0; } 89static inline int mtd_has_cmdlinepart(void) { return 0; }
90#endif 90#endif
91 91
92int mtd_is_master(struct mtd_info *mtd);
93int mtd_add_partition(struct mtd_info *master, char *name,
94 long long offset, long long length);
95int mtd_del_partition(struct mtd_info *master, int partno);
96
92#endif 97#endif
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index 4debb4514634..2f7d45bcbd24 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -52,6 +52,7 @@ struct mtd_oob_buf64 {
52#define MTD_NANDFLASH 4 52#define MTD_NANDFLASH 4
53#define MTD_DATAFLASH 6 53#define MTD_DATAFLASH 6
54#define MTD_UBIVOLUME 7 54#define MTD_UBIVOLUME 7
55#define MTD_MLCNANDFLASH 8
55 56
56#define MTD_WRITEABLE 0x400 /* Device is writeable */ 57#define MTD_WRITEABLE 0x400 /* Device is writeable */
57#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */ 58#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
@@ -119,7 +120,7 @@ struct otp_info {
119#define OTPGETREGIONCOUNT _IOW('M', 14, int) 120#define OTPGETREGIONCOUNT _IOW('M', 14, int)
120#define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) 121#define OTPGETREGIONINFO _IOW('M', 15, struct otp_info)
121#define OTPLOCK _IOR('M', 16, struct otp_info) 122#define OTPLOCK _IOR('M', 16, struct otp_info)
122#define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout) 123#define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout_user)
123#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) 124#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
124#define MTDFILEMODE _IO('M', 19) 125#define MTDFILEMODE _IO('M', 19)
125#define MEMERASE64 _IOW('M', 20, struct erase_info_user64) 126#define MEMERASE64 _IOW('M', 20, struct erase_info_user64)
@@ -144,13 +145,18 @@ struct nand_oobfree {
144}; 145};
145 146
146#define MTD_MAX_OOBFREE_ENTRIES 8 147#define MTD_MAX_OOBFREE_ENTRIES 8
148#define MTD_MAX_ECCPOS_ENTRIES 64
147/* 149/*
148 * ECC layout control structure. Exported to userspace for 150 * OBSOLETE: ECC layout control structure. Exported to user-space via ioctl
149 * diagnosis and to allow creation of raw images 151 * ECCGETLAYOUT for backwards compatbility and should not be mistaken as a
152 * complete set of ECC information. The ioctl truncates the larger internal
153 * structure to retain binary compatibility with the static declaration of the
154 * ioctl. Note that the "MTD_MAX_..._ENTRIES" macros represent the max size of
155 * the user struct, not the MAX size of the internal struct nand_ecclayout.
150 */ 156 */
151struct nand_ecclayout { 157struct nand_ecclayout_user {
152 __u32 eccbytes; 158 __u32 eccbytes;
153 __u32 eccpos[64]; 159 __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES];
154 __u32 oobavail; 160 __u32 oobavail;
155 struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; 161 struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
156}; 162};
diff --git a/include/mtd/mtd-user.h b/include/mtd/mtd-user.h
index aa3c2f86a913..83327c808c86 100644
--- a/include/mtd/mtd-user.h
+++ b/include/mtd/mtd-user.h
@@ -29,6 +29,6 @@ typedef struct mtd_info_user mtd_info_t;
29typedef struct erase_info_user erase_info_t; 29typedef struct erase_info_user erase_info_t;
30typedef struct region_info_user region_info_t; 30typedef struct region_info_user region_info_t;
31typedef struct nand_oobinfo nand_oobinfo_t; 31typedef struct nand_oobinfo nand_oobinfo_t;
32typedef struct nand_ecclayout nand_ecclayout_t; 32typedef struct nand_ecclayout_user nand_ecclayout_t;
33 33
34#endif /* __MTD_USER_H__ */ 34#endif /* __MTD_USER_H__ */
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index 55d700e8566e..daabae5817c6 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -49,7 +49,9 @@ struct sh_mobile_lcdc_sys_bus_ops {
49 unsigned long (*read_data)(void *handle); 49 unsigned long (*read_data)(void *handle);
50}; 50};
51 51
52struct module;
52struct sh_mobile_lcdc_board_cfg { 53struct sh_mobile_lcdc_board_cfg {
54 struct module *owner;
53 void *board_data; 55 void *board_data;
54 int (*setup_sys)(void *board_data, void *sys_ops_handle, 56 int (*setup_sys)(void *board_data, void *sys_ops_handle,
55 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 57 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
@@ -70,7 +72,8 @@ struct sh_mobile_lcdc_chan_cfg {
70 int interface_type; /* selects RGBn or SYSn I/F, see above */ 72 int interface_type; /* selects RGBn or SYSn I/F, see above */
71 int clock_divider; 73 int clock_divider;
72 unsigned long flags; /* LCDC_FLAGS_... */ 74 unsigned long flags; /* LCDC_FLAGS_... */
73 struct fb_videomode lcd_cfg; 75 const struct fb_videomode *lcd_cfg;
76 int num_cfg;
74 struct sh_mobile_lcdc_lcd_size_cfg lcd_size_cfg; 77 struct sh_mobile_lcdc_lcd_size_cfg lcd_size_cfg;
75 struct sh_mobile_lcdc_board_cfg board_cfg; 78 struct sh_mobile_lcdc_board_cfg board_cfg;
76 struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */ 79 struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */
diff --git a/ipc/shm.c b/ipc/shm.c
index fd658a1c2b88..7d3bb22a9302 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -479,6 +479,7 @@ static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_
479 { 479 {
480 struct shmid_ds out; 480 struct shmid_ds out;
481 481
482 memset(&out, 0, sizeof(out));
482 ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm); 483 ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm);
483 out.shm_segsz = in->shm_segsz; 484 out.shm_segsz = in->shm_segsz;
484 out.shm_atime = in->shm_atime; 485 out.shm_atime = in->shm_atime;