aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2015-10-23 03:29:33 +0200
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2015-10-23 03:29:33 +0200
commit15dfd0df63ce6847081d09b2bbd567cc0cc4eae1 (patch)
tree3b73f24fcef970bfcace3cbb297cfa57f3994682 /arch/arm
parent328aa7a45af61bc0060c80847daa67fef7b9c0d0 (diff)
parent0149138c4142da287d23f9d5c6038f7fb5e30ac2 (diff)
downloadkernel_samsung_smdk4412-15dfd0df63ce6847081d09b2bbd567cc0cc4eae1.zip
kernel_samsung_smdk4412-15dfd0df63ce6847081d09b2bbd567cc0cc4eae1.tar.gz
kernel_samsung_smdk4412-15dfd0df63ce6847081d09b2bbd567cc0cc4eae1.tar.bz2
initial merge with 3.2.72
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/boot/compressed/atags_to_fdt.c97
-rw-r--r--arch/arm/boot/compressed/libfdt_env.h15
-rw-r--r--arch/arm/boot/compressed/sdhi-sh7372.c95
-rw-r--r--arch/arm/boot/compressed/sdhi-shmobile.c449
-rw-r--r--arch/arm/boot/compressed/sdhi-shmobile.h11
-rw-r--r--arch/arm/boot/compressed/string.c127
-rw-r--r--arch/arm/boot/dts/at91sam9g20.dtsi119
-rw-r--r--arch/arm/boot/dts/at91sam9g45.dtsi106
-rw-r--r--arch/arm/boot/dts/at91sam9m10g45ek.dts35
-rw-r--r--arch/arm/boot/dts/highbank.dts198
-rw-r--r--arch/arm/boot/dts/imx51-babbage.dts135
-rw-r--r--arch/arm/boot/dts/imx51.dtsi246
-rw-r--r--arch/arm/boot/dts/imx53-ard.dts113
-rw-r--r--arch/arm/boot/dts/imx53-evk.dts120
-rw-r--r--arch/arm/boot/dts/imx53-qsb.dts125
-rw-r--r--arch/arm/boot/dts/imx53-smd.dts169
-rw-r--r--arch/arm/boot/dts/imx53.dtsi301
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto.dts62
-rw-r--r--arch/arm/boot/dts/imx6q.dtsi575
-rw-r--r--arch/arm/boot/dts/msm8660-surf.dts24
-rw-r--r--arch/arm/boot/dts/omap3-beagle.dts29
-rw-r--r--arch/arm/boot/dts/omap3.dtsi63
-rw-r--r--arch/arm/boot/dts/omap4-panda.dts29
-rw-r--r--arch/arm/boot/dts/omap4-sdp.dts29
-rw-r--r--arch/arm/boot/dts/omap4.dtsi103
-rw-r--r--arch/arm/boot/dts/picoxcell-pc3x2.dtsi249
-rw-r--r--arch/arm/boot/dts/picoxcell-pc3x3.dtsi365
-rw-r--r--arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts86
-rw-r--r--arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts92
-rw-r--r--arch/arm/boot/dts/prima2-cb.dts424
-rw-r--r--arch/arm/boot/dts/skeleton.dtsi13
-rw-r--r--arch/arm/boot/dts/tegra-harmony.dts71
-rw-r--r--arch/arm/boot/dts/tegra-seaboard.dts32
-rw-r--r--arch/arm/boot/dts/tegra-ventana.dts31
-rw-r--r--arch/arm/boot/dts/tegra20.dtsi147
-rw-r--r--arch/arm/boot/dts/usb_a9g20.dts30
-rw-r--r--arch/arm/boot/dts/versatile-ab.dts192
-rw-r--r--arch/arm/boot/dts/versatile-pb.dts48
-rw-r--r--arch/arm/boot/dts/zynq-ep107.dts52
-rw-r--r--arch/arm/configs/at91cap9_defconfig108
-rw-r--r--arch/arm/configs/at91sam9260_defconfig91
-rw-r--r--arch/arm/configs/at91sam9g20_defconfig124
-rw-r--r--arch/arm/configs/at91sam9g45_defconfig210
-rw-r--r--arch/arm/configs/at91sam9rl_defconfig79
-rw-r--r--arch/arm/configs/imx_v4_v5_defconfig172
-rw-r--r--arch/arm/configs/mx5_defconfig184
-rw-r--r--arch/arm/include/asm/exception.h19
-rw-r--r--arch/arm/include/asm/pgtable-2level-hwdef.h93
-rw-r--r--arch/arm/include/asm/pgtable-2level-types.h67
-rw-r--r--arch/arm/include/asm/pgtable-2level.h145
-rw-r--r--arch/arm/include/asm/suspend.h7
-rw-r--r--arch/arm/kernel/kprobes-arm.c1005
-rw-r--r--arch/arm/kernel/kprobes-common.c577
-rw-r--r--arch/arm/kernel/kprobes-test-arm.c1330
-rw-r--r--arch/arm/kernel/kprobes-test-thumb.c1187
-rw-r--r--arch/arm/kernel/kprobes-test.c1748
-rw-r--r--arch/arm/kernel/kprobes-test.h432
-rw-r--r--arch/arm/kernel/kprobes-thumb.c1469
-rw-r--r--arch/arm/kernel/kprobes.h428
-rw-r--r--arch/arm/kernel/suspend.c72
-rw-r--r--arch/arm/kernel/topology.c150
-rw-r--r--arch/arm/mach-at91/board-dt.c123
-rw-r--r--arch/arm/mach-at91/board-rsi-ews.c233
-rw-r--r--arch/arm/mach-at91/board-usb-a926x.c378
-rw-r--r--arch/arm/mach-at91/setup.c300
-rw-r--r--arch/arm/mach-at91/soc.h59
-rw-r--r--arch/arm/mach-davinci/include/mach/ddr2.h4
-rw-r--r--arch/arm/mach-davinci/include/mach/gpio-davinci.h91
-rw-r--r--arch/arm/mach-ep93xx/dma.c108
-rw-r--r--arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h100
-rw-r--r--arch/arm/mach-ep93xx/vision_ep9307.c364
-rw-r--r--arch/arm/mach-exynos/clock.c1491
-rw-r--r--arch/arm/mach-exynos/cpu.c293
-rw-r--r--arch/arm/mach-exynos/cpuidle.c92
-rw-r--r--arch/arm/mach-exynos/include/mach/exynos4-clock.h43
-rw-r--r--arch/arm/mach-exynos/mach-origen.c700
-rw-r--r--arch/arm/mach-exynos/pm.c428
-rw-r--r--arch/arm/mach-exynos/pmu.c230
-rw-r--r--arch/arm/mach-exynos/setup-i2c4.c~HEAD36
-rw-r--r--arch/arm/mach-exynos/setup-i2c4.c~v3.2.7223
-rw-r--r--arch/arm/mach-exynos/setup-i2c5.c~HEAD31
-rw-r--r--arch/arm/mach-exynos/setup-i2c5.c~v3.2.7223
-rw-r--r--arch/arm/mach-highbank/Makefile6
-rw-r--r--arch/arm/mach-highbank/Makefile.boot1
-rw-r--r--arch/arm/mach-highbank/clock.c62
-rw-r--r--arch/arm/mach-highbank/core.h9
-rw-r--r--arch/arm/mach-highbank/highbank.c149
-rw-r--r--arch/arm/mach-highbank/hotplug.c56
-rw-r--r--arch/arm/mach-highbank/include/mach/debug-macro.S19
-rw-r--r--arch/arm/mach-highbank/include/mach/entry-macro.S7
-rw-r--r--arch/arm/mach-highbank/include/mach/gpio.h1
-rw-r--r--arch/arm/mach-highbank/include/mach/io.h7
-rw-r--r--arch/arm/mach-highbank/include/mach/irqs.h6
-rw-r--r--arch/arm/mach-highbank/include/mach/memory.h1
-rw-r--r--arch/arm/mach-highbank/include/mach/system.h26
-rw-r--r--arch/arm/mach-highbank/include/mach/timex.h6
-rw-r--r--arch/arm/mach-highbank/include/mach/uncompress.h9
-rw-r--r--arch/arm/mach-highbank/include/mach/vmalloc.h1
-rw-r--r--arch/arm/mach-highbank/lluart.c34
-rw-r--r--arch/arm/mach-highbank/localtimer.c40
-rw-r--r--arch/arm/mach-highbank/platsmp.c78
-rw-r--r--arch/arm/mach-highbank/pm.c55
-rw-r--r--arch/arm/mach-highbank/sysregs.h52
-rw-r--r--arch/arm/mach-highbank/system.c33
-rw-r--r--arch/arm/mach-imx/clock-imx6q.c2030
-rw-r--r--arch/arm/mach-imx/cpu-imx25.c41
-rw-r--r--arch/arm/mach-imx/gpc.c113
-rw-r--r--arch/arm/mach-imx/head-v7.S99
-rw-r--r--arch/arm/mach-imx/hotplug.c67
-rw-r--r--arch/arm/mach-imx/lluart.c32
-rw-r--r--arch/arm/mach-imx/localtimer.c35
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c86
-rw-r--r--arch/arm/mach-imx/mm-imx3.c263
-rw-r--r--arch/arm/mach-imx/mmdc.c72
-rw-r--r--arch/arm/mach-imx/platsmp.c85
-rw-r--r--arch/arm/mach-imx/pm-imx6q.c70
-rw-r--r--arch/arm/mach-imx/src.c56
-rw-r--r--arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h48
-rw-r--r--arch/arm/mach-ixp4xx/miccpt-pci.c78
-rw-r--r--arch/arm/mach-ixp4xx/omixp-setup.c273
-rw-r--r--arch/arm/mach-ks8695/include/mach/gpio-ks8695.h39
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h50
-rw-r--r--arch/arm/mach-mmp/gplugd.c197
-rw-r--r--arch/arm/mach-mmp/include/mach/gpio-pxa.h30
-rw-r--r--arch/arm/mach-mmp/include/mach/sram.h35
-rw-r--r--arch/arm/mach-mmp/sram.c168
-rw-r--r--arch/arm/mach-msm/include/mach/msm_gpiomux.h38
-rw-r--r--arch/arm/mach-mx5/board-mx53_ard.c260
-rw-r--r--arch/arm/mach-mx5/imx51-dt.c118
-rw-r--r--arch/arm/mach-mx5/imx53-dt.c128
-rw-r--r--arch/arm/mach-mx5/pm-imx5.c83
-rw-r--r--arch/arm/mach-mxs/devices/platform-gpio-mxs.c53
-rw-r--r--arch/arm/mach-mxs/devices/platform-mxs-saif.c60
-rw-r--r--arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c51
-rw-r--r--arch/arm/mach-mxs/mach-m28evk.c366
-rw-r--r--arch/arm/mach-mxs/mm.c63
-rw-r--r--arch/arm/mach-omap1/timer.c173
-rw-r--r--arch/arm/mach-omap2/clockdomains2420_data.c154
-rw-r--r--arch/arm/mach-omap2/clockdomains2430_data.c181
-rw-r--r--arch/arm/mach-omap2/clockdomains3xxx_data.c398
-rw-r--r--arch/arm/mach-omap2/display.h29
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c173
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c325
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c130
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c150
-rw-r--r--arch/arm/mach-omap2/timer.c503
-rw-r--r--arch/arm/mach-omap2/twl-common.c328
-rw-r--r--arch/arm/mach-omap2/twl-common.h62
-rw-r--r--arch/arm/mach-omap2/vc.c367
-rw-r--r--arch/arm/mach-omap2/voltagedomains2xxx_data.c32
-rw-r--r--arch/arm/mach-omap2/vp.c283
-rw-r--r--arch/arm/mach-picoxcell/Makefile3
-rw-r--r--arch/arm/mach-picoxcell/Makefile.boot1
-rw-r--r--arch/arm/mach-picoxcell/common.c55
-rw-r--r--arch/arm/mach-picoxcell/common.h18
-rw-r--r--arch/arm/mach-picoxcell/include/mach/debug-macro.S35
-rw-r--r--arch/arm/mach-picoxcell/include/mach/entry-macro.S19
-rw-r--r--arch/arm/mach-picoxcell/include/mach/gpio.h1
-rw-r--r--arch/arm/mach-picoxcell/include/mach/hardware.h21
-rw-r--r--arch/arm/mach-picoxcell/include/mach/io.h22
-rw-r--r--arch/arm/mach-picoxcell/include/mach/irqs.h25
-rw-r--r--arch/arm/mach-picoxcell/include/mach/map.h25
-rw-r--r--arch/arm/mach-picoxcell/include/mach/memory.h1
-rw-r--r--arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h25
-rw-r--r--arch/arm/mach-picoxcell/include/mach/system.h31
-rw-r--r--arch/arm/mach-picoxcell/include/mach/timex.h25
-rw-r--r--arch/arm/mach-picoxcell/include/mach/uncompress.h21
-rw-r--r--arch/arm/mach-picoxcell/include/mach/vmalloc.h14
-rw-r--r--arch/arm/mach-picoxcell/io.c32
-rw-r--r--arch/arm/mach-picoxcell/time.c132
-rw-r--r--arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h241
-rw-r--r--arch/arm/mach-prima2/Makefile9
-rw-r--r--arch/arm/mach-prima2/Makefile.boot3
-rw-r--r--arch/arm/mach-prima2/clock.c510
-rw-r--r--arch/arm/mach-prima2/common.h26
-rw-r--r--arch/arm/mach-prima2/include/mach/clkdev.h15
-rw-r--r--arch/arm/mach-prima2/include/mach/debug-macro.S29
-rw-r--r--arch/arm/mach-prima2/include/mach/entry-macro.S29
-rw-r--r--arch/arm/mach-prima2/include/mach/hardware.h15
-rw-r--r--arch/arm/mach-prima2/include/mach/io.h16
-rw-r--r--arch/arm/mach-prima2/include/mach/irqs.h17
-rw-r--r--arch/arm/mach-prima2/include/mach/map.h16
-rw-r--r--arch/arm/mach-prima2/include/mach/system.h29
-rw-r--r--arch/arm/mach-prima2/include/mach/timex.h14
-rw-r--r--arch/arm/mach-prima2/include/mach/uart.h23
-rw-r--r--arch/arm/mach-prima2/include/mach/uncompress.h40
-rw-r--r--arch/arm/mach-prima2/include/mach/vmalloc.h16
-rw-r--r--arch/arm/mach-prima2/irq.c115
-rw-r--r--arch/arm/mach-prima2/l2x0.c31
-rw-r--r--arch/arm/mach-prima2/lluart.c25
-rw-r--r--arch/arm/mach-prima2/pm.c151
-rw-r--r--arch/arm/mach-prima2/pm.h29
-rw-r--r--arch/arm/mach-prima2/prima2.c43
-rw-r--r--arch/arm/mach-prima2/rstc.c70
-rw-r--r--arch/arm/mach-prima2/rtciobrg.c139
-rw-r--r--arch/arm/mach-prima2/sleep.S64
-rw-r--r--arch/arm/mach-prima2/timer.c252
-rw-r--r--arch/arm/mach-pxa/include/mach/gpio-pxa.h133
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa3xx.h14
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa95x.h7
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/crag6410.h23
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410-module.c182
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410.c717
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/pm-core.h117
-rw-r--r--arch/arm/mach-s5p64x0/irq-eint.c155
-rw-r--r--arch/arm/mach-s5p64x0/irq-pm.c92
-rw-r--r--arch/arm/mach-s5p64x0/pm.c204
-rw-r--r--arch/arm/mach-s5p64x0/setup-fb-24bpp.c29
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-audss.h18
-rw-r--r--arch/arm/mach-shmobile/board-kota2.c557
-rw-r--r--arch/arm/mach-shmobile/include/mach/intc.h246
-rw-r--r--arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h21
-rw-r--r--arch/arm/mach-shmobile/include/mach/sdhi.h16
-rw-r--r--arch/arm/mach-tegra/board-dt.c136
-rw-r--r--arch/arm/mach-tegra/include/mach/gpio-tegra.h39
-rw-r--r--arch/arm/mach-u300/include/mach/gpio-u300.h150
-rw-r--r--arch/arm/mach-ux500/cache-l2x0.c95
-rw-r--r--arch/arm/mach-ux500/timer.c68
-rw-r--r--arch/arm/mach-versatile/versatile_dt.c51
-rw-r--r--arch/arm/mach-vexpress/include/mach/gpio.h1
-rw-r--r--arch/arm/mach-zynq/Makefile6
-rw-r--r--arch/arm/mach-zynq/Makefile.boot3
-rw-r--r--arch/arm/mach-zynq/common.c118
-rw-r--r--arch/arm/mach-zynq/common.h24
-rw-r--r--arch/arm/mach-zynq/include/mach/clkdev.h32
-rw-r--r--arch/arm/mach-zynq/include/mach/debug-macro.S36
-rw-r--r--arch/arm/mach-zynq/include/mach/entry-macro.S30
-rw-r--r--arch/arm/mach-zynq/include/mach/hardware.h18
-rw-r--r--arch/arm/mach-zynq/include/mach/io.h33
-rw-r--r--arch/arm/mach-zynq/include/mach/irqs.h21
-rw-r--r--arch/arm/mach-zynq/include/mach/system.h28
-rw-r--r--arch/arm/mach-zynq/include/mach/timex.h23
-rw-r--r--arch/arm/mach-zynq/include/mach/uart.h25
-rw-r--r--arch/arm/mach-zynq/include/mach/uncompress.h51
-rw-r--r--arch/arm/mach-zynq/include/mach/vmalloc.h20
-rw-r--r--arch/arm/mach-zynq/include/mach/zynq_soc.h48
-rw-r--r--arch/arm/mach-zynq/timer.c298
-rw-r--r--arch/arm/plat-mxc/devices/platform-ahci-imx.c156
-rw-r--r--arch/arm/plat-mxc/devices/platform-gpio-mxc.c32
-rw-r--r--arch/arm/plat-mxc/devices/platform-pata_imx.c59
-rw-r--r--arch/arm/plat-mxc/gic.c41
-rw-r--r--arch/arm/plat-mxc/include/mach/mx6q.h33
-rw-r--r--arch/arm/plat-nomadik/include/plat/gpio-nomadik.h88
-rw-r--r--arch/arm/plat-omap/include/plat/iopgtable.h120
-rw-r--r--arch/arm/plat-omap/include/plat/voltage.h20
-rw-r--r--arch/arm/plat-pxa/include/plat/gpio-pxa.h44
-rw-r--r--arch/arm/plat-s3c24xx/dev-uart.c100
-rw-r--r--arch/arm/plat-s5p/sleep.S49
-rw-r--r--arch/arm/plat-samsung/devs.c1463
-rw-r--r--arch/arm/plat-samsung/dma-ops.c132
-rw-r--r--arch/arm/plat-samsung/include/plat/audio-simtec.h37
-rw-r--r--arch/arm/plat-samsung/include/plat/camport.h28
-rw-r--r--arch/arm/plat-samsung/include/plat/common-smdk.h15
-rw-r--r--arch/arm/plat-samsung/include/plat/cpu-freq-core.h293
-rw-r--r--arch/arm/plat-samsung/include/plat/dma-ops.h63
-rw-r--r--arch/arm/plat-samsung/include/plat/dma-pl330.h104
-rw-r--r--arch/arm/plat-samsung/include/plat/ehci.h21
-rw-r--r--arch/arm/plat-samsung/include/plat/exynos4.h35
-rw-r--r--arch/arm/plat-samsung/include/plat/fb-s3c2410.h72
-rw-r--r--arch/arm/plat-samsung/include/plat/fiq.h13
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-fns.h98
-rw-r--r--arch/arm/plat-samsung/include/plat/irq.h116
-rw-r--r--arch/arm/plat-samsung/include/plat/irqs.h80
-rw-r--r--arch/arm/plat-samsung/include/plat/map-s3c.h84
-rw-r--r--arch/arm/plat-samsung/include/plat/map-s5p.h61
-rw-r--r--arch/arm/plat-samsung/include/plat/mci.h52
-rw-r--r--arch/arm/plat-samsung/include/plat/mfc.h27
-rw-r--r--arch/arm/plat-samsung/include/plat/mipi_csis.h43
-rw-r--r--arch/arm/plat-samsung/include/plat/pll.h323
-rw-r--r--arch/arm/plat-samsung/include/plat/pwm-clock.h81
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-dma.h151
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-iis.h70
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-spi.h48
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-srom.h54
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-udc.h151
-rw-r--r--arch/arm/plat-samsung/include/plat/reset.h16
-rw-r--r--arch/arm/plat-samsung/include/plat/s3c2410.h33
-rw-r--r--arch/arm/plat-samsung/include/plat/s3c2412.h29
-rw-r--r--arch/arm/plat-samsung/include/plat/s3c2416.h31
-rw-r--r--arch/arm/plat-samsung/include/plat/s3c2443.h52
-rw-r--r--arch/arm/plat-samsung/include/plat/s3c244x.h42
-rw-r--r--arch/arm/plat-samsung/include/plat/s3c6400.h36
-rw-r--r--arch/arm/plat-samsung/include/plat/s3c6410.h29
-rw-r--r--arch/arm/plat-samsung/include/plat/s5p-clock.h55
-rw-r--r--arch/arm/plat-samsung/include/plat/s5p-time.h40
-rw-r--r--arch/arm/plat-samsung/include/plat/s5p6440.h36
-rw-r--r--arch/arm/plat-samsung/include/plat/s5p6450.h36
-rw-r--r--arch/arm/plat-samsung/include/plat/s5pc100.h33
-rw-r--r--arch/arm/plat-samsung/include/plat/s5pv210.h33
-rw-r--r--arch/arm/plat-samsung/include/plat/system-reset.h31
-rw-r--r--arch/arm/plat-samsung/include/plat/udc.h57
-rw-r--r--arch/arm/plat-samsung/include/plat/usb-phy.h22
-rw-r--r--arch/arm/plat-samsung/s3c-dma-ops.c131
293 files changed, 40744 insertions, 0 deletions
diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c
new file mode 100644
index 0000000..6ce11c4
--- /dev/null
+++ b/arch/arm/boot/compressed/atags_to_fdt.c
@@ -0,0 +1,97 @@
+#include <asm/setup.h>
+#include <libfdt.h>
+
+static int node_offset(void *fdt, const char *node_path)
+{
+ int offset = fdt_path_offset(fdt, node_path);
+ if (offset == -FDT_ERR_NOTFOUND)
+ offset = fdt_add_subnode(fdt, 0, node_path);
+ return offset;
+}
+
+static int setprop(void *fdt, const char *node_path, const char *property,
+ uint32_t *val_array, int size)
+{
+ int offset = node_offset(fdt, node_path);
+ if (offset < 0)
+ return offset;
+ return fdt_setprop(fdt, offset, property, val_array, size);
+}
+
+static int setprop_string(void *fdt, const char *node_path,
+ const char *property, const char *string)
+{
+ int offset = node_offset(fdt, node_path);
+ if (offset < 0)
+ return offset;
+ return fdt_setprop_string(fdt, offset, property, string);
+}
+
+static int setprop_cell(void *fdt, const char *node_path,
+ const char *property, uint32_t val)
+{
+ int offset = node_offset(fdt, node_path);
+ if (offset < 0)
+ return offset;
+ return fdt_setprop_cell(fdt, offset, property, val);
+}
+
+/*
+ * Convert and fold provided ATAGs into the provided FDT.
+ *
+ * REturn values:
+ * = 0 -> pretend success
+ * = 1 -> bad ATAG (may retry with another possible ATAG pointer)
+ * < 0 -> error from libfdt
+ */
+int atags_to_fdt(void *atag_list, void *fdt, int total_space)
+{
+ struct tag *atag = atag_list;
+ uint32_t mem_reg_property[2 * NR_BANKS];
+ int memcount = 0;
+ int ret;
+
+ /* make sure we've got an aligned pointer */
+ if ((u32)atag_list & 0x3)
+ return 1;
+
+ /* if we get a DTB here we're done already */
+ if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
+ return 0;
+
+ /* validate the ATAG */
+ if (atag->hdr.tag != ATAG_CORE ||
+ (atag->hdr.size != tag_size(tag_core) &&
+ atag->hdr.size != 2))
+ return 1;
+
+ /* let's give it all the room it could need */
+ ret = fdt_open_into(fdt, fdt, total_space);
+ if (ret < 0)
+ return ret;
+
+ for_each_tag(atag, atag_list) {
+ if (atag->hdr.tag == ATAG_CMDLINE) {
+ setprop_string(fdt, "/chosen", "bootargs",
+ atag->u.cmdline.cmdline);
+ } else if (atag->hdr.tag == ATAG_MEM) {
+ if (memcount >= sizeof(mem_reg_property)/4)
+ continue;
+ mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);
+ mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);
+ } else if (atag->hdr.tag == ATAG_INITRD2) {
+ uint32_t initrd_start, initrd_size;
+ initrd_start = atag->u.initrd.start;
+ initrd_size = atag->u.initrd.size;
+ setprop_cell(fdt, "/chosen", "linux,initrd-start",
+ initrd_start);
+ setprop_cell(fdt, "/chosen", "linux,initrd-end",
+ initrd_start + initrd_size);
+ }
+ }
+
+ if (memcount)
+ setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount);
+
+ return fdt_pack(fdt);
+}
diff --git a/arch/arm/boot/compressed/libfdt_env.h b/arch/arm/boot/compressed/libfdt_env.h
new file mode 100644
index 0000000..1f4e718
--- /dev/null
+++ b/arch/arm/boot/compressed/libfdt_env.h
@@ -0,0 +1,15 @@
+#ifndef _ARM_LIBFDT_ENV_H
+#define _ARM_LIBFDT_ENV_H
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/byteorder.h>
+
+#define fdt16_to_cpu(x) be16_to_cpu(x)
+#define cpu_to_fdt16(x) cpu_to_be16(x)
+#define fdt32_to_cpu(x) be32_to_cpu(x)
+#define cpu_to_fdt32(x) cpu_to_be32(x)
+#define fdt64_to_cpu(x) be64_to_cpu(x)
+#define cpu_to_fdt64(x) cpu_to_be64(x)
+
+#endif
diff --git a/arch/arm/boot/compressed/sdhi-sh7372.c b/arch/arm/boot/compressed/sdhi-sh7372.c
new file mode 100644
index 0000000..d279294
--- /dev/null
+++ b/arch/arm/boot/compressed/sdhi-sh7372.c
@@ -0,0 +1,95 @@
+/*
+ * SuperH Mobile SDHI
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2010 Kuninori Morimoto
+ * Copyright (C) 2010 Simon Horman
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Parts inspired by u-boot
+ */
+
+#include <linux/io.h>
+#include <mach/mmc.h>
+#include <linux/mmc/boot.h>
+#include <linux/mmc/tmio.h>
+
+#include "sdhi-shmobile.h"
+
+#define PORT179CR 0xe60520b3
+#define PORT180CR 0xe60520b4
+#define PORT181CR 0xe60520b5
+#define PORT182CR 0xe60520b6
+#define PORT183CR 0xe60520b7
+#define PORT184CR 0xe60520b8
+
+#define SMSTPCR3 0xe615013c
+
+#define CR_INPUT_ENABLE 0x10
+#define CR_FUNCTION1 0x01
+
+#define SDHI1_BASE (void __iomem *)0xe6860000
+#define SDHI_BASE SDHI1_BASE
+
+/* SuperH Mobile SDHI loader
+ *
+ * loads the zImage from an SD card starting from block 0
+ * on physical partition 1
+ *
+ * The image must be start with a vrl4 header and
+ * the zImage must start at offset 512 of the image. That is,
+ * at block 1 (=byte 512) of physical partition 1
+ *
+ * Use the following line to write the vrl4 formated zImage
+ * to an SD card
+ * # dd if=vrl4.out of=/dev/sdx bs=512
+ */
+asmlinkage void mmc_loader(unsigned short *buf, unsigned long len)
+{
+ int high_capacity;
+
+ mmc_init_progress();
+
+ mmc_update_progress(MMC_PROGRESS_ENTER);
+ /* Initialise SDHI1 */
+ /* PORT184CR: GPIO_FN_SDHICMD1 Control */
+ __raw_writeb(CR_FUNCTION1, PORT184CR);
+ /* PORT179CR: GPIO_FN_SDHICLK1 Control */
+ __raw_writeb(CR_INPUT_ENABLE|CR_FUNCTION1, PORT179CR);
+ /* PORT181CR: GPIO_FN_SDHID1_3 Control */
+ __raw_writeb(CR_FUNCTION1, PORT183CR);
+ /* PORT182CR: GPIO_FN_SDHID1_2 Control */
+ __raw_writeb(CR_FUNCTION1, PORT182CR);
+ /* PORT183CR: GPIO_FN_SDHID1_1 Control */
+ __raw_writeb(CR_FUNCTION1, PORT181CR);
+ /* PORT180CR: GPIO_FN_SDHID1_0 Control */
+ __raw_writeb(CR_FUNCTION1, PORT180CR);
+
+ /* Enable clock to SDHI1 hardware block */
+ __raw_writel(__raw_readl(SMSTPCR3) & ~(1 << 13), SMSTPCR3);
+
+ /* setup SDHI hardware */
+ mmc_update_progress(MMC_PROGRESS_INIT);
+ high_capacity = sdhi_boot_init(SDHI_BASE);
+ if (high_capacity < 0)
+ goto err;
+
+ mmc_update_progress(MMC_PROGRESS_LOAD);
+ /* load kernel */
+ if (sdhi_boot_do_read(SDHI_BASE, high_capacity,
+ 0, /* Kernel is at block 1 */
+ (len + TMIO_BBS - 1) / TMIO_BBS, buf))
+ goto err;
+
+ /* Disable clock to SDHI1 hardware block */
+ __raw_writel(__raw_readl(SMSTPCR3) | (1 << 13), SMSTPCR3);
+
+ mmc_update_progress(MMC_PROGRESS_DONE);
+
+ return;
+err:
+ for(;;);
+}
diff --git a/arch/arm/boot/compressed/sdhi-shmobile.c b/arch/arm/boot/compressed/sdhi-shmobile.c
new file mode 100644
index 0000000..bd3d469
--- /dev/null
+++ b/arch/arm/boot/compressed/sdhi-shmobile.c
@@ -0,0 +1,449 @@
+/*
+ * SuperH Mobile SDHI
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2010 Kuninori Morimoto
+ * Copyright (C) 2010 Simon Horman
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Parts inspired by u-boot
+ */
+
+#include <linux/io.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/tmio.h>
+#include <mach/sdhi.h>
+
+#define OCR_FASTBOOT (1<<29)
+#define OCR_HCS (1<<30)
+#define OCR_BUSY (1<<31)
+
+#define RESP_CMD12 0x00000030
+
+static inline u16 sd_ctrl_read16(void __iomem *base, int addr)
+{
+ return __raw_readw(base + addr);
+}
+
+static inline u32 sd_ctrl_read32(void __iomem *base, int addr)
+{
+ return __raw_readw(base + addr) |
+ __raw_readw(base + addr + 2) << 16;
+}
+
+static inline void sd_ctrl_write16(void __iomem *base, int addr, u16 val)
+{
+ __raw_writew(val, base + addr);
+}
+
+static inline void sd_ctrl_write32(void __iomem *base, int addr, u32 val)
+{
+ __raw_writew(val, base + addr);
+ __raw_writew(val >> 16, base + addr + 2);
+}
+
+#define ALL_ERROR (TMIO_STAT_CMD_IDX_ERR | TMIO_STAT_CRCFAIL | \
+ TMIO_STAT_STOPBIT_ERR | TMIO_STAT_DATATIMEOUT | \
+ TMIO_STAT_RXOVERFLOW | TMIO_STAT_TXUNDERRUN | \
+ TMIO_STAT_CMDTIMEOUT | TMIO_STAT_ILL_ACCESS | \
+ TMIO_STAT_ILL_FUNC)
+
+static int sdhi_intr(void __iomem *base)
+{
+ unsigned long state = sd_ctrl_read32(base, CTL_STATUS);
+
+ if (state & ALL_ERROR) {
+ sd_ctrl_write32(base, CTL_STATUS, ~ALL_ERROR);
+ sd_ctrl_write32(base, CTL_IRQ_MASK,
+ ALL_ERROR |
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+ return -EINVAL;
+ }
+ if (state & TMIO_STAT_CMDRESPEND) {
+ sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND);
+ sd_ctrl_write32(base, CTL_IRQ_MASK,
+ TMIO_STAT_CMDRESPEND |
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+ return 0;
+ }
+ if (state & TMIO_STAT_RXRDY) {
+ sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_RXRDY);
+ sd_ctrl_write32(base, CTL_IRQ_MASK,
+ TMIO_STAT_RXRDY | TMIO_STAT_TXUNDERRUN |
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+ return 0;
+ }
+ if (state & TMIO_STAT_DATAEND) {
+ sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_DATAEND);
+ sd_ctrl_write32(base, CTL_IRQ_MASK,
+ TMIO_STAT_DATAEND |
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+ return 0;
+ }
+
+ return -EAGAIN;
+}
+
+static int sdhi_boot_wait_resp_end(void __iomem *base)
+{
+ int err = -EAGAIN, timeout = 10000000;
+
+ while (timeout--) {
+ err = sdhi_intr(base);
+ if (err != -EAGAIN)
+ break;
+ udelay(1);
+ }
+
+ return err;
+}
+
+/* SDHI_CLK_CTRL */
+#define CLK_MMC_ENABLE (1 << 8)
+#define CLK_MMC_INIT (1 << 6) /* clk / 256 */
+
+static void sdhi_boot_mmc_clk_stop(void __iomem *base)
+{
+ sd_ctrl_write16(base, CTL_CLK_AND_WAIT_CTL, 0x0000);
+ msleep(10);
+ sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL, ~CLK_MMC_ENABLE &
+ sd_ctrl_read16(base, CTL_SD_CARD_CLK_CTL));
+ msleep(10);
+}
+
+static void sdhi_boot_mmc_clk_start(void __iomem *base)
+{
+ sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL, CLK_MMC_ENABLE |
+ sd_ctrl_read16(base, CTL_SD_CARD_CLK_CTL));
+ msleep(10);
+ sd_ctrl_write16(base, CTL_CLK_AND_WAIT_CTL, CLK_MMC_ENABLE);
+ msleep(10);
+}
+
+static void sdhi_boot_reset(void __iomem *base)
+{
+ sd_ctrl_write16(base, CTL_RESET_SD, 0x0000);
+ msleep(10);
+ sd_ctrl_write16(base, CTL_RESET_SD, 0x0001);
+ msleep(10);
+}
+
+/* Set MMC clock / power.
+ * Note: This controller uses a simple divider scheme therefore it cannot
+ * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
+ * MMC wont run that fast, it has to be clocked at 12MHz which is the next
+ * slowest setting.
+ */
+static int sdhi_boot_mmc_set_ios(void __iomem *base, struct mmc_ios *ios)
+{
+ if (sd_ctrl_read32(base, CTL_STATUS) & TMIO_STAT_CMD_BUSY)
+ return -EBUSY;
+
+ if (ios->clock)
+ sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL,
+ ios->clock | CLK_MMC_ENABLE);
+
+ /* Power sequence - OFF -> ON -> UP */
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF: /* power down SD bus */
+ sdhi_boot_mmc_clk_stop(base);
+ break;
+ case MMC_POWER_ON: /* power up SD bus */
+ break;
+ case MMC_POWER_UP: /* start bus clock */
+ sdhi_boot_mmc_clk_start(base);
+ break;
+ }
+
+ switch (ios->bus_width) {
+ case MMC_BUS_WIDTH_1:
+ sd_ctrl_write16(base, CTL_SD_MEM_CARD_OPT, 0x80e0);
+ break;
+ case MMC_BUS_WIDTH_4:
+ sd_ctrl_write16(base, CTL_SD_MEM_CARD_OPT, 0x00e0);
+ break;
+ }
+
+ /* Let things settle. delay taken from winCE driver */
+ udelay(140);
+
+ return 0;
+}
+
+/* These are the bitmasks the tmio chip requires to implement the MMC response
+ * types. Note that R1 and R6 are the same in this scheme. */
+#define RESP_NONE 0x0300
+#define RESP_R1 0x0400
+#define RESP_R1B 0x0500
+#define RESP_R2 0x0600
+#define RESP_R3 0x0700
+#define DATA_PRESENT 0x0800
+#define TRANSFER_READ 0x1000
+
+static int sdhi_boot_request(void __iomem *base, struct mmc_command *cmd)
+{
+ int err, c = cmd->opcode;
+
+ switch (mmc_resp_type(cmd)) {
+ case MMC_RSP_NONE: c |= RESP_NONE; break;
+ case MMC_RSP_R1: c |= RESP_R1; break;
+ case MMC_RSP_R1B: c |= RESP_R1B; break;
+ case MMC_RSP_R2: c |= RESP_R2; break;
+ case MMC_RSP_R3: c |= RESP_R3; break;
+ default:
+ return -EINVAL;
+ }
+
+ /* No interrupts so this may not be cleared */
+ sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND);
+
+ sd_ctrl_write32(base, CTL_IRQ_MASK, TMIO_STAT_CMDRESPEND |
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+ sd_ctrl_write32(base, CTL_ARG_REG, cmd->arg);
+ sd_ctrl_write16(base, CTL_SD_CMD, c);
+
+
+ sd_ctrl_write32(base, CTL_IRQ_MASK,
+ ~(TMIO_STAT_CMDRESPEND | ALL_ERROR) &
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+
+ err = sdhi_boot_wait_resp_end(base);
+ if (err)
+ return err;
+
+ cmd->resp[0] = sd_ctrl_read32(base, CTL_RESPONSE);
+
+ return 0;
+}
+
+static int sdhi_boot_do_read_single(void __iomem *base, int high_capacity,
+ unsigned long block, unsigned short *buf)
+{
+ int err, i;
+
+ /* CMD17 - Read */
+ {
+ struct mmc_command cmd;
+
+ cmd.opcode = MMC_READ_SINGLE_BLOCK | \
+ TRANSFER_READ | DATA_PRESENT;
+ if (high_capacity)
+ cmd.arg = block;
+ else
+ cmd.arg = block * TMIO_BBS;
+ cmd.flags = MMC_RSP_R1;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ }
+
+ sd_ctrl_write32(base, CTL_IRQ_MASK,
+ ~(TMIO_STAT_DATAEND | TMIO_STAT_RXRDY |
+ TMIO_STAT_TXUNDERRUN) &
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+ err = sdhi_boot_wait_resp_end(base);
+ if (err)
+ return err;
+
+ sd_ctrl_write16(base, CTL_SD_XFER_LEN, TMIO_BBS);
+ for (i = 0; i < TMIO_BBS / sizeof(*buf); i++)
+ *buf++ = sd_ctrl_read16(base, RESP_CMD12);
+
+ err = sdhi_boot_wait_resp_end(base);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+int sdhi_boot_do_read(void __iomem *base, int high_capacity,
+ unsigned long offset, unsigned short count,
+ unsigned short *buf)
+{
+ unsigned long i;
+ int err = 0;
+
+ for (i = 0; i < count; i++) {
+ err = sdhi_boot_do_read_single(base, high_capacity, offset + i,
+ buf + (i * TMIO_BBS /
+ sizeof(*buf)));
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+#define VOLTAGES (MMC_VDD_32_33 | MMC_VDD_33_34)
+
+int sdhi_boot_init(void __iomem *base)
+{
+ bool sd_v2 = false, sd_v1_0 = false;
+ unsigned short cid;
+ int err, high_capacity = 0;
+
+ sdhi_boot_mmc_clk_stop(base);
+ sdhi_boot_reset(base);
+
+ /* mmc0: clock 400000Hz busmode 1 powermode 2 cs 0 Vdd 21 width 0 timing 0 */
+ {
+ struct mmc_ios ios;
+ ios.power_mode = MMC_POWER_ON;
+ ios.bus_width = MMC_BUS_WIDTH_1;
+ ios.clock = CLK_MMC_INIT;
+ err = sdhi_boot_mmc_set_ios(base, &ios);
+ if (err)
+ return err;
+ }
+
+ /* CMD0 */
+ {
+ struct mmc_command cmd;
+ msleep(1);
+ cmd.opcode = MMC_GO_IDLE_STATE;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_NONE;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ msleep(2);
+ }
+
+ /* CMD8 - Test for SD version 2 */
+ {
+ struct mmc_command cmd;
+ cmd.opcode = SD_SEND_IF_COND;
+ cmd.arg = (VOLTAGES != 0) << 8 | 0xaa;
+ cmd.flags = MMC_RSP_R1;
+ err = sdhi_boot_request(base, &cmd); /* Ignore error */
+ if ((cmd.resp[0] & 0xff) == 0xaa)
+ sd_v2 = true;
+ }
+
+ /* CMD55 - Get OCR (SD) */
+ {
+ int timeout = 1000;
+ struct mmc_command cmd;
+
+ cmd.arg = 0;
+
+ do {
+ cmd.opcode = MMC_APP_CMD;
+ cmd.flags = MMC_RSP_R1;
+ cmd.arg = 0;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ break;
+
+ cmd.opcode = SD_APP_OP_COND;
+ cmd.flags = MMC_RSP_R3;
+ cmd.arg = (VOLTAGES & 0xff8000);
+ if (sd_v2)
+ cmd.arg |= OCR_HCS;
+ cmd.arg |= OCR_FASTBOOT;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ break;
+
+ msleep(1);
+ } while((!(cmd.resp[0] & OCR_BUSY)) && --timeout);
+
+ if (!err && timeout) {
+ if (!sd_v2)
+ sd_v1_0 = true;
+ high_capacity = (cmd.resp[0] & OCR_HCS) == OCR_HCS;
+ }
+ }
+
+ /* CMD1 - Get OCR (MMC) */
+ if (!sd_v2 && !sd_v1_0) {
+ int timeout = 1000;
+ struct mmc_command cmd;
+
+ do {
+ cmd.opcode = MMC_SEND_OP_COND;
+ cmd.arg = VOLTAGES | OCR_HCS;
+ cmd.flags = MMC_RSP_R3;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+
+ msleep(1);
+ } while((!(cmd.resp[0] & OCR_BUSY)) && --timeout);
+
+ if (!timeout)
+ return -EAGAIN;
+
+ high_capacity = (cmd.resp[0] & OCR_HCS) == OCR_HCS;
+ }
+
+ /* CMD2 - Get CID */
+ {
+ struct mmc_command cmd;
+ cmd.opcode = MMC_ALL_SEND_CID;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R2;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ }
+
+ /* CMD3
+ * MMC: Set the relative address
+ * SD: Get the relative address
+ * Also puts the card into the standby state
+ */
+ {
+ struct mmc_command cmd;
+ cmd.opcode = MMC_SET_RELATIVE_ADDR;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R1;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ cid = cmd.resp[0] >> 16;
+ }
+
+ /* CMD9 - Get CSD */
+ {
+ struct mmc_command cmd;
+ cmd.opcode = MMC_SEND_CSD;
+ cmd.arg = cid << 16;
+ cmd.flags = MMC_RSP_R2;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ }
+
+ /* CMD7 - Select the card */
+ {
+ struct mmc_command cmd;
+ cmd.opcode = MMC_SELECT_CARD;
+ //cmd.arg = rca << 16;
+ cmd.arg = cid << 16;
+ //cmd.flags = MMC_RSP_R1B;
+ cmd.flags = MMC_RSP_R1;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ }
+
+ /* CMD16 - Set the block size */
+ {
+ struct mmc_command cmd;
+ cmd.opcode = MMC_SET_BLOCKLEN;
+ cmd.arg = TMIO_BBS;
+ cmd.flags = MMC_RSP_R1;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ }
+
+ return high_capacity;
+}
diff --git a/arch/arm/boot/compressed/sdhi-shmobile.h b/arch/arm/boot/compressed/sdhi-shmobile.h
new file mode 100644
index 0000000..92eaa09
--- /dev/null
+++ b/arch/arm/boot/compressed/sdhi-shmobile.h
@@ -0,0 +1,11 @@
+#ifndef SDHI_MOBILE_H
+#define SDHI_MOBILE_H
+
+#include <linux/compiler.h>
+
+int sdhi_boot_do_read(void __iomem *base, int high_capacity,
+ unsigned long offset, unsigned short count,
+ unsigned short *buf);
+int sdhi_boot_init(void __iomem *base);
+
+#endif
diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c
new file mode 100644
index 0000000..36e53ef
--- /dev/null
+++ b/arch/arm/boot/compressed/string.c
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/boot/compressed/string.c
+ *
+ * Small subset of simple string routines
+ */
+
+#include <linux/string.h>
+
+void *memcpy(void *__dest, __const void *__src, size_t __n)
+{
+ int i = 0;
+ unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
+
+ for (i = __n >> 3; i > 0; i--) {
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ }
+
+ if (__n & 1 << 2) {
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ }
+
+ if (__n & 1 << 1) {
+ *d++ = *s++;
+ *d++ = *s++;
+ }
+
+ if (__n & 1)
+ *d++ = *s++;
+
+ return __dest;
+}
+
+void *memmove(void *__dest, __const void *__src, size_t count)
+{
+ unsigned char *d = __dest;
+ const unsigned char *s = __src;
+
+ if (__dest == __src)
+ return __dest;
+
+ if (__dest < __src)
+ return memcpy(__dest, __src, count);
+
+ while (count--)
+ d[count] = s[count];
+ return __dest;
+}
+
+size_t strlen(const char *s)
+{
+ const char *sc = s;
+
+ while (*sc != '\0')
+ sc++;
+ return sc - s;
+}
+
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+ const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count;
+ int res = 0;
+
+ while (su1 < end) {
+ res = *su1++ - *su2++;
+ if (res)
+ break;
+ }
+ return res;
+}
+
+int strcmp(const char *cs, const char *ct)
+{
+ unsigned char c1, c2;
+ int res = 0;
+
+ do {
+ c1 = *cs++;
+ c2 = *ct++;
+ res = c1 - c2;
+ if (res)
+ break;
+ } while (c1);
+ return res;
+}
+
+void *memchr(const void *s, int c, size_t count)
+{
+ const unsigned char *p = s;
+
+ while (count--)
+ if ((unsigned char)c == *p++)
+ return (void *)(p - 1);
+ return NULL;
+}
+
+char *strchr(const char *s, int c)
+{
+ while (*s != (char)c)
+ if (*s++ == '\0')
+ return NULL;
+ return (char *)s;
+}
+
+#undef memset
+
+void *memset(void *s, int c, size_t count)
+{
+ char *xs = s;
+ while (count--)
+ *xs++ = c;
+ return s;
+}
+
+void __memzero(void *s, size_t count)
+{
+ memset(s, 0, count);
+}
diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi
new file mode 100644
index 0000000..aeef042
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g20.dtsi
@@ -0,0 +1,119 @@
+/*
+ * at91sam9g20.dtsi - Device Tree Include file for AT91SAM9G20 family SoC
+ *
+ * Copyright (C) 2011 Atmel,
+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
+ * 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9G20 family SoC";
+ compatible = "atmel,at91sam9g20";
+ interrupt-parent = <&aic>;
+
+ aliases {
+ serial0 = &dbgu;
+ serial1 = &usart0;
+ serial2 = &usart1;
+ serial3 = &usart2;
+ serial4 = &usart3;
+ serial5 = &usart4;
+ serial6 = &usart5;
+ };
+ cpus {
+ cpu@0 {
+ compatible = "arm,arm926ejs";
+ };
+ };
+
+ memory@20000000 {
+ reg = <0x20000000 0x08000000>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ aic: interrupt-controller@fffff000 {
+ #interrupt-cells = <1>;
+ compatible = "atmel,at91rm9200-aic";
+ interrupt-controller;
+ interrupt-parent;
+ reg = <0xfffff000 0x200>;
+ };
+
+ dbgu: serial@fffff200 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffff200 0x200>;
+ interrupts = <1>;
+ status = "disabled";
+ };
+
+ usart0: serial@fffb0000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffb0000 0x200>;
+ interrupts = <6>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart1: serial@fffb4000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffb4000 0x200>;
+ interrupts = <7>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart2: serial@fffb8000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffb8000 0x200>;
+ interrupts = <8>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart3: serial@fffd0000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffd0000 0x200>;
+ interrupts = <23>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart4: serial@fffd4000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffd4000 0x200>;
+ interrupts = <24>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart5: serial@fffd8000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffd8000 0x200>;
+ interrupts = <25>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
new file mode 100644
index 0000000..db6a452
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -0,0 +1,106 @@
+/*
+ * at91sam9g45.dtsi - Device Tree Include file for AT91SAM9G45 family SoC
+ * applies to AT91SAM9G45, AT91SAM9M10,
+ * AT91SAM9G46, AT91SAM9M11 SoC
+ *
+ * Copyright (C) 2011 Atmel,
+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9G45 family SoC";
+ compatible = "atmel,at91sam9g45";
+ interrupt-parent = <&aic>;
+
+ aliases {
+ serial0 = &dbgu;
+ serial1 = &usart0;
+ serial2 = &usart1;
+ serial3 = &usart2;
+ serial4 = &usart3;
+ };
+ cpus {
+ cpu@0 {
+ compatible = "arm,arm926ejs";
+ };
+ };
+
+ memory@70000000 {
+ reg = <0x70000000 0x10000000>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ aic: interrupt-controller@fffff000 {
+ #interrupt-cells = <1>;
+ compatible = "atmel,at91rm9200-aic";
+ interrupt-controller;
+ interrupt-parent;
+ reg = <0xfffff000 0x200>;
+ };
+
+ dma: dma-controller@ffffec00 {
+ compatible = "atmel,at91sam9g45-dma";
+ reg = <0xffffec00 0x200>;
+ interrupts = <21>;
+ };
+
+ dbgu: serial@ffffee00 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xffffee00 0x200>;
+ interrupts = <1>;
+ status = "disabled";
+ };
+
+ usart0: serial@fff8c000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff8c000 0x200>;
+ interrupts = <7>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart1: serial@fff90000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff90000 0x200>;
+ interrupts = <8>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart2: serial@fff94000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff94000 0x200>;
+ interrupts = <9>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart3: serial@fff98000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff98000 0x200>;
+ interrupts = <10>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
new file mode 100644
index 0000000..85b34f5
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
@@ -0,0 +1,35 @@
+/*
+ * at91sam9m10g45ek.dts - Device Tree file for AT91SAM9M10G45-EK board
+ *
+ * Copyright (C) 2011 Atmel,
+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g45.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9M10G45-EK";
+ compatible = "atmel,at91sam9m10g45ek", "atmel,at91sam9g45", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:4M(bootstrap/uboot/kernel)ro,60M(rootfs),-(data) root=/dev/mtdblock1 rw rootfstype=jffs2";
+ };
+
+ memory@70000000 {
+ reg = <0x70000000 0x4000000>;
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@ffffee00 {
+ status = "okay";
+ };
+
+ usart1: serial@fff90000 {
+ status = "okay";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts
new file mode 100644
index 0000000..aeb1a75
--- /dev/null
+++ b/arch/arm/boot/dts/highbank.dts
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+
+/* First 4KB has pen for secondary cores. */
+/memreserve/ 0x00000000 0x0001000;
+
+/ {
+ model = "Calxeda Highbank";
+ compatible = "calxeda,highbank";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu@1 {
+ compatible = "arm,cortex-a9";
+ reg = <1>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu@2 {
+ compatible = "arm,cortex-a9";
+ reg = <2>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu@3 {
+ compatible = "arm,cortex-a9";
+ reg = <3>;
+ next-level-cache = <&L2>;
+ };
+ };
+
+ memory {
+ name = "memory";
+ device_type = "memory";
+ reg = <0x00000000 0xff900000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyAMA0";
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&intc>;
+ ranges;
+
+ timer@fff10600 {
+ compatible = "arm,smp-twd";
+ reg = <0xfff10600 0x20>;
+ interrupts = <1 13 0xf04>;
+ };
+
+ watchdog@fff10620 {
+ compatible = "arm,cortex-a9-wdt";
+ reg = <0xfff10620 0x20>;
+ interrupts = <1 14 0xf04>;
+ };
+
+ intc: interrupt-controller@fff11000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #size-cells = <0>;
+ #address-cells = <1>;
+ interrupt-controller;
+ interrupt-parent;
+ reg = <0xfff11000 0x1000>,
+ <0xfff10100 0x100>;
+ };
+
+ L2: l2-cache {
+ compatible = "arm,pl310-cache";
+ reg = <0xfff12000 0x1000>;
+ interrupts = <0 70 4>;
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a9-pmu";
+ interrupts = <0 76 4 0 75 4 0 74 4 0 73 4>;
+ };
+
+ sata@ffe08000 {
+ compatible = "calxeda,hb-ahci";
+ reg = <0xffe08000 0x10000>;
+ interrupts = <0 83 4>;
+ };
+
+ sdhci@ffe0e000 {
+ compatible = "calxeda,hb-sdhci";
+ reg = <0xffe0e000 0x1000>;
+ interrupts = <0 90 4>;
+ };
+
+ ipc@fff20000 {
+ compatible = "arm,pl320", "arm,primecell";
+ reg = <0xfff20000 0x1000>;
+ interrupts = <0 7 4>;
+ };
+
+ gpioe: gpio@fff30000 {
+ #gpio-cells = <2>;
+ compatible = "arm,pl061", "arm,primecell";
+ gpio-controller;
+ reg = <0xfff30000 0x1000>;
+ interrupts = <0 14 4>;
+ };
+
+ gpiof: gpio@fff31000 {
+ #gpio-cells = <2>;
+ compatible = "arm,pl061", "arm,primecell";
+ gpio-controller;
+ reg = <0xfff31000 0x1000>;
+ interrupts = <0 15 4>;
+ };
+
+ gpiog: gpio@fff32000 {
+ #gpio-cells = <2>;
+ compatible = "arm,pl061", "arm,primecell";
+ gpio-controller;
+ reg = <0xfff32000 0x1000>;
+ interrupts = <0 16 4>;
+ };
+
+ gpioh: gpio@fff33000 {
+ #gpio-cells = <2>;
+ compatible = "arm,pl061", "arm,primecell";
+ gpio-controller;
+ reg = <0xfff33000 0x1000>;
+ interrupts = <0 17 4>;
+ };
+
+ timer {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0xfff34000 0x1000>;
+ interrupts = <0 18 4>;
+ };
+
+ rtc@fff35000 {
+ compatible = "arm,pl031", "arm,primecell";
+ reg = <0xfff35000 0x1000>;
+ interrupts = <0 19 4>;
+ };
+
+ serial@fff36000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xfff36000 0x1000>;
+ interrupts = <0 20 4>;
+ };
+
+ smic@fff3a000 {
+ compatible = "ipmi-smic";
+ device_type = "ipmi";
+ reg = <0xfff3a000 0x1000>;
+ interrupts = <0 24 4>;
+ reg-size = <4>;
+ reg-spacing = <4>;
+ };
+
+ sregs@fff3c000 {
+ compatible = "calxeda,hb-sregs";
+ reg = <0xfff3c000 0x1000>;
+ };
+
+ dma@fff3d000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0xfff3d000 0x1000>;
+ interrupts = <0 92 4>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
new file mode 100644
index 0000000..4790df2
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx51.dtsi"
+
+/ {
+ model = "Freescale i.MX51 Babbage Board";
+ compatible = "fsl,imx51-babbage", "fsl,imx51";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+ };
+
+ memory {
+ reg = <0x90000000 0x20000000>;
+ };
+
+ soc {
+ aips@70000000 { /* aips-1 */
+ spba@70000000 {
+ esdhc@70004000 { /* ESDHC1 */
+ fsl,cd-controller;
+ fsl,wp-controller;
+ status = "okay";
+ };
+
+ esdhc@70008000 { /* ESDHC2 */
+ cd-gpios = <&gpio0 6 0>; /* GPIO1_6 */
+ wp-gpios = <&gpio0 5 0>; /* GPIO1_5 */
+ status = "okay";
+ };
+
+ uart2: uart@7000c000 { /* UART3 */
+ fsl,uart-has-rtscts;
+ status = "okay";
+ };
+
+ ecspi@70010000 { /* ECSPI1 */
+ fsl,spi-num-chipselects = <2>;
+ cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */
+ <&gpio3 25 0>; /* GPIO4_25 */
+ status = "okay";
+
+ pmic: mc13892@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mc13892";
+ spi-max-frequency = <6000000>;
+ reg = <0>;
+ mc13xxx-irq-gpios = <&gpio0 8 0>; /* GPIO1_8 */
+ fsl,mc13xxx-uses-regulator;
+ };
+
+ flash: at45db321d@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+ spi-max-frequency = <25000000>;
+ reg = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0x0 0x40000>;
+ read-only;
+ };
+
+ partition@40000 {
+ label = "Kernel";
+ reg = <0x40000 0x3c0000>;
+ };
+ };
+ };
+ };
+
+ wdog@73f98000 { /* WDOG1 */
+ status = "okay";
+ };
+
+ iomuxc@73fa8000 {
+ compatible = "fsl,imx51-iomuxc-babbage";
+ reg = <0x73fa8000 0x4000>;
+ };
+
+ uart0: uart@73fbc000 {
+ fsl,uart-has-rtscts;
+ status = "okay";
+ };
+
+ uart1: uart@73fc0000 {
+ status = "okay";
+ };
+ };
+
+ aips@80000000 { /* aips-2 */
+ sdma@83fb0000 {
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
+ };
+
+ i2c@83fc4000 { /* I2C2 */
+ status = "okay";
+
+ codec: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ };
+ };
+
+ fec@83fec000 {
+ phy-mode = "mii";
+ status = "okay";
+ };
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ power {
+ label = "Power Button";
+ gpios = <&gpio1 21 0>;
+ linux,code = <116>; /* KEY_POWER */
+ gpio-key,wakeup;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
new file mode 100644
index 0000000..327ab8e
--- /dev/null
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ };
+
+ tzic: tz-interrupt-controller@e0000000 {
+ compatible = "fsl,imx51-tzic", "fsl,tzic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0xe0000000 0x4000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ckil {
+ compatible = "fsl,imx-ckil", "fixed-clock";
+ clock-frequency = <32768>;
+ };
+
+ ckih1 {
+ compatible = "fsl,imx-ckih1", "fixed-clock";
+ clock-frequency = <22579200>;
+ };
+
+ ckih2 {
+ compatible = "fsl,imx-ckih2", "fixed-clock";
+ clock-frequency = <0>;
+ };
+
+ osc {
+ compatible = "fsl,imx-osc", "fixed-clock";
+ clock-frequency = <24000000>;
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&tzic>;
+ ranges;
+
+ aips@70000000 { /* AIPS1 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x70000000 0x10000000>;
+ ranges;
+
+ spba@70000000 {
+ compatible = "fsl,spba-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x70000000 0x40000>;
+ ranges;
+
+ esdhc@70004000 { /* ESDHC1 */
+ compatible = "fsl,imx51-esdhc";
+ reg = <0x70004000 0x4000>;
+ interrupts = <1>;
+ status = "disabled";
+ };
+
+ esdhc@70008000 { /* ESDHC2 */
+ compatible = "fsl,imx51-esdhc";
+ reg = <0x70008000 0x4000>;
+ interrupts = <2>;
+ status = "disabled";
+ };
+
+ uart2: uart@7000c000 { /* UART3 */
+ compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+ reg = <0x7000c000 0x4000>;
+ interrupts = <33>;
+ status = "disabled";
+ };
+
+ ecspi@70010000 { /* ECSPI1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx51-ecspi";
+ reg = <0x70010000 0x4000>;
+ interrupts = <36>;
+ status = "disabled";
+ };
+
+ esdhc@70020000 { /* ESDHC3 */
+ compatible = "fsl,imx51-esdhc";
+ reg = <0x70020000 0x4000>;
+ interrupts = <3>;
+ status = "disabled";
+ };
+
+ esdhc@70024000 { /* ESDHC4 */
+ compatible = "fsl,imx51-esdhc";
+ reg = <0x70024000 0x4000>;
+ interrupts = <4>;
+ status = "disabled";
+ };
+ };
+
+ gpio0: gpio@73f84000 { /* GPIO1 */
+ compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+ reg = <0x73f84000 0x4000>;
+ interrupts = <50 51>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio1: gpio@73f88000 { /* GPIO2 */
+ compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+ reg = <0x73f88000 0x4000>;
+ interrupts = <52 53>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio2: gpio@73f8c000 { /* GPIO3 */
+ compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+ reg = <0x73f8c000 0x4000>;
+ interrupts = <54 55>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio3: gpio@73f90000 { /* GPIO4 */
+ compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+ reg = <0x73f90000 0x4000>;
+ interrupts = <56 57>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ wdog@73f98000 { /* WDOG1 */
+ compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+ reg = <0x73f98000 0x4000>;
+ interrupts = <58>;
+ status = "disabled";
+ };
+
+ wdog@73f9c000 { /* WDOG2 */
+ compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+ reg = <0x73f9c000 0x4000>;
+ interrupts = <59>;
+ status = "disabled";
+ };
+
+ uart0: uart@73fbc000 {
+ compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+ reg = <0x73fbc000 0x4000>;
+ interrupts = <31>;
+ status = "disabled";
+ };
+
+ uart1: uart@73fc0000 {
+ compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+ reg = <0x73fc0000 0x4000>;
+ interrupts = <32>;
+ status = "disabled";
+ };
+ };
+
+ aips@80000000 { /* AIPS2 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x80000000 0x10000000>;
+ ranges;
+
+ ecspi@83fac000 { /* ECSPI2 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx51-ecspi";
+ reg = <0x83fac000 0x4000>;
+ interrupts = <37>;
+ status = "disabled";
+ };
+
+ sdma@83fb0000 {
+ compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
+ reg = <0x83fb0000 0x4000>;
+ interrupts = <6>;
+ };
+
+ cspi@83fc0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx51-cspi", "fsl,imx35-cspi";
+ reg = <0x83fc0000 0x4000>;
+ interrupts = <38>;
+ status = "disabled";
+ };
+
+ i2c@83fc4000 { /* I2C2 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+ reg = <0x83fc4000 0x4000>;
+ interrupts = <63>;
+ status = "disabled";
+ };
+
+ i2c@83fc8000 { /* I2C1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+ reg = <0x83fc8000 0x4000>;
+ interrupts = <62>;
+ status = "disabled";
+ };
+
+ fec@83fec000 {
+ compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+ reg = <0x83fec000 0x4000>;
+ interrupts = <87>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts
new file mode 100644
index 0000000..2ab7f80
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-ard.dts
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+ model = "Freescale i.MX53 Automotive Reference Design Board";
+ compatible = "fsl,imx53-ard", "fsl,imx53";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+ };
+
+ memory {
+ reg = <0x70000000 0x40000000>;
+ };
+
+ soc {
+ aips@50000000 { /* AIPS1 */
+ spba@50000000 {
+ esdhc@50004000 { /* ESDHC1 */
+ cd-gpios = <&gpio0 1 0>; /* GPIO1_1 */
+ wp-gpios = <&gpio0 9 0>; /* GPIO1_9 */
+ status = "okay";
+ };
+ };
+
+ wdog@53f98000 { /* WDOG1 */
+ status = "okay";
+ };
+
+ iomuxc@53fa8000 {
+ compatible = "fsl,imx53-iomuxc-ard";
+ reg = <0x53fa8000 0x4000>;
+ };
+
+ uart0: uart@53fbc000 { /* UART1 */
+ status = "okay";
+ };
+ };
+
+ aips@60000000 { /* AIPS2 */
+ sdma@63fb0000 {
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+ };
+ };
+ };
+
+ eim-cs1@f4000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,eim-bus", "simple-bus";
+ reg = <0xf4000000 0x3ff0000>;
+ ranges;
+
+ lan9220@f4000000 {
+ compatible = "smsc,lan9220", "smsc,lan9115";
+ reg = <0xf4000000 0x2000000>;
+ phy-mode = "mii";
+ interrupt-parent = <&gpio1>;
+ interrupts = <31>;
+ reg-io-width = <4>;
+ smsc,irq-push-pull;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ home {
+ label = "Home";
+ gpios = <&gpio4 10 0>; /* GPIO5_10 */
+ linux,code = <102>; /* KEY_HOME */
+ gpio-key,wakeup;
+ };
+
+ back {
+ label = "Back";
+ gpios = <&gpio4 11 0>; /* GPIO5_11 */
+ linux,code = <158>; /* KEY_BACK */
+ gpio-key,wakeup;
+ };
+
+ program {
+ label = "Program";
+ gpios = <&gpio4 12 0>; /* GPIO5_12 */
+ linux,code = <362>; /* KEY_PROGRAM */
+ gpio-key,wakeup;
+ };
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio4 13 0>; /* GPIO5_13 */
+ linux,code = <115>; /* KEY_VOLUMEUP */
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio3 0 0>; /* GPIO4_0 */
+ linux,code = <114>; /* KEY_VOLUMEDOWN */
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx53-evk.dts b/arch/arm/boot/dts/imx53-evk.dts
new file mode 100644
index 0000000..3f3a881
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-evk.dts
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+ model = "Freescale i.MX53 Evaluation Kit";
+ compatible = "fsl,imx53-evk", "fsl,imx53";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+ };
+
+ memory {
+ reg = <0x70000000 0x80000000>;
+ };
+
+ soc {
+ aips@50000000 { /* AIPS1 */
+ spba@50000000 {
+ esdhc@50004000 { /* ESDHC1 */
+ cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+ wp-gpios = <&gpio2 14 0>; /* GPIO3_14 */
+ status = "okay";
+ };
+
+ ecspi@50010000 { /* ECSPI1 */
+ fsl,spi-num-chipselects = <2>;
+ cs-gpios = <&gpio1 30 0>, /* GPIO2_30 */
+ <&gpio2 19 0>; /* GPIO3_19 */
+ status = "okay";
+
+ flash: at45db321d@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+ spi-max-frequency = <25000000>;
+ reg = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0x0 0x40000>;
+ read-only;
+ };
+
+ partition@40000 {
+ label = "Kernel";
+ reg = <0x40000 0x3c0000>;
+ };
+ };
+ };
+
+ esdhc@50020000 { /* ESDHC3 */
+ cd-gpios = <&gpio2 11 0>; /* GPIO3_11 */
+ wp-gpios = <&gpio2 12 0>; /* GPIO3_12 */
+ status = "okay";
+ };
+ };
+
+ wdog@53f98000 { /* WDOG1 */
+ status = "okay";
+ };
+
+ iomuxc@53fa8000 {
+ compatible = "fsl,imx53-iomuxc-evk";
+ reg = <0x53fa8000 0x4000>;
+ };
+
+ uart0: uart@53fbc000 { /* UART1 */
+ status = "okay";
+ };
+ };
+
+ aips@60000000 { /* AIPS2 */
+ sdma@63fb0000 {
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+ };
+
+ i2c@63fc4000 { /* I2C2 */
+ status = "okay";
+
+ pmic: mc13892@08 {
+ compatible = "fsl,mc13892", "fsl,mc13xxx";
+ reg = <0x08>;
+ };
+
+ codec: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ };
+ };
+
+ fec@63fec000 {
+ phy-mode = "rmii";
+ phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+ status = "okay";
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ green {
+ label = "Heartbeat";
+ gpios = <&gpio6 7 0>; /* GPIO7_7 */
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
new file mode 100644
index 0000000..ae6de6d
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+ model = "Freescale i.MX53 Quick Start Board";
+ compatible = "fsl,imx53-qsb", "fsl,imx53";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+ };
+
+ memory {
+ reg = <0x70000000 0x40000000>;
+ };
+
+ soc {
+ aips@50000000 { /* AIPS1 */
+ spba@50000000 {
+ esdhc@50004000 { /* ESDHC1 */
+ cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+ status = "okay";
+ };
+
+ esdhc@50020000 { /* ESDHC3 */
+ cd-gpios = <&gpio2 11 0>; /* GPIO3_11 */
+ wp-gpios = <&gpio2 12 0>; /* GPIO3_12 */
+ status = "okay";
+ };
+ };
+
+ wdog@53f98000 { /* WDOG1 */
+ status = "okay";
+ };
+
+ iomuxc@53fa8000 {
+ compatible = "fsl,imx53-iomuxc-qsb";
+ reg = <0x53fa8000 0x4000>;
+ };
+
+ uart0: uart@53fbc000 { /* UART1 */
+ status = "okay";
+ };
+ };
+
+ aips@60000000 { /* AIPS2 */
+ sdma@63fb0000 {
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+ };
+
+ i2c@63fc4000 { /* I2C2 */
+ status = "okay";
+
+ codec: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ };
+ };
+
+ i2c@63fc8000 { /* I2C1 */
+ status = "okay";
+
+ accelerometer: mma8450@1c {
+ compatible = "fsl,mma8450";
+ reg = <0x1c>;
+ };
+
+ pmic: dialog@48 {
+ compatible = "dialog,da9053", "dialog,da9052";
+ reg = <0x48>;
+ };
+ };
+
+ fec@63fec000 {
+ phy-mode = "rmii";
+ phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+ status = "okay";
+ };
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ power {
+ label = "Power Button";
+ gpios = <&gpio0 8 0>; /* GPIO1_8 */
+ linux,code = <116>; /* KEY_POWER */
+ gpio-key,wakeup;
+ };
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio1 14 0>; /* GPIO2_14 */
+ linux,code = <115>; /* KEY_VOLUMEUP */
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio1 15 0>; /* GPIO2_15 */
+ linux,code = <114>; /* KEY_VOLUMEDOWN */
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ user {
+ label = "Heartbeat";
+ gpios = <&gpio6 7 0>; /* GPIO7_7 */
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx53-smd.dts b/arch/arm/boot/dts/imx53-smd.dts
new file mode 100644
index 0000000..b1c062e
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-smd.dts
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+ model = "Freescale i.MX53 Smart Mobile Reference Design Board";
+ compatible = "fsl,imx53-smd", "fsl,imx53";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+ };
+
+ memory {
+ reg = <0x70000000 0x40000000>;
+ };
+
+ soc {
+ aips@50000000 { /* AIPS1 */
+ spba@50000000 {
+ esdhc@50004000 { /* ESDHC1 */
+ cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+ wp-gpios = <&gpio3 11 0>; /* GPIO4_11 */
+ status = "okay";
+ };
+
+ esdhc@50008000 { /* ESDHC2 */
+ fsl,card-wired;
+ status = "okay";
+ };
+
+ uart2: uart@5000c000 { /* UART3 */
+ fsl,uart-has-rtscts;
+ status = "okay";
+ };
+
+ ecspi@50010000 { /* ECSPI1 */
+ fsl,spi-num-chipselects = <2>;
+ cs-gpios = <&gpio1 30 0>, /* GPIO2_30 */
+ <&gpio2 19 0>; /* GPIO3_19 */
+ status = "okay";
+
+ zigbee: mc1323@0 {
+ compatible = "fsl,mc1323";
+ spi-max-frequency = <8000000>;
+ reg = <0>;
+ };
+
+ flash: m25p32@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,m25p32", "st,m25p";
+ spi-max-frequency = <20000000>;
+ reg = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0x0 0x40000>;
+ read-only;
+ };
+
+ partition@40000 {
+ label = "Kernel";
+ reg = <0x40000 0x3c0000>;
+ };
+ };
+ };
+
+ esdhc@50020000 { /* ESDHC3 */
+ fsl,card-wired;
+ status = "okay";
+ };
+ };
+
+ wdog@53f98000 { /* WDOG1 */
+ status = "okay";
+ };
+
+ iomuxc@53fa8000 {
+ compatible = "fsl,imx53-iomuxc-smd";
+ reg = <0x53fa8000 0x4000>;
+ };
+
+ uart0: uart@53fbc000 { /* UART1 */
+ status = "okay";
+ };
+
+ uart1: uart@53fc0000 { /* UART2 */
+ status = "okay";
+ };
+ };
+
+ aips@60000000 { /* AIPS2 */
+ sdma@63fb0000 {
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+ };
+
+ i2c@63fc4000 { /* I2C2 */
+ status = "okay";
+
+ codec: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ };
+
+ magnetometer: mag3110@0e {
+ compatible = "fsl,mag3110";
+ reg = <0x0e>;
+ };
+
+ touchkey: mpr121@5a {
+ compatible = "fsl,mpr121";
+ reg = <0x5a>;
+ };
+ };
+
+ i2c@63fc8000 { /* I2C1 */
+ status = "okay";
+
+ accelerometer: mma8450@1c {
+ compatible = "fsl,mma8450";
+ reg = <0x1c>;
+ };
+
+ camera: ov5642@3c {
+ compatible = "ovti,ov5642";
+ reg = <0x3c>;
+ };
+
+ pmic: dialog@48 {
+ compatible = "dialog,da9053", "dialog,da9052";
+ reg = <0x48>;
+ };
+ };
+
+ fec@63fec000 {
+ phy-mode = "rmii";
+ phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+ status = "okay";
+ };
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio1 14 0>; /* GPIO2_14 */
+ linux,code = <115>; /* KEY_VOLUMEUP */
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio1 15 0>; /* GPIO2_15 */
+ linux,code = <114>; /* KEY_VOLUMEDOWN */
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
new file mode 100644
index 0000000..099cd84
--- /dev/null
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ };
+
+ tzic: tz-interrupt-controller@0fffc000 {
+ compatible = "fsl,imx53-tzic", "fsl,tzic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x0fffc000 0x4000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ckil {
+ compatible = "fsl,imx-ckil", "fixed-clock";
+ clock-frequency = <32768>;
+ };
+
+ ckih1 {
+ compatible = "fsl,imx-ckih1", "fixed-clock";
+ clock-frequency = <22579200>;
+ };
+
+ ckih2 {
+ compatible = "fsl,imx-ckih2", "fixed-clock";
+ clock-frequency = <0>;
+ };
+
+ osc {
+ compatible = "fsl,imx-osc", "fixed-clock";
+ clock-frequency = <24000000>;
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&tzic>;
+ ranges;
+
+ aips@50000000 { /* AIPS1 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x50000000 0x10000000>;
+ ranges;
+
+ spba@50000000 {
+ compatible = "fsl,spba-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x50000000 0x40000>;
+ ranges;
+
+ esdhc@50004000 { /* ESDHC1 */
+ compatible = "fsl,imx53-esdhc";
+ reg = <0x50004000 0x4000>;
+ interrupts = <1>;
+ status = "disabled";
+ };
+
+ esdhc@50008000 { /* ESDHC2 */
+ compatible = "fsl,imx53-esdhc";
+ reg = <0x50008000 0x4000>;
+ interrupts = <2>;
+ status = "disabled";
+ };
+
+ uart2: uart@5000c000 { /* UART3 */
+ compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+ reg = <0x5000c000 0x4000>;
+ interrupts = <33>;
+ status = "disabled";
+ };
+
+ ecspi@50010000 { /* ECSPI1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+ reg = <0x50010000 0x4000>;
+ interrupts = <36>;
+ status = "disabled";
+ };
+
+ esdhc@50020000 { /* ESDHC3 */
+ compatible = "fsl,imx53-esdhc";
+ reg = <0x50020000 0x4000>;
+ interrupts = <3>;
+ status = "disabled";
+ };
+
+ esdhc@50024000 { /* ESDHC4 */
+ compatible = "fsl,imx53-esdhc";
+ reg = <0x50024000 0x4000>;
+ interrupts = <4>;
+ status = "disabled";
+ };
+ };
+
+ gpio0: gpio@53f84000 { /* GPIO1 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53f84000 0x4000>;
+ interrupts = <50 51>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio1: gpio@53f88000 { /* GPIO2 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53f88000 0x4000>;
+ interrupts = <52 53>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio2: gpio@53f8c000 { /* GPIO3 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53f8c000 0x4000>;
+ interrupts = <54 55>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio3: gpio@53f90000 { /* GPIO4 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53f90000 0x4000>;
+ interrupts = <56 57>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ wdog@53f98000 { /* WDOG1 */
+ compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
+ reg = <0x53f98000 0x4000>;
+ interrupts = <58>;
+ status = "disabled";
+ };
+
+ wdog@53f9c000 { /* WDOG2 */
+ compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
+ reg = <0x53f9c000 0x4000>;
+ interrupts = <59>;
+ status = "disabled";
+ };
+
+ uart0: uart@53fbc000 { /* UART1 */
+ compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+ reg = <0x53fbc000 0x4000>;
+ interrupts = <31>;
+ status = "disabled";
+ };
+
+ uart1: uart@53fc0000 { /* UART2 */
+ compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+ reg = <0x53fc0000 0x4000>;
+ interrupts = <32>;
+ status = "disabled";
+ };
+
+ gpio4: gpio@53fdc000 { /* GPIO5 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53fdc000 0x4000>;
+ interrupts = <103 104>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio5: gpio@53fe0000 { /* GPIO6 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53fe0000 0x4000>;
+ interrupts = <105 106>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio6: gpio@53fe4000 { /* GPIO7 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53fe4000 0x4000>;
+ interrupts = <107 108>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ i2c@53fec000 { /* I2C3 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+ reg = <0x53fec000 0x4000>;
+ interrupts = <64>;
+ status = "disabled";
+ };
+
+ uart3: uart@53ff0000 { /* UART4 */
+ compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+ reg = <0x53ff0000 0x4000>;
+ interrupts = <13>;
+ status = "disabled";
+ };
+ };
+
+ aips@60000000 { /* AIPS2 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x60000000 0x10000000>;
+ ranges;
+
+ uart4: uart@63f90000 { /* UART5 */
+ compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+ reg = <0x63f90000 0x4000>;
+ interrupts = <86>;
+ status = "disabled";
+ };
+
+ ecspi@63fac000 { /* ECSPI2 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+ reg = <0x63fac000 0x4000>;
+ interrupts = <37>;
+ status = "disabled";
+ };
+
+ sdma@63fb0000 {
+ compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
+ reg = <0x63fb0000 0x4000>;
+ interrupts = <6>;
+ };
+
+ cspi@63fc0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx53-cspi", "fsl,imx35-cspi";
+ reg = <0x63fc0000 0x4000>;
+ interrupts = <38>;
+ status = "disabled";
+ };
+
+ i2c@63fc4000 { /* I2C2 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+ reg = <0x63fc4000 0x4000>;
+ interrupts = <63>;
+ status = "disabled";
+ };
+
+ i2c@63fc8000 { /* I2C1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+ reg = <0x63fc8000 0x4000>;
+ interrupts = <62>;
+ status = "disabled";
+ };
+
+ fec@63fec000 {
+ compatible = "fsl,imx53-fec", "fsl,imx25-fec";
+ reg = <0x63fec000 0x4000>;
+ interrupts = <87>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6q-sabreauto.dts b/arch/arm/boot/dts/imx6q-sabreauto.dts
new file mode 100644
index 0000000..072974e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto.dts
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx6q.dtsi"
+
+/ {
+ model = "Freescale i.MX6 Quad SABRE Automotive Board";
+ compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 root=/dev/mmcblk3p3 rootwait";
+ };
+
+ memory {
+ reg = <0x10000000 0x80000000>;
+ };
+
+ soc {
+ aips-bus@02100000 { /* AIPS2 */
+ enet@02188000 {
+ phy-mode = "rgmii";
+ local-mac-address = [00 04 9F 01 1B 61];
+ status = "okay";
+ };
+
+ usdhc@02198000 { /* uSDHC3 */
+ cd-gpios = <&gpio5 11 0>; /* GPIO6_11 */
+ wp-gpios = <&gpio5 14 0>; /* GPIO6_14 */
+ status = "okay";
+ };
+
+ usdhc@0219c000 { /* uSDHC4 */
+ fsl,card-wired;
+ status = "okay";
+ };
+
+ uart3: uart@021f0000 { /* UART4 */
+ status = "okay";
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ debug-led {
+ label = "Heartbeat";
+ gpios = <&gpio2 25 0>; /* GPIO3_25 */
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
new file mode 100644
index 0000000..7dda599
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -0,0 +1,575 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu@1 {
+ compatible = "arm,cortex-a9";
+ reg = <1>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu@2 {
+ compatible = "arm,cortex-a9";
+ reg = <2>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu@3 {
+ compatible = "arm,cortex-a9";
+ reg = <3>;
+ next-level-cache = <&L2>;
+ };
+ };
+
+ intc: interrupt-controller@00a01000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-controller;
+ reg = <0x00a01000 0x1000>,
+ <0x00a00100 0x100>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ckil {
+ compatible = "fsl,imx-ckil", "fixed-clock";
+ clock-frequency = <32768>;
+ };
+
+ ckih1 {
+ compatible = "fsl,imx-ckih1", "fixed-clock";
+ clock-frequency = <0>;
+ };
+
+ osc {
+ compatible = "fsl,imx-osc", "fixed-clock";
+ clock-frequency = <24000000>;
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&intc>;
+ ranges;
+
+ timer@00a00600 {
+ compatible = "arm,smp-twd";
+ reg = <0x00a00600 0x100>;
+ interrupts = <1 13 0xf4>;
+ };
+
+ L2: l2-cache@00a02000 {
+ compatible = "arm,pl310-cache";
+ reg = <0x00a02000 0x1000>;
+ interrupts = <0 92 0x04>;
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ aips-bus@02000000 { /* AIPS1 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02000000 0x100000>;
+ ranges;
+
+ spba-bus@02000000 {
+ compatible = "fsl,spba-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02000000 0x40000>;
+ ranges;
+
+ spdif@02004000 {
+ reg = <0x02004000 0x4000>;
+ interrupts = <0 52 0x04>;
+ };
+
+ ecspi@02008000 { /* eCSPI1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02008000 0x4000>;
+ interrupts = <0 31 0x04>;
+ status = "disabled";
+ };
+
+ ecspi@0200c000 { /* eCSPI2 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ reg = <0x0200c000 0x4000>;
+ interrupts = <0 32 0x04>;
+ status = "disabled";
+ };
+
+ ecspi@02010000 { /* eCSPI3 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02010000 0x4000>;
+ interrupts = <0 33 0x04>;
+ status = "disabled";
+ };
+
+ ecspi@02014000 { /* eCSPI4 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02014000 0x4000>;
+ interrupts = <0 34 0x04>;
+ status = "disabled";
+ };
+
+ ecspi@02018000 { /* eCSPI5 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02018000 0x4000>;
+ interrupts = <0 35 0x04>;
+ status = "disabled";
+ };
+
+ uart0: uart@02020000 { /* UART1 */
+ compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02020000 0x4000>;
+ interrupts = <0 26 0x04>;
+ status = "disabled";
+ };
+
+ esai@02024000 {
+ reg = <0x02024000 0x4000>;
+ interrupts = <0 51 0x04>;
+ };
+
+ ssi@02028000 { /* SSI1 */
+ reg = <0x02028000 0x4000>;
+ interrupts = <0 46 0x04>;
+ };
+
+ ssi@0202c000 { /* SSI2 */
+ reg = <0x0202c000 0x4000>;
+ interrupts = <0 47 0x04>;
+ };
+
+ ssi@02030000 { /* SSI3 */
+ reg = <0x02030000 0x4000>;
+ interrupts = <0 48 0x04>;
+ };
+
+ asrc@02034000 {
+ reg = <0x02034000 0x4000>;
+ interrupts = <0 50 0x04>;
+ };
+
+ spba@0203c000 {
+ reg = <0x0203c000 0x4000>;
+ };
+ };
+
+ vpu@02040000 {
+ reg = <0x02040000 0x3c000>;
+ interrupts = <0 3 0x04 0 12 0x04>;
+ };
+
+ aipstz@0207c000 { /* AIPSTZ1 */
+ reg = <0x0207c000 0x4000>;
+ };
+
+ pwm@02080000 { /* PWM1 */
+ reg = <0x02080000 0x4000>;
+ interrupts = <0 83 0x04>;
+ };
+
+ pwm@02084000 { /* PWM2 */
+ reg = <0x02084000 0x4000>;
+ interrupts = <0 84 0x04>;
+ };
+
+ pwm@02088000 { /* PWM3 */
+ reg = <0x02088000 0x4000>;
+ interrupts = <0 85 0x04>;
+ };
+
+ pwm@0208c000 { /* PWM4 */
+ reg = <0x0208c000 0x4000>;
+ interrupts = <0 86 0x04>;
+ };
+
+ flexcan@02090000 { /* CAN1 */
+ reg = <0x02090000 0x4000>;
+ interrupts = <0 110 0x04>;
+ };
+
+ flexcan@02094000 { /* CAN2 */
+ reg = <0x02094000 0x4000>;
+ interrupts = <0 111 0x04>;
+ };
+
+ gpt@02098000 {
+ compatible = "fsl,imx6q-gpt";
+ reg = <0x02098000 0x4000>;
+ interrupts = <0 55 0x04>;
+ };
+
+ gpio0: gpio@0209c000 { /* GPIO1 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x0209c000 0x4000>;
+ interrupts = <0 66 0x04 0 67 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio1: gpio@020a0000 { /* GPIO2 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x020a0000 0x4000>;
+ interrupts = <0 68 0x04 0 69 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio2: gpio@020a4000 { /* GPIO3 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x020a4000 0x4000>;
+ interrupts = <0 70 0x04 0 71 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio3: gpio@020a8000 { /* GPIO4 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x020a8000 0x4000>;
+ interrupts = <0 72 0x04 0 73 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio4: gpio@020ac000 { /* GPIO5 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x020ac000 0x4000>;
+ interrupts = <0 74 0x04 0 75 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio5: gpio@020b0000 { /* GPIO6 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x020b0000 0x4000>;
+ interrupts = <0 76 0x04 0 77 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio6: gpio@020b4000 { /* GPIO7 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x020b4000 0x4000>;
+ interrupts = <0 78 0x04 0 79 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ kpp@020b8000 {
+ reg = <0x020b8000 0x4000>;
+ interrupts = <0 82 0x04>;
+ };
+
+ wdog@020bc000 { /* WDOG1 */
+ compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
+ reg = <0x020bc000 0x4000>;
+ interrupts = <0 80 0x04>;
+ status = "disabled";
+ };
+
+ wdog@020c0000 { /* WDOG2 */
+ compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
+ reg = <0x020c0000 0x4000>;
+ interrupts = <0 81 0x04>;
+ status = "disabled";
+ };
+
+ ccm@020c4000 {
+ compatible = "fsl,imx6q-ccm";
+ reg = <0x020c4000 0x4000>;
+ interrupts = <0 87 0x04 0 88 0x04>;
+ };
+
+ anatop@020c8000 {
+ compatible = "fsl,imx6q-anatop";
+ reg = <0x020c8000 0x1000>;
+ interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
+ };
+
+ usbphy@020c9000 { /* USBPHY1 */
+ reg = <0x020c9000 0x1000>;
+ interrupts = <0 44 0x04>;
+ };
+
+ usbphy@020ca000 { /* USBPHY2 */
+ reg = <0x020ca000 0x1000>;
+ interrupts = <0 45 0x04>;
+ };
+
+ snvs@020cc000 {
+ reg = <0x020cc000 0x4000>;
+ interrupts = <0 19 0x04 0 20 0x04>;
+ };
+
+ epit@020d0000 { /* EPIT1 */
+ reg = <0x020d0000 0x4000>;
+ interrupts = <0 56 0x04>;
+ };
+
+ epit@020d4000 { /* EPIT2 */
+ reg = <0x020d4000 0x4000>;
+ interrupts = <0 57 0x04>;
+ };
+
+ src@020d8000 {
+ compatible = "fsl,imx6q-src";
+ reg = <0x020d8000 0x4000>;
+ interrupts = <0 91 0x04 0 96 0x04>;
+ };
+
+ gpc@020dc000 {
+ compatible = "fsl,imx6q-gpc";
+ reg = <0x020dc000 0x4000>;
+ interrupts = <0 89 0x04 0 90 0x04>;
+ };
+
+ iomuxc@020e0000 {
+ reg = <0x020e0000 0x4000>;
+ };
+
+ dcic@020e4000 { /* DCIC1 */
+ reg = <0x020e4000 0x4000>;
+ interrupts = <0 124 0x04>;
+ };
+
+ dcic@020e8000 { /* DCIC2 */
+ reg = <0x020e8000 0x4000>;
+ interrupts = <0 125 0x04>;
+ };
+
+ sdma@020ec000 {
+ compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
+ reg = <0x020ec000 0x4000>;
+ interrupts = <0 2 0x04>;
+ };
+ };
+
+ aips-bus@02100000 { /* AIPS2 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02100000 0x100000>;
+ ranges;
+
+ caam@02100000 {
+ reg = <0x02100000 0x40000>;
+ interrupts = <0 105 0x04 0 106 0x04>;
+ };
+
+ aipstz@0217c000 { /* AIPSTZ2 */
+ reg = <0x0217c000 0x4000>;
+ };
+
+ enet@02188000 {
+ compatible = "fsl,imx6q-fec";
+ reg = <0x02188000 0x4000>;
+ interrupts = <0 118 0x04 0 119 0x04>;
+ status = "disabled";
+ };
+
+ mlb@0218c000 {
+ reg = <0x0218c000 0x4000>;
+ interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
+ };
+
+ usdhc@02190000 { /* uSDHC1 */
+ compatible = "fsl,imx6q-usdhc";
+ reg = <0x02190000 0x4000>;
+ interrupts = <0 22 0x04>;
+ status = "disabled";
+ };
+
+ usdhc@02194000 { /* uSDHC2 */
+ compatible = "fsl,imx6q-usdhc";
+ reg = <0x02194000 0x4000>;
+ interrupts = <0 23 0x04>;
+ status = "disabled";
+ };
+
+ usdhc@02198000 { /* uSDHC3 */
+ compatible = "fsl,imx6q-usdhc";
+ reg = <0x02198000 0x4000>;
+ interrupts = <0 24 0x04>;
+ status = "disabled";
+ };
+
+ usdhc@0219c000 { /* uSDHC4 */
+ compatible = "fsl,imx6q-usdhc";
+ reg = <0x0219c000 0x4000>;
+ interrupts = <0 25 0x04>;
+ status = "disabled";
+ };
+
+ i2c@021a0000 { /* I2C1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+ reg = <0x021a0000 0x4000>;
+ interrupts = <0 36 0x04>;
+ status = "disabled";
+ };
+
+ i2c@021a4000 { /* I2C2 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+ reg = <0x021a4000 0x4000>;
+ interrupts = <0 37 0x04>;
+ status = "disabled";
+ };
+
+ i2c@021a8000 { /* I2C3 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+ reg = <0x021a8000 0x4000>;
+ interrupts = <0 38 0x04>;
+ status = "disabled";
+ };
+
+ romcp@021ac000 {
+ reg = <0x021ac000 0x4000>;
+ };
+
+ mmdc@021b0000 { /* MMDC0 */
+ compatible = "fsl,imx6q-mmdc";
+ reg = <0x021b0000 0x4000>;
+ };
+
+ mmdc@021b4000 { /* MMDC1 */
+ reg = <0x021b4000 0x4000>;
+ };
+
+ weim@021b8000 {
+ reg = <0x021b8000 0x4000>;
+ interrupts = <0 14 0x04>;
+ };
+
+ ocotp@021bc000 {
+ reg = <0x021bc000 0x4000>;
+ };
+
+ ocotp@021c0000 {
+ reg = <0x021c0000 0x4000>;
+ interrupts = <0 21 0x04>;
+ };
+
+ tzasc@021d0000 { /* TZASC1 */
+ reg = <0x021d0000 0x4000>;
+ interrupts = <0 108 0x04>;
+ };
+
+ tzasc@021d4000 { /* TZASC2 */
+ reg = <0x021d4000 0x4000>;
+ interrupts = <0 109 0x04>;
+ };
+
+ audmux@021d8000 {
+ reg = <0x021d8000 0x4000>;
+ };
+
+ mipi@021dc000 { /* MIPI-CSI */
+ reg = <0x021dc000 0x4000>;
+ };
+
+ mipi@021e0000 { /* MIPI-DSI */
+ reg = <0x021e0000 0x4000>;
+ };
+
+ vdoa@021e4000 {
+ reg = <0x021e4000 0x4000>;
+ interrupts = <0 18 0x04>;
+ };
+
+ uart1: uart@021e8000 { /* UART2 */
+ compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021e8000 0x4000>;
+ interrupts = <0 27 0x04>;
+ status = "disabled";
+ };
+
+ uart2: uart@021ec000 { /* UART3 */
+ compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021ec000 0x4000>;
+ interrupts = <0 28 0x04>;
+ status = "disabled";
+ };
+
+ uart3: uart@021f0000 { /* UART4 */
+ compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021f0000 0x4000>;
+ interrupts = <0 29 0x04>;
+ status = "disabled";
+ };
+
+ uart4: uart@021f4000 { /* UART5 */
+ compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021f4000 0x4000>;
+ interrupts = <0 30 0x04>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/msm8660-surf.dts
new file mode 100644
index 0000000..15ded0d
--- /dev/null
+++ b/arch/arm/boot/dts/msm8660-surf.dts
@@ -0,0 +1,24 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Qualcomm MSM8660 SURF";
+ compatible = "qcom,msm8660-surf", "qcom,msm8660";
+ interrupt-parent = <&intc>;
+
+ intc: interrupt-controller@02080000 {
+ compatible = "qcom,msm-8660-qgic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = < 0x02080000 0x1000 >,
+ < 0x02081000 0x1000 >;
+ };
+
+ serial@19c400000 {
+ compatible = "qcom,msm-hsuart", "qcom,msm-uart";
+ reg = <0x19c40000 0x1000>,
+ <0x19c00000 0x1000>;
+ interrupts = <195>;
+ };
+};
diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
new file mode 100644
index 0000000..9486be6
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-beagle.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap3.dtsi"
+
+/ {
+ model = "TI OMAP3 BeagleBoard";
+ compatible = "ti,omap3-beagle", "ti,omap3";
+
+ /*
+ * Since the initial device tree board file does not create any
+ * devices (MMC, network...), the only way to boot is to provide a
+ * ramdisk.
+ */
+ chosen {
+ bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug earlyprintk";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x20000000>; /* 512 MB */
+ };
+};
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
new file mode 100644
index 0000000..d202bb5
--- /dev/null
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -0,0 +1,63 @@
+/*
+ * Device Tree Source for OMAP3 SoC
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "ti,omap3430", "ti,omap3";
+
+ cpus {
+ cpu@0 {
+ compatible = "arm,cortex-a8";
+ };
+ };
+
+ /*
+ * The soc node represents the soc top level view. It is uses for IPs
+ * that are not memory mapped in the MPU view or for the MPU itself.
+ */
+ soc {
+ compatible = "ti,omap-infra";
+ mpu {
+ compatible = "ti,omap3-mpu";
+ ti,hwmods = "mpu";
+ };
+
+ iva {
+ compatible = "ti,iva2.2";
+ ti,hwmods = "iva";
+
+ dsp {
+ compatible = "ti,omap3-c64";
+ };
+ };
+ };
+
+ /*
+ * XXX: Use a flat representation of the OMAP3 interconnect.
+ * The real OMAP interconnect network is quite complex.
+ * Since that will not bring real advantage to represent that in DT for
+ * the moment, just use a fake OCP bus entry to represent the whole bus
+ * hierarchy.
+ */
+ ocp {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ ti,hwmods = "l3_main";
+
+ intc: interrupt-controller@1 {
+ compatible = "ti,omap3-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts
new file mode 100644
index 0000000..c702657
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-panda.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap4.dtsi"
+
+/ {
+ model = "TI OMAP4 PandaBoard";
+ compatible = "ti,omap4-panda", "ti,omap4430", "ti,omap4";
+
+ /*
+ * Since the initial device tree board file does not create any
+ * devices (MMC, network...), the only way to boot is to provide a
+ * ramdisk.
+ */
+ chosen {
+ bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x40000000>; /* 1 GB */
+ };
+};
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
new file mode 100644
index 0000000..066e28c
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap4.dtsi"
+
+/ {
+ model = "TI OMAP4 SDP board";
+ compatible = "ti,omap4-sdp", "ti,omap4430", "ti,omap4";
+
+ /*
+ * Since the initial device tree board file does not create any
+ * devices (MMC, network...), the only way to boot is to provide a
+ * ramdisk.
+ */
+ chosen {
+ bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x40000000>; /* 1 GB */
+ };
+};
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
new file mode 100644
index 0000000..4c61c82
--- /dev/null
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Carveout for multimedia usecases
+ * It should be the last 48MB of the first 512MB memory part
+ * In theory, it should not even exist. That zone should be reserved
+ * dynamically during the .reserve callback.
+ */
+/memreserve/ 0x9d000000 0x03000000;
+
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "ti,omap4430", "ti,omap4";
+ interrupt-parent = <&gic>;
+
+ aliases {
+ };
+
+ cpus {
+ cpu@0 {
+ compatible = "arm,cortex-a9";
+ };
+ cpu@1 {
+ compatible = "arm,cortex-a9";
+ };
+ };
+
+ /*
+ * The soc node represents the soc top level view. It is uses for IPs
+ * that are not memory mapped in the MPU view or for the MPU itself.
+ */
+ soc {
+ compatible = "ti,omap-infra";
+ mpu {
+ compatible = "ti,omap4-mpu";
+ ti,hwmods = "mpu";
+ };
+
+ dsp {
+ compatible = "ti,omap3-c64";
+ ti,hwmods = "dsp";
+ };
+
+ iva {
+ compatible = "ti,ivahd";
+ ti,hwmods = "iva";
+ };
+ };
+
+ /*
+ * XXX: Use a flat representation of the OMAP4 interconnect.
+ * The real OMAP interconnect network is quite complex.
+ *
+ * MPU -+-- MPU_PRIVATE - GIC, L2
+ * |
+ * +----------------+----------+
+ * | | |
+ * + +- EMIF - DDR |
+ * | | |
+ * | + +--------+
+ * | | |
+ * | +- L4_ABE - AESS, MCBSP, TIMERs...
+ * | |
+ * +- L3_MAIN --+- L4_CORE - IPs...
+ * |
+ * +- L4_PER - IPs...
+ * |
+ * +- L4_CFG -+- L4_WKUP - IPs...
+ * | |
+ * | +- IPs...
+ * +- IPU ----+
+ * | |
+ * +- DSP ----+
+ * | |
+ * +- DSS ----+
+ *
+ * Since that will not bring real advantage to represent that in DT for
+ * the moment, just use a fake OCP bus entry to represent the whole bus
+ * hierarchy.
+ */
+ ocp {
+ compatible = "ti,omap4-l3-noc", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
+
+ gic: interrupt-controller@48241000 {
+ compatible = "arm,cortex-a9-gic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x48241000 0x1000>,
+ <0x48240100 0x0100>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/picoxcell-pc3x2.dtsi b/arch/arm/boot/dts/picoxcell-pc3x2.dtsi
new file mode 100644
index 0000000..f0a8c20
--- /dev/null
+++ b/arch/arm/boot/dts/picoxcell-pc3x2.dtsi
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+/include/ "skeleton.dtsi"
+/ {
+ model = "Picochip picoXcell PC3X2";
+ compatible = "picochip,pc3x2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,1176jz-s";
+ clock-frequency = <400000000>;
+ reg = <0>;
+ d-cache-line-size = <32>;
+ d-cache-size = <32768>;
+ i-cache-line-size = <32>;
+ i-cache-size = <32768>;
+ };
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pclk: clock@0 {
+ compatible = "fixed-clock";
+ clock-outputs = "bus", "pclk";
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+ };
+
+ paxi {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x80000000 0x400000>;
+
+ emac: gem@30000 {
+ compatible = "cadence,gem";
+ reg = <0x30000 0x10000>;
+ interrupts = <31>;
+ };
+
+ dmac1: dmac@40000 {
+ compatible = "snps,dw-dmac";
+ reg = <0x40000 0x10000>;
+ interrupts = <25>;
+ };
+
+ dmac2: dmac@50000 {
+ compatible = "snps,dw-dmac";
+ reg = <0x50000 0x10000>;
+ interrupts = <26>;
+ };
+
+ vic0: interrupt-controller@60000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0x60000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ vic1: interrupt-controller@64000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0x64000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ fuse: picoxcell-fuse@80000 {
+ compatible = "picoxcell,fuse-pc3x2";
+ reg = <0x80000 0x10000>;
+ };
+
+ ssi: picoxcell-spi@90000 {
+ compatible = "picoxcell,spi";
+ reg = <0x90000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <10>;
+ };
+
+ ipsec: spacc@100000 {
+ compatible = "picochip,spacc-ipsec";
+ reg = <0x100000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <24>;
+ ref-clock = <&pclk>, "ref";
+ };
+
+ srtp: spacc@140000 {
+ compatible = "picochip,spacc-srtp";
+ reg = <0x140000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <23>;
+ };
+
+ l2_engine: spacc@180000 {
+ compatible = "picochip,spacc-l2";
+ reg = <0x180000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <22>;
+ ref-clock = <&pclk>, "ref";
+ };
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x200000 0x80000>;
+
+ rtc0: rtc@00000 {
+ compatible = "picochip,pc3x2-rtc";
+ clock-freq = <200000000>;
+ reg = <0x00000 0xf>;
+ interrupt-parent = <&vic1>;
+ interrupts = <8>;
+ };
+
+ timer0: timer@10000 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <4>;
+ clock-freq = <200000000>;
+ reg = <0x10000 0x14>;
+ };
+
+ timer1: timer@10014 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <5>;
+ clock-freq = <200000000>;
+ reg = <0x10014 0x14>;
+ };
+
+ timer2: timer@10028 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <6>;
+ clock-freq = <200000000>;
+ reg = <0x10028 0x14>;
+ };
+
+ timer3: timer@1003c {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <7>;
+ clock-freq = <200000000>;
+ reg = <0x1003c 0x14>;
+ };
+
+ gpio: gpio@20000 {
+ compatible = "snps,dw-apb-gpio";
+ reg = <0x20000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-io-width = <4>;
+
+ banka: gpio-controller@0 {
+ compatible = "snps,dw-apb-gpio-bank";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-generic,nr-gpio = <8>;
+
+ regoffset-dat = <0x50>;
+ regoffset-set = <0x00>;
+ regoffset-dirout = <0x04>;
+ };
+
+ bankb: gpio-controller@1 {
+ compatible = "snps,dw-apb-gpio-bank";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-generic,nr-gpio = <8>;
+
+ regoffset-dat = <0x54>;
+ regoffset-set = <0x0c>;
+ regoffset-dirout = <0x10>;
+ };
+ };
+
+ uart0: uart@30000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x30000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <10>;
+ clock-frequency = <3686400>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
+
+ uart1: uart@40000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x40000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <9>;
+ clock-frequency = <3686400>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
+
+ wdog: watchdog@50000 {
+ compatible = "snps,dw-apb-wdg";
+ reg = <0x50000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <11>;
+ bus-clock = <&pclk>, "bus";
+ };
+ };
+ };
+
+ rwid-axi {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ ebi@50000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <0 0 0x40000000 0x08000000
+ 1 0 0x48000000 0x08000000
+ 2 0 0x50000000 0x08000000
+ 3 0 0x58000000 0x08000000>;
+ };
+
+ axi2pico@c0000000 {
+ compatible = "picochip,axi2pico-pc3x2";
+ reg = <0xc0000000 0x10000>;
+ interrupts = <13 14 15 16 17 18 19 20 21>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/picoxcell-pc3x3.dtsi b/arch/arm/boot/dts/picoxcell-pc3x3.dtsi
new file mode 100644
index 0000000..daa962d
--- /dev/null
+++ b/arch/arm/boot/dts/picoxcell-pc3x3.dtsi
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+/include/ "skeleton.dtsi"
+/ {
+ model = "Picochip picoXcell PC3X3";
+ compatible = "picochip,pc3x3";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,1176jz-s";
+ cpu-clock = <&arm_clk>, "cpu";
+ reg = <0>;
+ d-cache-line-size = <32>;
+ d-cache-size = <32768>;
+ i-cache-line-size = <32>;
+ i-cache-size = <32768>;
+ };
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ clkgate: clkgate@800a0048 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x800a0048 4>;
+ compatible = "picochip,pc3x3-clk-gate";
+
+ tzprot_clk: clock@0 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <0>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ spi_clk: clock@1 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <1>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ dmac0_clk: clock@2 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <2>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ dmac1_clk: clock@3 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <3>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ ebi_clk: clock@4 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <4>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ ipsec_clk: clock@5 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <5>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ l2_clk: clock@6 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <6>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ trng_clk: clock@7 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <7>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ fuse_clk: clock@8 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <8>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ otp_clk: clock@9 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <9>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+ };
+
+ arm_clk: clock@11 {
+ compatible = "picochip,pc3x3-pll";
+ reg = <0x800a0050 0x8>;
+ picochip,min-freq = <140000000>;
+ picochip,max-freq = <700000000>;
+ ref-clock = <&ref_clk>, "ref";
+ clock-outputs = "cpu";
+ };
+
+ pclk: clock@12 {
+ compatible = "fixed-clock";
+ clock-outputs = "bus", "pclk";
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+ };
+
+ paxi {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x80000000 0x400000>;
+
+ emac: gem@30000 {
+ compatible = "cadence,gem";
+ reg = <0x30000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <31>;
+ };
+
+ dmac1: dmac@40000 {
+ compatible = "snps,dw-dmac";
+ reg = <0x40000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <25>;
+ };
+
+ dmac2: dmac@50000 {
+ compatible = "snps,dw-dmac";
+ reg = <0x50000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <26>;
+ };
+
+ vic0: interrupt-controller@60000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0x60000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ vic1: interrupt-controller@64000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0x64000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ fuse: picoxcell-fuse@80000 {
+ compatible = "picoxcell,fuse-pc3x3";
+ reg = <0x80000 0x10000>;
+ };
+
+ ssi: picoxcell-spi@90000 {
+ compatible = "picoxcell,spi";
+ reg = <0x90000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <10>;
+ };
+
+ ipsec: spacc@100000 {
+ compatible = "picochip,spacc-ipsec";
+ reg = <0x100000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <24>;
+ ref-clock = <&ipsec_clk>, "ref";
+ };
+
+ srtp: spacc@140000 {
+ compatible = "picochip,spacc-srtp";
+ reg = <0x140000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <23>;
+ };
+
+ l2_engine: spacc@180000 {
+ compatible = "picochip,spacc-l2";
+ reg = <0x180000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <22>;
+ ref-clock = <&l2_clk>, "ref";
+ };
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x200000 0x80000>;
+
+ rtc0: rtc@00000 {
+ compatible = "picochip,pc3x2-rtc";
+ clock-freq = <200000000>;
+ reg = <0x00000 0xf>;
+ interrupt-parent = <&vic0>;
+ interrupts = <8>;
+ };
+
+ timer0: timer@10000 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <4>;
+ clock-freq = <200000000>;
+ reg = <0x10000 0x14>;
+ };
+
+ timer1: timer@10014 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <5>;
+ clock-freq = <200000000>;
+ reg = <0x10014 0x14>;
+ };
+
+ gpio: gpio@20000 {
+ compatible = "snps,dw-apb-gpio";
+ reg = <0x20000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-io-width = <4>;
+
+ banka: gpio-controller@0 {
+ compatible = "snps,dw-apb-gpio-bank";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-generic,nr-gpio = <8>;
+
+ regoffset-dat = <0x50>;
+ regoffset-set = <0x00>;
+ regoffset-dirout = <0x04>;
+ };
+
+ bankb: gpio-controller@1 {
+ compatible = "snps,dw-apb-gpio-bank";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-generic,nr-gpio = <16>;
+
+ regoffset-dat = <0x54>;
+ regoffset-set = <0x0c>;
+ regoffset-dirout = <0x10>;
+ };
+
+ bankd: gpio-controller@2 {
+ compatible = "snps,dw-apb-gpio-bank";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-generic,nr-gpio = <30>;
+
+ regoffset-dat = <0x5c>;
+ regoffset-set = <0x24>;
+ regoffset-dirout = <0x28>;
+ };
+ };
+
+ uart0: uart@30000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x30000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <10>;
+ clock-frequency = <3686400>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
+
+ uart1: uart@40000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x40000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <9>;
+ clock-frequency = <3686400>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
+
+ wdog: watchdog@50000 {
+ compatible = "snps,dw-apb-wdg";
+ reg = <0x50000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <11>;
+ bus-clock = <&pclk>, "bus";
+ };
+
+ timer2: timer@60000 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <6>;
+ clock-freq = <200000000>;
+ reg = <0x60000 0x14>;
+ };
+
+ timer3: timer@60014 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <7>;
+ clock-freq = <200000000>;
+ reg = <0x60014 0x14>;
+ };
+ };
+ };
+
+ rwid-axi {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ ebi@50000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <0 0 0x40000000 0x08000000
+ 1 0 0x48000000 0x08000000
+ 2 0 0x50000000 0x08000000
+ 3 0 0x58000000 0x08000000>;
+ };
+
+ axi2pico@c0000000 {
+ compatible = "picochip,axi2pico-pc3x3";
+ reg = <0xc0000000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <13 14 15 16 17 18 19 20 21>;
+ };
+
+ otp@ffff8000 {
+ compatible = "picochip,otp-pc3x3";
+ reg = <0xffff8000 0x8000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts b/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts
new file mode 100644
index 0000000..1297414
--- /dev/null
+++ b/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/include/ "picoxcell-pc3x2.dtsi"
+/ {
+ model = "Picochip PC7302 (PC3X2)";
+ compatible = "picochip,pc7302-pc3x2", "picochip,pc3x2";
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x08000000>;
+ };
+
+ chosen {
+ linux,stdout-path = &uart0;
+ };
+
+ clocks {
+ ref_clk: clock@1 {
+ compatible = "fixed-clock";
+ clock-outputs = "ref";
+ clock-frequency = <20000000>;
+ };
+ };
+
+ rwid-axi {
+ ebi@50000000 {
+ nand: gpio-nand@2,0 {
+ compatible = "gpio-control-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <2 0x0000 0x1000>;
+ bus-clock = <&pclk>, "bus";
+ gpio-control-nand,io-sync-reg =
+ <0x00000000 0x80220000>;
+
+ gpios = <&banka 1 0 /* rdy */
+ &banka 2 0 /* nce */
+ &banka 3 0 /* ale */
+ &banka 4 0 /* cle */
+ 0 /* nwp */>;
+
+ boot@100000 {
+ label = "Boot";
+ reg = <0x100000 0x80000>;
+ };
+
+ redundant-boot@200000 {
+ label = "Redundant Boot";
+ reg = <0x200000 0x80000>;
+ };
+
+ boot-env@300000 {
+ label = "Boot Evironment";
+ reg = <0x300000 0x20000>;
+ };
+
+ redundant-boot-env@320000 {
+ label = "Redundant Boot Environment";
+ reg = <0x300000 0x20000>;
+ };
+
+ kernel@380000 {
+ label = "Kernel";
+ reg = <0x380000 0x800000>;
+ };
+
+ fs@b80000 {
+ label = "File System";
+ reg = <0xb80000 0xf480000>;
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts b/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts
new file mode 100644
index 0000000..9e317a4
--- /dev/null
+++ b/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/include/ "picoxcell-pc3x3.dtsi"
+/ {
+ model = "Picochip PC7302 (PC3X3)";
+ compatible = "picochip,pc7302-pc3x3", "picochip,pc3x3";
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x08000000>;
+ };
+
+ chosen {
+ linux,stdout-path = &uart0;
+ };
+
+ clocks {
+ ref_clk: clock@10 {
+ compatible = "fixed-clock";
+ clock-outputs = "ref";
+ clock-frequency = <20000000>;
+ };
+
+ clkgate: clkgate@800a0048 {
+ clock@4 {
+ picochip,clk-no-disable;
+ };
+ };
+ };
+
+ rwid-axi {
+ ebi@50000000 {
+ nand: gpio-nand@2,0 {
+ compatible = "gpio-control-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <2 0x0000 0x1000>;
+ bus-clock = <&ebi_clk>, "bus";
+ gpio-control-nand,io-sync-reg =
+ <0x00000000 0x80220000>;
+
+ gpios = <&banka 1 0 /* rdy */
+ &banka 2 0 /* nce */
+ &banka 3 0 /* ale */
+ &banka 4 0 /* cle */
+ 0 /* nwp */>;
+
+ boot@100000 {
+ label = "Boot";
+ reg = <0x100000 0x80000>;
+ };
+
+ redundant-boot@200000 {
+ label = "Redundant Boot";
+ reg = <0x200000 0x80000>;
+ };
+
+ boot-env@300000 {
+ label = "Boot Evironment";
+ reg = <0x300000 0x20000>;
+ };
+
+ redundant-boot-env@320000 {
+ label = "Redundant Boot Environment";
+ reg = <0x300000 0x20000>;
+ };
+
+ kernel@380000 {
+ label = "Kernel";
+ reg = <0x380000 0x800000>;
+ };
+
+ fs@b80000 {
+ label = "File System";
+ reg = <0xb80000 0xf480000>;
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/prima2-cb.dts b/arch/arm/boot/dts/prima2-cb.dts
new file mode 100644
index 0000000..34ae3a6
--- /dev/null
+++ b/arch/arm/boot/dts/prima2-cb.dts
@@ -0,0 +1,424 @@
+/dts-v1/;
+/ {
+ model = "SiRF Prima2 eVB";
+ compatible = "sirf,prima2-cb", "sirf,prima2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+
+ memory {
+ reg = <0x00000000 0x20000000>;
+ };
+
+ chosen {
+ bootargs = "mem=512M real_root=/dev/mmcblk0p2 console=ttyS0 panel=1 bootsplash=true bpp=16 androidboot.console=ttyS1";
+ linux,stdout-path = &uart1;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ reg = <0x0>;
+ d-cache-line-size = <32>;
+ i-cache-line-size = <32>;
+ d-cache-size = <32768>;
+ i-cache-size = <32768>;
+ /* from bootloader */
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+ };
+ };
+
+ axi {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x40000000 0x40000000 0x80000000>;
+
+ l2-cache-controller@80040000 {
+ compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache";
+ reg = <0x80040000 0x1000>;
+ interrupts = <59>;
+ arm,tag-latency = <1 1 1>;
+ arm,data-latency = <1 1 1>;
+ arm,filter-ranges = <0 0x40000000>;
+ };
+
+ intc: interrupt-controller@80020000 {
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "sirf,prima2-intc";
+ reg = <0x80020000 0x1000>;
+ };
+
+ sys-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x88000000 0x88000000 0x40000>;
+
+ clock-controller@88000000 {
+ compatible = "sirf,prima2-clkc";
+ reg = <0x88000000 0x1000>;
+ interrupts = <3>;
+ };
+
+ reset-controller@88010000 {
+ compatible = "sirf,prima2-rstc";
+ reg = <0x88010000 0x1000>;
+ };
+
+ rsc-controller@88020000 {
+ compatible = "sirf,prima2-rsc";
+ reg = <0x88020000 0x1000>;
+ };
+ };
+
+ mem-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x90000000 0x90000000 0x10000>;
+
+ memory-controller@90000000 {
+ compatible = "sirf,prima2-memc";
+ reg = <0x90000000 0x10000>;
+ interrupts = <27>;
+ };
+ };
+
+ disp-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x90010000 0x90010000 0x30000>;
+
+ display@90010000 {
+ compatible = "sirf,prima2-lcd";
+ reg = <0x90010000 0x20000>;
+ interrupts = <30>;
+ };
+
+ vpp@90020000 {
+ compatible = "sirf,prima2-vpp";
+ reg = <0x90020000 0x10000>;
+ interrupts = <31>;
+ };
+ };
+
+ graphics-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x98000000 0x98000000 0x8000000>;
+
+ graphics@98000000 {
+ compatible = "powervr,sgx531";
+ reg = <0x98000000 0x8000000>;
+ interrupts = <6>;
+ };
+ };
+
+ multimedia-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0xa0000000 0xa0000000 0x8000000>;
+
+ multimedia@a0000000 {
+ compatible = "sirf,prima2-video-codec";
+ reg = <0xa0000000 0x8000000>;
+ interrupts = <5>;
+ };
+ };
+
+ dsp-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0xa8000000 0xa8000000 0x2000000>;
+
+ dspif@a8000000 {
+ compatible = "sirf,prima2-dspif";
+ reg = <0xa8000000 0x10000>;
+ interrupts = <9>;
+ };
+
+ gps@a8010000 {
+ compatible = "sirf,prima2-gps";
+ reg = <0xa8010000 0x10000>;
+ interrupts = <7>;
+ };
+
+ dsp@a9000000 {
+ compatible = "sirf,prima2-dsp";
+ reg = <0xa9000000 0x1000000>;
+ interrupts = <8>;
+ };
+ };
+
+ peri-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0xb0000000 0xb0000000 0x180000>;
+
+ timer@b0020000 {
+ compatible = "sirf,prima2-tick";
+ reg = <0xb0020000 0x1000>;
+ interrupts = <0>;
+ };
+
+ nand@b0030000 {
+ compatible = "sirf,prima2-nand";
+ reg = <0xb0030000 0x10000>;
+ interrupts = <41>;
+ };
+
+ audio@b0040000 {
+ compatible = "sirf,prima2-audio";
+ reg = <0xb0040000 0x10000>;
+ interrupts = <35>;
+ };
+
+ uart0: uart@b0050000 {
+ cell-index = <0>;
+ compatible = "sirf,prima2-uart";
+ reg = <0xb0050000 0x10000>;
+ interrupts = <17>;
+ };
+
+ uart1: uart@b0060000 {
+ cell-index = <1>;
+ compatible = "sirf,prima2-uart";
+ reg = <0xb0060000 0x10000>;
+ interrupts = <18>;
+ };
+
+ uart2: uart@b0070000 {
+ cell-index = <2>;
+ compatible = "sirf,prima2-uart";
+ reg = <0xb0070000 0x10000>;
+ interrupts = <19>;
+ };
+
+ usp0: usp@b0080000 {
+ cell-index = <0>;
+ compatible = "sirf,prima2-usp";
+ reg = <0xb0080000 0x10000>;
+ interrupts = <20>;
+ };
+
+ usp1: usp@b0090000 {
+ cell-index = <1>;
+ compatible = "sirf,prima2-usp";
+ reg = <0xb0090000 0x10000>;
+ interrupts = <21>;
+ };
+
+ usp2: usp@b00a0000 {
+ cell-index = <2>;
+ compatible = "sirf,prima2-usp";
+ reg = <0xb00a0000 0x10000>;
+ interrupts = <22>;
+ };
+
+ dmac0: dma-controller@b00b0000 {
+ cell-index = <0>;
+ compatible = "sirf,prima2-dmac";
+ reg = <0xb00b0000 0x10000>;
+ interrupts = <12>;
+ };
+
+ dmac1: dma-controller@b0160000 {
+ cell-index = <1>;
+ compatible = "sirf,prima2-dmac";
+ reg = <0xb0160000 0x10000>;
+ interrupts = <13>;
+ };
+
+ vip@b00C0000 {
+ compatible = "sirf,prima2-vip";
+ reg = <0xb00C0000 0x10000>;
+ };
+
+ spi0: spi@b00d0000 {
+ cell-index = <0>;
+ compatible = "sirf,prima2-spi";
+ reg = <0xb00d0000 0x10000>;
+ interrupts = <15>;
+ };
+
+ spi1: spi@b0170000 {
+ cell-index = <1>;
+ compatible = "sirf,prima2-spi";
+ reg = <0xb0170000 0x10000>;
+ interrupts = <16>;
+ };
+
+ i2c0: i2c@b00e0000 {
+ cell-index = <0>;
+ compatible = "sirf,prima2-i2c";
+ reg = <0xb00e0000 0x10000>;
+ interrupts = <24>;
+ };
+
+ i2c1: i2c@b00f0000 {
+ cell-index = <1>;
+ compatible = "sirf,prima2-i2c";
+ reg = <0xb00f0000 0x10000>;
+ interrupts = <25>;
+ };
+
+ tsc@b0110000 {
+ compatible = "sirf,prima2-tsc";
+ reg = <0xb0110000 0x10000>;
+ interrupts = <33>;
+ };
+
+ gpio: gpio-controller@b0120000 {
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ compatible = "sirf,prima2-gpio-pinmux";
+ reg = <0xb0120000 0x10000>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ pwm@b0130000 {
+ compatible = "sirf,prima2-pwm";
+ reg = <0xb0130000 0x10000>;
+ };
+
+ efusesys@b0140000 {
+ compatible = "sirf,prima2-efuse";
+ reg = <0xb0140000 0x10000>;
+ };
+
+ pulsec@b0150000 {
+ compatible = "sirf,prima2-pulsec";
+ reg = <0xb0150000 0x10000>;
+ interrupts = <48>;
+ };
+
+ pci-iobg {
+ compatible = "sirf,prima2-pciiobg", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x56000000 0x56000000 0x1b00000>;
+
+ sd0: sdhci@56000000 {
+ cell-index = <0>;
+ compatible = "sirf,prima2-sdhc";
+ reg = <0x56000000 0x100000>;
+ interrupts = <38>;
+ };
+
+ sd1: sdhci@56100000 {
+ cell-index = <1>;
+ compatible = "sirf,prima2-sdhc";
+ reg = <0x56100000 0x100000>;
+ interrupts = <38>;
+ };
+
+ sd2: sdhci@56200000 {
+ cell-index = <2>;
+ compatible = "sirf,prima2-sdhc";
+ reg = <0x56200000 0x100000>;
+ interrupts = <23>;
+ };
+
+ sd3: sdhci@56300000 {
+ cell-index = <3>;
+ compatible = "sirf,prima2-sdhc";
+ reg = <0x56300000 0x100000>;
+ interrupts = <23>;
+ };
+
+ sd4: sdhci@56400000 {
+ cell-index = <4>;
+ compatible = "sirf,prima2-sdhc";
+ reg = <0x56400000 0x100000>;
+ interrupts = <39>;
+ };
+
+ sd5: sdhci@56500000 {
+ cell-index = <5>;
+ compatible = "sirf,prima2-sdhc";
+ reg = <0x56500000 0x100000>;
+ interrupts = <39>;
+ };
+
+ pci-copy@57900000 {
+ compatible = "sirf,prima2-pcicp";
+ reg = <0x57900000 0x100000>;
+ interrupts = <40>;
+ };
+
+ rom-interface@57a00000 {
+ compatible = "sirf,prima2-romif";
+ reg = <0x57a00000 0x100000>;
+ };
+ };
+ };
+
+ rtc-iobg {
+ compatible = "sirf,prima2-rtciobg", "sirf-prima2-rtciobg-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x80030000 0x10000>;
+
+ gpsrtc@1000 {
+ compatible = "sirf,prima2-gpsrtc";
+ reg = <0x1000 0x1000>;
+ interrupts = <55 56 57>;
+ };
+
+ sysrtc@2000 {
+ compatible = "sirf,prima2-sysrtc";
+ reg = <0x2000 0x1000>;
+ interrupts = <52 53 54>;
+ };
+
+ pwrc@3000 {
+ compatible = "sirf,prima2-pwrc";
+ reg = <0x3000 0x1000>;
+ interrupts = <32>;
+ };
+ };
+
+ uus-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0xb8000000 0xb8000000 0x40000>;
+
+ usb0: usb@b00e0000 {
+ compatible = "chipidea,ci13611a-prima2";
+ reg = <0xb8000000 0x10000>;
+ interrupts = <10>;
+ };
+
+ usb1: usb@b00f0000 {
+ compatible = "chipidea,ci13611a-prima2";
+ reg = <0xb8010000 0x10000>;
+ interrupts = <11>;
+ };
+
+ sata@b00f0000 {
+ compatible = "synopsys,dwc-ahsata";
+ reg = <0xb8020000 0x10000>;
+ interrupts = <37>;
+ };
+
+ security@b00f0000 {
+ compatible = "sirf,prima2-security";
+ reg = <0xb8030000 0x10000>;
+ interrupts = <42>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/skeleton.dtsi b/arch/arm/boot/dts/skeleton.dtsi
new file mode 100644
index 0000000..b41d241
--- /dev/null
+++ b/arch/arm/boot/dts/skeleton.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Skeleton device tree; the bare minimum needed to boot; just include and
+ * add a compatible value. The bootloader will typically populate the memory
+ * node.
+ */
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ chosen { };
+ aliases { };
+ memory { device_type = "memory"; reg = <0 0>; };
+};
diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts
new file mode 100644
index 0000000..0e225b8
--- /dev/null
+++ b/arch/arm/boot/dts/tegra-harmony.dts
@@ -0,0 +1,71 @@
+/dts-v1/;
+
+/memreserve/ 0x1c000000 0x04000000;
+/include/ "tegra20.dtsi"
+
+/ {
+ model = "NVIDIA Tegra2 Harmony evaluation board";
+ compatible = "nvidia,harmony", "nvidia,tegra20";
+
+ chosen {
+ bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk0p2 rw rootwait";
+ };
+
+ memory@0 {
+ reg = < 0x00000000 0x40000000 >;
+ };
+
+ i2c@7000c000 {
+ clock-frequency = <400000>;
+
+ codec: wm8903@1a {
+ compatible = "wlf,wm8903";
+ reg = <0x1a>;
+ interrupts = < 347 >;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ /* 0x8000 = Not configured */
+ gpio-cfg = < 0x8000 0x8000 0 0x8000 0x8000 >;
+ };
+ };
+
+ i2c@7000c400 {
+ clock-frequency = <400000>;
+ };
+
+ i2c@7000c500 {
+ clock-frequency = <400000>;
+ };
+
+ i2c@7000d000 {
+ clock-frequency = <400000>;
+ };
+
+ sound {
+ compatible = "nvidia,harmony-sound", "nvidia,tegra-wm8903";
+
+ spkr-en-gpios = <&codec 2 0>;
+ hp-det-gpios = <&gpio 178 0>;
+ int-mic-en-gpios = <&gpio 184 0>;
+ ext-mic-en-gpios = <&gpio 185 0>;
+ };
+
+ serial@70006300 {
+ clock-frequency = < 216000000 >;
+ };
+
+ sdhci@c8000200 {
+ cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+ wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+ power-gpios = <&gpio 155 0>; /* gpio PT3 */
+ };
+
+ sdhci@c8000600 {
+ cd-gpios = <&gpio 58 0>; /* gpio PH2 */
+ wp-gpios = <&gpio 59 0>; /* gpio PH3 */
+ power-gpios = <&gpio 70 0>; /* gpio PI6 */
+ support-8bit;
+ };
+};
diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts
new file mode 100644
index 0000000..a72299b
--- /dev/null
+++ b/arch/arm/boot/dts/tegra-seaboard.dts
@@ -0,0 +1,32 @@
+/dts-v1/;
+
+/memreserve/ 0x1c000000 0x04000000;
+/include/ "tegra20.dtsi"
+
+/ {
+ model = "NVIDIA Seaboard";
+ compatible = "nvidia,seaboard", "nvidia,tegra20";
+
+ chosen {
+ bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk1p3 rw rootwait";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = < 0x00000000 0x40000000 >;
+ };
+
+ serial@70006300 {
+ clock-frequency = < 216000000 >;
+ };
+
+ sdhci@c8000400 {
+ cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+ wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+ power-gpios = <&gpio 70 0>; /* gpio PI6 */
+ };
+
+ sdhci@c8000600 {
+ support-8bit;
+ };
+};
diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts
new file mode 100644
index 0000000..3f9abd6
--- /dev/null
+++ b/arch/arm/boot/dts/tegra-ventana.dts
@@ -0,0 +1,31 @@
+/dts-v1/;
+
+/memreserve/ 0x1c000000 0x04000000;
+/include/ "tegra20.dtsi"
+
+/ {
+ model = "NVIDIA Tegra2 Ventana evaluation board";
+ compatible = "nvidia,ventana", "nvidia,tegra20";
+
+ chosen {
+ bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/ram rdinit=/sbin/init";
+ };
+
+ memory {
+ reg = < 0x00000000 0x40000000 >;
+ };
+
+ serial@70006300 {
+ clock-frequency = < 216000000 >;
+ };
+
+ sdhci@c8000400 {
+ cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+ wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+ power-gpios = <&gpio 70 0>; /* gpio PI6 */
+ };
+
+ sdhci@c8000600 {
+ support-8bit;
+ };
+};
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
new file mode 100644
index 0000000..65d7e6a
--- /dev/null
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -0,0 +1,147 @@
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "nvidia,tegra20";
+ interrupt-parent = <&intc>;
+
+ intc: interrupt-controller@50041000 {
+ compatible = "nvidia,tegra20-gic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = < 0x50041000 0x1000 >,
+ < 0x50040100 0x0100 >;
+ };
+
+ i2c@7000c000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "nvidia,tegra20-i2c";
+ reg = <0x7000C000 0x100>;
+ interrupts = < 70 >;
+ };
+
+ i2c@7000c400 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "nvidia,tegra20-i2c";
+ reg = <0x7000C400 0x100>;
+ interrupts = < 116 >;
+ };
+
+ i2c@7000c500 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "nvidia,tegra20-i2c";
+ reg = <0x7000C500 0x100>;
+ interrupts = < 124 >;
+ };
+
+ i2c@7000d000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "nvidia,tegra20-i2c";
+ reg = <0x7000D000 0x200>;
+ interrupts = < 85 >;
+ };
+
+ i2s@70002800 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "nvidia,tegra20-i2s";
+ reg = <0x70002800 0x200>;
+ interrupts = < 45 >;
+ dma-channel = < 2 >;
+ };
+
+ i2s@70002a00 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "nvidia,tegra20-i2s";
+ reg = <0x70002a00 0x200>;
+ interrupts = < 35 >;
+ dma-channel = < 1 >;
+ };
+
+ das@70000c00 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "nvidia,tegra20-das";
+ reg = <0x70000c00 0x80>;
+ };
+
+ gpio: gpio@6000d000 {
+ compatible = "nvidia,tegra20-gpio";
+ reg = < 0x6000d000 0x1000 >;
+ interrupts = < 64 65 66 67 87 119 121 >;
+ #gpio-cells = <2>;
+ gpio-controller;
+ };
+
+ pinmux: pinmux@70000000 {
+ compatible = "nvidia,tegra20-pinmux";
+ reg = < 0x70000014 0x10 /* Tri-state registers */
+ 0x70000080 0x20 /* Mux registers */
+ 0x700000a0 0x14 /* Pull-up/down registers */
+ 0x70000868 0xa8 >; /* Pad control registers */
+ };
+
+ serial@70006000 {
+ compatible = "nvidia,tegra20-uart";
+ reg = <0x70006000 0x40>;
+ reg-shift = <2>;
+ interrupts = < 68 >;
+ };
+
+ serial@70006040 {
+ compatible = "nvidia,tegra20-uart";
+ reg = <0x70006040 0x40>;
+ reg-shift = <2>;
+ interrupts = < 69 >;
+ };
+
+ serial@70006200 {
+ compatible = "nvidia,tegra20-uart";
+ reg = <0x70006200 0x100>;
+ reg-shift = <2>;
+ interrupts = < 78 >;
+ };
+
+ serial@70006300 {
+ compatible = "nvidia,tegra20-uart";
+ reg = <0x70006300 0x100>;
+ reg-shift = <2>;
+ interrupts = < 122 >;
+ };
+
+ serial@70006400 {
+ compatible = "nvidia,tegra20-uart";
+ reg = <0x70006400 0x100>;
+ reg-shift = <2>;
+ interrupts = < 123 >;
+ };
+
+ sdhci@c8000000 {
+ compatible = "nvidia,tegra20-sdhci";
+ reg = <0xc8000000 0x200>;
+ interrupts = < 46 >;
+ };
+
+ sdhci@c8000200 {
+ compatible = "nvidia,tegra20-sdhci";
+ reg = <0xc8000200 0x200>;
+ interrupts = < 47 >;
+ };
+
+ sdhci@c8000400 {
+ compatible = "nvidia,tegra20-sdhci";
+ reg = <0xc8000400 0x200>;
+ interrupts = < 51 >;
+ };
+
+ sdhci@c8000600 {
+ compatible = "nvidia,tegra20-sdhci";
+ reg = <0xc8000600 0x200>;
+ interrupts = < 63 >;
+ };
+};
+
diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts
new file mode 100644
index 0000000..d66e2c0
--- /dev/null
+++ b/arch/arm/boot/dts/usb_a9g20.dts
@@ -0,0 +1,30 @@
+/*
+ * usb_a9g20.dts - Device Tree file for Caloa USB A9G20 board
+ *
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g20.dtsi"
+
+/ {
+ model = "Calao USB A9G20";
+ compatible = "calao,usb-a9g20", "atmel,at91sam9g20", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:128k(at91bootstrap),256k(barebox)ro,128k(bareboxenv),128k(bareboxenv2),4M(kernel),120M(rootfs),-(data) root=/dev/mtdblock5 rw rootfstype=ubifs";
+ };
+
+ memory@20000000 {
+ reg = <0x20000000 0x4000000>;
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@fffff200 {
+ status = "okay";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts
new file mode 100644
index 0000000..0b32925
--- /dev/null
+++ b/arch/arm/boot/dts/versatile-ab.dts
@@ -0,0 +1,192 @@
+/dts-v1/;
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "ARM Versatile AB";
+ compatible = "arm,versatile-ab";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&vic>;
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ i2c0 = &i2c0;
+ };
+
+ memory {
+ reg = <0x0 0x08000000>;
+ };
+
+ flash@34000000 {
+ compatible = "arm,versatile-flash";
+ reg = <0x34000000 0x4000000>;
+ bank-width = <4>;
+ };
+
+ i2c0: i2c@10002000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "arm,versatile-i2c";
+ reg = <0x10002000 0x1000>;
+
+ rtc@68 {
+ compatible = "dallas,ds1338";
+ reg = <0x68>;
+ };
+ };
+
+ net@10010000 {
+ compatible = "smsc,lan91c111";
+ reg = <0x10010000 0x10000>;
+ interrupts = <25>;
+ };
+
+ lcd@10008000 {
+ compatible = "arm,versatile-lcd";
+ reg = <0x10008000 0x1000>;
+ };
+
+ amba {
+ compatible = "arm,amba-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ vic: intc@10140000 {
+ compatible = "arm,versatile-vic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x10140000 0x1000>;
+ };
+
+ sic: intc@10003000 {
+ compatible = "arm,versatile-sic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x10003000 0x1000>;
+ interrupt-parent = <&vic>;
+ interrupts = <31>; /* Cascaded to vic */
+ };
+
+ dma@10130000 {
+ compatible = "arm,pl081", "arm,primecell";
+ reg = <0x10130000 0x1000>;
+ interrupts = <17>;
+ };
+
+ uart0: uart@101f1000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x101f1000 0x1000>;
+ interrupts = <12>;
+ };
+
+ uart1: uart@101f2000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x101f2000 0x1000>;
+ interrupts = <13>;
+ };
+
+ uart2: uart@101f3000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x101f3000 0x1000>;
+ interrupts = <14>;
+ };
+
+ smc@10100000 {
+ compatible = "arm,primecell";
+ reg = <0x10100000 0x1000>;
+ };
+
+ mpmc@10110000 {
+ compatible = "arm,primecell";
+ reg = <0x10110000 0x1000>;
+ };
+
+ display@10120000 {
+ compatible = "arm,pl110", "arm,primecell";
+ reg = <0x10120000 0x1000>;
+ interrupts = <16>;
+ };
+
+ sctl@101e0000 {
+ compatible = "arm,primecell";
+ reg = <0x101e0000 0x1000>;
+ };
+
+ watchdog@101e1000 {
+ compatible = "arm,primecell";
+ reg = <0x101e1000 0x1000>;
+ interrupts = <0>;
+ };
+
+ gpio0: gpio@101e4000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x101e4000 0x1000>;
+ gpio-controller;
+ interrupts = <6>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio1: gpio@101e5000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x101e5000 0x1000>;
+ interrupts = <7>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ rtc@101e8000 {
+ compatible = "arm,pl030", "arm,primecell";
+ reg = <0x101e8000 0x1000>;
+ interrupts = <10>;
+ };
+
+ sci@101f0000 {
+ compatible = "arm,primecell";
+ reg = <0x101f0000 0x1000>;
+ interrupts = <15>;
+ };
+
+ ssp@101f4000 {
+ compatible = "arm,pl022", "arm,primecell";
+ reg = <0x101f4000 0x1000>;
+ interrupts = <11>;
+ };
+
+ fpga {
+ compatible = "arm,versatile-fpga", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x10000000 0x10000>;
+
+ aaci@4000 {
+ compatible = "arm,primecell";
+ reg = <0x4000 0x1000>;
+ interrupts = <24>;
+ };
+ mmc@5000 {
+ compatible = "arm,primecell";
+ reg = < 0x5000 0x1000>;
+ interrupts = <22>;
+ };
+ kmi@6000 {
+ compatible = "arm,pl050", "arm,primecell";
+ reg = <0x6000 0x1000>;
+ interrupt-parent = <&sic>;
+ interrupts = <3>;
+ };
+ kmi@7000 {
+ compatible = "arm,pl050", "arm,primecell";
+ reg = <0x7000 0x1000>;
+ interrupt-parent = <&sic>;
+ interrupts = <4>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts
new file mode 100644
index 0000000..8a614e3
--- /dev/null
+++ b/arch/arm/boot/dts/versatile-pb.dts
@@ -0,0 +1,48 @@
+/include/ "versatile-ab.dts"
+
+/ {
+ model = "ARM Versatile PB";
+ compatible = "arm,versatile-pb";
+
+ amba {
+ gpio2: gpio@101e6000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x101e6000 0x1000>;
+ interrupts = <8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio3: gpio@101e7000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x101e7000 0x1000>;
+ interrupts = <9>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ fpga {
+ uart@9000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x9000 0x1000>;
+ interrupt-parent = <&sic>;
+ interrupts = <6>;
+ };
+ sci@a000 {
+ compatible = "arm,primecell";
+ reg = <0xa000 0x1000>;
+ interrupt-parent = <&sic>;
+ interrupts = <5>;
+ };
+ mmc@b000 {
+ compatible = "arm,primecell";
+ reg = <0xb000 0x1000>;
+ interrupts = <23>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-ep107.dts
new file mode 100644
index 0000000..37ca192
--- /dev/null
+++ b/arch/arm/boot/dts/zynq-ep107.dts
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/ {
+ model = "Xilinx Zynq EP107";
+ compatible = "xlnx,zynq-ep107";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x10000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk";
+ linux,stdout-path = &uart0;
+ };
+
+ amba {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ intc: interrupt-controller@f8f01000 {
+ interrupt-controller;
+ compatible = "arm,gic";
+ reg = <0xF8F01000 0x1000>;
+ #interrupt-cells = <2>;
+ };
+
+ uart0: uart@e0000000 {
+ compatible = "xlnx,xuartps";
+ reg = <0xE0000000 0x1000>;
+ interrupts = <59 0>;
+ clock = <50000000>;
+ };
+ };
+};
diff --git a/arch/arm/configs/at91cap9_defconfig b/arch/arm/configs/at91cap9_defconfig
new file mode 100644
index 0000000..8826eb2
--- /dev/null
+++ b/arch/arm/configs/at91cap9_defconfig
@@ -0,0 +1,108 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91CAP9=y
+CONFIG_MACH_AT91CAP9ADK=y
+CONFIG_MTD_AT91_DATAFLASH_CARD=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_AEABI=y
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/at91sam9260_defconfig b/arch/arm/configs/at91sam9260_defconfig
new file mode 100644
index 0000000..505b376
--- /dev/null
+++ b/arch/arm/configs/at91sam9260_defconfig
@@ -0,0 +1,91 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9260=y
+CONFIG_ARCH_AT91SAM9260_SAM9XE=y
+CONFIG_MACH_AT91SAM9260EK=y
+CONFIG_MACH_CAM60=y
+CONFIG_MACH_SAM9_L9260=y
+CONFIG_MACH_AFEB9260=y
+CONFIG_MACH_USB_A9260=y
+CONFIG_MACH_QIL_A9260=y
+CONFIG_MACH_CPU9260=y
+CONFIG_MACH_FLEXIBITY=y
+CONFIG_MACH_SNAPPER_9260=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/at91sam9g20_defconfig b/arch/arm/configs/at91sam9g20_defconfig
new file mode 100644
index 0000000..9123568
--- /dev/null
+++ b/arch/arm/configs/at91sam9g20_defconfig
@@ -0,0 +1,124 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9G20=y
+CONFIG_MACH_AT91SAM9G20EK=y
+CONFIG_MACH_AT91SAM9G20EK_2MMC=y
+CONFIG_MACH_CPU9G20=y
+CONFIG_MACH_ACMENETUSFOXG20=y
+CONFIG_MACH_PORTUXG20=y
+CONFIG_MACH_STAMP9G20=y
+CONFIG_MACH_PCONTROL_G20=y
+CONFIG_MACH_GSIA18S=y
+CONFIG_MACH_USB_A9G20=y
+CONFIG_MACH_SNAPPER_9260=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_AEABI=y
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+CONFIG_SPI_SPIDEV=y
+# CONFIG_HWMON is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PROCFS is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
diff --git a/arch/arm/configs/at91sam9g45_defconfig b/arch/arm/configs/at91sam9g45_defconfig
new file mode 100644
index 0000000..8aab786
--- /dev/null
+++ b/arch/arm/configs/at91sam9g45_defconfig
@@ -0,0 +1,210 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9G45=y
+CONFIG_MACH_AT91SAM9M10G45EK=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_AT91_SLOW_CLOCK=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x71100000,25165824 root=/dev/ram0 rw"
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_CFG80211=y
+CONFIG_LIB80211=y
+CONFIG_MAC80211=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_MISC_DEVICES=y
+CONFIG_ATMEL_PWM=y
+CONFIG_ATMEL_TCLIB=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_LIBERTAS_THINFIRM=m
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AT76C50X_USB=m
+CONFIG_USB_ZD1201=m
+CONFIG_RTL8187=m
+CONFIG_ATH_COMMON=m
+CONFIG_ATH9K=m
+CONFIG_CARL9170=m
+CONFIG_B43=m
+CONFIG_B43_PHY_N=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_SPI=m
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RTL8192CU=m
+CONFIG_WL1251=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL12XX_MENU=m
+CONFIG_WL12XX=m
+CONFIG_WL12XX_SDIO=m
+CONFIG_ZD1211RW=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_INPUT_POLLDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=480
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=272
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_QT1070=m
+CONFIG_KEYBOARD_QT2160=m
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
+# CONFIG_SERIO is not set
+CONFIG_LEGACY_PTY_COUNT=4
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_FB_UDL=m
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_ATMEL_LCDC=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_ATMEL_AC97C=y
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ATMEL_USBA=m
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_MMC=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_SDIO_UART=m
+CONFIG_MMC_ATMELMCI=y
+CONFIG_LEDS_ATMEL_PWM=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91RM9200=y
+CONFIG_DMADEVICES=y
+CONFIG_AT_HDMAC=y
+CONFIG_DMATEST=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_FANOTIFY=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+# CONFIG_CRYPTO_HW is not set
diff --git a/arch/arm/configs/at91sam9rl_defconfig b/arch/arm/configs/at91sam9rl_defconfig
new file mode 100644
index 0000000..ad562ee
--- /dev/null
+++ b/arch/arm/configs/at91sam9rl_defconfig
@@ -0,0 +1,79 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9RL=y
+CONFIG_MACH_AT91SAM9RLEK=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,17105363 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=24576
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
new file mode 100644
index 0000000..cf497ce
--- /dev/null
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -0,0 +1,172 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EXPERT=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_MXC=y
+CONFIG_ARCH_IMX_V4_V5=y
+CONFIG_ARCH_MX1ADS=y
+CONFIG_MACH_SCB9328=y
+CONFIG_MACH_APF9328=y
+CONFIG_MACH_MX21ADS=y
+CONFIG_MACH_MX25_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX25SD=y
+CONFIG_MACH_MX27ADS=y
+CONFIG_MACH_PCM038=y
+CONFIG_MACH_CPUIMX27=y
+CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
+CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
+CONFIG_MACH_MX27_3DS=y
+CONFIG_MACH_IMX27_VISSTRIM_M10=y
+CONFIG_MACH_IMX27LITE=y
+CONFIG_MACH_PCA100=y
+CONFIG_MACH_MXT_TD60=y
+CONFIG_MACH_IMX27IPCAM=y
+CONFIG_MXC_IRQ_PRIOR=y
+CONFIG_MXC_PWM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+CONFIG_PM_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# CONFIG_MTD_CFI_I2 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_MXC=y
+CONFIG_MTD_UBI=y
+CONFIG_MISC_DEVICES=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_NETDEVICES=y
+CONFIG_DM9000=y
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC_PHY=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_W1=y
+CONFIG_W1_MASTER_MXC=y
+CONFIG_W1_SLAVE_THERM=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13783=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_FB=y
+CONFIG_FB_IMX=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_MX27VIS_AIC32X4=y
+CONFIG_SND_SOC_PHYCORE_AC97=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_USB_HID=m
+CONFIG_USB=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_ULPI=y
+CONFIG_MMC=y
+CONFIG_MMC_MXC=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_MC13783=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_IMXDI=y
+CONFIG_RTC_MXC=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=y
+CONFIG_IMX_DMA=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx5_defconfig b/arch/arm/configs/mx5_defconfig
new file mode 100644
index 0000000..d0d8dfe
--- /dev/null
+++ b/arch/arm/configs/mx5_defconfig
@@ -0,0 +1,184 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_RELAY=y
+CONFIG_EXPERT=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_MXC=y
+CONFIG_ARCH_MX5=y
+CONFIG_MACH_MX51_BABBAGE=y
+CONFIG_MACH_MX51_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX51=y
+CONFIG_MACH_EUKREA_CPUIMX51SD=y
+CONFIG_MACH_MX51_EFIKAMX=y
+CONFIG_MACH_MX51_EFIKASB=y
+CONFIG_MACH_MX53_EVK=y
+CONFIG_MACH_MX53_SMD=y
+CONFIG_MACH_MX53_LOCO=y
+CONFIG_MACH_MX53_ARD=y
+CONFIG_MXC_PWM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_IMX=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=m
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_ICPLUS_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_NATIONAL_PHY=y
+CONFIG_STE10XP=y
+CONFIG_LSI_ET1011C_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_MXC=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=m
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
diff --git a/arch/arm/include/asm/exception.h b/arch/arm/include/asm/exception.h
new file mode 100644
index 0000000..5abaf5b
--- /dev/null
+++ b/arch/arm/include/asm/exception.h
@@ -0,0 +1,19 @@
+/*
+ * Annotations for marking C functions as exception handlers.
+ *
+ * These should only be used for C functions that are called from the low
+ * level exception entry code and not any intervening C code.
+ */
+#ifndef __ASM_ARM_EXCEPTION_H
+#define __ASM_ARM_EXCEPTION_H
+
+#include <linux/ftrace.h>
+
+#define __exception __attribute__((section(".exception.text")))
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#define __exception_irq_entry __irq_entry
+#else
+#define __exception_irq_entry __exception
+#endif
+
+#endif /* __ASM_ARM_EXCEPTION_H */
diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h
new file mode 100644
index 0000000..5cfba15
--- /dev/null
+++ b/arch/arm/include/asm/pgtable-2level-hwdef.h
@@ -0,0 +1,93 @@
+/*
+ * arch/arm/include/asm/pgtable-2level-hwdef.h
+ *
+ * Copyright (C) 1995-2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _ASM_PGTABLE_2LEVEL_HWDEF_H
+#define _ASM_PGTABLE_2LEVEL_HWDEF_H
+
+/*
+ * Hardware page table definitions.
+ *
+ * + Level 1 descriptor (PMD)
+ * - common
+ */
+#define PMD_TYPE_MASK (_AT(pmdval_t, 3) << 0)
+#define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0)
+#define PMD_TYPE_TABLE (_AT(pmdval_t, 1) << 0)
+#define PMD_TYPE_SECT (_AT(pmdval_t, 2) << 0)
+#define PMD_BIT4 (_AT(pmdval_t, 1) << 4)
+#define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5)
+#define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */
+/*
+ * - section
+ */
+#define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2)
+#define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3)
+#define PMD_SECT_XN (_AT(pmdval_t, 1) << 4) /* v6 */
+#define PMD_SECT_AP_WRITE (_AT(pmdval_t, 1) << 10)
+#define PMD_SECT_AP_READ (_AT(pmdval_t, 1) << 11)
+#define PMD_SECT_TEX(x) (_AT(pmdval_t, (x)) << 12) /* v5 */
+#define PMD_SECT_APX (_AT(pmdval_t, 1) << 15) /* v6 */
+#define PMD_SECT_S (_AT(pmdval_t, 1) << 16) /* v6 */
+#define PMD_SECT_nG (_AT(pmdval_t, 1) << 17) /* v6 */
+#define PMD_SECT_SUPER (_AT(pmdval_t, 1) << 18) /* v6 */
+#define PMD_SECT_AF (_AT(pmdval_t, 0))
+
+#define PMD_SECT_UNCACHED (_AT(pmdval_t, 0))
+#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE)
+#define PMD_SECT_WT (PMD_SECT_CACHEABLE)
+#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
+#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
+#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
+#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2))
+
+/*
+ * - coarse table (not used)
+ */
+
+/*
+ * + Level 2 descriptor (PTE)
+ * - common
+ */
+#define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0)
+#define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0)
+#define PTE_TYPE_LARGE (_AT(pteval_t, 1) << 0)
+#define PTE_TYPE_SMALL (_AT(pteval_t, 2) << 0)
+#define PTE_TYPE_EXT (_AT(pteval_t, 3) << 0) /* v5 */
+#define PTE_BUFFERABLE (_AT(pteval_t, 1) << 2)
+#define PTE_CACHEABLE (_AT(pteval_t, 1) << 3)
+
+/*
+ * - extended small page/tiny page
+ */
+#define PTE_EXT_XN (_AT(pteval_t, 1) << 0) /* v6 */
+#define PTE_EXT_AP_MASK (_AT(pteval_t, 3) << 4)
+#define PTE_EXT_AP0 (_AT(pteval_t, 1) << 4)
+#define PTE_EXT_AP1 (_AT(pteval_t, 2) << 4)
+#define PTE_EXT_AP_UNO_SRO (_AT(pteval_t, 0) << 4)
+#define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0)
+#define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1)
+#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0)
+#define PTE_EXT_TEX(x) (_AT(pteval_t, (x)) << 6) /* v5 */
+#define PTE_EXT_APX (_AT(pteval_t, 1) << 9) /* v6 */
+#define PTE_EXT_COHERENT (_AT(pteval_t, 1) << 9) /* XScale3 */
+#define PTE_EXT_SHARED (_AT(pteval_t, 1) << 10) /* v6 */
+#define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* v6 */
+
+/*
+ * - small page
+ */
+#define PTE_SMALL_AP_MASK (_AT(pteval_t, 0xff) << 4)
+#define PTE_SMALL_AP_UNO_SRO (_AT(pteval_t, 0x00) << 4)
+#define PTE_SMALL_AP_UNO_SRW (_AT(pteval_t, 0x55) << 4)
+#define PTE_SMALL_AP_URO_SRW (_AT(pteval_t, 0xaa) << 4)
+#define PTE_SMALL_AP_URW_SRW (_AT(pteval_t, 0xff) << 4)
+
+#define PHYS_MASK (~0UL)
+
+#endif
diff --git a/arch/arm/include/asm/pgtable-2level-types.h b/arch/arm/include/asm/pgtable-2level-types.h
new file mode 100644
index 0000000..66cb5b0
--- /dev/null
+++ b/arch/arm/include/asm/pgtable-2level-types.h
@@ -0,0 +1,67 @@
+/*
+ * arch/arm/include/asm/pgtable-2level-types.h
+ *
+ * Copyright (C) 1995-2003 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _ASM_PGTABLE_2LEVEL_TYPES_H
+#define _ASM_PGTABLE_2LEVEL_TYPES_H
+
+#include <asm/types.h>
+
+typedef u32 pteval_t;
+typedef u32 pmdval_t;
+
+#undef STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { pteval_t pte; } pte_t;
+typedef struct { pmdval_t pmd; } pmd_t;
+typedef struct { pmdval_t pgd[2]; } pgd_t;
+typedef struct { pteval_t pgprot; } pgprot_t;
+
+#define pte_val(x) ((x).pte)
+#define pmd_val(x) ((x).pmd)
+#define pgd_val(x) ((x).pgd[0])
+#define pgprot_val(x) ((x).pgprot)
+
+#define __pte(x) ((pte_t) { (x) } )
+#define __pmd(x) ((pmd_t) { (x) } )
+#define __pgprot(x) ((pgprot_t) { (x) } )
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef pteval_t pte_t;
+typedef pmdval_t pmd_t;
+typedef pmdval_t pgd_t[2];
+typedef pteval_t pgprot_t;
+
+#define pte_val(x) (x)
+#define pmd_val(x) (x)
+#define pgd_val(x) ((x)[0])
+#define pgprot_val(x) (x)
+
+#define __pte(x) (x)
+#define __pmd(x) (x)
+#define __pgprot(x) (x)
+
+#endif /* STRICT_MM_TYPECHECKS */
+
+#endif /* _ASM_PGTABLE_2LEVEL_TYPES_H */
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h
new file mode 100644
index 0000000..1cb80c4
--- /dev/null
+++ b/arch/arm/include/asm/pgtable-2level.h
@@ -0,0 +1,145 @@
+/*
+ * arch/arm/include/asm/pgtable-2level.h
+ *
+ * Copyright (C) 1995-2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _ASM_PGTABLE_2LEVEL_H
+#define _ASM_PGTABLE_2LEVEL_H
+
+/*
+ * Hardware-wise, we have a two level page table structure, where the first
+ * level has 4096 entries, and the second level has 256 entries. Each entry
+ * is one 32-bit word. Most of the bits in the second level entry are used
+ * by hardware, and there aren't any "accessed" and "dirty" bits.
+ *
+ * Linux on the other hand has a three level page table structure, which can
+ * be wrapped to fit a two level page table structure easily - using the PGD
+ * and PTE only. However, Linux also expects one "PTE" table per page, and
+ * at least a "dirty" bit.
+ *
+ * Therefore, we tweak the implementation slightly - we tell Linux that we
+ * have 2048 entries in the first level, each of which is 8 bytes (iow, two
+ * hardware pointers to the second level.) The second level contains two
+ * hardware PTE tables arranged contiguously, preceded by Linux versions
+ * which contain the state information Linux needs. We, therefore, end up
+ * with 512 entries in the "PTE" level.
+ *
+ * This leads to the page tables having the following layout:
+ *
+ * pgd pte
+ * | |
+ * +--------+
+ * | | +------------+ +0
+ * +- - - - + | Linux pt 0 |
+ * | | +------------+ +1024
+ * +--------+ +0 | Linux pt 1 |
+ * | |-----> +------------+ +2048
+ * +- - - - + +4 | h/w pt 0 |
+ * | |-----> +------------+ +3072
+ * +--------+ +8 | h/w pt 1 |
+ * | | +------------+ +4096
+ *
+ * See L_PTE_xxx below for definitions of bits in the "Linux pt", and
+ * PTE_xxx for definitions of bits appearing in the "h/w pt".
+ *
+ * PMD_xxx definitions refer to bits in the first level page table.
+ *
+ * The "dirty" bit is emulated by only granting hardware write permission
+ * iff the page is marked "writable" and "dirty" in the Linux PTE. This
+ * means that a write to a clean page will cause a permission fault, and
+ * the Linux MM layer will mark the page dirty via handle_pte_fault().
+ * For the hardware to notice the permission change, the TLB entry must
+ * be flushed, and ptep_set_access_flags() does that for us.
+ *
+ * The "accessed" or "young" bit is emulated by a similar method; we only
+ * allow accesses to the page if the "young" bit is set. Accesses to the
+ * page will cause a fault, and handle_pte_fault() will set the young bit
+ * for us as long as the page is marked present in the corresponding Linux
+ * PTE entry. Again, ptep_set_access_flags() will ensure that the TLB is
+ * up to date.
+ *
+ * However, when the "young" bit is cleared, we deny access to the page
+ * by clearing the hardware PTE. Currently Linux does not flush the TLB
+ * for us in this case, which means the TLB will retain the transation
+ * until either the TLB entry is evicted under pressure, or a context
+ * switch which changes the user space mapping occurs.
+ */
+#define PTRS_PER_PTE 512
+#define PTRS_PER_PMD 1
+#define PTRS_PER_PGD 2048
+
+#define PTE_HWTABLE_PTRS (PTRS_PER_PTE)
+#define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t))
+#define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32))
+
+/*
+ * PMD_SHIFT determines the size of the area a second-level page table can map
+ * PGDIR_SHIFT determines what a third-level page table entry can map
+ */
+#define PMD_SHIFT 21
+#define PGDIR_SHIFT 21
+
+#define PMD_SIZE (1UL << PMD_SHIFT)
+#define PMD_MASK (~(PMD_SIZE-1))
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+/*
+ * section address mask and size definitions.
+ */
+#define SECTION_SHIFT 20
+#define SECTION_SIZE (1UL << SECTION_SHIFT)
+#define SECTION_MASK (~(SECTION_SIZE-1))
+
+/*
+ * ARMv6 supersection address mask and size definitions.
+ */
+#define SUPERSECTION_SHIFT 24
+#define SUPERSECTION_SIZE (1UL << SUPERSECTION_SHIFT)
+#define SUPERSECTION_MASK (~(SUPERSECTION_SIZE-1))
+
+#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
+
+/*
+ * "Linux" PTE definitions.
+ *
+ * We keep two sets of PTEs - the hardware and the linux version.
+ * This allows greater flexibility in the way we map the Linux bits
+ * onto the hardware tables, and allows us to have YOUNG and DIRTY
+ * bits.
+ *
+ * The PTE table pointer refers to the hardware entries; the "Linux"
+ * entries are stored 1024 bytes below.
+ */
+#define L_PTE_PRESENT (_AT(pteval_t, 1) << 0)
+#define L_PTE_YOUNG (_AT(pteval_t, 1) << 1)
+#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */
+#define L_PTE_DIRTY (_AT(pteval_t, 1) << 6)
+#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7)
+#define L_PTE_USER (_AT(pteval_t, 1) << 8)
+#define L_PTE_XN (_AT(pteval_t, 1) << 9)
+#define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */
+#define L_PTE_NONE (_AT(pteval_t, 1) << 11)
+
+/*
+ * These are the memory types, defined to be compatible with
+ * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB
+ */
+#define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */
+#define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */
+#define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 0x02) << 2) /* 0010 */
+#define L_PTE_MT_WRITEBACK (_AT(pteval_t, 0x03) << 2) /* 0011 */
+#define L_PTE_MT_MINICACHE (_AT(pteval_t, 0x06) << 2) /* 0110 (sa1100, xscale) */
+#define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 0x07) << 2) /* 0111 */
+#define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 0x04) << 2) /* 0100 */
+#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */
+#define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */
+#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */
+#define L_PTE_MT_VECTORS (_AT(pteval_t, 0x0f) << 2) /* 1111 */
+#define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2)
+
+#endif /* _ASM_PGTABLE_2LEVEL_H */
diff --git a/arch/arm/include/asm/suspend.h b/arch/arm/include/asm/suspend.h
new file mode 100644
index 0000000..1c0a551
--- /dev/null
+++ b/arch/arm/include/asm/suspend.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_ARM_SUSPEND_H
+#define __ASM_ARM_SUSPEND_H
+
+extern void cpu_resume(void);
+extern int cpu_suspend(unsigned long, int (*)(unsigned long));
+
+#endif
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
new file mode 100644
index 0000000..8a30c89
--- /dev/null
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -0,0 +1,1005 @@
+/*
+ * arch/arm/kernel/kprobes-decode.c
+ *
+ * Copyright (C) 2006, 2007 Motorola Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+/*
+ * We do not have hardware single-stepping on ARM, This
+ * effort is further complicated by the ARM not having a
+ * "next PC" register. Instructions that change the PC
+ * can't be safely single-stepped in a MP environment, so
+ * we have a lot of work to do:
+ *
+ * In the prepare phase:
+ * *) If it is an instruction that does anything
+ * with the CPU mode, we reject it for a kprobe.
+ * (This is out of laziness rather than need. The
+ * instructions could be simulated.)
+ *
+ * *) Otherwise, decode the instruction rewriting its
+ * registers to take fixed, ordered registers and
+ * setting a handler for it to run the instruction.
+ *
+ * In the execution phase by an instruction's handler:
+ *
+ * *) If the PC is written to by the instruction, the
+ * instruction must be fully simulated in software.
+ *
+ * *) Otherwise, a modified form of the instruction is
+ * directly executed. Its handler calls the
+ * instruction in insn[0]. In insn[1] is a
+ * "mov pc, lr" to return.
+ *
+ * Before calling, load up the reordered registers
+ * from the original instruction's registers. If one
+ * of the original input registers is the PC, compute
+ * and adjust the appropriate input register.
+ *
+ * After call completes, copy the output registers to
+ * the original instruction's original registers.
+ *
+ * We don't use a real breakpoint instruction since that
+ * would have us in the kernel go from SVC mode to SVC
+ * mode losing the link register. Instead we use an
+ * undefined instruction. To simplify processing, the
+ * undefined instruction used for kprobes must be reserved
+ * exclusively for kprobes use.
+ *
+ * TODO: ifdef out some instruction decoding based on architecture.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+#include <linux/module.h>
+
+#include "kprobes.h"
+
+#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
+
+#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
+
+#if __LINUX_ARM_ARCH__ >= 6
+#define BLX(reg) "blx "reg" \n\t"
+#else
+#define BLX(reg) "mov lr, pc \n\t" \
+ "mov pc, "reg" \n\t"
+#endif
+
+/*
+ * To avoid the complications of mimicing single-stepping on a
+ * processor without a Next-PC or a single-step mode, and to
+ * avoid having to deal with the side-effects of boosting, we
+ * simulate or emulate (almost) all ARM instructions.
+ *
+ * "Simulation" is where the instruction's behavior is duplicated in
+ * C code. "Emulation" is where the original instruction is rewritten
+ * and executed, often by altering its registers.
+ *
+ * By having all behavior of the kprobe'd instruction completed before
+ * returning from the kprobe_handler(), all locks (scheduler and
+ * interrupt) can safely be released. There is no need for secondary
+ * breakpoints, no race with MP or preemptable kernels, nor having to
+ * clean up resources counts at a later time impacting overall system
+ * performance. By rewriting the instruction, only the minimum registers
+ * need to be loaded and saved back optimizing performance.
+ *
+ * Calling the insnslot_*_rwflags version of a function doesn't hurt
+ * anything even when the CPSR flags aren't updated by the
+ * instruction. It's just a little slower in return for saving
+ * a little space by not having a duplicate function that doesn't
+ * update the flags. (The same optimization can be said for
+ * instructions that do or don't perform register writeback)
+ * Also, instructions can either read the flags, only write the
+ * flags, or read and write the flags. To save combinations
+ * rather than for sheer performance, flag functions just assume
+ * read and write of flags.
+ */
+
+static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ long iaddr = (long)p->addr;
+ int disp = branch_displacement(insn);
+
+ if (insn & (1 << 24))
+ regs->ARM_lr = iaddr + 4;
+
+ regs->ARM_pc = iaddr + 8 + disp;
+}
+
+static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ long iaddr = (long)p->addr;
+ int disp = branch_displacement(insn);
+
+ regs->ARM_lr = iaddr + 4;
+ regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);
+ regs->ARM_cpsr |= PSR_T_BIT;
+}
+
+static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rm = insn & 0xf;
+ long rmv = regs->uregs[rm];
+
+ if (insn & (1 << 5))
+ regs->ARM_lr = (long)p->addr + 4;
+
+ regs->ARM_pc = rmv & ~0x1;
+ regs->ARM_cpsr &= ~PSR_T_BIT;
+ if (rmv & 0x1)
+ regs->ARM_cpsr |= PSR_T_BIT;
+}
+
+static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 12) & 0xf;
+ unsigned long mask = 0xf8ff03df; /* Mask out execution state */
+ regs->uregs[rd] = regs->ARM_cpsr & mask;
+}
+
+static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->uregs[12] = regs->uregs[13];
+}
+
+static void __kprobes
+emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = (unsigned long)p->addr + 8;
+ int rt = (insn >> 12) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rtv asm("r0") = regs->uregs[rt];
+ register unsigned long rt2v asm("r1") = regs->uregs[rt+1];
+ register unsigned long rnv asm("r2") = (rn == 15) ? pc
+ : regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ BLX("%[fn]")
+ : "=r" (rtv), "=r" (rt2v), "=r" (rnv)
+ : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
+ [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rt] = rtv;
+ regs->uregs[rt+1] = rt2v;
+ if (is_writeback(insn))
+ regs->uregs[rn] = rnv;
+}
+
+static void __kprobes
+emulate_ldr(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = (unsigned long)p->addr + 8;
+ int rt = (insn >> 12) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rtv asm("r0");
+ register unsigned long rnv asm("r2") = (rn == 15) ? pc
+ : regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ BLX("%[fn]")
+ : "=r" (rtv), "=r" (rnv)
+ : "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ if (rt == 15)
+ load_write_pc(rtv, regs);
+ else
+ regs->uregs[rt] = rtv;
+
+ if (is_writeback(insn))
+ regs->uregs[rn] = rnv;
+}
+
+static void __kprobes
+emulate_str(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long rtpc = (unsigned long)p->addr + str_pc_offset;
+ unsigned long rnpc = (unsigned long)p->addr + 8;
+ int rt = (insn >> 12) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rtv asm("r0") = (rt == 15) ? rtpc
+ : regs->uregs[rt];
+ register unsigned long rnv asm("r2") = (rn == 15) ? rnpc
+ : regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ BLX("%[fn]")
+ : "=r" (rnv)
+ : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ if (is_writeback(insn))
+ regs->uregs[rn] = rnv;
+}
+
+static void __kprobes
+emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = (unsigned long)p->addr + 8;
+ int rd = (insn >> 12) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+ int rs = (insn >> 8) & 0xf;
+
+ register unsigned long rdv asm("r0") = regs->uregs[rd];
+ register unsigned long rnv asm("r2") = (rn == 15) ? pc
+ : regs->uregs[rn];
+ register unsigned long rmv asm("r3") = (rm == 15) ? pc
+ : regs->uregs[rm];
+ register unsigned long rsv asm("r1") = regs->uregs[rs];
+ unsigned long cpsr = regs->ARM_cpsr;
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[cpsr] \n\t"
+ BLX("%[fn]")
+ "mrs %[cpsr], cpsr \n\t"
+ : "=r" (rdv), [cpsr] "=r" (cpsr)
+ : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
+ "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ if (rd == 15)
+ alu_write_pc(rdv, regs);
+ else
+ regs->uregs[rd] = rdv;
+ regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static void __kprobes
+emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 12) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rdv asm("r0") = regs->uregs[rd];
+ register unsigned long rnv asm("r2") = regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+ unsigned long cpsr = regs->ARM_cpsr;
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[cpsr] \n\t"
+ BLX("%[fn]")
+ "mrs %[cpsr], cpsr \n\t"
+ : "=r" (rdv), [cpsr] "=r" (cpsr)
+ : "0" (rdv), "r" (rnv), "r" (rmv),
+ "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rd] = rdv;
+ regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static void __kprobes
+emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 16) & 0xf;
+ int rn = (insn >> 12) & 0xf;
+ int rm = insn & 0xf;
+ int rs = (insn >> 8) & 0xf;
+
+ register unsigned long rdv asm("r2") = regs->uregs[rd];
+ register unsigned long rnv asm("r0") = regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+ register unsigned long rsv asm("r1") = regs->uregs[rs];
+ unsigned long cpsr = regs->ARM_cpsr;
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[cpsr] \n\t"
+ BLX("%[fn]")
+ "mrs %[cpsr], cpsr \n\t"
+ : "=r" (rdv), [cpsr] "=r" (cpsr)
+ : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
+ "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rd] = rdv;
+ regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static void __kprobes
+emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 12) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rdv asm("r0") = regs->uregs[rd];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ BLX("%[fn]")
+ : "=r" (rdv)
+ : "0" (rdv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rd] = rdv;
+}
+
+static void __kprobes
+emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rdlo = (insn >> 12) & 0xf;
+ int rdhi = (insn >> 16) & 0xf;
+ int rn = insn & 0xf;
+ int rm = (insn >> 8) & 0xf;
+
+ register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
+ register unsigned long rdhiv asm("r2") = regs->uregs[rdhi];
+ register unsigned long rnv asm("r3") = regs->uregs[rn];
+ register unsigned long rmv asm("r1") = regs->uregs[rm];
+ unsigned long cpsr = regs->ARM_cpsr;
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[cpsr] \n\t"
+ BLX("%[fn]")
+ "mrs %[cpsr], cpsr \n\t"
+ : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr)
+ : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
+ "2" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rdlo] = rdlov;
+ regs->uregs[rdhi] = rdhiv;
+ regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+/*
+ * For the instruction masking and comparisons in all the "space_*"
+ * functions below, Do _not_ rearrange the order of tests unless
+ * you're very, very sure of what you are doing. For the sake of
+ * efficiency, the masks for some tests sometimes assume other test
+ * have been done prior to them so the number of patterns to test
+ * for an instruction set can be as broad as possible to reduce the
+ * number of tests needed.
+ */
+
+static const union decode_item arm_1111_table[] = {
+ /* Unconditional instructions */
+
+ /* memory hint 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx */
+ /* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */
+ /* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */
+ /* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_SIMULATE (0xfe300000, 0xf4100000, kprobe_simulate_nop),
+
+ /* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */
+ /* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */
+ /* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */
+ /* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */
+ DECODE_SIMULATE (0xfe300010, 0xf6100000, kprobe_simulate_nop),
+
+ /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */
+ DECODE_SIMULATE (0xfe000000, 0xfa000000, simulate_blx1),
+
+ /* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
+ /* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
+ /* SRS 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
+ /* RFE 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
+
+ /* Coprocessor instructions... */
+ /* MCRR2 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx */
+ /* MRRC2 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx */
+ /* LDC2 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
+ /* STC2 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
+ /* CDP2 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
+ /* MCR2 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
+ /* MRC2 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
+
+ /* Other unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = {
+ /* Miscellaneous instructions */
+
+ /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
+ DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs,
+ REGS(0, NOPC, 0, 0, 0)),
+
+ /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
+ DECODE_SIMULATE (0x0ff000f0, 0x01200010, simulate_blx2bx),
+
+ /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
+ DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx,
+ REGS(0, 0, 0, 0, NOPC)),
+
+ /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
+ DECODE_EMULATEX (0x0ff000f0, 0x01600010, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, NOPC)),
+
+ /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */
+ /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */
+ /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */
+ /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */
+ DECODE_EMULATEX (0x0f9000f0, 0x01000050, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+ /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
+ /* MSR cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
+ /* MRS spsr cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
+ /* BKPT 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
+ /* SMC cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
+ /* And unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = {
+ /* Halfword multiply and multiply-accumulate */
+
+ /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
+ DECODE_EMULATEX (0x0ff00090, 0x01400080, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
+ REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+ /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
+ DECODE_OR (0x0ff000b0, 0x012000a0),
+ /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
+ DECODE_EMULATEX (0x0ff00090, 0x01600080, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, 0, NOPC, 0, NOPC)),
+
+ /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */
+ DECODE_OR (0x0ff00090, 0x01000080),
+ /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */
+ DECODE_EMULATEX (0x0ff000b0, 0x01200080, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_0000_____1001_table[] = {
+ /* Multiply and multiply-accumulate */
+
+ /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */
+ /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */
+ DECODE_EMULATEX (0x0fe000f0, 0x00000090, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, 0, NOPC, 0, NOPC)),
+
+ /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */
+ /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */
+ DECODE_OR (0x0fe000f0, 0x00200090),
+ /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */
+ DECODE_EMULATEX (0x0ff000f0, 0x00600090, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+ /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */
+ DECODE_OR (0x0ff000f0, 0x00400090),
+ /* UMULL cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */
+ /* UMULLS cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */
+ /* UMLAL cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */
+ /* UMLALS cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */
+ /* SMULL cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */
+ /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */
+ /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */
+ /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */
+ DECODE_EMULATEX (0x0f8000f0, 0x00800090, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
+ REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_0001_____1001_table[] = {
+ /* Synchronization primitives */
+
+#if __LINUX_ARM_ARCH__ < 6
+ /* Deprecated on ARMv6 and may be UNDEFINED on v7 */
+ /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */
+ DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(NOPC, NOPC, 0, 0, NOPC)),
+#endif
+ /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */
+ /* And unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_000x_____1xx1_table[] = {
+ /* Extra load/store instructions */
+
+ /* STRHT cccc 0000 xx10 xxxx xxxx xxxx 1011 xxxx */
+ /* ??? cccc 0000 xx10 xxxx xxxx xxxx 11x1 xxxx */
+ /* LDRHT cccc 0000 xx11 xxxx xxxx xxxx 1011 xxxx */
+ /* LDRSBT cccc 0000 xx11 xxxx xxxx xxxx 1101 xxxx */
+ /* LDRSHT cccc 0000 xx11 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_REJECT (0x0f200090, 0x00200090),
+
+ /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */
+ DECODE_REJECT (0x0e10e0d0, 0x0000e0d0),
+
+ /* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */
+ /* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_EMULATEX (0x0e5000d0, 0x000000d0, emulate_ldrdstrd,
+ REGS(NOPCWB, NOPCX, 0, 0, NOPC)),
+
+ /* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */
+ /* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_EMULATEX (0x0e5000d0, 0x004000d0, emulate_ldrdstrd,
+ REGS(NOPCWB, NOPCX, 0, 0, 0)),
+
+ /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */
+ DECODE_EMULATEX (0x0e5000f0, 0x000000b0, emulate_str,
+ REGS(NOPCWB, NOPC, 0, 0, NOPC)),
+
+ /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */
+ /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */
+ /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_EMULATEX (0x0e500090, 0x00100090, emulate_ldr,
+ REGS(NOPCWB, NOPC, 0, 0, NOPC)),
+
+ /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */
+ DECODE_EMULATEX (0x0e5000f0, 0x004000b0, emulate_str,
+ REGS(NOPCWB, NOPC, 0, 0, 0)),
+
+ /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */
+ /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */
+ /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_EMULATEX (0x0e500090, 0x00500090, emulate_ldr,
+ REGS(NOPCWB, NOPC, 0, 0, 0)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_000x_table[] = {
+ /* Data-processing (register) */
+
+ /* <op>S PC, ... cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */
+ DECODE_REJECT (0x0e10f000, 0x0010f000),
+
+ /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */
+ DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, simulate_mov_ipsp),
+
+ /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */
+ /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */
+ /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */
+ /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */
+ DECODE_EMULATEX (0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(ANY, 0, 0, 0, ANY)),
+
+ /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */
+ /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */
+ DECODE_EMULATEX (0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(0, ANY, 0, 0, ANY)),
+
+ /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */
+ /* EOR (register) cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */
+ /* SUB (register) cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */
+ /* RSB (register) cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */
+ /* ADD (register) cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */
+ /* ADC (register) cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */
+ /* SBC (register) cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */
+ /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */
+ /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */
+ /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */
+ DECODE_EMULATEX (0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(ANY, ANY, 0, 0, ANY)),
+
+ /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */
+ /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */
+ /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */
+ /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */
+ DECODE_EMULATEX (0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(ANY, 0, NOPC, 0, ANY)),
+
+ /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */
+ /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */
+ DECODE_EMULATEX (0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(0, ANY, NOPC, 0, ANY)),
+
+ /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */
+ /* EOR (reg-shift reg) cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */
+ /* SUB (reg-shift reg) cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */
+ /* RSB (reg-shift reg) cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */
+ /* ADD (reg-shift reg) cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */
+ /* ADC (reg-shift reg) cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */
+ /* SBC (reg-shift reg) cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */
+ /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */
+ /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */
+ /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */
+ DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(ANY, ANY, NOPC, 0, ANY)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_001x_table[] = {
+ /* Data-processing (immediate) */
+
+ /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
+ /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0fb00000, 0x03000000, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, 0)),
+
+ /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
+ DECODE_OR (0x0fff00ff, 0x03200001),
+ /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
+ DECODE_EMULATE (0x0fff00ff, 0x03200004, kprobe_emulate_none),
+ /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
+ /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
+ /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
+ DECODE_SIMULATE (0x0fff00fc, 0x03200000, kprobe_simulate_nop),
+ /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */
+ /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
+ /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0x0fb00000, 0x03200000),
+
+ /* <op>S PC, ... cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */
+ DECODE_REJECT (0x0e10f000, 0x0210f000),
+
+ /* TST (immediate) cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */
+ /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */
+ /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */
+ /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(ANY, 0, 0, 0, 0)),
+
+ /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */
+ /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(0, ANY, 0, 0, 0)),
+
+ /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */
+ /* EOR (immediate) cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */
+ /* SUB (immediate) cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */
+ /* RSB (immediate) cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */
+ /* ADD (immediate) cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */
+ /* ADC (immediate) cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */
+ /* SBC (immediate) cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */
+ /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */
+ /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */
+ /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(ANY, ANY, 0, 0, 0)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_0110_____xxx1_table[] = {
+ /* Media instructions */
+
+ /* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */
+ DECODE_EMULATEX (0x0ff000f0, 0x068000b0, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+ /* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */
+ /* USAT cccc 0110 111x xxxx xxxx xxxx xx01 xxxx */
+ DECODE_OR(0x0fa00030, 0x06a00010),
+ /* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */
+ /* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */
+ DECODE_EMULATEX (0x0fb000f0, 0x06a00030, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(0, NOPC, 0, 0, NOPC)),
+
+ /* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
+ /* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
+ /* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
+ /* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
+ DECODE_EMULATEX (0x0fb00070, 0x06b00030, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, NOPC)),
+
+ /* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */
+ DECODE_REJECT (0x0fb00010, 0x06000010),
+ /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1011 xxxx */
+ DECODE_REJECT (0x0f8000f0, 0x060000b0),
+ /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1101 xxxx */
+ DECODE_REJECT (0x0f8000f0, 0x060000d0),
+ /* SADD16 cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx */
+ /* SADDSUBX cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx */
+ /* SSUBADDX cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx */
+ /* SSUB16 cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx */
+ /* SADD8 cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx */
+ /* SSUB8 cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx */
+ /* QADD16 cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx */
+ /* QADDSUBX cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx */
+ /* QSUBADDX cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx */
+ /* QSUB16 cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx */
+ /* QADD8 cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx */
+ /* QSUB8 cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx */
+ /* SHADD16 cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx */
+ /* SHADDSUBX cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx */
+ /* SHSUBADDX cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx */
+ /* SHSUB16 cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx */
+ /* SHADD8 cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx */
+ /* SHSUB8 cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx */
+ /* UADD16 cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx */
+ /* UADDSUBX cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx */
+ /* USUBADDX cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx */
+ /* USUB16 cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx */
+ /* UADD8 cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx */
+ /* USUB8 cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx */
+ /* UQADD16 cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx */
+ /* UQADDSUBX cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx */
+ /* UQSUBADDX cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx */
+ /* UQSUB16 cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx */
+ /* UQADD8 cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx */
+ /* UQSUB8 cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx */
+ /* UHADD16 cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx */
+ /* UHADDSUBX cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx */
+ /* UHSUBADDX cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx */
+ /* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */
+ /* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */
+ /* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_EMULATEX (0x0f800010, 0x06000010, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+ /* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */
+ /* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */
+ DECODE_EMULATEX (0x0ff00030, 0x06800010, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+ /* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */
+ /* ??? cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx */
+ DECODE_REJECT (0x0fb000f0, 0x06900070),
+
+ /* SXTB16 cccc 0110 1000 1111 xxxx xxxx 0111 xxxx */
+ /* SXTB cccc 0110 1010 1111 xxxx xxxx 0111 xxxx */
+ /* SXTH cccc 0110 1011 1111 xxxx xxxx 0111 xxxx */
+ /* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */
+ /* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */
+ /* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */
+ DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, NOPC)),
+
+ /* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */
+ /* SXTAB cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx */
+ /* SXTAH cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx */
+ /* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */
+ /* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */
+ /* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */
+ DECODE_EMULATEX (0x0f8000f0, 0x06800070, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(NOPCX, NOPC, 0, 0, NOPC)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_0111_____xxx1_table[] = {
+ /* Media instructions */
+
+ /* UNDEFINED cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_REJECT (0x0ff000f0, 0x07f000f0),
+
+ /* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
+ /* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
+ DECODE_EMULATEX (0x0ff00090, 0x07400010, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
+ REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+ /* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */
+ /* SMUSD cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx */
+ DECODE_OR (0x0ff0f090, 0x0700f010),
+ /* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */
+ DECODE_OR (0x0ff0f0d0, 0x0750f010),
+ /* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */
+ DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, 0, NOPC, 0, NOPC)),
+
+ /* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */
+ /* SMLSD cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx */
+ DECODE_OR (0x0ff00090, 0x07000010),
+ /* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */
+ DECODE_OR (0x0ff000d0, 0x07500010),
+ /* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */
+ DECODE_EMULATEX (0x0ff000f0, 0x07800010, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, NOPCX, NOPC, 0, NOPC)),
+
+ /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */
+ DECODE_EMULATEX (0x0ff000d0, 0x075000d0, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+ /* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */
+ /* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */
+ DECODE_EMULATEX (0x0fa00070, 0x07a00050, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, NOPC)),
+
+ /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */
+ DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, 0)),
+
+ /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */
+ DECODE_EMULATEX (0x0fe00070, 0x07c00010, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, NOPCX)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_01xx_table[] = {
+ /* Load/store word and unsigned byte */
+
+ /* LDRB/STRB pc,[...] cccc 01xx x0xx xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0x0c40f000, 0x0440f000),
+
+ /* STRT cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRT cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */
+ /* STRBT cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRBT cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0x0d200000, 0x04200000),
+
+ /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */
+ /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0e100000, 0x04000000, emulate_str,
+ REGS(NOPCWB, ANY, 0, 0, 0)),
+
+ /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0e100000, 0x04100000, emulate_ldr,
+ REGS(NOPCWB, ANY, 0, 0, 0)),
+
+ /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */
+ /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0e100000, 0x06000000, emulate_str,
+ REGS(NOPCWB, ANY, 0, 0, NOPC)),
+
+ /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0e100000, 0x06100000, emulate_ldr,
+ REGS(NOPCWB, ANY, 0, 0, NOPC)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_100x_table[] = {
+ /* Block data transfer instructions */
+
+ /* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
+ /* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_CUSTOM (0x0e400000, 0x08000000, kprobe_decode_ldmstm),
+
+ /* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
+ /* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */
+ /* LDM (exception ret) cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */
+ DECODE_END
+};
+
+const union decode_item kprobe_decode_arm_table[] = {
+ /*
+ * Unconditional instructions
+ * 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xf0000000, 0xf0000000, arm_1111_table),
+
+ /*
+ * Miscellaneous instructions
+ * cccc 0001 0xx0 xxxx xxxx xxxx 0xxx xxxx
+ */
+ DECODE_TABLE (0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table),
+
+ /*
+ * Halfword multiply and multiply-accumulate
+ * cccc 0001 0xx0 xxxx xxxx xxxx 1xx0 xxxx
+ */
+ DECODE_TABLE (0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table),
+
+ /*
+ * Multiply and multiply-accumulate
+ * cccc 0000 xxxx xxxx xxxx xxxx 1001 xxxx
+ */
+ DECODE_TABLE (0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table),
+
+ /*
+ * Synchronization primitives
+ * cccc 0001 xxxx xxxx xxxx xxxx 1001 xxxx
+ */
+ DECODE_TABLE (0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table),
+
+ /*
+ * Extra load/store instructions
+ * cccc 000x xxxx xxxx xxxx xxxx 1xx1 xxxx
+ */
+ DECODE_TABLE (0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table),
+
+ /*
+ * Data-processing (register)
+ * cccc 000x xxxx xxxx xxxx xxxx xxx0 xxxx
+ * Data-processing (register-shifted register)
+ * cccc 000x xxxx xxxx xxxx xxxx 0xx1 xxxx
+ */
+ DECODE_TABLE (0x0e000000, 0x00000000, arm_cccc_000x_table),
+
+ /*
+ * Data-processing (immediate)
+ * cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0x0e000000, 0x02000000, arm_cccc_001x_table),
+
+ /*
+ * Media instructions
+ * cccc 011x xxxx xxxx xxxx xxxx xxx1 xxxx
+ */
+ DECODE_TABLE (0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table),
+ DECODE_TABLE (0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table),
+
+ /*
+ * Load/store word and unsigned byte
+ * cccc 01xx xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0x0c000000, 0x04000000, arm_cccc_01xx_table),
+
+ /*
+ * Block data transfer instructions
+ * cccc 100x xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0x0e000000, 0x08000000, arm_cccc_100x_table),
+
+ /* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
+ /* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
+ DECODE_SIMULATE (0x0e000000, 0x0a000000, simulate_bbl),
+
+ /*
+ * Supervisor Call, and coprocessor instructions
+ */
+
+ /* MCRR cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx */
+ /* MRRC cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx */
+ /* LDC cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
+ /* STC cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
+ /* CDP cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
+ /* MCR cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
+ /* MRC cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
+ /* SVC cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0x0c000000, 0x0c000000),
+
+ DECODE_END
+};
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_arm_table);
+#endif
+
+static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->ARM_pc += 4;
+ p->ainsn.insn_handler(p, regs);
+}
+
+/* Return:
+ * INSN_REJECTED If instruction is one not allowed to kprobe,
+ * INSN_GOOD If instruction is supported and uses instruction slot,
+ * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
+ *
+ * For instructions we don't want to kprobe (INSN_REJECTED return result):
+ * These are generally ones that modify the processor state making
+ * them "hard" to simulate such as switches processor modes or
+ * make accesses in alternate modes. Any of these could be simulated
+ * if the work was put into it, but low return considering they
+ * should also be very rare.
+ */
+enum kprobe_insn __kprobes
+arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ asi->insn_singlestep = arm_singlestep;
+ asi->insn_check_cc = kprobe_condition_checks[insn>>28];
+ return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false);
+}
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
new file mode 100644
index 0000000..a5394fb4
--- /dev/null
+++ b/arch/arm/kernel/kprobes-common.c
@@ -0,0 +1,577 @@
+/*
+ * arch/arm/kernel/kprobes-common.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is
+ * Copyright (C) 2006, 2007 Motorola Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+
+#include "kprobes.h"
+
+
+#ifndef find_str_pc_offset
+
+/*
+ * For STR and STM instructions, an ARM core may choose to use either
+ * a +8 or a +12 displacement from the current instruction's address.
+ * Whichever value is chosen for a given core, it must be the same for
+ * both instructions and may not change. This function measures it.
+ */
+
+int str_pc_offset;
+
+void __init find_str_pc_offset(void)
+{
+ int addr, scratch, ret;
+
+ __asm__ (
+ "sub %[ret], pc, #4 \n\t"
+ "str pc, %[addr] \n\t"
+ "ldr %[scr], %[addr] \n\t"
+ "sub %[ret], %[scr], %[ret] \n\t"
+ : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
+
+ str_pc_offset = ret;
+}
+
+#endif /* !find_str_pc_offset */
+
+
+#ifndef test_load_write_pc_interworking
+
+bool load_write_pc_interworks;
+
+void __init test_load_write_pc_interworking(void)
+{
+ int arch = cpu_architecture();
+ BUG_ON(arch == CPU_ARCH_UNKNOWN);
+ load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T;
+}
+
+#endif /* !test_load_write_pc_interworking */
+
+
+#ifndef test_alu_write_pc_interworking
+
+bool alu_write_pc_interworks;
+
+void __init test_alu_write_pc_interworking(void)
+{
+ int arch = cpu_architecture();
+ BUG_ON(arch == CPU_ARCH_UNKNOWN);
+ alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7;
+}
+
+#endif /* !test_alu_write_pc_interworking */
+
+
+void __init arm_kprobe_decode_init(void)
+{
+ find_str_pc_offset();
+ test_load_write_pc_interworking();
+ test_alu_write_pc_interworking();
+}
+
+
+static unsigned long __kprobes __check_eq(unsigned long cpsr)
+{
+ return cpsr & PSR_Z_BIT;
+}
+
+static unsigned long __kprobes __check_ne(unsigned long cpsr)
+{
+ return (~cpsr) & PSR_Z_BIT;
+}
+
+static unsigned long __kprobes __check_cs(unsigned long cpsr)
+{
+ return cpsr & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_cc(unsigned long cpsr)
+{
+ return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_mi(unsigned long cpsr)
+{
+ return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_pl(unsigned long cpsr)
+{
+ return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_vs(unsigned long cpsr)
+{
+ return cpsr & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_vc(unsigned long cpsr)
+{
+ return (~cpsr) & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_hi(unsigned long cpsr)
+{
+ cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+ return cpsr & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_ls(unsigned long cpsr)
+{
+ cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+ return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_ge(unsigned long cpsr)
+{
+ cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_lt(unsigned long cpsr)
+{
+ cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_gt(unsigned long cpsr)
+{
+ unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
+ return (~temp) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_le(unsigned long cpsr)
+{
+ unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
+ return temp & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_al(unsigned long cpsr)
+{
+ return true;
+}
+
+kprobe_check_cc * const kprobe_condition_checks[16] = {
+ &__check_eq, &__check_ne, &__check_cs, &__check_cc,
+ &__check_mi, &__check_pl, &__check_vs, &__check_vc,
+ &__check_hi, &__check_ls, &__check_ge, &__check_lt,
+ &__check_gt, &__check_le, &__check_al, &__check_al
+};
+
+
+void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs)
+{
+}
+
+void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs)
+{
+ p->ainsn.insn_fn();
+}
+
+static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rn = (insn >> 16) & 0xf;
+ int lbit = insn & (1 << 20);
+ int wbit = insn & (1 << 21);
+ int ubit = insn & (1 << 23);
+ int pbit = insn & (1 << 24);
+ long *addr = (long *)regs->uregs[rn];
+ int reg_bit_vector;
+ int reg_count;
+
+ reg_count = 0;
+ reg_bit_vector = insn & 0xffff;
+ while (reg_bit_vector) {
+ reg_bit_vector &= (reg_bit_vector - 1);
+ ++reg_count;
+ }
+
+ if (!ubit)
+ addr -= reg_count;
+ addr += (!pbit == !ubit);
+
+ reg_bit_vector = insn & 0xffff;
+ while (reg_bit_vector) {
+ int reg = __ffs(reg_bit_vector);
+ reg_bit_vector &= (reg_bit_vector - 1);
+ if (lbit)
+ regs->uregs[reg] = *addr++;
+ else
+ *addr++ = regs->uregs[reg];
+ }
+
+ if (wbit) {
+ if (!ubit)
+ addr -= reg_count;
+ addr -= (!pbit == !ubit);
+ regs->uregs[rn] = (long)addr;
+ }
+}
+
+static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->ARM_pc = (long)p->addr + str_pc_offset;
+ simulate_ldm1stm1(p, regs);
+ regs->ARM_pc = (long)p->addr + 4;
+}
+
+static void __kprobes simulate_ldm1_pc(struct kprobe *p, struct pt_regs *regs)
+{
+ simulate_ldm1stm1(p, regs);
+ load_write_pc(regs->ARM_pc, regs);
+}
+
+static void __kprobes
+emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+ register void *rregs asm("r1") = regs;
+ register void *rfn asm("lr") = p->ainsn.insn_fn;
+
+ __asm__ __volatile__ (
+ "stmdb sp!, {%[regs], r11} \n\t"
+ "ldmia %[regs], {r0-r12} \n\t"
+#if __LINUX_ARM_ARCH__ >= 6
+ "blx %[fn] \n\t"
+#else
+ "str %[fn], [sp, #-4]! \n\t"
+ "adr lr, 1f \n\t"
+ "ldr pc, [sp], #4 \n\t"
+ "1: \n\t"
+#endif
+ "ldr lr, [sp], #4 \n\t" /* lr = regs */
+ "stmia lr, {r0-r12} \n\t"
+ "ldr r11, [sp], #4 \n\t"
+ : [regs] "=r" (rregs), [fn] "=r" (rfn)
+ : "0" (rregs), "1" (rfn)
+ : "r0", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r12", "memory", "cc"
+ );
+}
+
+static void __kprobes
+emulate_generic_r2_14_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+ emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+2));
+}
+
+static void __kprobes
+emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs)
+{
+ emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+3));
+ load_write_pc(regs->ARM_pc, regs);
+}
+
+enum kprobe_insn __kprobes
+kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ kprobe_insn_handler_t *handler = 0;
+ unsigned reglist = insn & 0xffff;
+ int is_ldm = insn & 0x100000;
+ int rn = (insn >> 16) & 0xf;
+
+ if (rn <= 12 && (reglist & 0xe000) == 0) {
+ /* Instruction only uses registers in the range R0..R12 */
+ handler = emulate_generic_r0_12_noflags;
+
+ } else if (rn >= 2 && (reglist & 0x8003) == 0) {
+ /* Instruction only uses registers in the range R2..R14 */
+ rn -= 2;
+ reglist >>= 2;
+ handler = emulate_generic_r2_14_noflags;
+
+ } else if (rn >= 3 && (reglist & 0x0007) == 0) {
+ /* Instruction only uses registers in the range R3..R15 */
+ if (is_ldm && (reglist & 0x8000)) {
+ rn -= 3;
+ reglist >>= 3;
+ handler = emulate_ldm_r3_15;
+ }
+ }
+
+ if (handler) {
+ /* We can emulate the instruction in (possibly) modified form */
+ asi->insn[0] = (insn & 0xfff00000) | (rn << 16) | reglist;
+ asi->insn_handler = handler;
+ return INSN_GOOD;
+ }
+
+ /* Fallback to slower simulation... */
+ if (reglist & 0x8000)
+ handler = is_ldm ? simulate_ldm1_pc : simulate_stm1_pc;
+ else
+ handler = simulate_ldm1stm1;
+ asi->insn_handler = handler;
+ return INSN_GOOD_NO_SLOT;
+}
+
+
+/*
+ * Prepare an instruction slot to receive an instruction for emulating.
+ * This is done by placing a subroutine return after the location where the
+ * instruction will be placed. We also modify ARM instructions to be
+ * unconditional as the condition code will already be checked before any
+ * emulation handler is called.
+ */
+static kprobe_opcode_t __kprobes
+prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ bool thumb)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+ if (thumb) {
+ u16 *thumb_insn = (u16 *)asi->insn;
+ thumb_insn[1] = 0x4770; /* Thumb bx lr */
+ thumb_insn[2] = 0x4770; /* Thumb bx lr */
+ return insn;
+ }
+ asi->insn[1] = 0xe12fff1e; /* ARM bx lr */
+#else
+ asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */
+#endif
+ /* Make an ARM instruction unconditional */
+ if (insn < 0xe0000000)
+ insn = (insn | 0xe0000000) & ~0x10000000;
+ return insn;
+}
+
+/*
+ * Write a (probably modified) instruction into the slot previously prepared by
+ * prepare_emulated_insn
+ */
+static void __kprobes
+set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ bool thumb)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+ if (thumb) {
+ u16 *ip = (u16 *)asi->insn;
+ if (is_wide_instruction(insn))
+ *ip++ = insn >> 16;
+ *ip++ = insn;
+ return;
+ }
+#endif
+ asi->insn[0] = insn;
+}
+
+/*
+ * When we modify the register numbers encoded in an instruction to be emulated,
+ * the new values come from this define. For ARM and 32-bit Thumb instructions
+ * this gives...
+ *
+ * bit position 16 12 8 4 0
+ * ---------------+---+---+---+---+---+
+ * register r2 r0 r1 -- r3
+ */
+#define INSN_NEW_BITS 0x00020103
+
+/* Each nibble has same value as that at INSN_NEW_BITS bit 16 */
+#define INSN_SAMEAS16_BITS 0x22222222
+
+/*
+ * Validate and modify each of the registers encoded in an instruction.
+ *
+ * Each nibble in regs contains a value from enum decode_reg_type. For each
+ * non-zero value, the corresponding nibble in pinsn is validated and modified
+ * according to the type.
+ */
+static bool __kprobes decode_regs(kprobe_opcode_t* pinsn, u32 regs)
+{
+ kprobe_opcode_t insn = *pinsn;
+ kprobe_opcode_t mask = 0xf; /* Start at least significant nibble */
+
+ for (; regs != 0; regs >>= 4, mask <<= 4) {
+
+ kprobe_opcode_t new_bits = INSN_NEW_BITS;
+
+ switch (regs & 0xf) {
+
+ case REG_TYPE_NONE:
+ /* Nibble not a register, skip to next */
+ continue;
+
+ case REG_TYPE_ANY:
+ /* Any register is allowed */
+ break;
+
+ case REG_TYPE_SAMEAS16:
+ /* Replace register with same as at bit position 16 */
+ new_bits = INSN_SAMEAS16_BITS;
+ break;
+
+ case REG_TYPE_SP:
+ /* Only allow SP (R13) */
+ if ((insn ^ 0xdddddddd) & mask)
+ goto reject;
+ break;
+
+ case REG_TYPE_PC:
+ /* Only allow PC (R15) */
+ if ((insn ^ 0xffffffff) & mask)
+ goto reject;
+ break;
+
+ case REG_TYPE_NOSP:
+ /* Reject SP (R13) */
+ if (((insn ^ 0xdddddddd) & mask) == 0)
+ goto reject;
+ break;
+
+ case REG_TYPE_NOSPPC:
+ case REG_TYPE_NOSPPCX:
+ /* Reject SP and PC (R13 and R15) */
+ if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0)
+ goto reject;
+ break;
+
+ case REG_TYPE_NOPCWB:
+ if (!is_writeback(insn))
+ break; /* No writeback, so any register is OK */
+ /* fall through... */
+ case REG_TYPE_NOPC:
+ case REG_TYPE_NOPCX:
+ /* Reject PC (R15) */
+ if (((insn ^ 0xffffffff) & mask) == 0)
+ goto reject;
+ break;
+ }
+
+ /* Replace value of nibble with new register number... */
+ insn &= ~mask;
+ insn |= new_bits & mask;
+ }
+
+ *pinsn = insn;
+ return true;
+
+reject:
+ return false;
+}
+
+static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
+ [DECODE_TYPE_TABLE] = sizeof(struct decode_table),
+ [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom),
+ [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate),
+ [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate),
+ [DECODE_TYPE_OR] = sizeof(struct decode_or),
+ [DECODE_TYPE_REJECT] = sizeof(struct decode_reject)
+};
+
+/*
+ * kprobe_decode_insn operates on data tables in order to decode an ARM
+ * architecture instruction onto which a kprobe has been placed.
+ *
+ * These instruction decoding tables are a concatenation of entries each
+ * of which consist of one of the following structs:
+ *
+ * decode_table
+ * decode_custom
+ * decode_simulate
+ * decode_emulate
+ * decode_or
+ * decode_reject
+ *
+ * Each of these starts with a struct decode_header which has the following
+ * fields:
+ *
+ * type_regs
+ * mask
+ * value
+ *
+ * The least significant DECODE_TYPE_BITS of type_regs contains a value
+ * from enum decode_type, this indicates which of the decode_* structs
+ * the entry contains. The value DECODE_TYPE_END indicates the end of the
+ * table.
+ *
+ * When the table is parsed, each entry is checked in turn to see if it
+ * matches the instruction to be decoded using the test:
+ *
+ * (insn & mask) == value
+ *
+ * If no match is found before the end of the table is reached then decoding
+ * fails with INSN_REJECTED.
+ *
+ * When a match is found, decode_regs() is called to validate and modify each
+ * of the registers encoded in the instruction; the data it uses to do this
+ * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding
+ * to fail with INSN_REJECTED.
+ *
+ * Once the instruction has passed the above tests, further processing
+ * depends on the type of the table entry's decode struct.
+ *
+ */
+int __kprobes
+kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ const union decode_item *table, bool thumb)
+{
+ const struct decode_header *h = (struct decode_header *)table;
+ const struct decode_header *next;
+ bool matched = false;
+
+ insn = prepare_emulated_insn(insn, asi, thumb);
+
+ for (;; h = next) {
+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+ u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS;
+
+ if (type == DECODE_TYPE_END)
+ return INSN_REJECTED;
+
+ next = (struct decode_header *)
+ ((uintptr_t)h + decode_struct_sizes[type]);
+
+ if (!matched && (insn & h->mask.bits) != h->value.bits)
+ continue;
+
+ if (!decode_regs(&insn, regs))
+ return INSN_REJECTED;
+
+ switch (type) {
+
+ case DECODE_TYPE_TABLE: {
+ struct decode_table *d = (struct decode_table *)h;
+ next = (struct decode_header *)d->table.table;
+ break;
+ }
+
+ case DECODE_TYPE_CUSTOM: {
+ struct decode_custom *d = (struct decode_custom *)h;
+ return (*d->decoder.decoder)(insn, asi);
+ }
+
+ case DECODE_TYPE_SIMULATE: {
+ struct decode_simulate *d = (struct decode_simulate *)h;
+ asi->insn_handler = d->handler.handler;
+ return INSN_GOOD_NO_SLOT;
+ }
+
+ case DECODE_TYPE_EMULATE: {
+ struct decode_emulate *d = (struct decode_emulate *)h;
+ asi->insn_handler = d->handler.handler;
+ set_emulated_insn(insn, asi, thumb);
+ return INSN_GOOD;
+ }
+
+ case DECODE_TYPE_OR:
+ matched = true;
+ break;
+
+ case DECODE_TYPE_REJECT:
+ default:
+ return INSN_REJECTED;
+ }
+ }
+ }
diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c
new file mode 100644
index 0000000..ba32b39
--- /dev/null
+++ b/arch/arm/kernel/kprobes-test-arm.c
@@ -0,0 +1,1330 @@
+/*
+ * arch/arm/kernel/kprobes-test-arm.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "kprobes-test.h"
+
+
+#define TEST_ISA "32"
+
+#define TEST_ARM_TO_THUMB_INTERWORK_R(code1, reg, val, code2) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_REG(reg, val) \
+ TEST_ARG_REG(14, 99f) \
+ TEST_ARG_END("") \
+ "50: nop \n\t" \
+ "1: "code1 #reg code2" \n\t" \
+ " bx lr \n\t" \
+ ".thumb \n\t" \
+ "3: adr lr, 2f \n\t" \
+ " bx lr \n\t" \
+ ".arm \n\t" \
+ "2: nop \n\t" \
+ TESTCASE_END
+
+#define TEST_ARM_TO_THUMB_INTERWORK_P(code1, reg, val, code2) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_PTR(reg, val) \
+ TEST_ARG_REG(14, 99f) \
+ TEST_ARG_MEM(15, 3f+1) \
+ TEST_ARG_END("") \
+ "50: nop \n\t" \
+ "1: "code1 #reg code2" \n\t" \
+ " bx lr \n\t" \
+ ".thumb \n\t" \
+ "3: adr lr, 2f \n\t" \
+ " bx lr \n\t" \
+ ".arm \n\t" \
+ "2: nop \n\t" \
+ TESTCASE_END
+
+
+void kprobe_arm_test_cases(void)
+{
+ kprobe_test_flags = 0;
+
+ TEST_GROUP("Data-processing (register), (register-shifted register), (immediate)")
+
+#define _DATA_PROCESSING_DNM(op,s,val) \
+ TEST_RR( op "eq" s " r0, r",1, VAL1,", r",2, val, "") \
+ TEST_RR( op "ne" s " r1, r",1, VAL1,", r",2, val, ", lsl #3") \
+ TEST_RR( op "cs" s " r2, r",3, VAL1,", r",2, val, ", lsr #4") \
+ TEST_RR( op "cc" s " r3, r",3, VAL1,", r",2, val, ", asr #5") \
+ TEST_RR( op "mi" s " r4, r",5, VAL1,", r",2, N(val),", asr #6") \
+ TEST_RR( op "pl" s " r5, r",5, VAL1,", r",2, val, ", ror #7") \
+ TEST_RR( op "vs" s " r6, r",7, VAL1,", r",2, val, ", rrx") \
+ TEST_R( op "vc" s " r6, r",7, VAL1,", pc, lsl #3") \
+ TEST_R( op "vc" s " r6, r",7, VAL1,", sp, lsr #4") \
+ TEST_R( op "vc" s " r6, pc, r",7, VAL1,", asr #5") \
+ TEST_R( op "vc" s " r6, sp, r",7, VAL1,", ror #6") \
+ TEST_RRR( op "hi" s " r8, r",9, VAL1,", r",14,val, ", lsl r",0, 3,"")\
+ TEST_RRR( op "ls" s " r9, r",9, VAL1,", r",14,val, ", lsr r",7, 4,"")\
+ TEST_RRR( op "ge" s " r10, r",11,VAL1,", r",14,val, ", asr r",7, 5,"")\
+ TEST_RRR( op "lt" s " r11, r",11,VAL1,", r",14,N(val),", asr r",7, 6,"")\
+ TEST_RR( op "gt" s " r12, r13" ", r",14,val, ", ror r",14,7,"")\
+ TEST_RR( op "le" s " r14, r",0, val, ", r13" ", lsl r",14,8,"")\
+ TEST_RR( op s " r12, pc" ", r",14,val, ", ror r",14,7,"")\
+ TEST_RR( op s " r14, r",0, val, ", pc" ", lsl r",14,8,"")\
+ TEST_R( op "eq" s " r0, r",11,VAL1,", #0xf5") \
+ TEST_R( op "ne" s " r11, r",0, VAL1,", #0xf5000000") \
+ TEST_R( op s " r7, r",8, VAL2,", #0x000af000") \
+ TEST( op s " r4, pc" ", #0x00005a00")
+
+#define DATA_PROCESSING_DNM(op,val) \
+ _DATA_PROCESSING_DNM(op,"",val) \
+ _DATA_PROCESSING_DNM(op,"s",val)
+
+#define DATA_PROCESSING_NM(op,val) \
+ TEST_RR( op "ne r",1, VAL1,", r",2, val, "") \
+ TEST_RR( op "eq r",1, VAL1,", r",2, val, ", lsl #3") \
+ TEST_RR( op "cc r",3, VAL1,", r",2, val, ", lsr #4") \
+ TEST_RR( op "cs r",3, VAL1,", r",2, val, ", asr #5") \
+ TEST_RR( op "pl r",5, VAL1,", r",2, N(val),", asr #6") \
+ TEST_RR( op "mi r",5, VAL1,", r",2, val, ", ror #7") \
+ TEST_RR( op "vc r",7, VAL1,", r",2, val, ", rrx") \
+ TEST_R ( op "vs r",7, VAL1,", pc, lsl #3") \
+ TEST_R ( op "vs r",7, VAL1,", sp, lsr #4") \
+ TEST_R( op "vs pc, r",7, VAL1,", asr #5") \
+ TEST_R( op "vs sp, r",7, VAL1,", ror #6") \
+ TEST_RRR( op "ls r",9, VAL1,", r",14,val, ", lsl r",0, 3,"") \
+ TEST_RRR( op "hi r",9, VAL1,", r",14,val, ", lsr r",7, 4,"") \
+ TEST_RRR( op "lt r",11,VAL1,", r",14,val, ", asr r",7, 5,"") \
+ TEST_RRR( op "ge r",11,VAL1,", r",14,N(val),", asr r",7, 6,"") \
+ TEST_RR( op "le r13" ", r",14,val, ", ror r",14,7,"") \
+ TEST_RR( op "gt r",0, val, ", r13" ", lsl r",14,8,"") \
+ TEST_RR( op " pc" ", r",14,val, ", ror r",14,7,"") \
+ TEST_RR( op " r",0, val, ", pc" ", lsl r",14,8,"") \
+ TEST_R( op "eq r",11,VAL1,", #0xf5") \
+ TEST_R( op "ne r",0, VAL1,", #0xf5000000") \
+ TEST_R( op " r",8, VAL2,", #0x000af000")
+
+#define _DATA_PROCESSING_DM(op,s,val) \
+ TEST_R( op "eq" s " r0, r",1, val, "") \
+ TEST_R( op "ne" s " r1, r",1, val, ", lsl #3") \
+ TEST_R( op "cs" s " r2, r",3, val, ", lsr #4") \
+ TEST_R( op "cc" s " r3, r",3, val, ", asr #5") \
+ TEST_R( op "mi" s " r4, r",5, N(val),", asr #6") \
+ TEST_R( op "pl" s " r5, r",5, val, ", ror #7") \
+ TEST_R( op "vs" s " r6, r",10,val, ", rrx") \
+ TEST( op "vs" s " r7, pc, lsl #3") \
+ TEST( op "vs" s " r7, sp, lsr #4") \
+ TEST_RR( op "vc" s " r8, r",7, val, ", lsl r",0, 3,"") \
+ TEST_RR( op "hi" s " r9, r",9, val, ", lsr r",7, 4,"") \
+ TEST_RR( op "ls" s " r10, r",9, val, ", asr r",7, 5,"") \
+ TEST_RR( op "ge" s " r11, r",11,N(val),", asr r",7, 6,"") \
+ TEST_RR( op "lt" s " r12, r",11,val, ", ror r",14,7,"") \
+ TEST_R( op "gt" s " r14, r13" ", lsl r",14,8,"") \
+ TEST_R( op "le" s " r14, pc" ", lsl r",14,8,"") \
+ TEST( op "eq" s " r0, #0xf5") \
+ TEST( op "ne" s " r11, #0xf5000000") \
+ TEST( op s " r7, #0x000af000") \
+ TEST( op s " r4, #0x00005a00")
+
+#define DATA_PROCESSING_DM(op,val) \
+ _DATA_PROCESSING_DM(op,"",val) \
+ _DATA_PROCESSING_DM(op,"s",val)
+
+ DATA_PROCESSING_DNM("and",0xf00f00ff)
+ DATA_PROCESSING_DNM("eor",0xf00f00ff)
+ DATA_PROCESSING_DNM("sub",VAL2)
+ DATA_PROCESSING_DNM("rsb",VAL2)
+ DATA_PROCESSING_DNM("add",VAL2)
+ DATA_PROCESSING_DNM("adc",VAL2)
+ DATA_PROCESSING_DNM("sbc",VAL2)
+ DATA_PROCESSING_DNM("rsc",VAL2)
+ DATA_PROCESSING_NM("tst",0xf00f00ff)
+ DATA_PROCESSING_NM("teq",0xf00f00ff)
+ DATA_PROCESSING_NM("cmp",VAL2)
+ DATA_PROCESSING_NM("cmn",VAL2)
+ DATA_PROCESSING_DNM("orr",0xf00f00ff)
+ DATA_PROCESSING_DM("mov",VAL2)
+ DATA_PROCESSING_DNM("bic",0xf00f00ff)
+ DATA_PROCESSING_DM("mvn",VAL2)
+
+ TEST("mov ip, sp") /* This has special case emulation code */
+
+ TEST_SUPPORTED("mov pc, #0x1000");
+ TEST_SUPPORTED("mov sp, #0x1000");
+ TEST_SUPPORTED("cmp pc, #0x1000");
+ TEST_SUPPORTED("cmp sp, #0x1000");
+
+ /* Data-processing with PC as shift*/
+ TEST_UNSUPPORTED(".word 0xe15c0f1e @ cmp r12, r14, asl pc")
+ TEST_UNSUPPORTED(".word 0xe1a0cf1e @ mov r12, r14, asl pc")
+ TEST_UNSUPPORTED(".word 0xe08caf1e @ add r10, r12, r14, asl pc")
+
+ /* Data-processing with PC as shift*/
+ TEST_UNSUPPORTED("movs pc, r1")
+ TEST_UNSUPPORTED("movs pc, r1, lsl r2")
+ TEST_UNSUPPORTED("movs pc, #0x10000")
+ TEST_UNSUPPORTED("adds pc, lr, r1")
+ TEST_UNSUPPORTED("adds pc, lr, r1, lsl r2")
+ TEST_UNSUPPORTED("adds pc, lr, #4")
+
+ /* Data-processing with SP as target */
+ TEST("add sp, sp, #16")
+ TEST("sub sp, sp, #8")
+ TEST("bic sp, sp, #0x20")
+ TEST("orr sp, sp, #0x20")
+ TEST_PR( "add sp, r",10,0,", r",11,4,"")
+ TEST_PRR("add sp, r",10,0,", r",11,4,", asl r",12,1,"")
+ TEST_P( "mov sp, r",10,0,"")
+ TEST_PR( "mov sp, r",10,0,", asl r",12,0,"")
+
+ /* Data-processing with PC as target */
+ TEST_BF( "add pc, pc, #2f-1b-8")
+ TEST_BF_R ("add pc, pc, r",14,2f-1f-8,"")
+ TEST_BF_R ("add pc, r",14,2f-1f-8,", pc")
+ TEST_BF_R ("mov pc, r",0,2f,"")
+ TEST_BF_RR("mov pc, r",0,2f,", asl r",1,0,"")
+ TEST_BB( "sub pc, pc, #1b-2b+8")
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_BB( "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before ARMv6 */
+#endif
+ TEST_BB_R( "sub pc, pc, r",14, 1f-2f+8,"")
+ TEST_BB_R( "rsb pc, r",14,1f-2f+8,", pc")
+ TEST_RR( "add pc, pc, r",10,-2,", asl r",11,1,"")
+#ifdef CONFIG_THUMB2_KERNEL
+ TEST_ARM_TO_THUMB_INTERWORK_R("add pc, pc, r",0,3f-1f-8+1,"")
+ TEST_ARM_TO_THUMB_INTERWORK_R("sub pc, r",0,3f+8+1,", #8")
+#endif
+ TEST_GROUP("Miscellaneous instructions")
+
+ TEST("mrs r0, cpsr")
+ TEST("mrspl r7, cpsr")
+ TEST("mrs r14, cpsr")
+ TEST_UNSUPPORTED(".word 0xe10ff000 @ mrs r15, cpsr")
+ TEST_UNSUPPORTED("mrs r0, spsr")
+ TEST_UNSUPPORTED("mrs lr, spsr")
+
+ TEST_UNSUPPORTED("msr cpsr, r0")
+ TEST_UNSUPPORTED("msr cpsr_f, lr")
+ TEST_UNSUPPORTED("msr spsr, r0")
+
+ TEST_BF_R("bx r",0,2f,"")
+ TEST_BB_R("bx r",7,2f,"")
+ TEST_BF_R("bxeq r",14,2f,"")
+
+ TEST_R("clz r0, r",0, 0x0,"")
+ TEST_R("clzeq r7, r",14,0x1,"")
+ TEST_R("clz lr, r",7, 0xffffffff,"")
+ TEST( "clz r4, sp")
+ TEST_UNSUPPORTED(".word 0x016fff10 @ clz pc, r0")
+ TEST_UNSUPPORTED(".word 0x016f0f1f @ clz r0, pc")
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_UNSUPPORTED("bxj r0")
+#endif
+
+ TEST_BF_R("blx r",0,2f,"")
+ TEST_BB_R("blx r",7,2f,"")
+ TEST_BF_R("blxeq r",14,2f,"")
+ TEST_UNSUPPORTED(".word 0x0120003f @ blx pc")
+
+ TEST_RR( "qadd r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "qaddvs lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_R( "qadd lr, r",9, VAL2,", r13")
+ TEST_RR( "qsub r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "qsubvs lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_R( "qsub lr, r",9, VAL2,", r13")
+ TEST_RR( "qdadd r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "qdaddvs lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_R( "qdadd lr, r",9, VAL2,", r13")
+ TEST_RR( "qdsub r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "qdsubvs lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_R( "qdsub lr, r",9, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe101f050 @ qadd pc, r0, r1")
+ TEST_UNSUPPORTED(".word 0xe121f050 @ qsub pc, r0, r1")
+ TEST_UNSUPPORTED(".word 0xe141f050 @ qdadd pc, r0, r1")
+ TEST_UNSUPPORTED(".word 0xe161f050 @ qdsub pc, r0, r1")
+ TEST_UNSUPPORTED(".word 0xe16f2050 @ qdsub r2, r0, pc")
+ TEST_UNSUPPORTED(".word 0xe161205f @ qdsub r2, pc, r1")
+
+ TEST_UNSUPPORTED("bkpt 0xffff")
+ TEST_UNSUPPORTED("bkpt 0x0000")
+
+ TEST_UNSUPPORTED(".word 0xe1600070 @ smc #0")
+
+ TEST_GROUP("Halfword multiply and multiply-accumulate")
+
+ TEST_RRR( "smlabb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlabbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smlabb lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe10f3281 @ smlabb pc, r1, r2, r3")
+ TEST_RRR( "smlatb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlatbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smlatb lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe10f32a1 @ smlatb pc, r1, r2, r3")
+ TEST_RRR( "smlabt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlabtge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smlabt lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe10f32c1 @ smlabt pc, r1, r2, r3")
+ TEST_RRR( "smlatt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlattge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smlatt lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe10f32e1 @ smlatt pc, r1, r2, r3")
+
+ TEST_RRR( "smlawb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlawbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smlawb lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe12f3281 @ smlawb pc, r1, r2, r3")
+ TEST_RRR( "smlawt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlawtge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smlawt lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe12f32c1 @ smlawt pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe12032cf @ smlawt r0, pc, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe1203fc1 @ smlawt r0, r1, pc, r3")
+ TEST_UNSUPPORTED(".word 0xe120f2c1 @ smlawt r0, r1, r2, pc")
+
+ TEST_RR( "smulwb r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulwbge r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_R( "smulwb lr, r",1, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe12f02a1 @ smulwb pc, r1, r2")
+ TEST_RR( "smulwt r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulwtge r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_R( "smulwt lr, r",1, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe12f02e1 @ smulwt pc, r1, r2")
+
+ TEST_RRRR( "smlalbb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalbble r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "smlalbb r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe14f1382 @ smlalbb pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe141f382 @ smlalbb r1, pc, r2, r3")
+ TEST_RRRR( "smlaltb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlaltble r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "smlaltb r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe14f13a2 @ smlaltb pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe141f3a2 @ smlaltb r1, pc, r2, r3")
+ TEST_RRRR( "smlalbt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalbtle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "smlalbt r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe14f13c2 @ smlalbt pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe141f3c2 @ smlalbt r1, pc, r2, r3")
+ TEST_RRRR( "smlaltt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalttle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "smlaltt r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe14f13e2 @ smlalbb pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe140f3e2 @ smlalbb r0, pc, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe14013ef @ smlalbb r0, r1, pc, r3")
+ TEST_UNSUPPORTED(".word 0xe1401fe2 @ smlalbb r0, r1, r2, pc")
+
+ TEST_RR( "smulbb r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulbbge r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_R( "smulbb lr, r",1, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe16f0281 @ smulbb pc, r1, r2")
+ TEST_RR( "smultb r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smultbge r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_R( "smultb lr, r",1, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe16f02a1 @ smultb pc, r1, r2")
+ TEST_RR( "smulbt r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulbtge r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_R( "smulbt lr, r",1, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe16f02c1 @ smultb pc, r1, r2")
+ TEST_RR( "smultt r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulttge r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_R( "smultt lr, r",1, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe16f02e1 @ smultt pc, r1, r2")
+ TEST_UNSUPPORTED(".word 0xe16002ef @ smultt r0, pc, r2")
+ TEST_UNSUPPORTED(".word 0xe1600fe1 @ smultt r0, r1, pc")
+
+ TEST_GROUP("Multiply and multiply-accumulate")
+
+ TEST_RR( "mul r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "mulls r7, r",8, VAL2,", r",9, VAL2,"")
+ TEST_R( "mul lr, r",4, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe00f0291 @ mul pc, r1, r2")
+ TEST_UNSUPPORTED(".word 0xe000029f @ mul r0, pc, r2")
+ TEST_UNSUPPORTED(".word 0xe0000f91 @ mul r0, r1, pc")
+ TEST_RR( "muls r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "mullss r7, r",8, VAL2,", r",9, VAL2,"")
+ TEST_R( "muls lr, r",4, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe01f0291 @ muls pc, r1, r2")
+
+ TEST_RRR( "mla r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "mlahi r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "mla lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe02f3291 @ mla pc, r1, r2, r3")
+ TEST_RRR( "mlas r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "mlahis r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "mlas lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe03f3291 @ mlas pc, r1, r2, r3")
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_RR( "umaal r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "umaalls r7, r8, r",9, VAL2,", r",10, VAL1,"")
+ TEST_R( "umaal lr, r12, r",11,VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe041f392 @ umaal pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0500090 @ undef")
+ TEST_UNSUPPORTED(".word 0xe05fff9f @ undef")
+
+ TEST_RRR( "mls r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "mlshi r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "mls lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe06f3291 @ mls pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe060329f @ mls r0, pc, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0603f91 @ mls r0, r1, pc, r3")
+ TEST_UNSUPPORTED(".word 0xe060f291 @ mls r0, r1, r2, pc")
+#endif
+
+ TEST_UNSUPPORTED(".word 0xe0700090 @ undef")
+ TEST_UNSUPPORTED(".word 0xe07fff9f @ undef")
+
+ TEST_RR( "umull r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "umullls r7, r8, r",9, VAL2,", r",10, VAL1,"")
+ TEST_R( "umull lr, r12, r",11,VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe081f392 @ umull pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe08f1392 @ umull r1, pc, r2, r3")
+ TEST_RR( "umulls r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "umulllss r7, r8, r",9, VAL2,", r",10, VAL1,"")
+ TEST_R( "umulls lr, r12, r",11,VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe091f392 @ umulls pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe09f1392 @ umulls r1, pc, r2, r3")
+
+ TEST_RRRR( "umlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "umlalle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "umlal r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe0af1392 @ umlal pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0a1f392 @ umlal r1, pc, r2, r3")
+ TEST_RRRR( "umlals r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "umlalles r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "umlals r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe0bf1392 @ umlals pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0b1f392 @ umlals r1, pc, r2, r3")
+
+ TEST_RR( "smull r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "smullls r7, r8, r",9, VAL2,", r",10, VAL1,"")
+ TEST_R( "smull lr, r12, r",11,VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe0c1f392 @ smull pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0cf1392 @ smull r1, pc, r2, r3")
+ TEST_RR( "smulls r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "smulllss r7, r8, r",9, VAL2,", r",10, VAL1,"")
+ TEST_R( "smulls lr, r12, r",11,VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe0d1f392 @ smulls pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0df1392 @ smulls r1, pc, r2, r3")
+
+ TEST_RRRR( "smlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "smlal r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe0ef1392 @ smlal pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0e1f392 @ smlal r1, pc, r2, r3")
+ TEST_RRRR( "smlals r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalles r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "smlals r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe0ff1392 @ smlals pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0f0f392 @ smlals r0, pc, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0f0139f @ smlals r0, r1, pc, r3")
+ TEST_UNSUPPORTED(".word 0xe0f01f92 @ smlals r0, r1, r2, pc")
+
+ TEST_GROUP("Synchronization primitives")
+
+#if __LINUX_ARM_ARCH__ < 6
+ TEST_RP("swp lr, r",7,VAL2,", [r",8,0,"]")
+ TEST_R( "swpvs r0, r",1,VAL1,", [sp]")
+ TEST_RP("swp sp, r",14,VAL2,", [r",12,13*4,"]")
+#else
+ TEST_UNSUPPORTED(".word 0xe108e097 @ swp lr, r7, [r8]")
+ TEST_UNSUPPORTED(".word 0x610d0091 @ swpvs r0, r1, [sp]")
+ TEST_UNSUPPORTED(".word 0xe10cd09e @ swp sp, r14 [r12]")
+#endif
+ TEST_UNSUPPORTED(".word 0xe102f091 @ swp pc, r1, [r2]")
+ TEST_UNSUPPORTED(".word 0xe102009f @ swp r0, pc, [r2]")
+ TEST_UNSUPPORTED(".word 0xe10f0091 @ swp r0, r1, [pc]")
+#if __LINUX_ARM_ARCH__ < 6
+ TEST_RP("swpb lr, r",7,VAL2,", [r",8,0,"]")
+ TEST_R( "swpvsb r0, r",1,VAL1,", [sp]")
+#else
+ TEST_UNSUPPORTED(".word 0xe148e097 @ swpb lr, r7, [r8]")
+ TEST_UNSUPPORTED(".word 0x614d0091 @ swpvsb r0, r1, [sp]")
+#endif
+ TEST_UNSUPPORTED(".word 0xe142f091 @ swpb pc, r1, [r2]")
+
+ TEST_UNSUPPORTED(".word 0xe1100090") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe1200090") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe1300090") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe1500090") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe1600090") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe1700090") /* Unallocated space */
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_UNSUPPORTED("ldrex r2, [sp]")
+ TEST_UNSUPPORTED("strexd r0, r2, r3, [sp]")
+ TEST_UNSUPPORTED("ldrexd r2, r3, [sp]")
+ TEST_UNSUPPORTED("strexb r0, r2, [sp]")
+ TEST_UNSUPPORTED("ldrexb r2, [sp]")
+ TEST_UNSUPPORTED("strexh r0, r2, [sp]")
+ TEST_UNSUPPORTED("ldrexh r2, [sp]")
+#endif
+ TEST_GROUP("Extra load/store instructions")
+
+ TEST_RPR( "strh r",0, VAL1,", [r",1, 48,", -r",2, 24,"]")
+ TEST_RPR( "streqh r",14,VAL2,", [r",13,0, ", r",12, 48,"]")
+ TEST_RPR( "strh r",1, VAL1,", [r",2, 24,", r",3, 48,"]!")
+ TEST_RPR( "strneh r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
+ TEST_RPR( "strh r",2, VAL1,", [r",3, 24,"], r",4, 48,"")
+ TEST_RPR( "strh r",10,VAL2,", [r",9, 48,"], -r",11,24,"")
+ TEST_UNSUPPORTED(".word 0xe1afc0ba @ strh r12, [pc, r10]!")
+ TEST_UNSUPPORTED(".word 0xe089f0bb @ strh pc, [r9], r11")
+ TEST_UNSUPPORTED(".word 0xe089a0bf @ strh r10, [r9], pc")
+
+ TEST_PR( "ldrh r0, [r",0, 48,", -r",2, 24,"]")
+ TEST_PR( "ldrcsh r14, [r",13,0, ", r",12, 48,"]")
+ TEST_PR( "ldrh r1, [r",2, 24,", r",3, 48,"]!")
+ TEST_PR( "ldrcch r12, [r",11,48,", -r",10,24,"]!")
+ TEST_PR( "ldrh r2, [r",3, 24,"], r",4, 48,"")
+ TEST_PR( "ldrh r10, [r",9, 48,"], -r",11,24,"")
+ TEST_UNSUPPORTED(".word 0xe1bfc0ba @ ldrh r12, [pc, r10]!")
+ TEST_UNSUPPORTED(".word 0xe099f0bb @ ldrh pc, [r9], r11")
+ TEST_UNSUPPORTED(".word 0xe099a0bf @ ldrh r10, [r9], pc")
+
+ TEST_RP( "strh r",0, VAL1,", [r",1, 24,", #-2]")
+ TEST_RP( "strmih r",14,VAL2,", [r",13,0, ", #2]")
+ TEST_RP( "strh r",1, VAL1,", [r",2, 24,", #4]!")
+ TEST_RP( "strplh r",12,VAL2,", [r",11,24,", #-4]!")
+ TEST_RP( "strh r",2, VAL1,", [r",3, 24,"], #48")
+ TEST_RP( "strh r",10,VAL2,", [r",9, 64,"], #-48")
+ TEST_UNSUPPORTED(".word 0xe1efc3b0 @ strh r12, [pc, #48]!")
+ TEST_UNSUPPORTED(".word 0xe0c9f3b0 @ strh pc, [r9], #48")
+
+ TEST_P( "ldrh r0, [r",0, 24,", #-2]")
+ TEST_P( "ldrvsh r14, [r",13,0, ", #2]")
+ TEST_P( "ldrh r1, [r",2, 24,", #4]!")
+ TEST_P( "ldrvch r12, [r",11,24,", #-4]!")
+ TEST_P( "ldrh r2, [r",3, 24,"], #48")
+ TEST_P( "ldrh r10, [r",9, 64,"], #-48")
+ TEST( "ldrh r0, [pc, #0]")
+ TEST_UNSUPPORTED(".word 0xe1ffc3b0 @ ldrh r12, [pc, #48]!")
+ TEST_UNSUPPORTED(".word 0xe0d9f3b0 @ ldrh pc, [r9], #48")
+
+ TEST_PR( "ldrsb r0, [r",0, 48,", -r",2, 24,"]")
+ TEST_PR( "ldrhisb r14, [r",13,0,", r",12, 48,"]")
+ TEST_PR( "ldrsb r1, [r",2, 24,", r",3, 48,"]!")
+ TEST_PR( "ldrlssb r12, [r",11,48,", -r",10,24,"]!")
+ TEST_PR( "ldrsb r2, [r",3, 24,"], r",4, 48,"")
+ TEST_PR( "ldrsb r10, [r",9, 48,"], -r",11,24,"")
+ TEST_UNSUPPORTED(".word 0xe1bfc0da @ ldrsb r12, [pc, r10]!")
+ TEST_UNSUPPORTED(".word 0xe099f0db @ ldrsb pc, [r9], r11")
+
+ TEST_P( "ldrsb r0, [r",0, 24,", #-1]")
+ TEST_P( "ldrgesb r14, [r",13,0, ", #1]")
+ TEST_P( "ldrsb r1, [r",2, 24,", #4]!")
+ TEST_P( "ldrltsb r12, [r",11,24,", #-4]!")
+ TEST_P( "ldrsb r2, [r",3, 24,"], #48")
+ TEST_P( "ldrsb r10, [r",9, 64,"], #-48")
+ TEST( "ldrsb r0, [pc, #0]")
+ TEST_UNSUPPORTED(".word 0xe1ffc3d0 @ ldrsb r12, [pc, #48]!")
+ TEST_UNSUPPORTED(".word 0xe0d9f3d0 @ ldrsb pc, [r9], #48")
+
+ TEST_PR( "ldrsh r0, [r",0, 48,", -r",2, 24,"]")
+ TEST_PR( "ldrgtsh r14, [r",13,0, ", r",12, 48,"]")
+ TEST_PR( "ldrsh r1, [r",2, 24,", r",3, 48,"]!")
+ TEST_PR( "ldrlesh r12, [r",11,48,", -r",10,24,"]!")
+ TEST_PR( "ldrsh r2, [r",3, 24,"], r",4, 48,"")
+ TEST_PR( "ldrsh r10, [r",9, 48,"], -r",11,24,"")
+ TEST_UNSUPPORTED(".word 0xe1bfc0fa @ ldrsh r12, [pc, r10]!")
+ TEST_UNSUPPORTED(".word 0xe099f0fb @ ldrsh pc, [r9], r11")
+
+ TEST_P( "ldrsh r0, [r",0, 24,", #-1]")
+ TEST_P( "ldreqsh r14, [r",13,0 ,", #1]")
+ TEST_P( "ldrsh r1, [r",2, 24,", #4]!")
+ TEST_P( "ldrnesh r12, [r",11,24,", #-4]!")
+ TEST_P( "ldrsh r2, [r",3, 24,"], #48")
+ TEST_P( "ldrsh r10, [r",9, 64,"], #-48")
+ TEST( "ldrsh r0, [pc, #0]")
+ TEST_UNSUPPORTED(".word 0xe1ffc3f0 @ ldrsh r12, [pc, #48]!")
+ TEST_UNSUPPORTED(".word 0xe0d9f3f0 @ ldrsh pc, [r9], #48")
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_UNSUPPORTED("strht r1, [r2], r3")
+ TEST_UNSUPPORTED("ldrht r1, [r2], r3")
+ TEST_UNSUPPORTED("strht r1, [r2], #48")
+ TEST_UNSUPPORTED("ldrht r1, [r2], #48")
+ TEST_UNSUPPORTED("ldrsbt r1, [r2], r3")
+ TEST_UNSUPPORTED("ldrsbt r1, [r2], #48")
+ TEST_UNSUPPORTED("ldrsht r1, [r2], r3")
+ TEST_UNSUPPORTED("ldrsht r1, [r2], #48")
+#endif
+
+ TEST_RPR( "strd r",0, VAL1,", [r",1, 48,", -r",2,24,"]")
+ TEST_RPR( "strccd r",8, VAL2,", [r",13,0, ", r",12,48,"]")
+ TEST_RPR( "strd r",4, VAL1,", [r",2, 24,", r",3, 48,"]!")
+ TEST_RPR( "strcsd r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
+ TEST_RPR( "strd r",2, VAL1,", [r",5, 24,"], r",4,48,"")
+ TEST_RPR( "strd r",10,VAL2,", [r",9, 48,"], -r",7,24,"")
+ TEST_UNSUPPORTED(".word 0xe1afc0fa @ strd r12, [pc, r10]!")
+
+ TEST_PR( "ldrd r0, [r",0, 48,", -r",2,24,"]")
+ TEST_PR( "ldrmid r8, [r",13,0, ", r",12,48,"]")
+ TEST_PR( "ldrd r4, [r",2, 24,", r",3, 48,"]!")
+ TEST_PR( "ldrpld r6, [r",11,48,", -r",10,24,"]!")
+ TEST_PR( "ldrd r2, [r",5, 24,"], r",4,48,"")
+ TEST_PR( "ldrd r10, [r",9,48,"], -r",7,24,"")
+ TEST_UNSUPPORTED(".word 0xe1afc0da @ ldrd r12, [pc, r10]!")
+ TEST_UNSUPPORTED(".word 0xe089f0db @ ldrd pc, [r9], r11")
+ TEST_UNSUPPORTED(".word 0xe089e0db @ ldrd lr, [r9], r11")
+ TEST_UNSUPPORTED(".word 0xe089c0df @ ldrd r12, [r9], pc")
+
+ TEST_RP( "strd r",0, VAL1,", [r",1, 24,", #-8]")
+ TEST_RP( "strvsd r",8, VAL2,", [r",13,0, ", #8]")
+ TEST_RP( "strd r",4, VAL1,", [r",2, 24,", #16]!")
+ TEST_RP( "strvcd r",12,VAL2,", [r",11,24,", #-16]!")
+ TEST_RP( "strd r",2, VAL1,", [r",4, 24,"], #48")
+ TEST_RP( "strd r",10,VAL2,", [r",9, 64,"], #-48")
+ TEST_UNSUPPORTED(".word 0xe1efc3f0 @ strd r12, [pc, #48]!")
+
+ TEST_P( "ldrd r0, [r",0, 24,", #-8]")
+ TEST_P( "ldrhid r8, [r",13,0, ", #8]")
+ TEST_P( "ldrd r4, [r",2, 24,", #16]!")
+ TEST_P( "ldrlsd r6, [r",11,24,", #-16]!")
+ TEST_P( "ldrd r2, [r",5, 24,"], #48")
+ TEST_P( "ldrd r10, [r",9,6,"], #-48")
+ TEST_UNSUPPORTED(".word 0xe1efc3d0 @ ldrd r12, [pc, #48]!")
+ TEST_UNSUPPORTED(".word 0xe0c9f3d0 @ ldrd pc, [r9], #48")
+ TEST_UNSUPPORTED(".word 0xe0c9e3d0 @ ldrd lr, [r9], #48")
+
+ TEST_GROUP("Miscellaneous")
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST("movw r0, #0")
+ TEST("movw r0, #0xffff")
+ TEST("movw lr, #0xffff")
+ TEST_UNSUPPORTED(".word 0xe300f000 @ movw pc, #0")
+ TEST_R("movt r",0, VAL1,", #0")
+ TEST_R("movt r",0, VAL2,", #0xffff")
+ TEST_R("movt r",14,VAL1,", #0xffff")
+ TEST_UNSUPPORTED(".word 0xe340f000 @ movt pc, #0")
+#endif
+
+ TEST_UNSUPPORTED("msr cpsr, 0x13")
+ TEST_UNSUPPORTED("msr cpsr_f, 0xf0000000")
+ TEST_UNSUPPORTED("msr spsr, 0x13")
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_SUPPORTED("yield")
+ TEST("sev")
+ TEST("nop")
+ TEST("wfi")
+ TEST_SUPPORTED("wfe")
+ TEST_UNSUPPORTED("dbg #0")
+#endif
+
+ TEST_GROUP("Load/store word and unsigned byte")
+
+#define LOAD_STORE(byte) \
+ TEST_RP( "str"byte" r",0, VAL1,", [r",1, 24,", #-2]") \
+ TEST_RP( "str"byte" r",14,VAL2,", [r",13,0, ", #2]") \
+ TEST_RP( "str"byte" r",1, VAL1,", [r",2, 24,", #4]!") \
+ TEST_RP( "str"byte" r",12,VAL2,", [r",11,24,", #-4]!") \
+ TEST_RP( "str"byte" r",2, VAL1,", [r",3, 24,"], #48") \
+ TEST_RP( "str"byte" r",10,VAL2,", [r",9, 64,"], #-48") \
+ TEST_RPR("str"byte" r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") \
+ TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 48,"]") \
+ TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") \
+ TEST_RPR("str"byte" r",12,VAL2,", [r",11,48,", -r",10,24,"]!") \
+ TEST_RPR("str"byte" r",2, VAL1,", [r",3, 24,"], r",4, 48,"") \
+ TEST_RPR("str"byte" r",10,VAL2,", [r",9, 48,"], -r",11,24,"") \
+ TEST_RPR("str"byte" r",0, VAL1,", [r",1, 24,", r",2, 32,", asl #1]")\
+ TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 32,", lsr #2]")\
+ TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 32,", asr #3]!")\
+ TEST_RPR("str"byte" r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\
+ TEST_P( "ldr"byte" r0, [r",0, 24,", #-2]") \
+ TEST_P( "ldr"byte" r14, [r",13,0, ", #2]") \
+ TEST_P( "ldr"byte" r1, [r",2, 24,", #4]!") \
+ TEST_P( "ldr"byte" r12, [r",11,24,", #-4]!") \
+ TEST_P( "ldr"byte" r2, [r",3, 24,"], #48") \
+ TEST_P( "ldr"byte" r10, [r",9, 64,"], #-48") \
+ TEST_PR( "ldr"byte" r0, [r",0, 48,", -r",2, 24,"]") \
+ TEST_PR( "ldr"byte" r14, [r",13,0, ", r",12, 48,"]") \
+ TEST_PR( "ldr"byte" r1, [r",2, 24,", r",3, 48,"]!") \
+ TEST_PR( "ldr"byte" r12, [r",11,48,", -r",10,24,"]!") \
+ TEST_PR( "ldr"byte" r2, [r",3, 24,"], r",4, 48,"") \
+ TEST_PR( "ldr"byte" r10, [r",9, 48,"], -r",11,24,"") \
+ TEST_PR( "ldr"byte" r0, [r",0, 24,", r",2, 32,", asl #1]") \
+ TEST_PR( "ldr"byte" r14, [r",13,0, ", r",12, 32,", lsr #2]") \
+ TEST_PR( "ldr"byte" r1, [r",2, 24,", r",3, 32,", asr #3]!") \
+ TEST_PR( "ldr"byte" r12, [r",11,24,", r",10, 4,", ror #31]!") \
+ TEST( "ldr"byte" r0, [pc, #0]") \
+ TEST_R( "ldr"byte" r12, [pc, r",14,0,"]")
+
+ LOAD_STORE("")
+ TEST_P( "str pc, [r",0,0,", #15*4]")
+ TEST_R( "str pc, [sp, r",2,15*4,"]")
+ TEST_BF( "ldr pc, [sp, #15*4]")
+ TEST_BF_R("ldr pc, [sp, r",2,15*4,"]")
+
+ TEST_P( "str sp, [r",0,0,", #13*4]")
+ TEST_R( "str sp, [sp, r",2,13*4,"]")
+ TEST_BF( "ldr sp, [sp, #13*4]")
+ TEST_BF_R("ldr sp, [sp, r",2,13*4,"]")
+
+#ifdef CONFIG_THUMB2_KERNEL
+ TEST_ARM_TO_THUMB_INTERWORK_P("ldr pc, [r",0,0,", #15*4]")
+#endif
+ TEST_UNSUPPORTED(".word 0xe5af6008 @ str r6, [pc, #8]!")
+ TEST_UNSUPPORTED(".word 0xe7af6008 @ str r6, [pc, r8]!")
+ TEST_UNSUPPORTED(".word 0xe5bf6008 @ ldr r6, [pc, #8]!")
+ TEST_UNSUPPORTED(".word 0xe7bf6008 @ ldr r6, [pc, r8]!")
+ TEST_UNSUPPORTED(".word 0xe788600f @ str r6, [r8, pc]")
+ TEST_UNSUPPORTED(".word 0xe798600f @ ldr r6, [r8, pc]")
+
+ LOAD_STORE("b")
+ TEST_UNSUPPORTED(".word 0xe5f7f008 @ ldrb pc, [r7, #8]!")
+ TEST_UNSUPPORTED(".word 0xe7f7f008 @ ldrb pc, [r7, r8]!")
+ TEST_UNSUPPORTED(".word 0xe5ef6008 @ strb r6, [pc, #8]!")
+ TEST_UNSUPPORTED(".word 0xe7ef6008 @ strb r6, [pc, r3]!")
+ TEST_UNSUPPORTED(".word 0xe5ff6008 @ ldrb r6, [pc, #8]!")
+ TEST_UNSUPPORTED(".word 0xe7ff6008 @ ldrb r6, [pc, r3]!")
+
+ TEST_UNSUPPORTED("ldrt r0, [r1], #4")
+ TEST_UNSUPPORTED("ldrt r1, [r2], r3")
+ TEST_UNSUPPORTED("strt r2, [r3], #4")
+ TEST_UNSUPPORTED("strt r3, [r4], r5")
+ TEST_UNSUPPORTED("ldrbt r4, [r5], #4")
+ TEST_UNSUPPORTED("ldrbt r5, [r6], r7")
+ TEST_UNSUPPORTED("strbt r6, [r7], #4")
+ TEST_UNSUPPORTED("strbt r7, [r8], r9")
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_GROUP("Parallel addition and subtraction, signed")
+
+ TEST_UNSUPPORTED(".word 0xe6000010") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe60fffff") /* Unallocated space */
+
+ TEST_RR( "sadd16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sadd16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe61cff1a @ sadd16 pc, r12, r10")
+ TEST_RR( "sasx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sasx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe61cff3a @ sasx pc, r12, r10")
+ TEST_RR( "ssax r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "ssax r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe61cff5a @ ssax pc, r12, r10")
+ TEST_RR( "ssub16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "ssub16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe61cff7a @ ssub16 pc, r12, r10")
+ TEST_RR( "sadd8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sadd8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe61cff9a @ sadd8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe61000b0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe61fffbf") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe61000d0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe61fffdf") /* Unallocated space */
+ TEST_RR( "ssub8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "ssub8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe61cfffa @ ssub8 pc, r12, r10")
+
+ TEST_RR( "qadd16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "qadd16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe62cff1a @ qadd16 pc, r12, r10")
+ TEST_RR( "qasx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "qasx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe62cff3a @ qasx pc, r12, r10")
+ TEST_RR( "qsax r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "qsax r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe62cff5a @ qsax pc, r12, r10")
+ TEST_RR( "qsub16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "qsub16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe62cff7a @ qsub16 pc, r12, r10")
+ TEST_RR( "qadd8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "qadd8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe62cff9a @ qadd8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe62000b0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe62fffbf") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe62000d0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe62fffdf") /* Unallocated space */
+ TEST_RR( "qsub8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "qsub8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe62cfffa @ qsub8 pc, r12, r10")
+
+ TEST_RR( "shadd16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "shadd16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe63cff1a @ shadd16 pc, r12, r10")
+ TEST_RR( "shasx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "shasx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe63cff3a @ shasx pc, r12, r10")
+ TEST_RR( "shsax r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "shsax r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe63cff5a @ shsax pc, r12, r10")
+ TEST_RR( "shsub16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "shsub16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe63cff7a @ shsub16 pc, r12, r10")
+ TEST_RR( "shadd8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "shadd8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe63cff9a @ shadd8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe63000b0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe63fffbf") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe63000d0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe63fffdf") /* Unallocated space */
+ TEST_RR( "shsub8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "shsub8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe63cfffa @ shsub8 pc, r12, r10")
+
+ TEST_GROUP("Parallel addition and subtraction, unsigned")
+
+ TEST_UNSUPPORTED(".word 0xe6400010") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe64fffff") /* Unallocated space */
+
+ TEST_RR( "uadd16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uadd16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe65cff1a @ uadd16 pc, r12, r10")
+ TEST_RR( "uasx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uasx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe65cff3a @ uasx pc, r12, r10")
+ TEST_RR( "usax r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "usax r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe65cff5a @ usax pc, r12, r10")
+ TEST_RR( "usub16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "usub16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe65cff7a @ usub16 pc, r12, r10")
+ TEST_RR( "uadd8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uadd8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe65cff9a @ uadd8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe65000b0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe65fffbf") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe65000d0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe65fffdf") /* Unallocated space */
+ TEST_RR( "usub8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "usub8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe65cfffa @ usub8 pc, r12, r10")
+
+ TEST_RR( "uqadd16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uqadd16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe66cff1a @ uqadd16 pc, r12, r10")
+ TEST_RR( "uqasx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uqasx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe66cff3a @ uqasx pc, r12, r10")
+ TEST_RR( "uqsax r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uqsax r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe66cff5a @ uqsax pc, r12, r10")
+ TEST_RR( "uqsub16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uqsub16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe66cff7a @ uqsub16 pc, r12, r10")
+ TEST_RR( "uqadd8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uqadd8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe66cff9a @ uqadd8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe66000b0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe66fffbf") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe66000d0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe66fffdf") /* Unallocated space */
+ TEST_RR( "uqsub8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uqsub8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe66cfffa @ uqsub8 pc, r12, r10")
+
+ TEST_RR( "uhadd16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uhadd16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe67cff1a @ uhadd16 pc, r12, r10")
+ TEST_RR( "uhasx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uhasx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe67cff3a @ uhasx pc, r12, r10")
+ TEST_RR( "uhsax r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uhsax r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe67cff5a @ uhsax pc, r12, r10")
+ TEST_RR( "uhsub16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uhsub16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe67cff7a @ uhsub16 pc, r12, r10")
+ TEST_RR( "uhadd8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uhadd8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe67cff9a @ uhadd8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe67000b0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe67fffbf") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe67000d0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe67fffdf") /* Unallocated space */
+ TEST_RR( "uhsub8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uhsub8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe67cfffa @ uhsub8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe67feffa @ uhsub8 r14, pc, r10")
+ TEST_UNSUPPORTED(".word 0xe67cefff @ uhsub8 r14, r12, pc")
+#endif /* __LINUX_ARM_ARCH__ >= 7 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_GROUP("Packing, unpacking, saturation, and reversal")
+
+ TEST_RR( "pkhbt r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "pkhbt r14,r",12, HH1,", r",10,HH2,", lsl #2")
+ TEST_UNSUPPORTED(".word 0xe68cf11a @ pkhbt pc, r12, r10, lsl #2")
+ TEST_RR( "pkhtb r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "pkhtb r14,r",12, HH1,", r",10,HH2,", asr #2")
+ TEST_UNSUPPORTED(".word 0xe68cf15a @ pkhtb pc, r12, r10, asr #2")
+ TEST_UNSUPPORTED(".word 0xe68fe15a @ pkhtb r14, pc, r10, asr #2")
+ TEST_UNSUPPORTED(".word 0xe68ce15f @ pkhtb r14, r12, pc, asr #2")
+ TEST_UNSUPPORTED(".word 0xe6900010") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe69fffdf") /* Unallocated space */
+
+ TEST_R( "ssat r0, #24, r",0, VAL1,"")
+ TEST_R( "ssat r14, #24, r",12, VAL2,"")
+ TEST_R( "ssat r0, #24, r",0, VAL1,", lsl #8")
+ TEST_R( "ssat r14, #24, r",12, VAL2,", asr #8")
+ TEST_UNSUPPORTED(".word 0xe6b7f01c @ ssat pc, #24, r12")
+
+ TEST_R( "usat r0, #24, r",0, VAL1,"")
+ TEST_R( "usat r14, #24, r",12, VAL2,"")
+ TEST_R( "usat r0, #24, r",0, VAL1,", lsl #8")
+ TEST_R( "usat r14, #24, r",12, VAL2,", asr #8")
+ TEST_UNSUPPORTED(".word 0xe6f7f01c @ usat pc, #24, r12")
+
+ TEST_RR( "sxtab16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "sxtb16 r8, r",7, HH1,"")
+ TEST_UNSUPPORTED(".word 0xe68cf47a @ sxtab16 pc,r12, r10, ror #8")
+
+ TEST_RR( "sel r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "sel r14, r",12,VAL1,", r",10, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe68cffba @ sel pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe68fefba @ sel r14, pc, r10")
+ TEST_UNSUPPORTED(".word 0xe68cefbf @ sel r14, r12, pc")
+
+ TEST_R( "ssat16 r0, #12, r",0, HH1,"")
+ TEST_R( "ssat16 r14, #12, r",12, HH2,"")
+ TEST_UNSUPPORTED(".word 0xe6abff3c @ ssat16 pc, #12, r12")
+
+ TEST_RR( "sxtab r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sxtab r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "sxtb r8, r",7, HH1,"")
+ TEST_UNSUPPORTED(".word 0xe6acf47a @ sxtab pc,r12, r10, ror #8")
+
+ TEST_R( "rev r0, r",0, VAL1,"")
+ TEST_R( "rev r14, r",12, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe6bfff3c @ rev pc, r12")
+
+ TEST_RR( "sxtah r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sxtah r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "sxth r8, r",7, HH1,"")
+ TEST_UNSUPPORTED(".word 0xe6bcf47a @ sxtah pc,r12, r10, ror #8")
+
+ TEST_R( "rev16 r0, r",0, VAL1,"")
+ TEST_R( "rev16 r14, r",12, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe6bfffbc @ rev16 pc, r12")
+
+ TEST_RR( "uxtab16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "uxtb16 r8, r",7, HH1,"")
+ TEST_UNSUPPORTED(".word 0xe6ccf47a @ uxtab16 pc,r12, r10, ror #8")
+
+ TEST_R( "usat16 r0, #12, r",0, HH1,"")
+ TEST_R( "usat16 r14, #12, r",12, HH2,"")
+ TEST_UNSUPPORTED(".word 0xe6ecff3c @ usat16 pc, #12, r12")
+ TEST_UNSUPPORTED(".word 0xe6ecef3f @ usat16 r14, #12, pc")
+
+ TEST_RR( "uxtab r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uxtab r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "uxtb r8, r",7, HH1,"")
+ TEST_UNSUPPORTED(".word 0xe6ecf47a @ uxtab pc,r12, r10, ror #8")
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_R( "rbit r0, r",0, VAL1,"")
+ TEST_R( "rbit r14, r",12, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe6ffff3c @ rbit pc, r12")
+#endif
+
+ TEST_RR( "uxtah r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uxtah r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "uxth r8, r",7, HH1,"")
+ TEST_UNSUPPORTED(".word 0xe6fff077 @ uxth pc, r7")
+ TEST_UNSUPPORTED(".word 0xe6ff807f @ uxth r8, pc")
+ TEST_UNSUPPORTED(".word 0xe6fcf47a @ uxtah pc, r12, r10, ror #8")
+ TEST_UNSUPPORTED(".word 0xe6fce47f @ uxtah r14, r12, pc, ror #8")
+
+ TEST_R( "revsh r0, r",0, VAL1,"")
+ TEST_R( "revsh r14, r",12, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe6ffff3c @ revsh pc, r12")
+ TEST_UNSUPPORTED(".word 0xe6ffef3f @ revsh r14, pc")
+
+ TEST_UNSUPPORTED(".word 0xe6900070") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe69fff7f") /* Unallocated space */
+
+ TEST_UNSUPPORTED(".word 0xe6d00070") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe6dfff7f") /* Unallocated space */
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_GROUP("Signed multiplies")
+
+ TEST_RRR( "smlad r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smlad r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe70f8a1c @ smlad pc, r12, r10, r8")
+ TEST_RRR( "smladx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smladx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe70f8a3c @ smladx pc, r12, r10, r8")
+
+ TEST_RR( "smuad r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smuad r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe70ffa1c @ smuad pc, r12, r10")
+ TEST_RR( "smuadx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smuadx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe70ffa3c @ smuadx pc, r12, r10")
+
+ TEST_RRR( "smlsd r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smlsd r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe70f8a5c @ smlsd pc, r12, r10, r8")
+ TEST_RRR( "smlsdx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smlsdx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe70f8a7c @ smlsdx pc, r12, r10, r8")
+
+ TEST_RR( "smusd r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smusd r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe70ffa5c @ smusd pc, r12, r10")
+ TEST_RR( "smusdx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smusdx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe70ffa7c @ smusdx pc, r12, r10")
+
+ TEST_RRRR( "smlald r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+ TEST_RRRR( "smlald r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+ TEST_UNSUPPORTED(".word 0xe74af819 @ smlald pc, r10, r9, r8")
+ TEST_UNSUPPORTED(".word 0xe74fb819 @ smlald r11, pc, r9, r8")
+ TEST_UNSUPPORTED(".word 0xe74ab81f @ smlald r11, r10, pc, r8")
+ TEST_UNSUPPORTED(".word 0xe74abf19 @ smlald r11, r10, r9, pc")
+
+ TEST_RRRR( "smlaldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+ TEST_RRRR( "smlaldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+ TEST_UNSUPPORTED(".word 0xe74af839 @ smlaldx pc, r10, r9, r8")
+ TEST_UNSUPPORTED(".word 0xe74fb839 @ smlaldx r11, pc, r9, r8")
+
+ TEST_RRR( "smmla r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmla r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe75f8a1c @ smmla pc, r12, r10, r8")
+ TEST_RRR( "smmlar r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmlar r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe75f8a3c @ smmlar pc, r12, r10, r8")
+
+ TEST_RR( "smmul r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "smmul r14, r",12,VAL2,", r",10,VAL1,"")
+ TEST_UNSUPPORTED(".word 0xe75ffa1c @ smmul pc, r12, r10")
+ TEST_RR( "smmulr r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "smmulr r14, r",12,VAL2,", r",10,VAL1,"")
+ TEST_UNSUPPORTED(".word 0xe75ffa3c @ smmulr pc, r12, r10")
+
+ TEST_RRR( "smmls r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmls r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe75f8adc @ smmls pc, r12, r10, r8")
+ TEST_RRR( "smmlsr r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmlsr r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe75f8afc @ smmlsr pc, r12, r10, r8")
+ TEST_UNSUPPORTED(".word 0xe75e8aff @ smmlsr r14, pc, r10, r8")
+ TEST_UNSUPPORTED(".word 0xe75e8ffc @ smmlsr r14, r12, pc, r8")
+ TEST_UNSUPPORTED(".word 0xe75efafc @ smmlsr r14, r12, r10, pc")
+
+ TEST_RR( "usad8 r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "usad8 r14, r",12,VAL2,", r",10,VAL1,"")
+ TEST_UNSUPPORTED(".word 0xe75ffa1c @ usad8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe75efa1f @ usad8 r14, pc, r10")
+ TEST_UNSUPPORTED(".word 0xe75eff1c @ usad8 r14, r12, pc")
+
+ TEST_RRR( "usada8 r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL3,"")
+ TEST_RRR( "usada8 r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"")
+ TEST_UNSUPPORTED(".word 0xe78f8a1c @ usada8 pc, r12, r10, r8")
+ TEST_UNSUPPORTED(".word 0xe78e8a1f @ usada8 r14, pc, r10, r8")
+ TEST_UNSUPPORTED(".word 0xe78e8f1c @ usada8 r14, r12, pc, r8")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_GROUP("Bit Field")
+
+ TEST_R( "sbfx r0, r",0 , VAL1,", #0, #31")
+ TEST_R( "sbfxeq r14, r",12, VAL2,", #8, #16")
+ TEST_R( "sbfx r4, r",10, VAL1,", #16, #15")
+ TEST_UNSUPPORTED(".word 0xe7aff45c @ sbfx pc, r12, #8, #16")
+
+ TEST_R( "ubfx r0, r",0 , VAL1,", #0, #31")
+ TEST_R( "ubfxcs r14, r",12, VAL2,", #8, #16")
+ TEST_R( "ubfx r4, r",10, VAL1,", #16, #15")
+ TEST_UNSUPPORTED(".word 0xe7eff45c @ ubfx pc, r12, #8, #16")
+ TEST_UNSUPPORTED(".word 0xe7efc45f @ ubfx r12, pc, #8, #16")
+
+ TEST_R( "bfc r",0, VAL1,", #4, #20")
+ TEST_R( "bfcvs r",14,VAL2,", #4, #20")
+ TEST_R( "bfc r",7, VAL1,", #0, #31")
+ TEST_R( "bfc r",8, VAL2,", #0, #31")
+ TEST_UNSUPPORTED(".word 0xe7def01f @ bfc pc, #0, #31");
+
+ TEST_RR( "bfi r",0, VAL1,", r",0 , VAL2,", #0, #31")
+ TEST_RR( "bfipl r",12,VAL1,", r",14 , VAL2,", #4, #20")
+ TEST_UNSUPPORTED(".word 0xe7d7f21e @ bfi pc, r14, #4, #20")
+
+ TEST_UNSUPPORTED(".word 0x07f000f0") /* Permanently UNDEFINED */
+ TEST_UNSUPPORTED(".word 0x07ffffff") /* Permanently UNDEFINED */
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+ TEST_GROUP("Branch, branch with link, and block data transfer")
+
+ TEST_P( "stmda r",0, 16*4,", {r0}")
+ TEST_P( "stmeqda r",4, 16*4,", {r0-r15}")
+ TEST_P( "stmneda r",8, 16*4,"!, {r8-r15}")
+ TEST_P( "stmda r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_P( "stmda r",13,0, "!, {pc}")
+
+ TEST_P( "ldmda r",0, 16*4,", {r0}")
+ TEST_BF_P("ldmcsda r",4, 15*4,", {r0-r15}")
+ TEST_BF_P("ldmccda r",7, 15*4,"!, {r8-r15}")
+ TEST_P( "ldmda r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_BF_P("ldmda r",14,15*4,"!, {pc}")
+
+ TEST_P( "stmia r",0, 16*4,", {r0}")
+ TEST_P( "stmmiia r",4, 16*4,", {r0-r15}")
+ TEST_P( "stmplia r",8, 16*4,"!, {r8-r15}")
+ TEST_P( "stmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_P( "stmia r",14,0, "!, {pc}")
+
+ TEST_P( "ldmia r",0, 16*4,", {r0}")
+ TEST_BF_P("ldmvsia r",4, 0, ", {r0-r15}")
+ TEST_BF_P("ldmvcia r",7, 8*4, "!, {r8-r15}")
+ TEST_P( "ldmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_BF_P("ldmia r",14,15*4,"!, {pc}")
+
+ TEST_P( "stmdb r",0, 16*4,", {r0}")
+ TEST_P( "stmhidb r",4, 16*4,", {r0-r15}")
+ TEST_P( "stmlsdb r",8, 16*4,"!, {r8-r15}")
+ TEST_P( "stmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_P( "stmdb r",13,4, "!, {pc}")
+
+ TEST_P( "ldmdb r",0, 16*4,", {r0}")
+ TEST_BF_P("ldmgedb r",4, 16*4,", {r0-r15}")
+ TEST_BF_P("ldmltdb r",7, 16*4,"!, {r8-r15}")
+ TEST_P( "ldmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_BF_P("ldmdb r",14,16*4,"!, {pc}")
+
+ TEST_P( "stmib r",0, 16*4,", {r0}")
+ TEST_P( "stmgtib r",4, 16*4,", {r0-r15}")
+ TEST_P( "stmleib r",8, 16*4,"!, {r8-r15}")
+ TEST_P( "stmib r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_P( "stmib r",13,-4, "!, {pc}")
+
+ TEST_P( "ldmib r",0, 16*4,", {r0}")
+ TEST_BF_P("ldmeqib r",4, -4,", {r0-r15}")
+ TEST_BF_P("ldmneib r",7, 7*4,"!, {r8-r15}")
+ TEST_P( "ldmib r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_BF_P("ldmib r",14,14*4,"!, {pc}")
+
+ TEST_P( "stmdb r",13,16*4,"!, {r3-r12,lr}")
+ TEST_P( "stmeqdb r",13,16*4,"!, {r3-r12}")
+ TEST_P( "stmnedb r",2, 16*4,", {r3-r12,lr}")
+ TEST_P( "stmdb r",13,16*4,"!, {r2-r12,lr}")
+ TEST_P( "stmdb r",0, 16*4,", {r0-r12}")
+ TEST_P( "stmdb r",0, 16*4,", {r0-r12,lr}")
+
+ TEST_BF_P("ldmia r",13,5*4, "!, {r3-r12,pc}")
+ TEST_P( "ldmccia r",13,5*4, "!, {r3-r12}")
+ TEST_BF_P("ldmcsia r",2, 5*4, "!, {r3-r12,pc}")
+ TEST_BF_P("ldmia r",13,4*4, "!, {r2-r12,pc}")
+ TEST_P( "ldmia r",0, 16*4,", {r0-r12}")
+ TEST_P( "ldmia r",0, 16*4,", {r0-r12,lr}")
+
+#ifdef CONFIG_THUMB2_KERNEL
+ TEST_ARM_TO_THUMB_INTERWORK_P("ldmplia r",0,15*4,", {pc}")
+ TEST_ARM_TO_THUMB_INTERWORK_P("ldmmiia r",13,0,", {r0-r15}")
+#endif
+ TEST_BF("b 2f")
+ TEST_BF("bl 2f")
+ TEST_BB("b 2b")
+ TEST_BB("bl 2b")
+
+ TEST_BF("beq 2f")
+ TEST_BF("bleq 2f")
+ TEST_BB("bne 2b")
+ TEST_BB("blne 2b")
+
+ TEST_BF("bgt 2f")
+ TEST_BF("blgt 2f")
+ TEST_BB("blt 2b")
+ TEST_BB("bllt 2b")
+
+ TEST_GROUP("Supervisor Call, and coprocessor instructions")
+
+ /*
+ * We can't really test these by executing them, so all
+ * we can do is check that probes are, or are not allowed.
+ * At the moment none are allowed...
+ */
+#define TEST_COPROCESSOR(code) TEST_UNSUPPORTED(code)
+
+#define COPROCESSOR_INSTRUCTIONS_ST_LD(two,cc) \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #4]") \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #-4]") \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #4]!") \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #-4]!") \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13], #4") \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13], #-4") \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13], {1}") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #4]") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #-4]") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #4]!") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #-4]!") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], #4") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], #-4") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], {1}") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #4]") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #-4]") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #4]!") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #-4]!") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], #4") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], #-4") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], {1}") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #4]") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #-4]") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #4]!") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #-4]!") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], #4") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], #-4") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], {1}") \
+ \
+ TEST_COPROCESSOR( "stc"two" 0, cr0, [r15, #4]") \
+ TEST_COPROCESSOR( "stc"two" 0, cr0, [r15, #-4]") \
+ TEST_UNSUPPORTED(".word 0x"cc"daf0001 @ stc"two" 0, cr0, [r15, #4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"d2f0001 @ stc"two" 0, cr0, [r15, #-4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"caf0001 @ stc"two" 0, cr0, [r15], #4") \
+ TEST_UNSUPPORTED(".word 0x"cc"c2f0001 @ stc"two" 0, cr0, [r15], #-4") \
+ TEST_COPROCESSOR( "stc"two" 0, cr0, [r15], {1}") \
+ TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15, #4]") \
+ TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15, #-4]") \
+ TEST_UNSUPPORTED(".word 0x"cc"def0001 @ stc"two"l 0, cr0, [r15, #4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"d6f0001 @ stc"two"l 0, cr0, [r15, #-4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"cef0001 @ stc"two"l 0, cr0, [r15], #4") \
+ TEST_UNSUPPORTED(".word 0x"cc"c6f0001 @ stc"two"l 0, cr0, [r15], #-4") \
+ TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15], {1}") \
+ TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15, #4]") \
+ TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15, #-4]") \
+ TEST_UNSUPPORTED(".word 0x"cc"dbf0001 @ ldc"two" 0, cr0, [r15, #4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"d3f0001 @ ldc"two" 0, cr0, [r15, #-4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"cbf0001 @ ldc"two" 0, cr0, [r15], #4") \
+ TEST_UNSUPPORTED(".word 0x"cc"c3f0001 @ ldc"two" 0, cr0, [r15], #-4") \
+ TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15], {1}") \
+ TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15, #4]") \
+ TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15, #-4]") \
+ TEST_UNSUPPORTED(".word 0x"cc"dff0001 @ ldc"two"l 0, cr0, [r15, #4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"d7f0001 @ ldc"two"l 0, cr0, [r15, #-4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"cff0001 @ ldc"two"l 0, cr0, [r15], #4") \
+ TEST_UNSUPPORTED(".word 0x"cc"c7f0001 @ ldc"two"l 0, cr0, [r15], #-4") \
+ TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15], {1}")
+
+#define COPROCESSOR_INSTRUCTIONS_MC_MR(two,cc) \
+ \
+ TEST_COPROCESSOR( "mcrr"two" 0, 15, r0, r14, cr0") \
+ TEST_COPROCESSOR( "mcrr"two" 15, 0, r14, r0, cr15") \
+ TEST_UNSUPPORTED(".word 0x"cc"c4f00f0 @ mcrr"two" 0, 15, r0, r15, cr0") \
+ TEST_UNSUPPORTED(".word 0x"cc"c40ff0f @ mcrr"two" 15, 0, r15, r0, cr15") \
+ TEST_COPROCESSOR( "mrrc"two" 0, 15, r0, r14, cr0") \
+ TEST_COPROCESSOR( "mrrc"two" 15, 0, r14, r0, cr15") \
+ TEST_UNSUPPORTED(".word 0x"cc"c5f00f0 @ mrrc"two" 0, 15, r0, r15, cr0") \
+ TEST_UNSUPPORTED(".word 0x"cc"c50ff0f @ mrrc"two" 15, 0, r15, r0, cr15") \
+ TEST_COPROCESSOR( "cdp"two" 15, 15, cr15, cr15, cr15, 7") \
+ TEST_COPROCESSOR( "cdp"two" 0, 0, cr0, cr0, cr0, 0") \
+ TEST_COPROCESSOR( "mcr"two" 15, 7, r15, cr15, cr15, 7") \
+ TEST_COPROCESSOR( "mcr"two" 0, 0, r0, cr0, cr0, 0") \
+ TEST_COPROCESSOR( "mrc"two" 15, 7, r15, cr15, cr15, 7") \
+ TEST_COPROCESSOR( "mrc"two" 0, 0, r0, cr0, cr0, 0")
+
+ COPROCESSOR_INSTRUCTIONS_ST_LD("","e")
+ COPROCESSOR_INSTRUCTIONS_MC_MR("","e")
+ TEST_UNSUPPORTED("svc 0")
+ TEST_UNSUPPORTED("svc 0xffffff")
+
+ TEST_UNSUPPORTED("svc 0")
+
+ TEST_GROUP("Unconditional instruction")
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_UNSUPPORTED("srsda sp, 0x13")
+ TEST_UNSUPPORTED("srsdb sp, 0x13")
+ TEST_UNSUPPORTED("srsia sp, 0x13")
+ TEST_UNSUPPORTED("srsib sp, 0x13")
+ TEST_UNSUPPORTED("srsda sp!, 0x13")
+ TEST_UNSUPPORTED("srsdb sp!, 0x13")
+ TEST_UNSUPPORTED("srsia sp!, 0x13")
+ TEST_UNSUPPORTED("srsib sp!, 0x13")
+
+ TEST_UNSUPPORTED("rfeda sp")
+ TEST_UNSUPPORTED("rfedb sp")
+ TEST_UNSUPPORTED("rfeia sp")
+ TEST_UNSUPPORTED("rfeib sp")
+ TEST_UNSUPPORTED("rfeda sp!")
+ TEST_UNSUPPORTED("rfedb sp!")
+ TEST_UNSUPPORTED("rfeia sp!")
+ TEST_UNSUPPORTED("rfeib sp!")
+ TEST_UNSUPPORTED(".word 0xf81d0a00 @ rfeda pc")
+ TEST_UNSUPPORTED(".word 0xf91d0a00 @ rfedb pc")
+ TEST_UNSUPPORTED(".word 0xf89d0a00 @ rfeia pc")
+ TEST_UNSUPPORTED(".word 0xf99d0a00 @ rfeib pc")
+ TEST_UNSUPPORTED(".word 0xf83d0a00 @ rfeda pc!")
+ TEST_UNSUPPORTED(".word 0xf93d0a00 @ rfedb pc!")
+ TEST_UNSUPPORTED(".word 0xf8bd0a00 @ rfeia pc!")
+ TEST_UNSUPPORTED(".word 0xf9bd0a00 @ rfeib pc!")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_X( "blx __dummy_thumb_subroutine_even",
+ ".thumb \n\t"
+ ".space 4 \n\t"
+ ".type __dummy_thumb_subroutine_even, %%function \n\t"
+ "__dummy_thumb_subroutine_even: \n\t"
+ "mov r0, pc \n\t"
+ "bx lr \n\t"
+ ".arm \n\t"
+ )
+ TEST( "blx __dummy_thumb_subroutine_even")
+
+ TEST_X( "blx __dummy_thumb_subroutine_odd",
+ ".thumb \n\t"
+ ".space 2 \n\t"
+ ".type __dummy_thumb_subroutine_odd, %%function \n\t"
+ "__dummy_thumb_subroutine_odd: \n\t"
+ "mov r0, pc \n\t"
+ "bx lr \n\t"
+ ".arm \n\t"
+ )
+ TEST( "blx __dummy_thumb_subroutine_odd")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+ COPROCESSOR_INSTRUCTIONS_ST_LD("2","f")
+#if __LINUX_ARM_ARCH__ >= 6
+ COPROCESSOR_INSTRUCTIONS_MC_MR("2","f")
+#endif
+
+ TEST_GROUP("Miscellaneous instructions, memory hints, and Advanced SIMD instructions")
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_UNSUPPORTED("cps 0x13")
+ TEST_UNSUPPORTED("cpsie i")
+ TEST_UNSUPPORTED("cpsid i")
+ TEST_UNSUPPORTED("cpsie i,0x13")
+ TEST_UNSUPPORTED("cpsid i,0x13")
+ TEST_UNSUPPORTED("setend le")
+ TEST_UNSUPPORTED("setend be")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_P("pli [r",0,0b,", #16]")
+ TEST( "pli [pc, #0]")
+ TEST_RR("pli [r",12,0b,", r",0, 16,"]")
+ TEST_RR("pli [r",0, 0b,", -r",12,16,", lsl #4]")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 5
+ TEST_P("pld [r",0,32,", #-16]")
+ TEST( "pld [pc, #0]")
+ TEST_PR("pld [r",7, 24, ", r",0, 16,"]")
+ TEST_PR("pld [r",8, 24, ", -r",12,16,", lsl #4]")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_SUPPORTED( ".word 0xf590f000 @ pldw [r0, #0]")
+ TEST_SUPPORTED( ".word 0xf797f000 @ pldw [r7, r0]")
+ TEST_SUPPORTED( ".word 0xf798f18c @ pldw [r8, r12, lsl #3]");
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_UNSUPPORTED("clrex")
+ TEST_UNSUPPORTED("dsb")
+ TEST_UNSUPPORTED("dmb")
+ TEST_UNSUPPORTED("isb")
+#endif
+
+ verbose("\n");
+}
+
diff --git a/arch/arm/kernel/kprobes-test-thumb.c b/arch/arm/kernel/kprobes-test-thumb.c
new file mode 100644
index 0000000..5d8b857
--- /dev/null
+++ b/arch/arm/kernel/kprobes-test-thumb.c
@@ -0,0 +1,1187 @@
+/*
+ * arch/arm/kernel/kprobes-test-thumb.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "kprobes-test.h"
+
+
+#define TEST_ISA "16"
+
+#define DONT_TEST_IN_ITBLOCK(tests) \
+ kprobe_test_flags |= TEST_FLAG_NO_ITBLOCK; \
+ tests \
+ kprobe_test_flags &= ~TEST_FLAG_NO_ITBLOCK;
+
+#define CONDITION_INSTRUCTIONS(cc_pos, tests) \
+ kprobe_test_cc_position = cc_pos; \
+ DONT_TEST_IN_ITBLOCK(tests) \
+ kprobe_test_cc_position = 0;
+
+#define TEST_ITBLOCK(code) \
+ kprobe_test_flags |= TEST_FLAG_FULL_ITBLOCK; \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ "50: nop \n\t" \
+ "1: "code" \n\t" \
+ " mov r1, #0x11 \n\t" \
+ " mov r2, #0x22 \n\t" \
+ " mov r3, #0x33 \n\t" \
+ "2: nop \n\t" \
+ TESTCASE_END \
+ kprobe_test_flags &= ~TEST_FLAG_FULL_ITBLOCK;
+
+#define TEST_THUMB_TO_ARM_INTERWORK_P(code1, reg, val, code2) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_PTR(reg, val) \
+ TEST_ARG_REG(14, 99f+1) \
+ TEST_ARG_MEM(15, 3f) \
+ TEST_ARG_END("") \
+ " nop \n\t" /* To align 1f */ \
+ "50: nop \n\t" \
+ "1: "code1 #reg code2" \n\t" \
+ " bx lr \n\t" \
+ ".arm \n\t" \
+ "3: adr lr, 2f+1 \n\t" \
+ " bx lr \n\t" \
+ ".thumb \n\t" \
+ "2: nop \n\t" \
+ TESTCASE_END
+
+
+void kprobe_thumb16_test_cases(void)
+{
+ kprobe_test_flags = TEST_FLAG_NARROW_INSTR;
+
+ TEST_GROUP("Shift (immediate), add, subtract, move, and compare")
+
+ TEST_R( "lsls r7, r",0,VAL1,", #5")
+ TEST_R( "lsls r0, r",7,VAL2,", #11")
+ TEST_R( "lsrs r7, r",0,VAL1,", #5")
+ TEST_R( "lsrs r0, r",7,VAL2,", #11")
+ TEST_R( "asrs r7, r",0,VAL1,", #5")
+ TEST_R( "asrs r0, r",7,VAL2,", #11")
+ TEST_RR( "adds r2, r",0,VAL1,", r",7,VAL2,"")
+ TEST_RR( "adds r5, r",7,VAL2,", r",0,VAL2,"")
+ TEST_RR( "subs r2, r",0,VAL1,", r",7,VAL2,"")
+ TEST_RR( "subs r5, r",7,VAL2,", r",0,VAL2,"")
+ TEST_R( "adds r7, r",0,VAL1,", #5")
+ TEST_R( "adds r0, r",7,VAL2,", #2")
+ TEST_R( "subs r7, r",0,VAL1,", #5")
+ TEST_R( "subs r0, r",7,VAL2,", #2")
+ TEST( "movs.n r0, #0x5f")
+ TEST( "movs.n r7, #0xa0")
+ TEST_R( "cmp.n r",0,0x5e, ", #0x5f")
+ TEST_R( "cmp.n r",5,0x15f,", #0x5f")
+ TEST_R( "cmp.n r",7,0xa0, ", #0xa0")
+ TEST_R( "adds.n r",0,VAL1,", #0x5f")
+ TEST_R( "adds.n r",7,VAL2,", #0xa0")
+ TEST_R( "subs.n r",0,VAL1,", #0x5f")
+ TEST_R( "subs.n r",7,VAL2,", #0xa0")
+
+ TEST_GROUP("16-bit Thumb data-processing instructions")
+
+#define DATA_PROCESSING16(op,val) \
+ TEST_RR( op" r",0,VAL1,", r",7,val,"") \
+ TEST_RR( op" r",7,VAL2,", r",0,val,"")
+
+ DATA_PROCESSING16("ands",0xf00f00ff)
+ DATA_PROCESSING16("eors",0xf00f00ff)
+ DATA_PROCESSING16("lsls",11)
+ DATA_PROCESSING16("lsrs",11)
+ DATA_PROCESSING16("asrs",11)
+ DATA_PROCESSING16("adcs",VAL2)
+ DATA_PROCESSING16("sbcs",VAL2)
+ DATA_PROCESSING16("rors",11)
+ DATA_PROCESSING16("tst",0xf00f00ff)
+ TEST_R("rsbs r",0,VAL1,", #0")
+ TEST_R("rsbs r",7,VAL2,", #0")
+ DATA_PROCESSING16("cmp",0xf00f00ff)
+ DATA_PROCESSING16("cmn",0xf00f00ff)
+ DATA_PROCESSING16("orrs",0xf00f00ff)
+ DATA_PROCESSING16("muls",VAL2)
+ DATA_PROCESSING16("bics",0xf00f00ff)
+ DATA_PROCESSING16("mvns",VAL2)
+
+ TEST_GROUP("Special data instructions and branch and exchange")
+
+ TEST_RR( "add r",0, VAL1,", r",7,VAL2,"")
+ TEST_RR( "add r",3, VAL2,", r",8,VAL3,"")
+ TEST_RR( "add r",8, VAL3,", r",0,VAL1,"")
+ TEST_R( "add sp" ", r",8,-8, "")
+ TEST_R( "add r",14,VAL1,", pc")
+ TEST_BF_R("add pc" ", r",0,2f-1f-8,"")
+ TEST_UNSUPPORTED(".short 0x44ff @ add pc, pc")
+
+ TEST_RR( "cmp r",3,VAL1,", r",8,VAL2,"")
+ TEST_RR( "cmp r",8,VAL2,", r",0,VAL1,"")
+ TEST_R( "cmp sp" ", r",8,-8, "")
+
+ TEST_R( "mov r0, r",7,VAL2,"")
+ TEST_R( "mov r3, r",8,VAL3,"")
+ TEST_R( "mov r8, r",0,VAL1,"")
+ TEST_P( "mov sp, r",8,-8, "")
+ TEST( "mov lr, pc")
+ TEST_BF_R("mov pc, r",0,2f, "")
+
+ TEST_BF_R("bx r",0, 2f+1,"")
+ TEST_BF_R("bx r",14,2f+1,"")
+ TESTCASE_START("bx pc")
+ TEST_ARG_REG(14, 99f+1)
+ TEST_ARG_END("")
+ " nop \n\t" /* To align the bx pc*/
+ "50: nop \n\t"
+ "1: bx pc \n\t"
+ " bx lr \n\t"
+ ".arm \n\t"
+ " adr lr, 2f+1 \n\t"
+ " bx lr \n\t"
+ ".thumb \n\t"
+ "2: nop \n\t"
+ TESTCASE_END
+
+ TEST_BF_R("blx r",0, 2f+1,"")
+ TEST_BB_R("blx r",14,2f+1,"")
+ TEST_UNSUPPORTED(".short 0x47f8 @ blx pc")
+
+ TEST_GROUP("Load from Literal Pool")
+
+ TEST_X( "ldr r0, 3f",
+ ".align \n\t"
+ "3: .word "__stringify(VAL1))
+ TEST_X( "ldr r7, 3f",
+ ".space 128 \n\t"
+ ".align \n\t"
+ "3: .word "__stringify(VAL2))
+
+ TEST_GROUP("16-bit Thumb Load/store instructions")
+
+ TEST_RPR("str r",0, VAL1,", [r",1, 24,", r",2, 48,"]")
+ TEST_RPR("str r",7, VAL2,", [r",6, 24,", r",5, 48,"]")
+ TEST_RPR("strh r",0, VAL1,", [r",1, 24,", r",2, 48,"]")
+ TEST_RPR("strh r",7, VAL2,", [r",6, 24,", r",5, 48,"]")
+ TEST_RPR("strb r",0, VAL1,", [r",1, 24,", r",2, 48,"]")
+ TEST_RPR("strb r",7, VAL2,", [r",6, 24,", r",5, 48,"]")
+ TEST_PR( "ldrsb r0, [r",1, 24,", r",2, 48,"]")
+ TEST_PR( "ldrsb r7, [r",6, 24,", r",5, 50,"]")
+ TEST_PR( "ldr r0, [r",1, 24,", r",2, 48,"]")
+ TEST_PR( "ldr r7, [r",6, 24,", r",5, 48,"]")
+ TEST_PR( "ldrh r0, [r",1, 24,", r",2, 48,"]")
+ TEST_PR( "ldrh r7, [r",6, 24,", r",5, 50,"]")
+ TEST_PR( "ldrb r0, [r",1, 24,", r",2, 48,"]")
+ TEST_PR( "ldrb r7, [r",6, 24,", r",5, 50,"]")
+ TEST_PR( "ldrsh r0, [r",1, 24,", r",2, 48,"]")
+ TEST_PR( "ldrsh r7, [r",6, 24,", r",5, 50,"]")
+
+ TEST_RP("str r",0, VAL1,", [r",1, 24,", #120]")
+ TEST_RP("str r",7, VAL2,", [r",6, 24,", #120]")
+ TEST_P( "ldr r0, [r",1, 24,", #120]")
+ TEST_P( "ldr r7, [r",6, 24,", #120]")
+ TEST_RP("strb r",0, VAL1,", [r",1, 24,", #30]")
+ TEST_RP("strb r",7, VAL2,", [r",6, 24,", #30]")
+ TEST_P( "ldrb r0, [r",1, 24,", #30]")
+ TEST_P( "ldrb r7, [r",6, 24,", #30]")
+ TEST_RP("strh r",0, VAL1,", [r",1, 24,", #60]")
+ TEST_RP("strh r",7, VAL2,", [r",6, 24,", #60]")
+ TEST_P( "ldrh r0, [r",1, 24,", #60]")
+ TEST_P( "ldrh r7, [r",6, 24,", #60]")
+
+ TEST_R( "str r",0, VAL1,", [sp, #0]")
+ TEST_R( "str r",7, VAL2,", [sp, #160]")
+ TEST( "ldr r0, [sp, #0]")
+ TEST( "ldr r7, [sp, #160]")
+
+ TEST_RP("str r",0, VAL1,", [r",0, 24,"]")
+ TEST_P( "ldr r0, [r",0, 24,"]")
+
+ TEST_GROUP("Generate PC-/SP-relative address")
+
+ TEST("add r0, pc, #4")
+ TEST("add r7, pc, #1020")
+ TEST("add r0, sp, #4")
+ TEST("add r7, sp, #1020")
+
+ TEST_GROUP("Miscellaneous 16-bit instructions")
+
+ TEST_UNSUPPORTED( "cpsie i")
+ TEST_UNSUPPORTED( "cpsid i")
+ TEST_UNSUPPORTED( "setend le")
+ TEST_UNSUPPORTED( "setend be")
+
+ TEST("add sp, #"__stringify(TEST_MEMORY_SIZE)) /* Assumes TEST_MEMORY_SIZE < 0x400 */
+ TEST("sub sp, #0x7f*4")
+
+DONT_TEST_IN_ITBLOCK(
+ TEST_BF_R( "cbnz r",0,0, ", 2f")
+ TEST_BF_R( "cbz r",2,-1,", 2f")
+ TEST_BF_RX( "cbnz r",4,1, ", 2f", SPACE_0x20)
+ TEST_BF_RX( "cbz r",7,0, ", 2f", SPACE_0x40)
+)
+ TEST_R("sxth r0, r",7, HH1,"")
+ TEST_R("sxth r7, r",0, HH2,"")
+ TEST_R("sxtb r0, r",7, HH1,"")
+ TEST_R("sxtb r7, r",0, HH2,"")
+ TEST_R("uxth r0, r",7, HH1,"")
+ TEST_R("uxth r7, r",0, HH2,"")
+ TEST_R("uxtb r0, r",7, HH1,"")
+ TEST_R("uxtb r7, r",0, HH2,"")
+ TEST_R("rev r0, r",7, VAL1,"")
+ TEST_R("rev r7, r",0, VAL2,"")
+ TEST_R("rev16 r0, r",7, VAL1,"")
+ TEST_R("rev16 r7, r",0, VAL2,"")
+ TEST_UNSUPPORTED(".short 0xba80")
+ TEST_UNSUPPORTED(".short 0xbabf")
+ TEST_R("revsh r0, r",7, VAL1,"")
+ TEST_R("revsh r7, r",0, VAL2,"")
+
+#define TEST_POPPC(code, offset) \
+ TESTCASE_START(code) \
+ TEST_ARG_PTR(13, offset) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_F(code) \
+ TESTCASE_END
+
+ TEST("push {r0}")
+ TEST("push {r7}")
+ TEST("push {r14}")
+ TEST("push {r0-r7,r14}")
+ TEST("push {r0,r2,r4,r6,r14}")
+ TEST("push {r1,r3,r5,r7}")
+ TEST("pop {r0}")
+ TEST("pop {r7}")
+ TEST("pop {r0,r2,r4,r6}")
+ TEST_POPPC("pop {pc}",15*4)
+ TEST_POPPC("pop {r0-r7,pc}",7*4)
+ TEST_POPPC("pop {r1,r3,r5,r7,pc}",11*4)
+ TEST_THUMB_TO_ARM_INTERWORK_P("pop {pc} @ ",13,15*4,"")
+ TEST_THUMB_TO_ARM_INTERWORK_P("pop {r0-r7,pc} @ ",13,7*4,"")
+
+ TEST_UNSUPPORTED("bkpt.n 0")
+ TEST_UNSUPPORTED("bkpt.n 255")
+
+ TEST_SUPPORTED("yield")
+ TEST("sev")
+ TEST("nop")
+ TEST("wfi")
+ TEST_SUPPORTED("wfe")
+ TEST_UNSUPPORTED(".short 0xbf50") /* Unassigned hints */
+ TEST_UNSUPPORTED(".short 0xbff0") /* Unassigned hints */
+
+#define TEST_IT(code, code2) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ "50: nop \n\t" \
+ "1: "code" \n\t" \
+ " "code2" \n\t" \
+ "2: nop \n\t" \
+ TESTCASE_END
+
+DONT_TEST_IN_ITBLOCK(
+ TEST_IT("it eq","moveq r0,#0")
+ TEST_IT("it vc","movvc r0,#0")
+ TEST_IT("it le","movle r0,#0")
+ TEST_IT("ite eq","moveq r0,#0\n\t movne r1,#1")
+ TEST_IT("itet vc","movvc r0,#0\n\t movvs r1,#1\n\t movvc r2,#2")
+ TEST_IT("itete le","movle r0,#0\n\t movgt r1,#1\n\t movle r2,#2\n\t movgt r3,#3")
+ TEST_IT("itttt le","movle r0,#0\n\t movle r1,#1\n\t movle r2,#2\n\t movle r3,#3")
+ TEST_IT("iteee le","movle r0,#0\n\t movgt r1,#1\n\t movgt r2,#2\n\t movgt r3,#3")
+)
+
+ TEST_GROUP("Load and store multiple")
+
+ TEST_P("ldmia r",4, 16*4,"!, {r0,r7}")
+ TEST_P("ldmia r",7, 16*4,"!, {r0-r6}")
+ TEST_P("stmia r",4, 16*4,"!, {r0,r7}")
+ TEST_P("stmia r",0, 16*4,"!, {r0-r7}")
+
+ TEST_GROUP("Conditional branch and Supervisor Call instructions")
+
+CONDITION_INSTRUCTIONS(8,
+ TEST_BF("beq 2f")
+ TEST_BB("bne 2b")
+ TEST_BF("bgt 2f")
+ TEST_BB("blt 2b")
+)
+ TEST_UNSUPPORTED(".short 0xde00")
+ TEST_UNSUPPORTED(".short 0xdeff")
+ TEST_UNSUPPORTED("svc #0x00")
+ TEST_UNSUPPORTED("svc #0xff")
+
+ TEST_GROUP("Unconditional branch")
+
+ TEST_BF( "b 2f")
+ TEST_BB( "b 2b")
+ TEST_BF_X("b 2f", SPACE_0x400)
+ TEST_BB_X("b 2b", SPACE_0x400)
+
+ TEST_GROUP("Testing instructions in IT blocks")
+
+ TEST_ITBLOCK("subs.n r0, r0")
+
+ verbose("\n");
+}
+
+
+void kprobe_thumb32_test_cases(void)
+{
+ kprobe_test_flags = 0;
+
+ TEST_GROUP("Load/store multiple")
+
+ TEST_UNSUPPORTED("rfedb sp")
+ TEST_UNSUPPORTED("rfeia sp")
+ TEST_UNSUPPORTED("rfedb sp!")
+ TEST_UNSUPPORTED("rfeia sp!")
+
+ TEST_P( "stmia r",0, 16*4,", {r0,r8}")
+ TEST_P( "stmia r",4, 16*4,", {r0-r12,r14}")
+ TEST_P( "stmia r",7, 16*4,"!, {r8-r12,r14}")
+ TEST_P( "stmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+
+ TEST_P( "ldmia r",0, 16*4,", {r0,r8}")
+ TEST_P( "ldmia r",4, 0, ", {r0-r12,r14}")
+ TEST_BF_P("ldmia r",5, 8*4, "!, {r6-r12,r15}")
+ TEST_P( "ldmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_BF_P("ldmia r",14,14*4,"!, {r4,pc}")
+
+ TEST_P( "stmdb r",0, 16*4,", {r0,r8}")
+ TEST_P( "stmdb r",4, 16*4,", {r0-r12,r14}")
+ TEST_P( "stmdb r",5, 16*4,"!, {r8-r12,r14}")
+ TEST_P( "stmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+
+ TEST_P( "ldmdb r",0, 16*4,", {r0,r8}")
+ TEST_P( "ldmdb r",4, 16*4,", {r0-r12,r14}")
+ TEST_BF_P("ldmdb r",5, 16*4,"!, {r6-r12,r15}")
+ TEST_P( "ldmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_BF_P("ldmdb r",14,16*4,"!, {r4,pc}")
+
+ TEST_P( "stmdb r",13,16*4,"!, {r3-r12,lr}")
+ TEST_P( "stmdb r",13,16*4,"!, {r3-r12}")
+ TEST_P( "stmdb r",2, 16*4,", {r3-r12,lr}")
+ TEST_P( "stmdb r",13,16*4,"!, {r2-r12,lr}")
+ TEST_P( "stmdb r",0, 16*4,", {r0-r12}")
+ TEST_P( "stmdb r",0, 16*4,", {r0-r12,lr}")
+
+ TEST_BF_P("ldmia r",13,5*4, "!, {r3-r12,pc}")
+ TEST_P( "ldmia r",13,5*4, "!, {r3-r12}")
+ TEST_BF_P("ldmia r",2, 5*4, "!, {r3-r12,pc}")
+ TEST_BF_P("ldmia r",13,4*4, "!, {r2-r12,pc}")
+ TEST_P( "ldmia r",0, 16*4,", {r0-r12}")
+ TEST_P( "ldmia r",0, 16*4,", {r0-r12,lr}")
+
+ TEST_THUMB_TO_ARM_INTERWORK_P("ldmia r",0,14*4,", {r12,pc}")
+ TEST_THUMB_TO_ARM_INTERWORK_P("ldmia r",13,2*4,", {r0-r12,pc}")
+
+ TEST_UNSUPPORTED(".short 0xe88f,0x0101 @ stmia pc, {r0,r8}")
+ TEST_UNSUPPORTED(".short 0xe92f,0x5f00 @ stmdb pc!, {r8-r12,r14}")
+ TEST_UNSUPPORTED(".short 0xe8bd,0xc000 @ ldmia r13!, {r14,pc}")
+ TEST_UNSUPPORTED(".short 0xe93e,0xc000 @ ldmdb r14!, {r14,pc}")
+ TEST_UNSUPPORTED(".short 0xe8a7,0x3f00 @ stmia r7!, {r8-r12,sp}")
+ TEST_UNSUPPORTED(".short 0xe8a7,0x9f00 @ stmia r7!, {r8-r12,pc}")
+ TEST_UNSUPPORTED(".short 0xe93e,0x2010 @ ldmdb r14!, {r4,sp}")
+
+ TEST_GROUP("Load/store double or exclusive, table branch")
+
+ TEST_P( "ldrd r0, r1, [r",1, 24,", #-16]")
+ TEST( "ldrd r12, r14, [sp, #16]")
+ TEST_P( "ldrd r1, r0, [r",7, 24,", #-16]!")
+ TEST( "ldrd r14, r12, [sp, #16]!")
+ TEST_P( "ldrd r1, r0, [r",7, 24,"], #16")
+ TEST( "ldrd r7, r8, [sp], #-16")
+
+ TEST_X( "ldrd r12, r14, 3f",
+ ".align 3 \n\t"
+ "3: .word "__stringify(VAL1)" \n\t"
+ " .word "__stringify(VAL2))
+
+ TEST_UNSUPPORTED(".short 0xe9ff,0xec04 @ ldrd r14, r12, [pc, #16]!")
+ TEST_UNSUPPORTED(".short 0xe8ff,0xec04 @ ldrd r14, r12, [pc], #16")
+ TEST_UNSUPPORTED(".short 0xe9d4,0xd800 @ ldrd sp, r8, [r4]")
+ TEST_UNSUPPORTED(".short 0xe9d4,0xf800 @ ldrd pc, r8, [r4]")
+ TEST_UNSUPPORTED(".short 0xe9d4,0x7d00 @ ldrd r7, sp, [r4]")
+ TEST_UNSUPPORTED(".short 0xe9d4,0x7f00 @ ldrd r7, pc, [r4]")
+
+ TEST_RRP("strd r",0, VAL1,", r",1, VAL2,", [r",1, 24,", #-16]")
+ TEST_RR( "strd r",12,VAL2,", r",14,VAL1,", [sp, #16]")
+ TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,", #-16]!")
+ TEST_RR( "strd r",14,VAL2,", r",12,VAL1,", [sp, #16]!")
+ TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,"], #16")
+ TEST_RR( "strd r",7, VAL2,", r",8, VAL1,", [sp], #-16")
+ TEST_UNSUPPORTED(".short 0xe9ef,0xec04 @ strd r14, r12, [pc, #16]!")
+ TEST_UNSUPPORTED(".short 0xe8ef,0xec04 @ strd r14, r12, [pc], #16")
+
+ TEST_RX("tbb [pc, r",0, (9f-(1f+4)),"]",
+ "9: \n\t"
+ ".byte (2f-1b-4)>>1 \n\t"
+ ".byte (3f-1b-4)>>1 \n\t"
+ "3: mvn r0, r0 \n\t"
+ "2: nop \n\t")
+
+ TEST_RX("tbb [pc, r",4, (9f-(1f+4)+1),"]",
+ "9: \n\t"
+ ".byte (2f-1b-4)>>1 \n\t"
+ ".byte (3f-1b-4)>>1 \n\t"
+ "3: mvn r0, r0 \n\t"
+ "2: nop \n\t")
+
+ TEST_RRX("tbb [r",1,9f,", r",2,0,"]",
+ "9: \n\t"
+ ".byte (2f-1b-4)>>1 \n\t"
+ ".byte (3f-1b-4)>>1 \n\t"
+ "3: mvn r0, r0 \n\t"
+ "2: nop \n\t")
+
+ TEST_RX("tbh [pc, r",7, (9f-(1f+4))>>1,"]",
+ "9: \n\t"
+ ".short (2f-1b-4)>>1 \n\t"
+ ".short (3f-1b-4)>>1 \n\t"
+ "3: mvn r0, r0 \n\t"
+ "2: nop \n\t")
+
+ TEST_RX("tbh [pc, r",12, ((9f-(1f+4))>>1)+1,"]",
+ "9: \n\t"
+ ".short (2f-1b-4)>>1 \n\t"
+ ".short (3f-1b-4)>>1 \n\t"
+ "3: mvn r0, r0 \n\t"
+ "2: nop \n\t")
+
+ TEST_RRX("tbh [r",1,9f, ", r",14,1,"]",
+ "9: \n\t"
+ ".short (2f-1b-4)>>1 \n\t"
+ ".short (3f-1b-4)>>1 \n\t"
+ "3: mvn r0, r0 \n\t"
+ "2: nop \n\t")
+
+ TEST_UNSUPPORTED(".short 0xe8d1,0xf01f @ tbh [r1, pc]")
+ TEST_UNSUPPORTED(".short 0xe8d1,0xf01d @ tbh [r1, sp]")
+ TEST_UNSUPPORTED(".short 0xe8dd,0xf012 @ tbh [sp, r2]")
+
+ TEST_UNSUPPORTED("strexb r0, r1, [r2]")
+ TEST_UNSUPPORTED("strexh r0, r1, [r2]")
+ TEST_UNSUPPORTED("strexd r0, r1, [r2]")
+ TEST_UNSUPPORTED("ldrexb r0, [r1]")
+ TEST_UNSUPPORTED("ldrexh r0, [r1]")
+ TEST_UNSUPPORTED("ldrexd r0, [r1]")
+
+ TEST_GROUP("Data-processing (shifted register) and (modified immediate)")
+
+#define _DATA_PROCESSING32_DNM(op,s,val) \
+ TEST_RR(op s".w r0, r",1, VAL1,", r",2, val, "") \
+ TEST_RR(op s" r1, r",1, VAL1,", r",2, val, ", lsl #3") \
+ TEST_RR(op s" r2, r",3, VAL1,", r",2, val, ", lsr #4") \
+ TEST_RR(op s" r3, r",3, VAL1,", r",2, val, ", asr #5") \
+ TEST_RR(op s" r4, r",5, VAL1,", r",2, N(val),", asr #6") \
+ TEST_RR(op s" r5, r",5, VAL1,", r",2, val, ", ror #7") \
+ TEST_RR(op s" r8, r",9, VAL1,", r",10,val, ", rrx") \
+ TEST_R( op s" r0, r",11,VAL1,", #0x00010001") \
+ TEST_R( op s" r11, r",0, VAL1,", #0xf5000000") \
+ TEST_R( op s" r7, r",8, VAL2,", #0x000af000")
+
+#define DATA_PROCESSING32_DNM(op,val) \
+ _DATA_PROCESSING32_DNM(op,"",val) \
+ _DATA_PROCESSING32_DNM(op,"s",val)
+
+#define DATA_PROCESSING32_NM(op,val) \
+ TEST_RR(op".w r",1, VAL1,", r",2, val, "") \
+ TEST_RR(op" r",1, VAL1,", r",2, val, ", lsl #3") \
+ TEST_RR(op" r",3, VAL1,", r",2, val, ", lsr #4") \
+ TEST_RR(op" r",3, VAL1,", r",2, val, ", asr #5") \
+ TEST_RR(op" r",5, VAL1,", r",2, N(val),", asr #6") \
+ TEST_RR(op" r",5, VAL1,", r",2, val, ", ror #7") \
+ TEST_RR(op" r",9, VAL1,", r",10,val, ", rrx") \
+ TEST_R( op" r",11,VAL1,", #0x00010001") \
+ TEST_R( op" r",0, VAL1,", #0xf5000000") \
+ TEST_R( op" r",8, VAL2,", #0x000af000")
+
+#define _DATA_PROCESSING32_DM(op,s,val) \
+ TEST_R( op s".w r0, r",14, val, "") \
+ TEST_R( op s" r1, r",12, val, ", lsl #3") \
+ TEST_R( op s" r2, r",11, val, ", lsr #4") \
+ TEST_R( op s" r3, r",10, val, ", asr #5") \
+ TEST_R( op s" r4, r",9, N(val),", asr #6") \
+ TEST_R( op s" r5, r",8, val, ", ror #7") \
+ TEST_R( op s" r8, r",7,val, ", rrx") \
+ TEST( op s" r0, #0x00010001") \
+ TEST( op s" r11, #0xf5000000") \
+ TEST( op s" r7, #0x000af000") \
+ TEST( op s" r4, #0x00005a00")
+
+#define DATA_PROCESSING32_DM(op,val) \
+ _DATA_PROCESSING32_DM(op,"",val) \
+ _DATA_PROCESSING32_DM(op,"s",val)
+
+ DATA_PROCESSING32_DNM("and",0xf00f00ff)
+ DATA_PROCESSING32_NM("tst",0xf00f00ff)
+ DATA_PROCESSING32_DNM("bic",0xf00f00ff)
+ DATA_PROCESSING32_DNM("orr",0xf00f00ff)
+ DATA_PROCESSING32_DM("mov",VAL2)
+ DATA_PROCESSING32_DNM("orn",0xf00f00ff)
+ DATA_PROCESSING32_DM("mvn",VAL2)
+ DATA_PROCESSING32_DNM("eor",0xf00f00ff)
+ DATA_PROCESSING32_NM("teq",0xf00f00ff)
+ DATA_PROCESSING32_DNM("add",VAL2)
+ DATA_PROCESSING32_NM("cmn",VAL2)
+ DATA_PROCESSING32_DNM("adc",VAL2)
+ DATA_PROCESSING32_DNM("sbc",VAL2)
+ DATA_PROCESSING32_DNM("sub",VAL2)
+ DATA_PROCESSING32_NM("cmp",VAL2)
+ DATA_PROCESSING32_DNM("rsb",VAL2)
+
+ TEST_RR("pkhbt r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR("pkhbt r14,r",12, HH1,", r",10,HH2,", lsl #2")
+ TEST_RR("pkhtb r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR("pkhtb r14,r",12, HH1,", r",10,HH2,", asr #2")
+
+ TEST_UNSUPPORTED(".short 0xea17,0x0f0d @ tst.w r7, sp")
+ TEST_UNSUPPORTED(".short 0xea17,0x0f0f @ tst.w r7, pc")
+ TEST_UNSUPPORTED(".short 0xea1d,0x0f07 @ tst.w sp, r7")
+ TEST_UNSUPPORTED(".short 0xea1f,0x0f07 @ tst.w pc, r7")
+ TEST_UNSUPPORTED(".short 0xf01d,0x1f08 @ tst sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf01f,0x1f08 @ tst pc, #0x00080008")
+
+ TEST_UNSUPPORTED(".short 0xea97,0x0f0d @ teq.w r7, sp")
+ TEST_UNSUPPORTED(".short 0xea97,0x0f0f @ teq.w r7, pc")
+ TEST_UNSUPPORTED(".short 0xea9d,0x0f07 @ teq.w sp, r7")
+ TEST_UNSUPPORTED(".short 0xea9f,0x0f07 @ teq.w pc, r7")
+ TEST_UNSUPPORTED(".short 0xf09d,0x1f08 @ tst sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf09f,0x1f08 @ tst pc, #0x00080008")
+
+ TEST_UNSUPPORTED(".short 0xeb17,0x0f0d @ cmn.w r7, sp")
+ TEST_UNSUPPORTED(".short 0xeb17,0x0f0f @ cmn.w r7, pc")
+ TEST_P("cmn.w sp, r",7,0,"")
+ TEST_UNSUPPORTED(".short 0xeb1f,0x0f07 @ cmn.w pc, r7")
+ TEST( "cmn sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf11f,0x1f08 @ cmn pc, #0x00080008")
+
+ TEST_UNSUPPORTED(".short 0xebb7,0x0f0d @ cmp.w r7, sp")
+ TEST_UNSUPPORTED(".short 0xebb7,0x0f0f @ cmp.w r7, pc")
+ TEST_P("cmp.w sp, r",7,0,"")
+ TEST_UNSUPPORTED(".short 0xebbf,0x0f07 @ cmp.w pc, r7")
+ TEST( "cmp sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf1bf,0x1f08 @ cmp pc, #0x00080008")
+
+ TEST_UNSUPPORTED(".short 0xea5f,0x070d @ movs.w r7, sp")
+ TEST_UNSUPPORTED(".short 0xea5f,0x070f @ movs.w r7, pc")
+ TEST_UNSUPPORTED(".short 0xea5f,0x0d07 @ movs.w sp, r7")
+ TEST_UNSUPPORTED(".short 0xea4f,0x0f07 @ mov.w pc, r7")
+ TEST_UNSUPPORTED(".short 0xf04f,0x1d08 @ mov sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf04f,0x1f08 @ mov pc, #0x00080008")
+
+ TEST_R("add.w r0, sp, r",1, 4,"")
+ TEST_R("adds r0, sp, r",1, 4,", asl #3")
+ TEST_R("add r0, sp, r",1, 4,", asl #4")
+ TEST_R("add r0, sp, r",1, 16,", ror #1")
+ TEST_R("add.w sp, sp, r",1, 4,"")
+ TEST_R("add sp, sp, r",1, 4,", asl #3")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x1d01 @ add sp, sp, r1, asl #4")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x0d71 @ add sp, sp, r1, ror #1")
+ TEST( "add.w r0, sp, #24")
+ TEST( "add.w sp, sp, #24")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x0f01 @ add pc, sp, r1")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x000f @ add r0, sp, pc")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x000d @ add r0, sp, sp")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x0d0f @ add sp, sp, pc")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x0d0d @ add sp, sp, sp")
+
+ TEST_R("sub.w r0, sp, r",1, 4,"")
+ TEST_R("subs r0, sp, r",1, 4,", asl #3")
+ TEST_R("sub r0, sp, r",1, 4,", asl #4")
+ TEST_R("sub r0, sp, r",1, 16,", ror #1")
+ TEST_R("sub.w sp, sp, r",1, 4,"")
+ TEST_R("sub sp, sp, r",1, 4,", asl #3")
+ TEST_UNSUPPORTED(".short 0xebad,0x1d01 @ sub sp, sp, r1, asl #4")
+ TEST_UNSUPPORTED(".short 0xebad,0x0d71 @ sub sp, sp, r1, ror #1")
+ TEST_UNSUPPORTED(".short 0xebad,0x0f01 @ sub pc, sp, r1")
+ TEST( "sub.w r0, sp, #24")
+ TEST( "sub.w sp, sp, #24")
+
+ TEST_UNSUPPORTED(".short 0xea02,0x010f @ and r1, r2, pc")
+ TEST_UNSUPPORTED(".short 0xea0f,0x0103 @ and r1, pc, r3")
+ TEST_UNSUPPORTED(".short 0xea02,0x0f03 @ and pc, r2, r3")
+ TEST_UNSUPPORTED(".short 0xea02,0x010d @ and r1, r2, sp")
+ TEST_UNSUPPORTED(".short 0xea0d,0x0103 @ and r1, sp, r3")
+ TEST_UNSUPPORTED(".short 0xea02,0x0d03 @ and sp, r2, r3")
+ TEST_UNSUPPORTED(".short 0xf00d,0x1108 @ and r1, sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf00f,0x1108 @ and r1, pc, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf002,0x1d08 @ and sp, r8, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf002,0x1f08 @ and pc, r8, #0x00080008")
+
+ TEST_UNSUPPORTED(".short 0xeb02,0x010f @ add r1, r2, pc")
+ TEST_UNSUPPORTED(".short 0xeb0f,0x0103 @ add r1, pc, r3")
+ TEST_UNSUPPORTED(".short 0xeb02,0x0f03 @ add pc, r2, r3")
+ TEST_UNSUPPORTED(".short 0xeb02,0x010d @ add r1, r2, sp")
+ TEST_SUPPORTED( ".short 0xeb0d,0x0103 @ add r1, sp, r3")
+ TEST_UNSUPPORTED(".short 0xeb02,0x0d03 @ add sp, r2, r3")
+ TEST_SUPPORTED( ".short 0xf10d,0x1108 @ add r1, sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf10d,0x1f08 @ add pc, sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf10f,0x1108 @ add r1, pc, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf102,0x1d08 @ add sp, r8, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf102,0x1f08 @ add pc, r8, #0x00080008")
+
+ TEST_UNSUPPORTED(".short 0xeaa0,0x0000")
+ TEST_UNSUPPORTED(".short 0xeaf0,0x0000")
+ TEST_UNSUPPORTED(".short 0xeb20,0x0000")
+ TEST_UNSUPPORTED(".short 0xeb80,0x0000")
+ TEST_UNSUPPORTED(".short 0xebe0,0x0000")
+
+ TEST_UNSUPPORTED(".short 0xf0a0,0x0000")
+ TEST_UNSUPPORTED(".short 0xf0c0,0x0000")
+ TEST_UNSUPPORTED(".short 0xf0f0,0x0000")
+ TEST_UNSUPPORTED(".short 0xf120,0x0000")
+ TEST_UNSUPPORTED(".short 0xf180,0x0000")
+ TEST_UNSUPPORTED(".short 0xf1e0,0x0000")
+
+ TEST_GROUP("Coprocessor instructions")
+
+ TEST_UNSUPPORTED(".short 0xec00,0x0000")
+ TEST_UNSUPPORTED(".short 0xeff0,0x0000")
+ TEST_UNSUPPORTED(".short 0xfc00,0x0000")
+ TEST_UNSUPPORTED(".short 0xfff0,0x0000")
+
+ TEST_GROUP("Data-processing (plain binary immediate)")
+
+ TEST_R("addw r0, r",1, VAL1,", #0x123")
+ TEST( "addw r14, sp, #0xf5a")
+ TEST( "addw sp, sp, #0x20")
+ TEST( "addw r7, pc, #0x888")
+ TEST_UNSUPPORTED(".short 0xf20f,0x1f20 @ addw pc, pc, #0x120")
+ TEST_UNSUPPORTED(".short 0xf20d,0x1f20 @ addw pc, sp, #0x120")
+ TEST_UNSUPPORTED(".short 0xf20f,0x1d20 @ addw sp, pc, #0x120")
+ TEST_UNSUPPORTED(".short 0xf200,0x1d20 @ addw sp, r0, #0x120")
+
+ TEST_R("subw r0, r",1, VAL1,", #0x123")
+ TEST( "subw r14, sp, #0xf5a")
+ TEST( "subw sp, sp, #0x20")
+ TEST( "subw r7, pc, #0x888")
+ TEST_UNSUPPORTED(".short 0xf2af,0x1f20 @ subw pc, pc, #0x120")
+ TEST_UNSUPPORTED(".short 0xf2ad,0x1f20 @ subw pc, sp, #0x120")
+ TEST_UNSUPPORTED(".short 0xf2af,0x1d20 @ subw sp, pc, #0x120")
+ TEST_UNSUPPORTED(".short 0xf2a0,0x1d20 @ subw sp, r0, #0x120")
+
+ TEST("movw r0, #0")
+ TEST("movw r0, #0xffff")
+ TEST("movw lr, #0xffff")
+ TEST_UNSUPPORTED(".short 0xf240,0x0d00 @ movw sp, #0")
+ TEST_UNSUPPORTED(".short 0xf240,0x0f00 @ movw pc, #0")
+
+ TEST_R("movt r",0, VAL1,", #0")
+ TEST_R("movt r",0, VAL2,", #0xffff")
+ TEST_R("movt r",14,VAL1,", #0xffff")
+ TEST_UNSUPPORTED(".short 0xf2c0,0x0d00 @ movt sp, #0")
+ TEST_UNSUPPORTED(".short 0xf2c0,0x0f00 @ movt pc, #0")
+
+ TEST_R( "ssat r0, #24, r",0, VAL1,"")
+ TEST_R( "ssat r14, #24, r",12, VAL2,"")
+ TEST_R( "ssat r0, #24, r",0, VAL1,", lsl #8")
+ TEST_R( "ssat r14, #24, r",12, VAL2,", asr #8")
+ TEST_UNSUPPORTED(".short 0xf30c,0x0d17 @ ssat sp, #24, r12")
+ TEST_UNSUPPORTED(".short 0xf30c,0x0f17 @ ssat pc, #24, r12")
+ TEST_UNSUPPORTED(".short 0xf30d,0x0c17 @ ssat r12, #24, sp")
+ TEST_UNSUPPORTED(".short 0xf30f,0x0c17 @ ssat r12, #24, pc")
+
+ TEST_R( "usat r0, #24, r",0, VAL1,"")
+ TEST_R( "usat r14, #24, r",12, VAL2,"")
+ TEST_R( "usat r0, #24, r",0, VAL1,", lsl #8")
+ TEST_R( "usat r14, #24, r",12, VAL2,", asr #8")
+ TEST_UNSUPPORTED(".short 0xf38c,0x0d17 @ usat sp, #24, r12")
+ TEST_UNSUPPORTED(".short 0xf38c,0x0f17 @ usat pc, #24, r12")
+ TEST_UNSUPPORTED(".short 0xf38d,0x0c17 @ usat r12, #24, sp")
+ TEST_UNSUPPORTED(".short 0xf38f,0x0c17 @ usat r12, #24, pc")
+
+ TEST_R( "ssat16 r0, #12, r",0, HH1,"")
+ TEST_R( "ssat16 r14, #12, r",12, HH2,"")
+ TEST_UNSUPPORTED(".short 0xf32c,0x0d0b @ ssat16 sp, #12, r12")
+ TEST_UNSUPPORTED(".short 0xf32c,0x0f0b @ ssat16 pc, #12, r12")
+ TEST_UNSUPPORTED(".short 0xf32d,0x0c0b @ ssat16 r12, #12, sp")
+ TEST_UNSUPPORTED(".short 0xf32f,0x0c0b @ ssat16 r12, #12, pc")
+
+ TEST_R( "usat16 r0, #12, r",0, HH1,"")
+ TEST_R( "usat16 r14, #12, r",12, HH2,"")
+ TEST_UNSUPPORTED(".short 0xf3ac,0x0d0b @ usat16 sp, #12, r12")
+ TEST_UNSUPPORTED(".short 0xf3ac,0x0f0b @ usat16 pc, #12, r12")
+ TEST_UNSUPPORTED(".short 0xf3ad,0x0c0b @ usat16 r12, #12, sp")
+ TEST_UNSUPPORTED(".short 0xf3af,0x0c0b @ usat16 r12, #12, pc")
+
+ TEST_R( "sbfx r0, r",0 , VAL1,", #0, #31")
+ TEST_R( "sbfx r14, r",12, VAL2,", #8, #16")
+ TEST_R( "sbfx r4, r",10, VAL1,", #16, #15")
+ TEST_UNSUPPORTED(".short 0xf34c,0x2d0f @ sbfx sp, r12, #8, #16")
+ TEST_UNSUPPORTED(".short 0xf34c,0x2f0f @ sbfx pc, r12, #8, #16")
+ TEST_UNSUPPORTED(".short 0xf34d,0x2c0f @ sbfx r12, sp, #8, #16")
+ TEST_UNSUPPORTED(".short 0xf34f,0x2c0f @ sbfx r12, pc, #8, #16")
+
+ TEST_R( "ubfx r0, r",0 , VAL1,", #0, #31")
+ TEST_R( "ubfx r14, r",12, VAL2,", #8, #16")
+ TEST_R( "ubfx r4, r",10, VAL1,", #16, #15")
+ TEST_UNSUPPORTED(".short 0xf3cc,0x2d0f @ ubfx sp, r12, #8, #16")
+ TEST_UNSUPPORTED(".short 0xf3cc,0x2f0f @ ubfx pc, r12, #8, #16")
+ TEST_UNSUPPORTED(".short 0xf3cd,0x2c0f @ ubfx r12, sp, #8, #16")
+ TEST_UNSUPPORTED(".short 0xf3cf,0x2c0f @ ubfx r12, pc, #8, #16")
+
+ TEST_R( "bfc r",0, VAL1,", #4, #20")
+ TEST_R( "bfc r",14,VAL2,", #4, #20")
+ TEST_R( "bfc r",7, VAL1,", #0, #31")
+ TEST_R( "bfc r",8, VAL2,", #0, #31")
+ TEST_UNSUPPORTED(".short 0xf36f,0x0d1e @ bfc sp, #0, #31")
+ TEST_UNSUPPORTED(".short 0xf36f,0x0f1e @ bfc pc, #0, #31")
+
+ TEST_RR( "bfi r",0, VAL1,", r",0 , VAL2,", #0, #31")
+ TEST_RR( "bfi r",12,VAL1,", r",14 , VAL2,", #4, #20")
+ TEST_UNSUPPORTED(".short 0xf36e,0x1d17 @ bfi sp, r14, #4, #20")
+ TEST_UNSUPPORTED(".short 0xf36e,0x1f17 @ bfi pc, r14, #4, #20")
+ TEST_UNSUPPORTED(".short 0xf36d,0x1e17 @ bfi r14, sp, #4, #20")
+
+ TEST_GROUP("Branches and miscellaneous control")
+
+CONDITION_INSTRUCTIONS(22,
+ TEST_BF("beq.w 2f")
+ TEST_BB("bne.w 2b")
+ TEST_BF("bgt.w 2f")
+ TEST_BB("blt.w 2b")
+ TEST_BF_X("bpl.w 2f", SPACE_0x1000)
+)
+
+ TEST_UNSUPPORTED("msr cpsr, r0")
+ TEST_UNSUPPORTED("msr cpsr_f, r1")
+ TEST_UNSUPPORTED("msr spsr, r2")
+
+ TEST_UNSUPPORTED("cpsie.w i")
+ TEST_UNSUPPORTED("cpsid.w i")
+ TEST_UNSUPPORTED("cps 0x13")
+
+ TEST_SUPPORTED("yield.w")
+ TEST("sev.w")
+ TEST("nop.w")
+ TEST("wfi.w")
+ TEST_SUPPORTED("wfe.w")
+ TEST_UNSUPPORTED("dbg.w #0")
+
+ TEST_UNSUPPORTED("clrex")
+ TEST_UNSUPPORTED("dsb")
+ TEST_UNSUPPORTED("dmb")
+ TEST_UNSUPPORTED("isb")
+
+ TEST_UNSUPPORTED("bxj r0")
+
+ TEST_UNSUPPORTED("subs pc, lr, #4")
+
+ TEST("mrs r0, cpsr")
+ TEST("mrs r14, cpsr")
+ TEST_UNSUPPORTED(".short 0xf3ef,0x8d00 @ mrs sp, spsr")
+ TEST_UNSUPPORTED(".short 0xf3ef,0x8f00 @ mrs pc, spsr")
+ TEST_UNSUPPORTED("mrs r0, spsr")
+ TEST_UNSUPPORTED("mrs lr, spsr")
+
+ TEST_UNSUPPORTED(".short 0xf7f0,0x8000 @ smc #0")
+
+ TEST_UNSUPPORTED(".short 0xf7f0,0xa000 @ undefeined")
+
+ TEST_BF( "b.w 2f")
+ TEST_BB( "b.w 2b")
+ TEST_BF_X("b.w 2f", SPACE_0x1000)
+
+ TEST_BF( "bl.w 2f")
+ TEST_BB( "bl.w 2b")
+ TEST_BB_X("bl.w 2b", SPACE_0x1000)
+
+ TEST_X( "blx __dummy_arm_subroutine",
+ ".arm \n\t"
+ ".align \n\t"
+ ".type __dummy_arm_subroutine, %%function \n\t"
+ "__dummy_arm_subroutine: \n\t"
+ "mov r0, pc \n\t"
+ "bx lr \n\t"
+ ".thumb \n\t"
+ )
+ TEST( "blx __dummy_arm_subroutine")
+
+ TEST_GROUP("Store single data item")
+
+#define SINGLE_STORE(size) \
+ TEST_RP( "str"size" r",0, VAL1,", [r",11,-1024,", #1024]") \
+ TEST_RP( "str"size" r",14,VAL2,", [r",1, -1024,", #1080]") \
+ TEST_RP( "str"size" r",0, VAL1,", [r",11,256, ", #-120]") \
+ TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]") \
+ TEST_RP( "str"size" r",0, VAL1,", [r",11,24, "], #120") \
+ TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, "], #128") \
+ TEST_RP( "str"size" r",0, VAL1,", [r",11,24, "], #-120") \
+ TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, "], #-128") \
+ TEST_RP( "str"size" r",0, VAL1,", [r",11,24, ", #120]!") \
+ TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, ", #128]!") \
+ TEST_RP( "str"size" r",0, VAL1,", [r",11,256, ", #-120]!") \
+ TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]!") \
+ TEST_RPR("str"size".w r",0, VAL1,", [r",1, 0,", r",2, 4,"]") \
+ TEST_RPR("str"size" r",14,VAL2,", [r",10,0,", r",11,4,", lsl #1]") \
+ TEST_R( "str"size".w r",7, VAL1,", [sp, #24]") \
+ TEST_RP( "str"size".w r",0, VAL2,", [r",0,0, "]") \
+ TEST_UNSUPPORTED("str"size"t r0, [r1, #4]")
+
+ SINGLE_STORE("b")
+ SINGLE_STORE("h")
+ SINGLE_STORE("")
+
+ TEST("str sp, [sp]")
+ TEST_UNSUPPORTED(".short 0xf8cf,0xe000 @ str r14, [pc]")
+ TEST_UNSUPPORTED(".short 0xf8ce,0xf000 @ str pc, [r14]")
+
+ TEST_GROUP("Advanced SIMD element or structure load/store instructions")
+
+ TEST_UNSUPPORTED(".short 0xf900,0x0000")
+ TEST_UNSUPPORTED(".short 0xf92f,0xffff")
+ TEST_UNSUPPORTED(".short 0xf980,0x0000")
+ TEST_UNSUPPORTED(".short 0xf9ef,0xffff")
+
+ TEST_GROUP("Load single data item and memory hints")
+
+#define SINGLE_LOAD(size) \
+ TEST_P( "ldr"size" r0, [r",11,-1024, ", #1024]") \
+ TEST_P( "ldr"size" r14, [r",1, -1024,", #1080]") \
+ TEST_P( "ldr"size" r0, [r",11,256, ", #-120]") \
+ TEST_P( "ldr"size" r14, [r",1, 256, ", #-128]") \
+ TEST_P( "ldr"size" r0, [r",11,24, "], #120") \
+ TEST_P( "ldr"size" r14, [r",1, 24, "], #128") \
+ TEST_P( "ldr"size" r0, [r",11,24, "], #-120") \
+ TEST_P( "ldr"size" r14, [r",1,24, "], #-128") \
+ TEST_P( "ldr"size" r0, [r",11,24, ", #120]!") \
+ TEST_P( "ldr"size" r14, [r",1, 24, ", #128]!") \
+ TEST_P( "ldr"size" r0, [r",11,256, ", #-120]!") \
+ TEST_P( "ldr"size" r14, [r",1, 256, ", #-128]!") \
+ TEST_PR("ldr"size".w r0, [r",1, 0,", r",2, 4,"]") \
+ TEST_PR("ldr"size" r14, [r",10,0,", r",11,4,", lsl #1]") \
+ TEST_X( "ldr"size".w r0, 3f", \
+ ".align 3 \n\t" \
+ "3: .word "__stringify(VAL1)) \
+ TEST_X( "ldr"size".w r14, 3f", \
+ ".align 3 \n\t" \
+ "3: .word "__stringify(VAL2)) \
+ TEST( "ldr"size".w r7, 3b") \
+ TEST( "ldr"size".w r7, [sp, #24]") \
+ TEST_P( "ldr"size".w r0, [r",0,0, "]") \
+ TEST_UNSUPPORTED("ldr"size"t r0, [r1, #4]")
+
+ SINGLE_LOAD("b")
+ SINGLE_LOAD("sb")
+ SINGLE_LOAD("h")
+ SINGLE_LOAD("sh")
+ SINGLE_LOAD("")
+
+ TEST_BF_P("ldr pc, [r",14, 15*4,"]")
+ TEST_P( "ldr sp, [r",14, 13*4,"]")
+ TEST_BF_R("ldr pc, [sp, r",14, 15*4,"]")
+ TEST_R( "ldr sp, [sp, r",14, 13*4,"]")
+ TEST_THUMB_TO_ARM_INTERWORK_P("ldr pc, [r",0,0,", #15*4]")
+ TEST_SUPPORTED("ldr sp, 99f")
+ TEST_SUPPORTED("ldr pc, 99f")
+
+ TEST_UNSUPPORTED(".short 0xf854,0x700d @ ldr r7, [r4, sp]")
+ TEST_UNSUPPORTED(".short 0xf854,0x700f @ ldr r7, [r4, pc]")
+ TEST_UNSUPPORTED(".short 0xf814,0x700d @ ldrb r7, [r4, sp]")
+ TEST_UNSUPPORTED(".short 0xf814,0x700f @ ldrb r7, [r4, pc]")
+ TEST_UNSUPPORTED(".short 0xf89f,0xd004 @ ldrb sp, 99f")
+ TEST_UNSUPPORTED(".short 0xf814,0xd008 @ ldrb sp, [r4, r8]")
+ TEST_UNSUPPORTED(".short 0xf894,0xd000 @ ldrb sp, [r4]")
+
+ TEST_UNSUPPORTED(".short 0xf860,0x0000") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xf9ff,0xffff") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xf950,0x0000") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xf95f,0xffff") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xf800,0x0800") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xf97f,0xfaff") /* Unallocated space */
+
+ TEST( "pli [pc, #4]")
+ TEST( "pli [pc, #-4]")
+ TEST( "pld [pc, #4]")
+ TEST( "pld [pc, #-4]")
+
+ TEST_P( "pld [r",0,-1024,", #1024]")
+ TEST( ".short 0xf8b0,0xf400 @ pldw [r0, #1024]")
+ TEST_P( "pli [r",4, 0b,", #1024]")
+ TEST_P( "pld [r",7, 120,", #-120]")
+ TEST( ".short 0xf837,0xfc78 @ pldw [r7, #-120]")
+ TEST_P( "pli [r",11,120,", #-120]")
+ TEST( "pld [sp, #0]")
+
+ TEST_PR("pld [r",7, 24, ", r",0, 16,"]")
+ TEST_PR("pld [r",8, 24, ", r",12,16,", lsl #3]")
+ TEST_SUPPORTED(".short 0xf837,0xf000 @ pldw [r7, r0]")
+ TEST_SUPPORTED(".short 0xf838,0xf03c @ pldw [r8, r12, lsl #3]");
+ TEST_RR("pli [r",12,0b,", r",0, 16,"]")
+ TEST_RR("pli [r",0, 0b,", r",12,16,", lsl #3]")
+ TEST_R( "pld [sp, r",1, 16,"]")
+ TEST_UNSUPPORTED(".short 0xf817,0xf00d @pld [r7, sp]")
+ TEST_UNSUPPORTED(".short 0xf817,0xf00f @pld [r7, pc]")
+
+ TEST_GROUP("Data-processing (register)")
+
+#define SHIFTS32(op) \
+ TEST_RR(op" r0, r",1, VAL1,", r",2, 3, "") \
+ TEST_RR(op" r14, r",12,VAL2,", r",11,10,"")
+
+ SHIFTS32("lsl")
+ SHIFTS32("lsls")
+ SHIFTS32("lsr")
+ SHIFTS32("lsrs")
+ SHIFTS32("asr")
+ SHIFTS32("asrs")
+ SHIFTS32("ror")
+ SHIFTS32("rors")
+
+ TEST_UNSUPPORTED(".short 0xfa01,0xff02 @ lsl pc, r1, r2")
+ TEST_UNSUPPORTED(".short 0xfa01,0xfd02 @ lsl sp, r1, r2")
+ TEST_UNSUPPORTED(".short 0xfa0f,0xf002 @ lsl r0, pc, r2")
+ TEST_UNSUPPORTED(".short 0xfa0d,0xf002 @ lsl r0, sp, r2")
+ TEST_UNSUPPORTED(".short 0xfa01,0xf00f @ lsl r0, r1, pc")
+ TEST_UNSUPPORTED(".short 0xfa01,0xf00d @ lsl r0, r1, sp")
+
+ TEST_RR( "sxtah r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sxtah r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "sxth r8, r",7, HH1,"")
+
+ TEST_UNSUPPORTED(".short 0xfa0f,0xff87 @ sxth pc, r7");
+ TEST_UNSUPPORTED(".short 0xfa0f,0xfd87 @ sxth sp, r7");
+ TEST_UNSUPPORTED(".short 0xfa0f,0xf88f @ sxth r8, pc");
+ TEST_UNSUPPORTED(".short 0xfa0f,0xf88d @ sxth r8, sp");
+
+ TEST_RR( "uxtah r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uxtah r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "uxth r8, r",7, HH1,"")
+
+ TEST_RR( "sxtab16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "sxtb16 r8, r",7, HH1,"")
+
+ TEST_RR( "uxtab16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "uxtb16 r8, r",7, HH1,"")
+
+ TEST_RR( "sxtab r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sxtab r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "sxtb r8, r",7, HH1,"")
+
+ TEST_RR( "uxtab r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uxtab r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "uxtb r8, r",7, HH1,"")
+
+ TEST_UNSUPPORTED(".short 0xfa60,0x00f0")
+ TEST_UNSUPPORTED(".short 0xfa7f,0xffff")
+
+#define PARALLEL_ADD_SUB(op) \
+ TEST_RR( op"add16 r0, r",0, HH1,", r",1, HH2,"") \
+ TEST_RR( op"add16 r14, r",12,HH2,", r",10,HH1,"") \
+ TEST_RR( op"asx r0, r",0, HH1,", r",1, HH2,"") \
+ TEST_RR( op"asx r14, r",12,HH2,", r",10,HH1,"") \
+ TEST_RR( op"sax r0, r",0, HH1,", r",1, HH2,"") \
+ TEST_RR( op"sax r14, r",12,HH2,", r",10,HH1,"") \
+ TEST_RR( op"sub16 r0, r",0, HH1,", r",1, HH2,"") \
+ TEST_RR( op"sub16 r14, r",12,HH2,", r",10,HH1,"") \
+ TEST_RR( op"add8 r0, r",0, HH1,", r",1, HH2,"") \
+ TEST_RR( op"add8 r14, r",12,HH2,", r",10,HH1,"") \
+ TEST_RR( op"sub8 r0, r",0, HH1,", r",1, HH2,"") \
+ TEST_RR( op"sub8 r14, r",12,HH2,", r",10,HH1,"")
+
+ TEST_GROUP("Parallel addition and subtraction, signed")
+
+ PARALLEL_ADD_SUB("s")
+ PARALLEL_ADD_SUB("q")
+ PARALLEL_ADD_SUB("sh")
+
+ TEST_GROUP("Parallel addition and subtraction, unsigned")
+
+ PARALLEL_ADD_SUB("u")
+ PARALLEL_ADD_SUB("uq")
+ PARALLEL_ADD_SUB("uh")
+
+ TEST_GROUP("Miscellaneous operations")
+
+ TEST_RR("qadd r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR("qadd lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_RR("qsub r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR("qsub lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_RR("qdadd r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR("qdadd lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_RR("qdsub r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR("qdsub lr, r",9, VAL2,", r",8, VAL1,"")
+
+ TEST_R("rev.w r0, r",0, VAL1,"")
+ TEST_R("rev r14, r",12, VAL2,"")
+ TEST_R("rev16.w r0, r",0, VAL1,"")
+ TEST_R("rev16 r14, r",12, VAL2,"")
+ TEST_R("rbit r0, r",0, VAL1,"")
+ TEST_R("rbit r14, r",12, VAL2,"")
+ TEST_R("revsh.w r0, r",0, VAL1,"")
+ TEST_R("revsh r14, r",12, VAL2,"")
+
+ TEST_UNSUPPORTED(".short 0xfa9c,0xff8c @ rev pc, r12");
+ TEST_UNSUPPORTED(".short 0xfa9c,0xfd8c @ rev sp, r12");
+ TEST_UNSUPPORTED(".short 0xfa9f,0xfe8f @ rev r14, pc");
+ TEST_UNSUPPORTED(".short 0xfa9d,0xfe8d @ rev r14, sp");
+
+ TEST_RR("sel r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR("sel r14, r",12,VAL1,", r",10, VAL2,"")
+
+ TEST_R("clz r0, r",0, 0x0,"")
+ TEST_R("clz r7, r",14,0x1,"")
+ TEST_R("clz lr, r",7, 0xffffffff,"")
+
+ TEST_UNSUPPORTED(".short 0xfa80,0xf030") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfab0,0xf000") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */
+
+ TEST_GROUP("Multiply, multiply accumulate, and absolute difference operations")
+
+ TEST_RR( "mul r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "mul r7, r",8, VAL2,", r",9, VAL2,"")
+ TEST_UNSUPPORTED(".short 0xfb08,0xff09 @ mul pc, r8, r9")
+ TEST_UNSUPPORTED(".short 0xfb08,0xfd09 @ mul sp, r8, r9")
+ TEST_UNSUPPORTED(".short 0xfb0f,0xf709 @ mul r7, pc, r9")
+ TEST_UNSUPPORTED(".short 0xfb0d,0xf709 @ mul r7, sp, r9")
+ TEST_UNSUPPORTED(".short 0xfb08,0xf70f @ mul r7, r8, pc")
+ TEST_UNSUPPORTED(".short 0xfb08,0xf70d @ mul r7, r8, sp")
+
+ TEST_RRR( "mla r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "mla r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_UNSUPPORTED(".short 0xfb08,0xaf09 @ mla pc, r8, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb08,0xad09 @ mla sp, r8, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb0f,0xa709 @ mla r7, pc, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb0d,0xa709 @ mla r7, sp, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb08,0xa70f @ mla r7, r8, pc, r10");
+ TEST_UNSUPPORTED(".short 0xfb08,0xa70d @ mla r7, r8, sp, r10");
+ TEST_UNSUPPORTED(".short 0xfb08,0xd709 @ mla r7, r8, r9, sp");
+
+ TEST_RRR( "mls r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "mls r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+
+ TEST_RRR( "smlabb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlabb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RRR( "smlatb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlatb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RRR( "smlabt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlabt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RRR( "smlatt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlatt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smulbb r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulbb r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_RR( "smultb r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smultb r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_RR( "smulbt r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulbt r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_RR( "smultt r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smultt r7, r",8, VAL3,", r",9, VAL1,"")
+
+ TEST_RRR( "smlad r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smlad r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_RRR( "smladx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smladx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_RR( "smuad r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smuad r14, r",12,HH2,", r",10,HH1,"")
+ TEST_RR( "smuadx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smuadx r14, r",12,HH2,", r",10,HH1,"")
+
+ TEST_RRR( "smlawb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlawb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RRR( "smlawt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlawt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smulwb r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulwb r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_RR( "smulwt r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulwt r7, r",8, VAL3,", r",9, VAL1,"")
+
+ TEST_RRR( "smlsd r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smlsd r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_RRR( "smlsdx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smlsdx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_RR( "smusd r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smusd r14, r",12,HH2,", r",10,HH1,"")
+ TEST_RR( "smusdx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smusdx r14, r",12,HH2,", r",10,HH1,"")
+
+ TEST_RRR( "smmla r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmla r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_RRR( "smmlar r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmlar r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_RR( "smmul r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "smmul r14, r",12,VAL2,", r",10,VAL1,"")
+ TEST_RR( "smmulr r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "smmulr r14, r",12,VAL2,", r",10,VAL1,"")
+
+ TEST_RRR( "smmls r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmls r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_RRR( "smmlsr r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmlsr r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+
+ TEST_RRR( "usada8 r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL3,"")
+ TEST_RRR( "usada8 r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"")
+ TEST_RR( "usad8 r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "usad8 r14, r",12,VAL2,", r",10,VAL1,"")
+
+ TEST_UNSUPPORTED(".short 0xfb00,0xf010") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfb0f,0xff1f") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfb70,0xf010") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfb70,0x0010") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */
+
+ TEST_GROUP("Long multiply, long multiply accumulate, and divide")
+
+ TEST_RR( "smull r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "smull r7, r8, r",9, VAL2,", r",10, VAL1,"")
+ TEST_UNSUPPORTED(".short 0xfb89,0xf80a @ smull pc, r8, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb89,0xd80a @ smull sp, r8, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb89,0x7f0a @ smull r7, pc, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb89,0x7d0a @ smull r7, sp, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb8f,0x780a @ smull r7, r8, pc, r10");
+ TEST_UNSUPPORTED(".short 0xfb8d,0x780a @ smull r7, r8, sp, r10");
+ TEST_UNSUPPORTED(".short 0xfb89,0x780f @ smull r7, r8, r9, pc");
+ TEST_UNSUPPORTED(".short 0xfb89,0x780d @ smull r7, r8, r9, sp");
+
+ TEST_RR( "umull r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "umull r7, r8, r",9, VAL2,", r",10, VAL1,"")
+
+ TEST_RRRR( "smlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+ TEST_RRRR( "smlalbb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalbb r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRRR( "smlalbt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalbt r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRRR( "smlaltb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlaltb r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRRR( "smlaltt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlaltt r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+ TEST_RRRR( "smlald r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+ TEST_RRRR( "smlald r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+ TEST_RRRR( "smlaldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+ TEST_RRRR( "smlaldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+
+ TEST_RRRR( "smlsld r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+ TEST_RRRR( "smlsld r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+ TEST_RRRR( "smlsldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+ TEST_RRRR( "smlsldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+
+ TEST_RRRR( "umlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "umlal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRRR( "umaal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "umaal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+ TEST_GROUP("Coprocessor instructions")
+
+ TEST_UNSUPPORTED(".short 0xfc00,0x0000")
+ TEST_UNSUPPORTED(".short 0xffff,0xffff")
+
+ TEST_GROUP("Testing instructions in IT blocks")
+
+ TEST_ITBLOCK("sub.w r0, r0")
+
+ verbose("\n");
+}
+
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c
new file mode 100644
index 0000000..e17cdd6
--- /dev/null
+++ b/arch/arm/kernel/kprobes-test.c
@@ -0,0 +1,1748 @@
+/*
+ * arch/arm/kernel/kprobes-test.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * This file contains test code for ARM kprobes.
+ *
+ * The top level function run_all_tests() executes tests for all of the
+ * supported instruction sets: ARM, 16-bit Thumb, and 32-bit Thumb. These tests
+ * fall into two categories; run_api_tests() checks basic functionality of the
+ * kprobes API, and run_test_cases() is a comprehensive test for kprobes
+ * instruction decoding and simulation.
+ *
+ * run_test_cases() first checks the kprobes decoding table for self consistency
+ * (using table_test()) then executes a series of test cases for each of the CPU
+ * instruction forms. coverage_start() and coverage_end() are used to verify
+ * that these test cases cover all of the possible combinations of instructions
+ * described by the kprobes decoding tables.
+ *
+ * The individual test cases are in kprobes-test-arm.c and kprobes-test-thumb.c
+ * which use the macros defined in kprobes-test.h. The rest of this
+ * documentation will describe the operation of the framework used by these
+ * test cases.
+ */
+
+/*
+ * TESTING METHODOLOGY
+ * -------------------
+ *
+ * The methodology used to test an ARM instruction 'test_insn' is to use
+ * inline assembler like:
+ *
+ * test_before: nop
+ * test_case: test_insn
+ * test_after: nop
+ *
+ * When the test case is run a kprobe is placed of each nop. The
+ * post-handler of the test_before probe is used to modify the saved CPU
+ * register context to that which we require for the test case. The
+ * pre-handler of the of the test_after probe saves a copy of the CPU
+ * register context. In this way we can execute test_insn with a specific
+ * register context and see the results afterwards.
+ *
+ * To actually test the kprobes instruction emulation we perform the above
+ * step a second time but with an additional kprobe on the test_case
+ * instruction itself. If the emulation is accurate then the results seen
+ * by the test_after probe will be identical to the first run which didn't
+ * have a probe on test_case.
+ *
+ * Each test case is run several times with a variety of variations in the
+ * flags value of stored in CPSR, and for Thumb code, different ITState.
+ *
+ * For instructions which can modify PC, a second test_after probe is used
+ * like this:
+ *
+ * test_before: nop
+ * test_case: test_insn
+ * test_after: nop
+ * b test_done
+ * test_after2: nop
+ * test_done:
+ *
+ * The test case is constructed such that test_insn branches to
+ * test_after2, or, if testing a conditional instruction, it may just
+ * continue to test_after. The probes inserted at both locations let us
+ * determine which happened. A similar approach is used for testing
+ * backwards branches...
+ *
+ * b test_before
+ * b test_done @ helps to cope with off by 1 branches
+ * test_after2: nop
+ * b test_done
+ * test_before: nop
+ * test_case: test_insn
+ * test_after: nop
+ * test_done:
+ *
+ * The macros used to generate the assembler instructions describe above
+ * are TEST_INSTRUCTION, TEST_BRANCH_F (branch forwards) and TEST_BRANCH_B
+ * (branch backwards). In these, the local variables numbered 1, 50, 2 and
+ * 99 represent: test_before, test_case, test_after2 and test_done.
+ *
+ * FRAMEWORK
+ * ---------
+ *
+ * Each test case is wrapped between the pair of macros TESTCASE_START and
+ * TESTCASE_END. As well as performing the inline assembler boilerplate,
+ * these call out to the kprobes_test_case_start() and
+ * kprobes_test_case_end() functions which drive the execution of the test
+ * case. The specific arguments to use for each test case are stored as
+ * inline data constructed using the various TEST_ARG_* macros. Putting
+ * this all together, a simple test case may look like:
+ *
+ * TESTCASE_START("Testing mov r0, r7")
+ * TEST_ARG_REG(7, 0x12345678) // Set r7=0x12345678
+ * TEST_ARG_END("")
+ * TEST_INSTRUCTION("mov r0, r7")
+ * TESTCASE_END
+ *
+ * Note, in practice the single convenience macro TEST_R would be used for this
+ * instead.
+ *
+ * The above would expand to assembler looking something like:
+ *
+ * @ TESTCASE_START
+ * bl __kprobes_test_case_start
+ * @ start of inline data...
+ * .ascii "mov r0, r7" @ text title for test case
+ * .byte 0
+ * .align 2
+ *
+ * @ TEST_ARG_REG
+ * .byte ARG_TYPE_REG
+ * .byte 7
+ * .short 0
+ * .word 0x1234567
+ *
+ * @ TEST_ARG_END
+ * .byte ARG_TYPE_END
+ * .byte TEST_ISA @ flags, including ISA being tested
+ * .short 50f-0f @ offset of 'test_before'
+ * .short 2f-0f @ offset of 'test_after2' (if relevent)
+ * .short 99f-0f @ offset of 'test_done'
+ * @ start of test case code...
+ * 0:
+ * .code TEST_ISA @ switch to ISA being tested
+ *
+ * @ TEST_INSTRUCTION
+ * 50: nop @ location for 'test_before' probe
+ * 1: mov r0, r7 @ the test case instruction 'test_insn'
+ * nop @ location for 'test_after' probe
+ *
+ * // TESTCASE_END
+ * 2:
+ * 99: bl __kprobes_test_case_end_##TEST_ISA
+ * .code NONMAL_ISA
+ *
+ * When the above is execute the following happens...
+ *
+ * __kprobes_test_case_start() is an assembler wrapper which sets up space
+ * for a stack buffer and calls the C function kprobes_test_case_start().
+ * This C function will do some initial processing of the inline data and
+ * setup some global state. It then inserts the test_before and test_after
+ * kprobes and returns a value which causes the assembler wrapper to jump
+ * to the start of the test case code, (local label '0').
+ *
+ * When the test case code executes, the test_before probe will be hit and
+ * test_before_post_handler will call setup_test_context(). This fills the
+ * stack buffer and CPU registers with a test pattern and then processes
+ * the test case arguments. In our example there is one TEST_ARG_REG which
+ * indicates that R7 should be loaded with the value 0x12345678.
+ *
+ * When the test_before probe ends, the test case continues and executes
+ * the "mov r0, r7" instruction. It then hits the test_after probe and the
+ * pre-handler for this (test_after_pre_handler) will save a copy of the
+ * CPU register context. This should now have R0 holding the same value as
+ * R7.
+ *
+ * Finally we get to the call to __kprobes_test_case_end_{32,16}. This is
+ * an assembler wrapper which switches back to the ISA used by the test
+ * code and calls the C function kprobes_test_case_end().
+ *
+ * For each run through the test case, test_case_run_count is incremented
+ * by one. For even runs, kprobes_test_case_end() saves a copy of the
+ * register and stack buffer contents from the test case just run. It then
+ * inserts a kprobe on the test case instruction 'test_insn' and returns a
+ * value to cause the test case code to be re-run.
+ *
+ * For odd numbered runs, kprobes_test_case_end() compares the register and
+ * stack buffer contents to those that were saved on the previous even
+ * numbered run (the one without the kprobe on test_insn). These should be
+ * the same if the kprobe instruction simulation routine is correct.
+ *
+ * The pair of test case runs is repeated with different combinations of
+ * flag values in CPSR and, for Thumb, different ITState. This is
+ * controlled by test_context_cpsr().
+ *
+ * BUILDING TEST CASES
+ * -------------------
+ *
+ *
+ * As an aid to building test cases, the stack buffer is initialised with
+ * some special values:
+ *
+ * [SP+13*4] Contains SP+120. This can be used to test instructions
+ * which load a value into SP.
+ *
+ * [SP+15*4] When testing branching instructions using TEST_BRANCH_{F,B},
+ * this holds the target address of the branch, 'test_after2'.
+ * This can be used to test instructions which load a PC value
+ * from memory.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kprobes.h>
+
+#include "kprobes.h"
+#include "kprobes-test.h"
+
+
+#define BENCHMARKING 1
+
+
+/*
+ * Test basic API
+ */
+
+static bool test_regs_ok;
+static int test_func_instance;
+static int pre_handler_called;
+static int post_handler_called;
+static int jprobe_func_called;
+static int kretprobe_handler_called;
+
+#define FUNC_ARG1 0x12345678
+#define FUNC_ARG2 0xabcdef
+
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+long arm_func(long r0, long r1);
+
+static void __used __naked __arm_kprobes_test_func(void)
+{
+ __asm__ __volatile__ (
+ ".arm \n\t"
+ ".type arm_func, %%function \n\t"
+ "arm_func: \n\t"
+ "adds r0, r0, r1 \n\t"
+ "bx lr \n\t"
+ ".code "NORMAL_ISA /* Back to Thumb if necessary */
+ : : : "r0", "r1", "cc"
+ );
+}
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+long thumb16_func(long r0, long r1);
+long thumb32even_func(long r0, long r1);
+long thumb32odd_func(long r0, long r1);
+
+static void __used __naked __thumb_kprobes_test_funcs(void)
+{
+ __asm__ __volatile__ (
+ ".type thumb16_func, %%function \n\t"
+ "thumb16_func: \n\t"
+ "adds.n r0, r0, r1 \n\t"
+ "bx lr \n\t"
+
+ ".align \n\t"
+ ".type thumb32even_func, %%function \n\t"
+ "thumb32even_func: \n\t"
+ "adds.w r0, r0, r1 \n\t"
+ "bx lr \n\t"
+
+ ".align \n\t"
+ "nop.n \n\t"
+ ".type thumb32odd_func, %%function \n\t"
+ "thumb32odd_func: \n\t"
+ "adds.w r0, r0, r1 \n\t"
+ "bx lr \n\t"
+
+ : : : "r0", "r1", "cc"
+ );
+}
+
+#endif /* CONFIG_THUMB2_KERNEL */
+
+
+static int call_test_func(long (*func)(long, long), bool check_test_regs)
+{
+ long ret;
+
+ ++test_func_instance;
+ test_regs_ok = false;
+
+ ret = (*func)(FUNC_ARG1, FUNC_ARG2);
+ if (ret != FUNC_ARG1 + FUNC_ARG2) {
+ pr_err("FAIL: call_test_func: func returned %lx\n", ret);
+ return false;
+ }
+
+ if (check_test_regs && !test_regs_ok) {
+ pr_err("FAIL: test regs not OK\n");
+ return false;
+ }
+
+ return true;
+}
+
+static int __kprobes pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ pre_handler_called = test_func_instance;
+ if (regs->ARM_r0 == FUNC_ARG1 && regs->ARM_r1 == FUNC_ARG2)
+ test_regs_ok = true;
+ return 0;
+}
+
+static void __kprobes post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags)
+{
+ post_handler_called = test_func_instance;
+ if (regs->ARM_r0 != FUNC_ARG1 + FUNC_ARG2 || regs->ARM_r1 != FUNC_ARG2)
+ test_regs_ok = false;
+}
+
+static struct kprobe the_kprobe = {
+ .addr = 0,
+ .pre_handler = pre_handler,
+ .post_handler = post_handler
+};
+
+static int test_kprobe(long (*func)(long, long))
+{
+ int ret;
+
+ the_kprobe.addr = (kprobe_opcode_t *)func;
+ ret = register_kprobe(&the_kprobe);
+ if (ret < 0) {
+ pr_err("FAIL: register_kprobe failed with %d\n", ret);
+ return ret;
+ }
+
+ ret = call_test_func(func, true);
+
+ unregister_kprobe(&the_kprobe);
+ the_kprobe.flags = 0; /* Clear disable flag to allow reuse */
+
+ if (!ret)
+ return -EINVAL;
+ if (pre_handler_called != test_func_instance) {
+ pr_err("FAIL: kprobe pre_handler not called\n");
+ return -EINVAL;
+ }
+ if (post_handler_called != test_func_instance) {
+ pr_err("FAIL: kprobe post_handler not called\n");
+ return -EINVAL;
+ }
+ if (!call_test_func(func, false))
+ return -EINVAL;
+ if (pre_handler_called == test_func_instance ||
+ post_handler_called == test_func_instance) {
+ pr_err("FAIL: probe called after unregistering\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void __kprobes jprobe_func(long r0, long r1)
+{
+ jprobe_func_called = test_func_instance;
+ if (r0 == FUNC_ARG1 && r1 == FUNC_ARG2)
+ test_regs_ok = true;
+ jprobe_return();
+}
+
+static struct jprobe the_jprobe = {
+ .entry = jprobe_func,
+};
+
+static int test_jprobe(long (*func)(long, long))
+{
+ int ret;
+
+ the_jprobe.kp.addr = (kprobe_opcode_t *)func;
+ ret = register_jprobe(&the_jprobe);
+ if (ret < 0) {
+ pr_err("FAIL: register_jprobe failed with %d\n", ret);
+ return ret;
+ }
+
+ ret = call_test_func(func, true);
+
+ unregister_jprobe(&the_jprobe);
+ the_jprobe.kp.flags = 0; /* Clear disable flag to allow reuse */
+
+ if (!ret)
+ return -EINVAL;
+ if (jprobe_func_called != test_func_instance) {
+ pr_err("FAIL: jprobe handler function not called\n");
+ return -EINVAL;
+ }
+ if (!call_test_func(func, false))
+ return -EINVAL;
+ if (jprobe_func_called == test_func_instance) {
+ pr_err("FAIL: probe called after unregistering\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __kprobes
+kretprobe_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ kretprobe_handler_called = test_func_instance;
+ if (regs_return_value(regs) == FUNC_ARG1 + FUNC_ARG2)
+ test_regs_ok = true;
+ return 0;
+}
+
+static struct kretprobe the_kretprobe = {
+ .handler = kretprobe_handler,
+};
+
+static int test_kretprobe(long (*func)(long, long))
+{
+ int ret;
+
+ the_kretprobe.kp.addr = (kprobe_opcode_t *)func;
+ ret = register_kretprobe(&the_kretprobe);
+ if (ret < 0) {
+ pr_err("FAIL: register_kretprobe failed with %d\n", ret);
+ return ret;
+ }
+
+ ret = call_test_func(func, true);
+
+ unregister_kretprobe(&the_kretprobe);
+ the_kretprobe.kp.flags = 0; /* Clear disable flag to allow reuse */
+
+ if (!ret)
+ return -EINVAL;
+ if (kretprobe_handler_called != test_func_instance) {
+ pr_err("FAIL: kretprobe handler not called\n");
+ return -EINVAL;
+ }
+ if (!call_test_func(func, false))
+ return -EINVAL;
+ if (jprobe_func_called == test_func_instance) {
+ pr_err("FAIL: kretprobe called after unregistering\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int run_api_tests(long (*func)(long, long))
+{
+ int ret;
+
+ pr_info(" kprobe\n");
+ ret = test_kprobe(func);
+ if (ret < 0)
+ return ret;
+
+ pr_info(" jprobe\n");
+ ret = test_jprobe(func);
+ if (ret < 0)
+ return ret;
+
+ pr_info(" kretprobe\n");
+ ret = test_kretprobe(func);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+
+/*
+ * Benchmarking
+ */
+
+#if BENCHMARKING
+
+static void __naked benchmark_nop(void)
+{
+ __asm__ __volatile__ (
+ "nop \n\t"
+ "bx lr"
+ );
+}
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define wide ".w"
+#else
+#define wide
+#endif
+
+static void __naked benchmark_pushpop1(void)
+{
+ __asm__ __volatile__ (
+ "stmdb"wide" sp!, {r3-r11,lr} \n\t"
+ "ldmia"wide" sp!, {r3-r11,pc}"
+ );
+}
+
+static void __naked benchmark_pushpop2(void)
+{
+ __asm__ __volatile__ (
+ "stmdb"wide" sp!, {r0-r8,lr} \n\t"
+ "ldmia"wide" sp!, {r0-r8,pc}"
+ );
+}
+
+static void __naked benchmark_pushpop3(void)
+{
+ __asm__ __volatile__ (
+ "stmdb"wide" sp!, {r4,lr} \n\t"
+ "ldmia"wide" sp!, {r4,pc}"
+ );
+}
+
+static void __naked benchmark_pushpop4(void)
+{
+ __asm__ __volatile__ (
+ "stmdb"wide" sp!, {r0,lr} \n\t"
+ "ldmia"wide" sp!, {r0,pc}"
+ );
+}
+
+
+#ifdef CONFIG_THUMB2_KERNEL
+
+static void __naked benchmark_pushpop_thumb(void)
+{
+ __asm__ __volatile__ (
+ "push.n {r0-r7,lr} \n\t"
+ "pop.n {r0-r7,pc}"
+ );
+}
+
+#endif
+
+static int __kprobes
+benchmark_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ return 0;
+}
+
+static int benchmark(void(*fn)(void))
+{
+ unsigned n, i, t, t0;
+
+ for (n = 1000; ; n *= 2) {
+ t0 = sched_clock();
+ for (i = n; i > 0; --i)
+ fn();
+ t = sched_clock() - t0;
+ if (t >= 250000000)
+ break; /* Stop once we took more than 0.25 seconds */
+ }
+ return t / n; /* Time for one iteration in nanoseconds */
+};
+
+static int kprobe_benchmark(void(*fn)(void), unsigned offset)
+{
+ struct kprobe k = {
+ .addr = (kprobe_opcode_t *)((uintptr_t)fn + offset),
+ .pre_handler = benchmark_pre_handler,
+ };
+
+ int ret = register_kprobe(&k);
+ if (ret < 0) {
+ pr_err("FAIL: register_kprobe failed with %d\n", ret);
+ return ret;
+ }
+
+ ret = benchmark(fn);
+
+ unregister_kprobe(&k);
+ return ret;
+};
+
+struct benchmarks {
+ void (*fn)(void);
+ unsigned offset;
+ const char *title;
+};
+
+static int run_benchmarks(void)
+{
+ int ret;
+ struct benchmarks list[] = {
+ {&benchmark_nop, 0, "nop"},
+ /*
+ * benchmark_pushpop{1,3} will have the optimised
+ * instruction emulation, whilst benchmark_pushpop{2,4} will
+ * be the equivalent unoptimised instructions.
+ */
+ {&benchmark_pushpop1, 0, "stmdb sp!, {r3-r11,lr}"},
+ {&benchmark_pushpop1, 4, "ldmia sp!, {r3-r11,pc}"},
+ {&benchmark_pushpop2, 0, "stmdb sp!, {r0-r8,lr}"},
+ {&benchmark_pushpop2, 4, "ldmia sp!, {r0-r8,pc}"},
+ {&benchmark_pushpop3, 0, "stmdb sp!, {r4,lr}"},
+ {&benchmark_pushpop3, 4, "ldmia sp!, {r4,pc}"},
+ {&benchmark_pushpop4, 0, "stmdb sp!, {r0,lr}"},
+ {&benchmark_pushpop4, 4, "ldmia sp!, {r0,pc}"},
+#ifdef CONFIG_THUMB2_KERNEL
+ {&benchmark_pushpop_thumb, 0, "push.n {r0-r7,lr}"},
+ {&benchmark_pushpop_thumb, 2, "pop.n {r0-r7,pc}"},
+#endif
+ {0}
+ };
+
+ struct benchmarks *b;
+ for (b = list; b->fn; ++b) {
+ ret = kprobe_benchmark(b->fn, b->offset);
+ if (ret < 0)
+ return ret;
+ pr_info(" %dns for kprobe %s\n", ret, b->title);
+ }
+
+ pr_info("\n");
+ return 0;
+}
+
+#endif /* BENCHMARKING */
+
+
+/*
+ * Decoding table self-consistency tests
+ */
+
+static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
+ [DECODE_TYPE_TABLE] = sizeof(struct decode_table),
+ [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom),
+ [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate),
+ [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate),
+ [DECODE_TYPE_OR] = sizeof(struct decode_or),
+ [DECODE_TYPE_REJECT] = sizeof(struct decode_reject)
+};
+
+static int table_iter(const union decode_item *table,
+ int (*fn)(const struct decode_header *, void *),
+ void *args)
+{
+ const struct decode_header *h = (struct decode_header *)table;
+ int result;
+
+ for (;;) {
+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+ if (type == DECODE_TYPE_END)
+ return 0;
+
+ result = fn(h, args);
+ if (result)
+ return result;
+
+ h = (struct decode_header *)
+ ((uintptr_t)h + decode_struct_sizes[type]);
+
+ }
+}
+
+static int table_test_fail(const struct decode_header *h, const char* message)
+{
+
+ pr_err("FAIL: kprobes test failure \"%s\" (mask %08x, value %08x)\n",
+ message, h->mask.bits, h->value.bits);
+ return -EINVAL;
+}
+
+struct table_test_args {
+ const union decode_item *root_table;
+ u32 parent_mask;
+ u32 parent_value;
+};
+
+static int table_test_fn(const struct decode_header *h, void *args)
+{
+ struct table_test_args *a = (struct table_test_args *)args;
+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+ if (h->value.bits & ~h->mask.bits)
+ return table_test_fail(h, "Match value has bits not in mask");
+
+ if ((h->mask.bits & a->parent_mask) != a->parent_mask)
+ return table_test_fail(h, "Mask has bits not in parent mask");
+
+ if ((h->value.bits ^ a->parent_value) & a->parent_mask)
+ return table_test_fail(h, "Value is inconsistent with parent");
+
+ if (type == DECODE_TYPE_TABLE) {
+ struct decode_table *d = (struct decode_table *)h;
+ struct table_test_args args2 = *a;
+ args2.parent_mask = h->mask.bits;
+ args2.parent_value = h->value.bits;
+ return table_iter(d->table.table, table_test_fn, &args2);
+ }
+
+ return 0;
+}
+
+static int table_test(const union decode_item *table)
+{
+ struct table_test_args args = {
+ .root_table = table,
+ .parent_mask = 0,
+ .parent_value = 0
+ };
+ return table_iter(args.root_table, table_test_fn, &args);
+}
+
+
+/*
+ * Decoding table test coverage analysis
+ *
+ * coverage_start() builds a coverage_table which contains a list of
+ * coverage_entry's to match each entry in the specified kprobes instruction
+ * decoding table.
+ *
+ * When test cases are run, coverage_add() is called to process each case.
+ * This looks up the corresponding entry in the coverage_table and sets it as
+ * being matched, as well as clearing the regs flag appropriate for the test.
+ *
+ * After all test cases have been run, coverage_end() is called to check that
+ * all entries in coverage_table have been matched and that all regs flags are
+ * cleared. I.e. that all possible combinations of instructions described by
+ * the kprobes decoding tables have had a test case executed for them.
+ */
+
+bool coverage_fail;
+
+#define MAX_COVERAGE_ENTRIES 256
+
+struct coverage_entry {
+ const struct decode_header *header;
+ unsigned regs;
+ unsigned nesting;
+ char matched;
+};
+
+struct coverage_table {
+ struct coverage_entry *base;
+ unsigned num_entries;
+ unsigned nesting;
+};
+
+struct coverage_table coverage;
+
+#define COVERAGE_ANY_REG (1<<0)
+#define COVERAGE_SP (1<<1)
+#define COVERAGE_PC (1<<2)
+#define COVERAGE_PCWB (1<<3)
+
+static const char coverage_register_lookup[16] = {
+ [REG_TYPE_ANY] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
+ [REG_TYPE_SAMEAS16] = COVERAGE_ANY_REG,
+ [REG_TYPE_SP] = COVERAGE_SP,
+ [REG_TYPE_PC] = COVERAGE_PC,
+ [REG_TYPE_NOSP] = COVERAGE_ANY_REG | COVERAGE_SP,
+ [REG_TYPE_NOSPPC] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
+ [REG_TYPE_NOPC] = COVERAGE_ANY_REG | COVERAGE_PC,
+ [REG_TYPE_NOPCWB] = COVERAGE_ANY_REG | COVERAGE_PC | COVERAGE_PCWB,
+ [REG_TYPE_NOPCX] = COVERAGE_ANY_REG,
+ [REG_TYPE_NOSPPCX] = COVERAGE_ANY_REG | COVERAGE_SP,
+};
+
+unsigned coverage_start_registers(const struct decode_header *h)
+{
+ unsigned regs = 0;
+ int i;
+ for (i = 0; i < 20; i += 4) {
+ int r = (h->type_regs.bits >> (DECODE_TYPE_BITS + i)) & 0xf;
+ regs |= coverage_register_lookup[r] << i;
+ }
+ return regs;
+}
+
+static int coverage_start_fn(const struct decode_header *h, void *args)
+{
+ struct coverage_table *coverage = (struct coverage_table *)args;
+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+ struct coverage_entry *entry = coverage->base + coverage->num_entries;
+
+ if (coverage->num_entries == MAX_COVERAGE_ENTRIES - 1) {
+ pr_err("FAIL: Out of space for test coverage data");
+ return -ENOMEM;
+ }
+
+ ++coverage->num_entries;
+
+ entry->header = h;
+ entry->regs = coverage_start_registers(h);
+ entry->nesting = coverage->nesting;
+ entry->matched = false;
+
+ if (type == DECODE_TYPE_TABLE) {
+ struct decode_table *d = (struct decode_table *)h;
+ int ret;
+ ++coverage->nesting;
+ ret = table_iter(d->table.table, coverage_start_fn, coverage);
+ --coverage->nesting;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int coverage_start(const union decode_item *table)
+{
+ coverage.base = kmalloc(MAX_COVERAGE_ENTRIES *
+ sizeof(struct coverage_entry), GFP_KERNEL);
+ coverage.num_entries = 0;
+ coverage.nesting = 0;
+ return table_iter(table, coverage_start_fn, &coverage);
+}
+
+static void
+coverage_add_registers(struct coverage_entry *entry, kprobe_opcode_t insn)
+{
+ int regs = entry->header->type_regs.bits >> DECODE_TYPE_BITS;
+ int i;
+ for (i = 0; i < 20; i += 4) {
+ enum decode_reg_type reg_type = (regs >> i) & 0xf;
+ int reg = (insn >> i) & 0xf;
+ int flag;
+
+ if (!reg_type)
+ continue;
+
+ if (reg == 13)
+ flag = COVERAGE_SP;
+ else if (reg == 15)
+ flag = COVERAGE_PC;
+ else
+ flag = COVERAGE_ANY_REG;
+ entry->regs &= ~(flag << i);
+
+ switch (reg_type) {
+
+ case REG_TYPE_NONE:
+ case REG_TYPE_ANY:
+ case REG_TYPE_SAMEAS16:
+ break;
+
+ case REG_TYPE_SP:
+ if (reg != 13)
+ return;
+ break;
+
+ case REG_TYPE_PC:
+ if (reg != 15)
+ return;
+ break;
+
+ case REG_TYPE_NOSP:
+ if (reg == 13)
+ return;
+ break;
+
+ case REG_TYPE_NOSPPC:
+ case REG_TYPE_NOSPPCX:
+ if (reg == 13 || reg == 15)
+ return;
+ break;
+
+ case REG_TYPE_NOPCWB:
+ if (!is_writeback(insn))
+ break;
+ if (reg == 15) {
+ entry->regs &= ~(COVERAGE_PCWB << i);
+ return;
+ }
+ break;
+
+ case REG_TYPE_NOPC:
+ case REG_TYPE_NOPCX:
+ if (reg == 15)
+ return;
+ break;
+ }
+
+ }
+}
+
+static void coverage_add(kprobe_opcode_t insn)
+{
+ struct coverage_entry *entry = coverage.base;
+ struct coverage_entry *end = coverage.base + coverage.num_entries;
+ bool matched = false;
+ unsigned nesting = 0;
+
+ for (; entry < end; ++entry) {
+ const struct decode_header *h = entry->header;
+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+ if (entry->nesting > nesting)
+ continue; /* Skip sub-table we didn't match */
+
+ if (entry->nesting < nesting)
+ break; /* End of sub-table we were scanning */
+
+ if (!matched) {
+ if ((insn & h->mask.bits) != h->value.bits)
+ continue;
+ entry->matched = true;
+ }
+
+ switch (type) {
+
+ case DECODE_TYPE_TABLE:
+ ++nesting;
+ break;
+
+ case DECODE_TYPE_CUSTOM:
+ case DECODE_TYPE_SIMULATE:
+ case DECODE_TYPE_EMULATE:
+ coverage_add_registers(entry, insn);
+ return;
+
+ case DECODE_TYPE_OR:
+ matched = true;
+ break;
+
+ case DECODE_TYPE_REJECT:
+ default:
+ return;
+ }
+
+ }
+}
+
+static void coverage_end(void)
+{
+ struct coverage_entry *entry = coverage.base;
+ struct coverage_entry *end = coverage.base + coverage.num_entries;
+
+ for (; entry < end; ++entry) {
+ u32 mask = entry->header->mask.bits;
+ u32 value = entry->header->value.bits;
+
+ if (entry->regs) {
+ pr_err("FAIL: Register test coverage missing for %08x %08x (%05x)\n",
+ mask, value, entry->regs);
+ coverage_fail = true;
+ }
+ if (!entry->matched) {
+ pr_err("FAIL: Test coverage entry missing for %08x %08x\n",
+ mask, value);
+ coverage_fail = true;
+ }
+ }
+
+ kfree(coverage.base);
+}
+
+
+/*
+ * Framework for instruction set test cases
+ */
+
+void __naked __kprobes_test_case_start(void)
+{
+ __asm__ __volatile__ (
+ "stmdb sp!, {r4-r11} \n\t"
+ "sub sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+ "bic r0, lr, #1 @ r0 = inline title string \n\t"
+ "mov r1, sp \n\t"
+ "bl kprobes_test_case_start \n\t"
+ "bx r0 \n\t"
+ );
+}
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+void __naked __kprobes_test_case_end_32(void)
+{
+ __asm__ __volatile__ (
+ "mov r4, lr \n\t"
+ "bl kprobes_test_case_end \n\t"
+ "cmp r0, #0 \n\t"
+ "movne pc, r0 \n\t"
+ "mov r0, r4 \n\t"
+ "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+ "ldmia sp!, {r4-r11} \n\t"
+ "mov pc, r0 \n\t"
+ );
+}
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+void __naked __kprobes_test_case_end_16(void)
+{
+ __asm__ __volatile__ (
+ "mov r4, lr \n\t"
+ "bl kprobes_test_case_end \n\t"
+ "cmp r0, #0 \n\t"
+ "bxne r0 \n\t"
+ "mov r0, r4 \n\t"
+ "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+ "ldmia sp!, {r4-r11} \n\t"
+ "bx r0 \n\t"
+ );
+}
+
+void __naked __kprobes_test_case_end_32(void)
+{
+ __asm__ __volatile__ (
+ ".arm \n\t"
+ "orr lr, lr, #1 @ will return to Thumb code \n\t"
+ "ldr pc, 1f \n\t"
+ "1: \n\t"
+ ".word __kprobes_test_case_end_16 \n\t"
+ );
+}
+
+#endif
+
+
+int kprobe_test_flags;
+int kprobe_test_cc_position;
+
+static int test_try_count;
+static int test_pass_count;
+static int test_fail_count;
+
+static struct pt_regs initial_regs;
+static struct pt_regs expected_regs;
+static struct pt_regs result_regs;
+
+static u32 expected_memory[TEST_MEMORY_SIZE/sizeof(u32)];
+
+static const char *current_title;
+static struct test_arg *current_args;
+static u32 *current_stack;
+static uintptr_t current_branch_target;
+
+static uintptr_t current_code_start;
+static kprobe_opcode_t current_instruction;
+
+
+#define TEST_CASE_PASSED -1
+#define TEST_CASE_FAILED -2
+
+static int test_case_run_count;
+static bool test_case_is_thumb;
+static int test_instance;
+
+/*
+ * We ignore the state of the imprecise abort disable flag (CPSR.A) because this
+ * can change randomly as the kernel doesn't take care to preserve or initialise
+ * this across context switches. Also, with Security Extentions, the flag may
+ * not be under control of the kernel; for this reason we ignore the state of
+ * the FIQ disable flag CPSR.F as well.
+ */
+#define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT)
+
+static unsigned long test_check_cc(int cc, unsigned long cpsr)
+{
+ unsigned long temp;
+
+ switch (cc) {
+ case 0x0: /* eq */
+ return cpsr & PSR_Z_BIT;
+
+ case 0x1: /* ne */
+ return (~cpsr) & PSR_Z_BIT;
+
+ case 0x2: /* cs */
+ return cpsr & PSR_C_BIT;
+
+ case 0x3: /* cc */
+ return (~cpsr) & PSR_C_BIT;
+
+ case 0x4: /* mi */
+ return cpsr & PSR_N_BIT;
+
+ case 0x5: /* pl */
+ return (~cpsr) & PSR_N_BIT;
+
+ case 0x6: /* vs */
+ return cpsr & PSR_V_BIT;
+
+ case 0x7: /* vc */
+ return (~cpsr) & PSR_V_BIT;
+
+ case 0x8: /* hi */
+ cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+ return cpsr & PSR_C_BIT;
+
+ case 0x9: /* ls */
+ cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+ return (~cpsr) & PSR_C_BIT;
+
+ case 0xa: /* ge */
+ cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ return (~cpsr) & PSR_N_BIT;
+
+ case 0xb: /* lt */
+ cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ return cpsr & PSR_N_BIT;
+
+ case 0xc: /* gt */
+ temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
+ return (~temp) & PSR_N_BIT;
+
+ case 0xd: /* le */
+ temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
+ return temp & PSR_N_BIT;
+
+ case 0xe: /* al */
+ case 0xf: /* unconditional */
+ return true;
+ }
+ BUG();
+ return false;
+}
+
+static int is_last_scenario;
+static int probe_should_run; /* 0 = no, 1 = yes, -1 = unknown */
+static int memory_needs_checking;
+
+static unsigned long test_context_cpsr(int scenario)
+{
+ unsigned long cpsr;
+
+ probe_should_run = 1;
+
+ /* Default case is that we cycle through 16 combinations of flags */
+ cpsr = (scenario & 0xf) << 28; /* N,Z,C,V flags */
+ cpsr |= (scenario & 0xf) << 16; /* GE flags */
+ cpsr |= (scenario & 0x1) << 27; /* Toggle Q flag */
+
+ if (!test_case_is_thumb) {
+ /* Testing ARM code */
+ probe_should_run = test_check_cc(current_instruction >> 28, cpsr) != 0;
+ if (scenario == 15)
+ is_last_scenario = true;
+
+ } else if (kprobe_test_flags & TEST_FLAG_NO_ITBLOCK) {
+ /* Testing Thumb code without setting ITSTATE */
+ if (kprobe_test_cc_position) {
+ int cc = (current_instruction >> kprobe_test_cc_position) & 0xf;
+ probe_should_run = test_check_cc(cc, cpsr) != 0;
+ }
+
+ if (scenario == 15)
+ is_last_scenario = true;
+
+ } else if (kprobe_test_flags & TEST_FLAG_FULL_ITBLOCK) {
+ /* Testing Thumb code with all combinations of ITSTATE */
+ unsigned x = (scenario >> 4);
+ unsigned cond_base = x % 7; /* ITSTATE<7:5> */
+ unsigned mask = x / 7 + 2; /* ITSTATE<4:0>, bits reversed */
+
+ if (mask > 0x1f) {
+ /* Finish by testing state from instruction 'itt al' */
+ cond_base = 7;
+ mask = 0x4;
+ if ((scenario & 0xf) == 0xf)
+ is_last_scenario = true;
+ }
+
+ cpsr |= cond_base << 13; /* ITSTATE<7:5> */
+ cpsr |= (mask & 0x1) << 12; /* ITSTATE<4> */
+ cpsr |= (mask & 0x2) << 10; /* ITSTATE<3> */
+ cpsr |= (mask & 0x4) << 8; /* ITSTATE<2> */
+ cpsr |= (mask & 0x8) << 23; /* ITSTATE<1> */
+ cpsr |= (mask & 0x10) << 21; /* ITSTATE<0> */
+
+ probe_should_run = test_check_cc((cpsr >> 12) & 0xf, cpsr) != 0;
+
+ } else {
+ /* Testing Thumb code with several combinations of ITSTATE */
+ switch (scenario) {
+ case 16: /* Clear NZCV flags and 'it eq' state (false as Z=0) */
+ cpsr = 0x00000800;
+ probe_should_run = 0;
+ break;
+ case 17: /* Set NZCV flags and 'it vc' state (false as V=1) */
+ cpsr = 0xf0007800;
+ probe_should_run = 0;
+ break;
+ case 18: /* Clear NZCV flags and 'it ls' state (true as C=0) */
+ cpsr = 0x00009800;
+ break;
+ case 19: /* Set NZCV flags and 'it cs' state (true as C=1) */
+ cpsr = 0xf0002800;
+ is_last_scenario = true;
+ break;
+ }
+ }
+
+ return cpsr;
+}
+
+static void setup_test_context(struct pt_regs *regs)
+{
+ int scenario = test_case_run_count>>1;
+ unsigned long val;
+ struct test_arg *args;
+ int i;
+
+ is_last_scenario = false;
+ memory_needs_checking = false;
+
+ /* Initialise test memory on stack */
+ val = (scenario & 1) ? VALM : ~VALM;
+ for (i = 0; i < TEST_MEMORY_SIZE / sizeof(current_stack[0]); ++i)
+ current_stack[i] = val + (i << 8);
+ /* Put target of branch on stack for tests which load PC from memory */
+ if (current_branch_target)
+ current_stack[15] = current_branch_target;
+ /* Put a value for SP on stack for tests which load SP from memory */
+ current_stack[13] = (u32)current_stack + 120;
+
+ /* Initialise register values to their default state */
+ val = (scenario & 2) ? VALR : ~VALR;
+ for (i = 0; i < 13; ++i)
+ regs->uregs[i] = val ^ (i << 8);
+ regs->ARM_lr = val ^ (14 << 8);
+ regs->ARM_cpsr &= ~(APSR_MASK | PSR_IT_MASK);
+ regs->ARM_cpsr |= test_context_cpsr(scenario);
+
+ /* Perform testcase specific register setup */
+ args = current_args;
+ for (; args[0].type != ARG_TYPE_END; ++args)
+ switch (args[0].type) {
+ case ARG_TYPE_REG: {
+ struct test_arg_regptr *arg =
+ (struct test_arg_regptr *)args;
+ regs->uregs[arg->reg] = arg->val;
+ break;
+ }
+ case ARG_TYPE_PTR: {
+ struct test_arg_regptr *arg =
+ (struct test_arg_regptr *)args;
+ regs->uregs[arg->reg] =
+ (unsigned long)current_stack + arg->val;
+ memory_needs_checking = true;
+ break;
+ }
+ case ARG_TYPE_MEM: {
+ struct test_arg_mem *arg = (struct test_arg_mem *)args;
+ current_stack[arg->index] = arg->val;
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+struct test_probe {
+ struct kprobe kprobe;
+ bool registered;
+ int hit;
+};
+
+static void unregister_test_probe(struct test_probe *probe)
+{
+ if (probe->registered) {
+ unregister_kprobe(&probe->kprobe);
+ probe->kprobe.flags = 0; /* Clear disable flag to allow reuse */
+ }
+ probe->registered = false;
+}
+
+static int register_test_probe(struct test_probe *probe)
+{
+ int ret;
+
+ if (probe->registered)
+ BUG();
+
+ ret = register_kprobe(&probe->kprobe);
+ if (ret >= 0) {
+ probe->registered = true;
+ probe->hit = -1;
+ }
+ return ret;
+}
+
+static int __kprobes
+test_before_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ container_of(p, struct test_probe, kprobe)->hit = test_instance;
+ return 0;
+}
+
+static void __kprobes
+test_before_post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags)
+{
+ setup_test_context(regs);
+ initial_regs = *regs;
+ initial_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
+}
+
+static int __kprobes
+test_case_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ container_of(p, struct test_probe, kprobe)->hit = test_instance;
+ return 0;
+}
+
+static int __kprobes
+test_after_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ if (container_of(p, struct test_probe, kprobe)->hit == test_instance)
+ return 0; /* Already run for this test instance */
+
+ result_regs = *regs;
+ result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
+
+ /* Undo any changes done to SP by the test case */
+ regs->ARM_sp = (unsigned long)current_stack;
+
+ container_of(p, struct test_probe, kprobe)->hit = test_instance;
+ return 0;
+}
+
+static struct test_probe test_before_probe = {
+ .kprobe.pre_handler = test_before_pre_handler,
+ .kprobe.post_handler = test_before_post_handler,
+};
+
+static struct test_probe test_case_probe = {
+ .kprobe.pre_handler = test_case_pre_handler,
+};
+
+static struct test_probe test_after_probe = {
+ .kprobe.pre_handler = test_after_pre_handler,
+};
+
+static struct test_probe test_after2_probe = {
+ .kprobe.pre_handler = test_after_pre_handler,
+};
+
+static void test_case_cleanup(void)
+{
+ unregister_test_probe(&test_before_probe);
+ unregister_test_probe(&test_case_probe);
+ unregister_test_probe(&test_after_probe);
+ unregister_test_probe(&test_after2_probe);
+}
+
+static void print_registers(struct pt_regs *regs)
+{
+ pr_err("r0 %08lx | r1 %08lx | r2 %08lx | r3 %08lx\n",
+ regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
+ pr_err("r4 %08lx | r5 %08lx | r6 %08lx | r7 %08lx\n",
+ regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7);
+ pr_err("r8 %08lx | r9 %08lx | r10 %08lx | r11 %08lx\n",
+ regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp);
+ pr_err("r12 %08lx | sp %08lx | lr %08lx | pc %08lx\n",
+ regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc);
+ pr_err("cpsr %08lx\n", regs->ARM_cpsr);
+}
+
+static void print_memory(u32 *mem, size_t size)
+{
+ int i;
+ for (i = 0; i < size / sizeof(u32); i += 4)
+ pr_err("%08x %08x %08x %08x\n", mem[i], mem[i+1],
+ mem[i+2], mem[i+3]);
+}
+
+static size_t expected_memory_size(u32 *sp)
+{
+ size_t size = sizeof(expected_memory);
+ int offset = (uintptr_t)sp - (uintptr_t)current_stack;
+ if (offset > 0)
+ size -= offset;
+ return size;
+}
+
+static void test_case_failed(const char *message)
+{
+ test_case_cleanup();
+
+ pr_err("FAIL: %s\n", message);
+ pr_err("FAIL: Test %s\n", current_title);
+ pr_err("FAIL: Scenario %d\n", test_case_run_count >> 1);
+}
+
+static unsigned long next_instruction(unsigned long pc)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+ if ((pc & 1) && !is_wide_instruction(*(u16 *)(pc - 1)))
+ return pc + 2;
+ else
+#endif
+ return pc + 4;
+}
+
+static uintptr_t __used kprobes_test_case_start(const char *title, void *stack)
+{
+ struct test_arg *args;
+ struct test_arg_end *end_arg;
+ unsigned long test_code;
+
+ args = (struct test_arg *)PTR_ALIGN(title + strlen(title) + 1, 4);
+
+ current_title = title;
+ current_args = args;
+ current_stack = stack;
+
+ ++test_try_count;
+
+ while (args->type != ARG_TYPE_END)
+ ++args;
+ end_arg = (struct test_arg_end *)args;
+
+ test_code = (unsigned long)(args + 1); /* Code starts after args */
+
+ test_case_is_thumb = end_arg->flags & ARG_FLAG_THUMB;
+ if (test_case_is_thumb)
+ test_code |= 1;
+
+ current_code_start = test_code;
+
+ current_branch_target = 0;
+ if (end_arg->branch_offset != end_arg->end_offset)
+ current_branch_target = test_code + end_arg->branch_offset;
+
+ test_code += end_arg->code_offset;
+ test_before_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+ test_code = next_instruction(test_code);
+ test_case_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+ if (test_case_is_thumb) {
+ u16 *p = (u16 *)(test_code & ~1);
+ current_instruction = p[0];
+ if (is_wide_instruction(current_instruction)) {
+ current_instruction <<= 16;
+ current_instruction |= p[1];
+ }
+ } else {
+ current_instruction = *(u32 *)test_code;
+ }
+
+ if (current_title[0] == '.')
+ verbose("%s\n", current_title);
+ else
+ verbose("%s\t@ %0*x\n", current_title,
+ test_case_is_thumb ? 4 : 8,
+ current_instruction);
+
+ test_code = next_instruction(test_code);
+ test_after_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+ if (kprobe_test_flags & TEST_FLAG_NARROW_INSTR) {
+ if (!test_case_is_thumb ||
+ is_wide_instruction(current_instruction)) {
+ test_case_failed("expected 16-bit instruction");
+ goto fail;
+ }
+ } else {
+ if (test_case_is_thumb &&
+ !is_wide_instruction(current_instruction)) {
+ test_case_failed("expected 32-bit instruction");
+ goto fail;
+ }
+ }
+
+ coverage_add(current_instruction);
+
+ if (end_arg->flags & ARG_FLAG_UNSUPPORTED) {
+ if (register_test_probe(&test_case_probe) < 0)
+ goto pass;
+ test_case_failed("registered probe for unsupported instruction");
+ goto fail;
+ }
+
+ if (end_arg->flags & ARG_FLAG_SUPPORTED) {
+ if (register_test_probe(&test_case_probe) >= 0)
+ goto pass;
+ test_case_failed("couldn't register probe for supported instruction");
+ goto fail;
+ }
+
+ if (register_test_probe(&test_before_probe) < 0) {
+ test_case_failed("register test_before_probe failed");
+ goto fail;
+ }
+ if (register_test_probe(&test_after_probe) < 0) {
+ test_case_failed("register test_after_probe failed");
+ goto fail;
+ }
+ if (current_branch_target) {
+ test_after2_probe.kprobe.addr =
+ (kprobe_opcode_t *)current_branch_target;
+ if (register_test_probe(&test_after2_probe) < 0) {
+ test_case_failed("register test_after2_probe failed");
+ goto fail;
+ }
+ }
+
+ /* Start first run of test case */
+ test_case_run_count = 0;
+ ++test_instance;
+ return current_code_start;
+pass:
+ test_case_run_count = TEST_CASE_PASSED;
+ return (uintptr_t)test_after_probe.kprobe.addr;
+fail:
+ test_case_run_count = TEST_CASE_FAILED;
+ return (uintptr_t)test_after_probe.kprobe.addr;
+}
+
+static bool check_test_results(void)
+{
+ size_t mem_size = 0;
+ u32 *mem = 0;
+
+ if (memcmp(&expected_regs, &result_regs, sizeof(expected_regs))) {
+ test_case_failed("registers differ");
+ goto fail;
+ }
+
+ if (memory_needs_checking) {
+ mem = (u32 *)result_regs.ARM_sp;
+ mem_size = expected_memory_size(mem);
+ if (memcmp(expected_memory, mem, mem_size)) {
+ test_case_failed("test memory differs");
+ goto fail;
+ }
+ }
+
+ return true;
+
+fail:
+ pr_err("initial_regs:\n");
+ print_registers(&initial_regs);
+ pr_err("expected_regs:\n");
+ print_registers(&expected_regs);
+ pr_err("result_regs:\n");
+ print_registers(&result_regs);
+
+ if (mem) {
+ pr_err("current_stack=%p\n", current_stack);
+ pr_err("expected_memory:\n");
+ print_memory(expected_memory, mem_size);
+ pr_err("result_memory:\n");
+ print_memory(mem, mem_size);
+ }
+
+ return false;
+}
+
+static uintptr_t __used kprobes_test_case_end(void)
+{
+ if (test_case_run_count < 0) {
+ if (test_case_run_count == TEST_CASE_PASSED)
+ /* kprobes_test_case_start did all the needed testing */
+ goto pass;
+ else
+ /* kprobes_test_case_start failed */
+ goto fail;
+ }
+
+ if (test_before_probe.hit != test_instance) {
+ test_case_failed("test_before_handler not run");
+ goto fail;
+ }
+
+ if (test_after_probe.hit != test_instance &&
+ test_after2_probe.hit != test_instance) {
+ test_case_failed("test_after_handler not run");
+ goto fail;
+ }
+
+ /*
+ * Even numbered test runs ran without a probe on the test case so
+ * we can gather reference results. The subsequent odd numbered run
+ * will have the probe inserted.
+ */
+ if ((test_case_run_count & 1) == 0) {
+ /* Save results from run without probe */
+ u32 *mem = (u32 *)result_regs.ARM_sp;
+ expected_regs = result_regs;
+ memcpy(expected_memory, mem, expected_memory_size(mem));
+
+ /* Insert probe onto test case instruction */
+ if (register_test_probe(&test_case_probe) < 0) {
+ test_case_failed("register test_case_probe failed");
+ goto fail;
+ }
+ } else {
+ /* Check probe ran as expected */
+ if (probe_should_run == 1) {
+ if (test_case_probe.hit != test_instance) {
+ test_case_failed("test_case_handler not run");
+ goto fail;
+ }
+ } else if (probe_should_run == 0) {
+ if (test_case_probe.hit == test_instance) {
+ test_case_failed("test_case_handler ran");
+ goto fail;
+ }
+ }
+
+ /* Remove probe for any subsequent reference run */
+ unregister_test_probe(&test_case_probe);
+
+ if (!check_test_results())
+ goto fail;
+
+ if (is_last_scenario)
+ goto pass;
+ }
+
+ /* Do next test run */
+ ++test_case_run_count;
+ ++test_instance;
+ return current_code_start;
+fail:
+ ++test_fail_count;
+ goto end;
+pass:
+ ++test_pass_count;
+end:
+ test_case_cleanup();
+ return 0;
+}
+
+
+/*
+ * Top level test functions
+ */
+
+static int run_test_cases(void (*tests)(void), const union decode_item *table)
+{
+ int ret;
+
+ pr_info(" Check decoding tables\n");
+ ret = table_test(table);
+ if (ret)
+ return ret;
+
+ pr_info(" Run test cases\n");
+ ret = coverage_start(table);
+ if (ret)
+ return ret;
+
+ tests();
+
+ coverage_end();
+ return 0;
+}
+
+
+static int __init run_all_tests(void)
+{
+ int ret = 0;
+
+ pr_info("Begining kprobe tests...\n");
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+ pr_info("Probe ARM code\n");
+ ret = run_api_tests(arm_func);
+ if (ret)
+ goto out;
+
+ pr_info("ARM instruction simulation\n");
+ ret = run_test_cases(kprobe_arm_test_cases, kprobe_decode_arm_table);
+ if (ret)
+ goto out;
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+ pr_info("Probe 16-bit Thumb code\n");
+ ret = run_api_tests(thumb16_func);
+ if (ret)
+ goto out;
+
+ pr_info("Probe 32-bit Thumb code, even halfword\n");
+ ret = run_api_tests(thumb32even_func);
+ if (ret)
+ goto out;
+
+ pr_info("Probe 32-bit Thumb code, odd halfword\n");
+ ret = run_api_tests(thumb32odd_func);
+ if (ret)
+ goto out;
+
+ pr_info("16-bit Thumb instruction simulation\n");
+ ret = run_test_cases(kprobe_thumb16_test_cases,
+ kprobe_decode_thumb16_table);
+ if (ret)
+ goto out;
+
+ pr_info("32-bit Thumb instruction simulation\n");
+ ret = run_test_cases(kprobe_thumb32_test_cases,
+ kprobe_decode_thumb32_table);
+ if (ret)
+ goto out;
+#endif
+
+ pr_info("Total instruction simulation tests=%d, pass=%d fail=%d\n",
+ test_try_count, test_pass_count, test_fail_count);
+ if (test_fail_count) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+#if BENCHMARKING
+ pr_info("Benchmarks\n");
+ ret = run_benchmarks();
+ if (ret)
+ goto out;
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+ /* We are able to run all test cases so coverage should be complete */
+ if (coverage_fail) {
+ pr_err("FAIL: Test coverage checks failed\n");
+ ret = -EINVAL;
+ goto out;
+ }
+#endif
+
+out:
+ if (ret == 0)
+ pr_info("Finished kprobe tests OK\n");
+ else
+ pr_err("kprobe tests failed\n");
+
+ return ret;
+}
+
+
+/*
+ * Module setup
+ */
+
+#ifdef MODULE
+
+static void __exit kprobe_test_exit(void)
+{
+}
+
+module_init(run_all_tests)
+module_exit(kprobe_test_exit)
+MODULE_LICENSE("GPL");
+
+#else /* !MODULE */
+
+late_initcall(run_all_tests);
+
+#endif
diff --git a/arch/arm/kernel/kprobes-test.h b/arch/arm/kernel/kprobes-test.h
new file mode 100644
index 0000000..e28a869
--- /dev/null
+++ b/arch/arm/kernel/kprobes-test.h
@@ -0,0 +1,432 @@
+/*
+ * arch/arm/kernel/kprobes-test.h
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define VERBOSE 0 /* Set to '1' for more logging of test cases */
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define NORMAL_ISA "16"
+#else
+#define NORMAL_ISA "32"
+#endif
+
+
+/* Flags used in kprobe_test_flags */
+#define TEST_FLAG_NO_ITBLOCK (1<<0)
+#define TEST_FLAG_FULL_ITBLOCK (1<<1)
+#define TEST_FLAG_NARROW_INSTR (1<<2)
+
+extern int kprobe_test_flags;
+extern int kprobe_test_cc_position;
+
+
+#define TEST_MEMORY_SIZE 256
+
+
+/*
+ * Test case structures.
+ *
+ * The arguments given to test cases can be one of three types.
+ *
+ * ARG_TYPE_REG
+ * Load a register with the given value.
+ *
+ * ARG_TYPE_PTR
+ * Load a register with a pointer into the stack buffer (SP + given value).
+ *
+ * ARG_TYPE_MEM
+ * Store the given value into the stack buffer at [SP+index].
+ *
+ */
+
+#define ARG_TYPE_END 0
+#define ARG_TYPE_REG 1
+#define ARG_TYPE_PTR 2
+#define ARG_TYPE_MEM 3
+
+#define ARG_FLAG_UNSUPPORTED 0x01
+#define ARG_FLAG_SUPPORTED 0x02
+#define ARG_FLAG_THUMB 0x10 /* Must be 16 so TEST_ISA can be used */
+#define ARG_FLAG_ARM 0x20 /* Must be 32 so TEST_ISA can be used */
+
+struct test_arg {
+ u8 type; /* ARG_TYPE_x */
+ u8 _padding[7];
+};
+
+struct test_arg_regptr {
+ u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR */
+ u8 reg;
+ u8 _padding[2];
+ u32 val;
+};
+
+struct test_arg_mem {
+ u8 type; /* ARG_TYPE_MEM */
+ u8 index;
+ u8 _padding[2];
+ u32 val;
+};
+
+struct test_arg_end {
+ u8 type; /* ARG_TYPE_END */
+ u8 flags; /* ARG_FLAG_x */
+ u16 code_offset;
+ u16 branch_offset;
+ u16 end_offset;
+};
+
+
+/*
+ * Building blocks for test cases.
+ *
+ * Each test case is wrapped between TESTCASE_START and TESTCASE_END.
+ *
+ * To specify arguments for a test case the TEST_ARG_{REG,PTR,MEM} macros are
+ * used followed by a terminating TEST_ARG_END.
+ *
+ * After this, the instruction to be tested is defined with TEST_INSTRUCTION.
+ * Or for branches, TEST_BRANCH_B and TEST_BRANCH_F (branch forwards/backwards).
+ *
+ * Some specific test cases may make use of other custom constructs.
+ */
+
+#if VERBOSE
+#define verbose(fmt, ...) pr_info(fmt, ##__VA_ARGS__)
+#else
+#define verbose(fmt, ...)
+#endif
+
+#define TEST_GROUP(title) \
+ verbose("\n"); \
+ verbose(title"\n"); \
+ verbose("---------------------------------------------------------\n");
+
+#define TESTCASE_START(title) \
+ __asm__ __volatile__ ( \
+ "bl __kprobes_test_case_start \n\t" \
+ /* don't use .asciz here as 'title' may be */ \
+ /* multiple strings to be concatenated. */ \
+ ".ascii "#title" \n\t" \
+ ".byte 0 \n\t" \
+ ".align 2 \n\t"
+
+#define TEST_ARG_REG(reg, val) \
+ ".byte "__stringify(ARG_TYPE_REG)" \n\t" \
+ ".byte "#reg" \n\t" \
+ ".short 0 \n\t" \
+ ".word "#val" \n\t"
+
+#define TEST_ARG_PTR(reg, val) \
+ ".byte "__stringify(ARG_TYPE_PTR)" \n\t" \
+ ".byte "#reg" \n\t" \
+ ".short 0 \n\t" \
+ ".word "#val" \n\t"
+
+#define TEST_ARG_MEM(index, val) \
+ ".byte "__stringify(ARG_TYPE_MEM)" \n\t" \
+ ".byte "#index" \n\t" \
+ ".short 0 \n\t" \
+ ".word "#val" \n\t"
+
+#define TEST_ARG_END(flags) \
+ ".byte "__stringify(ARG_TYPE_END)" \n\t" \
+ ".byte "TEST_ISA flags" \n\t" \
+ ".short 50f-0f \n\t" \
+ ".short 2f-0f \n\t" \
+ ".short 99f-0f \n\t" \
+ ".code "TEST_ISA" \n\t" \
+ "0: \n\t"
+
+#define TEST_INSTRUCTION(instruction) \
+ "50: nop \n\t" \
+ "1: "instruction" \n\t" \
+ " nop \n\t"
+
+#define TEST_BRANCH_F(instruction) \
+ TEST_INSTRUCTION(instruction) \
+ " b 99f \n\t" \
+ "2: nop \n\t"
+
+#define TEST_BRANCH_B(instruction) \
+ " b 50f \n\t" \
+ " b 99f \n\t" \
+ "2: nop \n\t" \
+ " b 99f \n\t" \
+ TEST_INSTRUCTION(instruction)
+
+#define TEST_BRANCH_FX(instruction, codex) \
+ TEST_INSTRUCTION(instruction) \
+ " b 99f \n\t" \
+ codex" \n\t" \
+ " b 99f \n\t" \
+ "2: nop \n\t"
+
+#define TEST_BRANCH_BX(instruction, codex) \
+ " b 50f \n\t" \
+ " b 99f \n\t" \
+ "2: nop \n\t" \
+ " b 99f \n\t" \
+ codex" \n\t" \
+ TEST_INSTRUCTION(instruction)
+
+#define TESTCASE_END \
+ "2: \n\t" \
+ "99: \n\t" \
+ " bl __kprobes_test_case_end_"TEST_ISA" \n\t" \
+ ".code "NORMAL_ISA" \n\t" \
+ : : \
+ : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc" \
+ );
+
+
+/*
+ * Macros to define test cases.
+ *
+ * Those of the form TEST_{R,P,M}* can be used to define test cases
+ * which take combinations of the three basic types of arguments. E.g.
+ *
+ * TEST_R One register argument
+ * TEST_RR Two register arguments
+ * TEST_RPR A register, a pointer, then a register argument
+ *
+ * For testing instructions which may branch, there are macros TEST_BF_*
+ * and TEST_BB_* for branching forwards and backwards.
+ *
+ * TEST_SUPPORTED and TEST_UNSUPPORTED don't cause the code to be executed,
+ * the just verify that a kprobe is or is not allowed on the given instruction.
+ */
+
+#define TEST(code) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code) \
+ TESTCASE_END
+
+#define TEST_UNSUPPORTED(code) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("|"__stringify(ARG_FLAG_UNSUPPORTED)) \
+ TEST_INSTRUCTION(code) \
+ TESTCASE_END
+
+#define TEST_SUPPORTED(code) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("|"__stringify(ARG_FLAG_SUPPORTED)) \
+ TEST_INSTRUCTION(code) \
+ TESTCASE_END
+
+#define TEST_R(code1, reg, val, code2) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_REG(reg, val) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg code2) \
+ TESTCASE_END
+
+#define TEST_RR(code1, reg1, val1, code2, reg2, val2, code3) \
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \
+ TESTCASE_END
+
+#define TEST_RRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_REG(reg3, val3) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TESTCASE_END
+
+#define TEST_RRRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4, reg4, val4) \
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_REG(reg3, val3) \
+ TEST_ARG_REG(reg4, val4) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4) \
+ TESTCASE_END
+
+#define TEST_P(code1, reg1, val1, code2) \
+ TESTCASE_START(code1 #reg1 code2) \
+ TEST_ARG_PTR(reg1, val1) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2) \
+ TESTCASE_END
+
+#define TEST_PR(code1, reg1, val1, code2, reg2, val2, code3) \
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
+ TEST_ARG_PTR(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \
+ TESTCASE_END
+
+#define TEST_RP(code1, reg1, val1, code2, reg2, val2, code3) \
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_PTR(reg2, val2) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \
+ TESTCASE_END
+
+#define TEST_PRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TEST_ARG_PTR(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_REG(reg3, val3) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TESTCASE_END
+
+#define TEST_RPR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_PTR(reg2, val2) \
+ TEST_ARG_REG(reg3, val3) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TESTCASE_END
+
+#define TEST_RRP(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_PTR(reg3, val3) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TESTCASE_END
+
+#define TEST_BF_P(code1, reg1, val1, code2) \
+ TESTCASE_START(code1 #reg1 code2) \
+ TEST_ARG_PTR(reg1, val1) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_F(code1 #reg1 code2) \
+ TESTCASE_END
+
+#define TEST_BF(code) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_F(code) \
+ TESTCASE_END
+
+#define TEST_BB(code) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_B(code) \
+ TESTCASE_END
+
+#define TEST_BF_R(code1, reg, val, code2) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_REG(reg, val) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_F(code1 #reg code2) \
+ TESTCASE_END
+
+#define TEST_BB_R(code1, reg, val, code2) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_REG(reg, val) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_B(code1 #reg code2) \
+ TESTCASE_END
+
+#define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3) \
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3) \
+ TESTCASE_END
+
+#define TEST_BF_X(code, codex) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_FX(code, codex) \
+ TESTCASE_END
+
+#define TEST_BB_X(code, codex) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_BX(code, codex) \
+ TESTCASE_END
+
+#define TEST_BF_RX(code1, reg, val, code2, codex) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_REG(reg, val) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_FX(code1 #reg code2, codex) \
+ TESTCASE_END
+
+#define TEST_X(code, codex) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code) \
+ " b 99f \n\t" \
+ " "codex" \n\t" \
+ TESTCASE_END
+
+#define TEST_RX(code1, reg, val, code2, codex) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_REG(reg, val) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 __stringify(reg) code2) \
+ " b 99f \n\t" \
+ " "codex" \n\t" \
+ TESTCASE_END
+
+#define TEST_RRX(code1, reg1, val1, code2, reg2, val2, code3, codex) \
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 __stringify(reg1) code2 __stringify(reg2) code3) \
+ " b 99f \n\t" \
+ " "codex" \n\t" \
+ TESTCASE_END
+
+
+/*
+ * Macros for defining space directives spread over multiple lines.
+ * These are required so the compiler guesses better the length of inline asm
+ * code and will spill the literal pool early enough to avoid generating PC
+ * relative loads with out of range offsets.
+ */
+#define TWICE(x) x x
+#define SPACE_0x8 TWICE(".space 4\n\t")
+#define SPACE_0x10 TWICE(SPACE_0x8)
+#define SPACE_0x20 TWICE(SPACE_0x10)
+#define SPACE_0x40 TWICE(SPACE_0x20)
+#define SPACE_0x80 TWICE(SPACE_0x40)
+#define SPACE_0x100 TWICE(SPACE_0x80)
+#define SPACE_0x200 TWICE(SPACE_0x100)
+#define SPACE_0x400 TWICE(SPACE_0x200)
+#define SPACE_0x800 TWICE(SPACE_0x400)
+#define SPACE_0x1000 TWICE(SPACE_0x800)
+
+
+/* Various values used in test cases... */
+#define N(val) (val ^ 0xffffffff)
+#define VAL1 0x12345678
+#define VAL2 N(VAL1)
+#define VAL3 0xa5f801
+#define VAL4 N(VAL3)
+#define VALM 0x456789ab
+#define VALR 0xdeaddead
+#define HH1 0x0123fecb
+#define HH2 0xa9874567
+
+
+#ifdef CONFIG_THUMB2_KERNEL
+void kprobe_thumb16_test_cases(void);
+void kprobe_thumb32_test_cases(void);
+#else
+void kprobe_arm_test_cases(void);
+#endif
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
new file mode 100644
index 0000000..8f96ec7
--- /dev/null
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -0,0 +1,1469 @@
+/*
+ * arch/arm/kernel/kprobes-thumb.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+#include <linux/module.h>
+
+#include "kprobes.h"
+
+
+/*
+ * True if current instruction is in an IT block.
+ */
+#define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000)
+
+/*
+ * Return the condition code to check for the currently executing instruction.
+ * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if
+ * in_it_block returns true.
+ */
+#define current_cond(cpsr) ((cpsr >> 12) & 0xf)
+
+/*
+ * Return the PC value for a probe in thumb code.
+ * This is the address of the probed instruction plus 4.
+ * We subtract one because the address will have bit zero set to indicate
+ * a pointer to thumb code.
+ */
+static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
+{
+ return (unsigned long)p->addr - 1 + 4;
+}
+
+static void __kprobes
+t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ unsigned long rnv = (rn == 15) ? pc : regs->uregs[rn];
+ unsigned long rmv = regs->uregs[rm];
+ unsigned int halfwords;
+
+ if (insn & 0x10) /* TBH */
+ halfwords = ((u16 *)rnv)[rmv];
+ else /* TBB */
+ halfwords = ((u8 *)rnv)[rmv];
+
+ regs->ARM_pc = pc + 2 * halfwords;
+}
+
+static void __kprobes
+t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 8) & 0xf;
+ unsigned long mask = 0xf8ff03df; /* Mask out execution state */
+ regs->uregs[rd] = regs->ARM_cpsr & mask;
+}
+
+static void __kprobes
+t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+
+ long offset = insn & 0x7ff; /* imm11 */
+ offset += (insn & 0x003f0000) >> 5; /* imm6 */
+ offset += (insn & 0x00002000) << 4; /* J1 */
+ offset += (insn & 0x00000800) << 7; /* J2 */
+ offset -= (insn & 0x04000000) >> 7; /* Apply sign bit */
+
+ regs->ARM_pc = pc + (offset * 2);
+}
+
+static enum kprobe_insn __kprobes
+t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ int cc = (insn >> 22) & 0xf;
+ asi->insn_check_cc = kprobe_condition_checks[cc];
+ asi->insn_handler = t32_simulate_cond_branch;
+ return INSN_GOOD_NO_SLOT;
+}
+
+static void __kprobes
+t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+
+ long offset = insn & 0x7ff; /* imm11 */
+ offset += (insn & 0x03ff0000) >> 5; /* imm10 */
+ offset += (insn & 0x00002000) << 9; /* J1 */
+ offset += (insn & 0x00000800) << 10; /* J2 */
+ if (insn & 0x04000000)
+ offset -= 0x00800000; /* Apply sign bit */
+ else
+ offset ^= 0x00600000; /* Invert J1 and J2 */
+
+ if (insn & (1 << 14)) {
+ /* BL or BLX */
+ regs->ARM_lr = (unsigned long)p->addr + 4;
+ if (!(insn & (1 << 12))) {
+ /* BLX so switch to ARM mode */
+ regs->ARM_cpsr &= ~PSR_T_BIT;
+ pc &= ~3;
+ }
+ }
+
+ regs->ARM_pc = pc + (offset * 2);
+}
+
+static void __kprobes
+t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long addr = thumb_probe_pc(p) & ~3;
+ int rt = (insn >> 12) & 0xf;
+ unsigned long rtv;
+
+ long offset = insn & 0xfff;
+ if (insn & 0x00800000)
+ addr += offset;
+ else
+ addr -= offset;
+
+ if (insn & 0x00400000) {
+ /* LDR */
+ rtv = *(unsigned long *)addr;
+ if (rt == 15) {
+ bx_write_pc(rtv, regs);
+ return;
+ }
+ } else if (insn & 0x00200000) {
+ /* LDRH */
+ if (insn & 0x01000000)
+ rtv = *(s16 *)addr;
+ else
+ rtv = *(u16 *)addr;
+ } else {
+ /* LDRB */
+ if (insn & 0x01000000)
+ rtv = *(s8 *)addr;
+ else
+ rtv = *(u8 *)addr;
+ }
+
+ regs->uregs[rt] = rtv;
+}
+
+static enum kprobe_insn __kprobes
+t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi);
+
+ /* Fixup modified instruction to have halfwords in correct order...*/
+ insn = asi->insn[0];
+ ((u16 *)asi->insn)[0] = insn >> 16;
+ ((u16 *)asi->insn)[1] = insn & 0xffff;
+
+ return ret;
+}
+
+static void __kprobes
+t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p) & ~3;
+ int rt1 = (insn >> 12) & 0xf;
+ int rt2 = (insn >> 8) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+
+ register unsigned long rt1v asm("r0") = regs->uregs[rt1];
+ register unsigned long rt2v asm("r1") = regs->uregs[rt2];
+ register unsigned long rnv asm("r2") = (rn == 15) ? pc
+ : regs->uregs[rn];
+
+ __asm__ __volatile__ (
+ "blx %[fn]"
+ : "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
+ : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ if (rn != 15)
+ regs->uregs[rn] = rnv; /* Writeback base register */
+ regs->uregs[rt1] = rt1v;
+ regs->uregs[rt2] = rt2v;
+}
+
+static void __kprobes
+t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rt = (insn >> 12) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rtv asm("r0") = regs->uregs[rt];
+ register unsigned long rnv asm("r2") = regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ "blx %[fn]"
+ : "=r" (rtv), "=r" (rnv)
+ : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rn] = rnv; /* Writeback base register */
+ if (rt == 15) /* Can't be true for a STR as they aren't allowed */
+ bx_write_pc(rtv, regs);
+ else
+ regs->uregs[rt] = rtv;
+}
+
+static void __kprobes
+t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 8) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rdv asm("r1") = regs->uregs[rd];
+ register unsigned long rnv asm("r2") = regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+ unsigned long cpsr = regs->ARM_cpsr;
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[cpsr] \n\t"
+ "blx %[fn] \n\t"
+ "mrs %[cpsr], cpsr \n\t"
+ : "=r" (rdv), [cpsr] "=r" (cpsr)
+ : "0" (rdv), "r" (rnv), "r" (rmv),
+ "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rd] = rdv;
+ regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static void __kprobes
+t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+ int rd = (insn >> 8) & 0xf;
+
+ register unsigned long rdv asm("r1") = regs->uregs[rd];
+ register unsigned long rnv asm("r2") = pc & ~3;
+
+ __asm__ __volatile__ (
+ "blx %[fn]"
+ : "=r" (rdv)
+ : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rd] = rdv;
+}
+
+static void __kprobes
+t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 8) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+
+ register unsigned long rdv asm("r1") = regs->uregs[rd];
+ register unsigned long rnv asm("r2") = regs->uregs[rn];
+
+ __asm__ __volatile__ (
+ "blx %[fn]"
+ : "=r" (rdv)
+ : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rd] = rdv;
+}
+
+static void __kprobes
+t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rdlo = (insn >> 12) & 0xf;
+ int rdhi = (insn >> 8) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
+ register unsigned long rdhiv asm("r1") = regs->uregs[rdhi];
+ register unsigned long rnv asm("r2") = regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ "blx %[fn]"
+ : "=r" (rdlov), "=r" (rdhiv)
+ : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
+ [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rdlo] = rdlov;
+ regs->uregs[rdhi] = rdhiv;
+}
+
+/* These emulation encodings are functionally equivalent... */
+#define t32_emulate_rd8rn16rm0ra12_noflags \
+ t32_emulate_rdlo12rdhi8rn16rm0_noflags
+
+static const union decode_item t32_table_1110_100x_x0xx[] = {
+ /* Load/store multiple instructions */
+
+ /* Rn is PC 1110 100x x0xx 1111 xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfe4f0000, 0xe80f0000),
+
+ /* SRS 1110 1000 00x0 xxxx xxxx xxxx xxxx xxxx */
+ /* RFE 1110 1000 00x1 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xffc00000, 0xe8000000),
+ /* SRS 1110 1001 10x0 xxxx xxxx xxxx xxxx xxxx */
+ /* RFE 1110 1001 10x1 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xffc00000, 0xe9800000),
+
+ /* STM Rn, {...pc} 1110 100x x0x0 xxxx 1xxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfe508000, 0xe8008000),
+ /* LDM Rn, {...lr,pc} 1110 100x x0x1 xxxx 11xx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfe50c000, 0xe810c000),
+ /* LDM/STM Rn, {...sp} 1110 100x x0xx xxxx xx1x xxxx xxxx xxxx */
+ DECODE_REJECT (0xfe402000, 0xe8002000),
+
+ /* STMIA 1110 1000 10x0 xxxx xxxx xxxx xxxx xxxx */
+ /* LDMIA 1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */
+ /* STMDB 1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */
+ /* LDMDB 1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_CUSTOM (0xfe400000, 0xe8000000, t32_decode_ldmstm),
+
+ DECODE_END
+};
+
+static const union decode_item t32_table_1110_100x_x1xx[] = {
+ /* Load/store dual, load/store exclusive, table branch */
+
+ /* STRD (immediate) 1110 1000 x110 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRD (immediate) 1110 1000 x111 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_OR (0xff600000, 0xe8600000),
+ /* STRD (immediate) 1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRD (immediate) 1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xff400000, 0xe9400000, t32_emulate_ldrdstrd,
+ REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)),
+
+ /* TBB 1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */
+ /* TBH 1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */
+ DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, t32_simulate_table_branch,
+ REGS(NOSP, 0, 0, 0, NOSPPC)),
+
+ /* STREX 1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */
+ /* LDREX 1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */
+ /* STREXB 1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */
+ /* STREXH 1110 1000 1100 xxxx xxxx xxxx 0101 xxxx */
+ /* STREXD 1110 1000 1100 xxxx xxxx xxxx 0111 xxxx */
+ /* LDREXB 1110 1000 1101 xxxx xxxx xxxx 0100 xxxx */
+ /* LDREXH 1110 1000 1101 xxxx xxxx xxxx 0101 xxxx */
+ /* LDREXD 1110 1000 1101 xxxx xxxx xxxx 0111 xxxx */
+ /* And unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item t32_table_1110_101x[] = {
+ /* Data-processing (shifted register) */
+
+ /* TST 1110 1010 0001 xxxx xxxx 1111 xxxx xxxx */
+ /* TEQ 1110 1010 1001 xxxx xxxx 1111 xxxx xxxx */
+ DECODE_EMULATEX (0xff700f00, 0xea100f00, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, 0, 0, NOSPPC)),
+
+ /* CMN 1110 1011 0001 xxxx xxxx 1111 xxxx xxxx */
+ DECODE_OR (0xfff00f00, 0xeb100f00),
+ /* CMP 1110 1011 1011 xxxx xxxx 1111 xxxx xxxx */
+ DECODE_EMULATEX (0xfff00f00, 0xebb00f00, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOPC, 0, 0, 0, NOSPPC)),
+
+ /* MOV 1110 1010 010x 1111 xxxx xxxx xxxx xxxx */
+ /* MVN 1110 1010 011x 1111 xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xffcf0000, 0xea4f0000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(0, 0, NOSPPC, 0, NOSPPC)),
+
+ /* ??? 1110 1010 101x xxxx xxxx xxxx xxxx xxxx */
+ /* ??? 1110 1010 111x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xffa00000, 0xeaa00000),
+ /* ??? 1110 1011 001x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xffe00000, 0xeb200000),
+ /* ??? 1110 1011 100x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xffe00000, 0xeb800000),
+ /* ??? 1110 1011 111x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xffe00000, 0xebe00000),
+
+ /* ADD/SUB SP, SP, Rm, LSL #0..3 */
+ /* 1110 1011 x0xx 1101 x000 1101 xx00 xxxx */
+ DECODE_EMULATEX (0xff4f7f30, 0xeb0d0d00, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(SP, 0, SP, 0, NOSPPC)),
+
+ /* ADD/SUB SP, SP, Rm, shift */
+ /* 1110 1011 x0xx 1101 xxxx 1101 xxxx xxxx */
+ DECODE_REJECT (0xff4f0f00, 0xeb0d0d00),
+
+ /* ADD/SUB Rd, SP, Rm, shift */
+ /* 1110 1011 x0xx 1101 xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xff4f0000, 0xeb0d0000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(SP, 0, NOPC, 0, NOSPPC)),
+
+ /* AND 1110 1010 000x xxxx xxxx xxxx xxxx xxxx */
+ /* BIC 1110 1010 001x xxxx xxxx xxxx xxxx xxxx */
+ /* ORR 1110 1010 010x xxxx xxxx xxxx xxxx xxxx */
+ /* ORN 1110 1010 011x xxxx xxxx xxxx xxxx xxxx */
+ /* EOR 1110 1010 100x xxxx xxxx xxxx xxxx xxxx */
+ /* PKH 1110 1010 110x xxxx xxxx xxxx xxxx xxxx */
+ /* ADD 1110 1011 000x xxxx xxxx xxxx xxxx xxxx */
+ /* ADC 1110 1011 010x xxxx xxxx xxxx xxxx xxxx */
+ /* SBC 1110 1011 011x xxxx xxxx xxxx xxxx xxxx */
+ /* SUB 1110 1011 101x xxxx xxxx xxxx xxxx xxxx */
+ /* RSB 1110 1011 110x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfe000000, 0xea000000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
+
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_0x0x___0[] = {
+ /* Data-processing (modified immediate) */
+
+ /* TST 1111 0x00 0001 xxxx 0xxx 1111 xxxx xxxx */
+ /* TEQ 1111 0x00 1001 xxxx 0xxx 1111 xxxx xxxx */
+ DECODE_EMULATEX (0xfb708f00, 0xf0100f00, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, 0, 0, 0)),
+
+ /* CMN 1111 0x01 0001 xxxx 0xxx 1111 xxxx xxxx */
+ DECODE_OR (0xfbf08f00, 0xf1100f00),
+ /* CMP 1111 0x01 1011 xxxx 0xxx 1111 xxxx xxxx */
+ DECODE_EMULATEX (0xfbf08f00, 0xf1b00f00, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOPC, 0, 0, 0, 0)),
+
+ /* MOV 1111 0x00 010x 1111 0xxx xxxx xxxx xxxx */
+ /* MVN 1111 0x00 011x 1111 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfbcf8000, 0xf04f0000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(0, 0, NOSPPC, 0, 0)),
+
+ /* ??? 1111 0x00 101x xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfbe08000, 0xf0a00000),
+ /* ??? 1111 0x00 110x xxxx 0xxx xxxx xxxx xxxx */
+ /* ??? 1111 0x00 111x xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfbc08000, 0xf0c00000),
+ /* ??? 1111 0x01 001x xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfbe08000, 0xf1200000),
+ /* ??? 1111 0x01 100x xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfbe08000, 0xf1800000),
+ /* ??? 1111 0x01 111x xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfbe08000, 0xf1e00000),
+
+ /* ADD Rd, SP, #imm 1111 0x01 000x 1101 0xxx xxxx xxxx xxxx */
+ /* SUB Rd, SP, #imm 1111 0x01 101x 1101 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfb4f8000, 0xf10d0000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(SP, 0, NOPC, 0, 0)),
+
+ /* AND 1111 0x00 000x xxxx 0xxx xxxx xxxx xxxx */
+ /* BIC 1111 0x00 001x xxxx 0xxx xxxx xxxx xxxx */
+ /* ORR 1111 0x00 010x xxxx 0xxx xxxx xxxx xxxx */
+ /* ORN 1111 0x00 011x xxxx 0xxx xxxx xxxx xxxx */
+ /* EOR 1111 0x00 100x xxxx 0xxx xxxx xxxx xxxx */
+ /* ADD 1111 0x01 000x xxxx 0xxx xxxx xxxx xxxx */
+ /* ADC 1111 0x01 010x xxxx 0xxx xxxx xxxx xxxx */
+ /* SBC 1111 0x01 011x xxxx 0xxx xxxx xxxx xxxx */
+ /* SUB 1111 0x01 101x xxxx 0xxx xxxx xxxx xxxx */
+ /* RSB 1111 0x01 110x xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfa008000, 0xf0000000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, 0)),
+
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_0x1x___0[] = {
+ /* Data-processing (plain binary immediate) */
+
+ /* ADDW Rd, PC, #imm 1111 0x10 0000 1111 0xxx xxxx xxxx xxxx */
+ DECODE_OR (0xfbff8000, 0xf20f0000),
+ /* SUBW Rd, PC, #imm 1111 0x10 1010 1111 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfbff8000, 0xf2af0000, t32_emulate_rd8pc16_noflags,
+ REGS(PC, 0, NOSPPC, 0, 0)),
+
+ /* ADDW SP, SP, #imm 1111 0x10 0000 1101 0xxx 1101 xxxx xxxx */
+ DECODE_OR (0xfbff8f00, 0xf20d0d00),
+ /* SUBW SP, SP, #imm 1111 0x10 1010 1101 0xxx 1101 xxxx xxxx */
+ DECODE_EMULATEX (0xfbff8f00, 0xf2ad0d00, t32_emulate_rd8rn16_noflags,
+ REGS(SP, 0, SP, 0, 0)),
+
+ /* ADDW 1111 0x10 0000 xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_OR (0xfbf08000, 0xf2000000),
+ /* SUBW 1111 0x10 1010 xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfbf08000, 0xf2a00000, t32_emulate_rd8rn16_noflags,
+ REGS(NOPCX, 0, NOSPPC, 0, 0)),
+
+ /* MOVW 1111 0x10 0100 xxxx 0xxx xxxx xxxx xxxx */
+ /* MOVT 1111 0x10 1100 xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfb708000, 0xf2400000, t32_emulate_rd8rn16_noflags,
+ REGS(0, 0, NOSPPC, 0, 0)),
+
+ /* SSAT16 1111 0x11 0010 xxxx 0000 xxxx 00xx xxxx */
+ /* SSAT 1111 0x11 00x0 xxxx 0xxx xxxx xxxx xxxx */
+ /* USAT16 1111 0x11 1010 xxxx 0000 xxxx 00xx xxxx */
+ /* USAT 1111 0x11 10x0 xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfb508000, 0xf3000000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, 0)),
+
+ /* SFBX 1111 0x11 0100 xxxx 0xxx xxxx xxxx xxxx */
+ /* UFBX 1111 0x11 1100 xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfb708000, 0xf3400000, t32_emulate_rd8rn16_noflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, 0)),
+
+ /* BFC 1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfbff8000, 0xf36f0000, t32_emulate_rd8rn16_noflags,
+ REGS(0, 0, NOSPPC, 0, 0)),
+
+ /* BFI 1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfbf08000, 0xf3600000, t32_emulate_rd8rn16_noflags,
+ REGS(NOSPPCX, 0, NOSPPC, 0, 0)),
+
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_0xxx___1[] = {
+ /* Branches and miscellaneous control */
+
+ /* YIELD 1111 0011 1010 xxxx 10x0 x000 0000 0001 */
+ DECODE_OR (0xfff0d7ff, 0xf3a08001),
+ /* SEV 1111 0011 1010 xxxx 10x0 x000 0000 0100 */
+ DECODE_EMULATE (0xfff0d7ff, 0xf3a08004, kprobe_emulate_none),
+ /* NOP 1111 0011 1010 xxxx 10x0 x000 0000 0000 */
+ /* WFE 1111 0011 1010 xxxx 10x0 x000 0000 0010 */
+ /* WFI 1111 0011 1010 xxxx 10x0 x000 0000 0011 */
+ DECODE_SIMULATE (0xfff0d7fc, 0xf3a08000, kprobe_simulate_nop),
+
+ /* MRS Rd, CPSR 1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */
+ DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, t32_simulate_mrs,
+ REGS(0, 0, NOSPPC, 0, 0)),
+
+ /*
+ * Unsupported instructions
+ * 1111 0x11 1xxx xxxx 10x0 xxxx xxxx xxxx
+ *
+ * MSR 1111 0011 100x xxxx 10x0 xxxx xxxx xxxx
+ * DBG hint 1111 0011 1010 xxxx 10x0 x000 1111 xxxx
+ * Unallocated hints 1111 0011 1010 xxxx 10x0 x000 xxxx xxxx
+ * CPS 1111 0011 1010 xxxx 10x0 xxxx xxxx xxxx
+ * CLREX/DSB/DMB/ISB 1111 0011 1011 xxxx 10x0 xxxx xxxx xxxx
+ * BXJ 1111 0011 1100 xxxx 10x0 xxxx xxxx xxxx
+ * SUBS PC,LR,#<imm8> 1111 0011 1101 xxxx 10x0 xxxx xxxx xxxx
+ * MRS Rd, SPSR 1111 0011 1111 xxxx 10x0 xxxx xxxx xxxx
+ * SMC 1111 0111 1111 xxxx 1000 xxxx xxxx xxxx
+ * UNDEFINED 1111 0111 1111 xxxx 1010 xxxx xxxx xxxx
+ * ??? 1111 0111 1xxx xxxx 1010 xxxx xxxx xxxx
+ */
+ DECODE_REJECT (0xfb80d000, 0xf3808000),
+
+ /* Bcc 1111 0xxx xxxx xxxx 10x0 xxxx xxxx xxxx */
+ DECODE_CUSTOM (0xf800d000, 0xf0008000, t32_decode_cond_branch),
+
+ /* BLX 1111 0xxx xxxx xxxx 11x0 xxxx xxxx xxx0 */
+ DECODE_OR (0xf800d001, 0xf000c000),
+ /* B 1111 0xxx xxxx xxxx 10x1 xxxx xxxx xxxx */
+ /* BL 1111 0xxx xxxx xxxx 11x1 xxxx xxxx xxxx */
+ DECODE_SIMULATE (0xf8009000, 0xf0009000, t32_simulate_branch),
+
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_100x_x0x1__1111[] = {
+ /* Memory hints */
+
+ /* PLD (literal) 1111 1000 x001 1111 1111 xxxx xxxx xxxx */
+ /* PLI (literal) 1111 1001 x001 1111 1111 xxxx xxxx xxxx */
+ DECODE_SIMULATE (0xfe7ff000, 0xf81ff000, kprobe_simulate_nop),
+
+ /* PLD{W} (immediate) 1111 1000 10x1 xxxx 1111 xxxx xxxx xxxx */
+ DECODE_OR (0xffd0f000, 0xf890f000),
+ /* PLD{W} (immediate) 1111 1000 00x1 xxxx 1111 1100 xxxx xxxx */
+ DECODE_OR (0xffd0ff00, 0xf810fc00),
+ /* PLI (immediate) 1111 1001 1001 xxxx 1111 xxxx xxxx xxxx */
+ DECODE_OR (0xfff0f000, 0xf990f000),
+ /* PLI (immediate) 1111 1001 0001 xxxx 1111 1100 xxxx xxxx */
+ DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, kprobe_simulate_nop,
+ REGS(NOPCX, 0, 0, 0, 0)),
+
+ /* PLD{W} (register) 1111 1000 00x1 xxxx 1111 0000 00xx xxxx */
+ DECODE_OR (0xffd0ffc0, 0xf810f000),
+ /* PLI (register) 1111 1001 0001 xxxx 1111 0000 00xx xxxx */
+ DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, kprobe_simulate_nop,
+ REGS(NOPCX, 0, 0, 0, NOSPPC)),
+
+ /* Other unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_100x[] = {
+ /* Store/Load single data item */
+
+ /* ??? 1111 100x x11x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfe600000, 0xf8600000),
+
+ /* ??? 1111 1001 0101 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfff00000, 0xf9500000),
+
+ /* ??? 1111 100x 0xxx xxxx xxxx 10x0 xxxx xxxx */
+ DECODE_REJECT (0xfe800d00, 0xf8000800),
+
+ /* STRBT 1111 1000 0000 xxxx xxxx 1110 xxxx xxxx */
+ /* STRHT 1111 1000 0010 xxxx xxxx 1110 xxxx xxxx */
+ /* STRT 1111 1000 0100 xxxx xxxx 1110 xxxx xxxx */
+ /* LDRBT 1111 1000 0001 xxxx xxxx 1110 xxxx xxxx */
+ /* LDRSBT 1111 1001 0001 xxxx xxxx 1110 xxxx xxxx */
+ /* LDRHT 1111 1000 0011 xxxx xxxx 1110 xxxx xxxx */
+ /* LDRSHT 1111 1001 0011 xxxx xxxx 1110 xxxx xxxx */
+ /* LDRT 1111 1000 0101 xxxx xxxx 1110 xxxx xxxx */
+ DECODE_REJECT (0xfe800f00, 0xf8000e00),
+
+ /* STR{,B,H} Rn,[PC...] 1111 1000 xxx0 1111 xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xff1f0000, 0xf80f0000),
+
+ /* STR{,B,H} PC,[Rn...] 1111 1000 xxx0 xxxx 1111 xxxx xxxx xxxx */
+ DECODE_REJECT (0xff10f000, 0xf800f000),
+
+ /* LDR (literal) 1111 1000 x101 1111 xxxx xxxx xxxx xxxx */
+ DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, t32_simulate_ldr_literal,
+ REGS(PC, ANY, 0, 0, 0)),
+
+ /* STR (immediate) 1111 1000 0100 xxxx xxxx 1xxx xxxx xxxx */
+ /* LDR (immediate) 1111 1000 0101 xxxx xxxx 1xxx xxxx xxxx */
+ DECODE_OR (0xffe00800, 0xf8400800),
+ /* STR (immediate) 1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */
+ /* LDR (immediate) 1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xffe00000, 0xf8c00000, t32_emulate_ldrstr,
+ REGS(NOPCX, ANY, 0, 0, 0)),
+
+ /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */
+ /* LDR (register) 1111 1000 0101 xxxx xxxx 0000 00xx xxxx */
+ DECODE_EMULATEX (0xffe00fc0, 0xf8400000, t32_emulate_ldrstr,
+ REGS(NOPCX, ANY, 0, 0, NOSPPC)),
+
+ /* LDRB (literal) 1111 1000 x001 1111 xxxx xxxx xxxx xxxx */
+ /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */
+ /* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */
+ /* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal,
+ REGS(PC, NOSPPCX, 0, 0, 0)),
+
+ /* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */
+ /* STRH (immediate) 1111 1000 0010 xxxx xxxx 1xxx xxxx xxxx */
+ /* LDRB (immediate) 1111 1000 0001 xxxx xxxx 1xxx xxxx xxxx */
+ /* LDRSB (immediate) 1111 1001 0001 xxxx xxxx 1xxx xxxx xxxx */
+ /* LDRH (immediate) 1111 1000 0011 xxxx xxxx 1xxx xxxx xxxx */
+ /* LDRSH (immediate) 1111 1001 0011 xxxx xxxx 1xxx xxxx xxxx */
+ DECODE_OR (0xfec00800, 0xf8000800),
+ /* STRB (immediate) 1111 1000 1000 xxxx xxxx xxxx xxxx xxxx */
+ /* STRH (immediate) 1111 1000 1010 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRB (immediate) 1111 1000 1001 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRSB (immediate) 1111 1001 1001 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRH (immediate) 1111 1000 1011 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRSH (immediate) 1111 1001 1011 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfec00000, 0xf8800000, t32_emulate_ldrstr,
+ REGS(NOPCX, NOSPPCX, 0, 0, 0)),
+
+ /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */
+ /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */
+ /* LDRB (register) 1111 1000 0001 xxxx xxxx 0000 00xx xxxx */
+ /* LDRSB (register) 1111 1001 0001 xxxx xxxx 0000 00xx xxxx */
+ /* LDRH (register) 1111 1000 0011 xxxx xxxx 0000 00xx xxxx */
+ /* LDRSH (register) 1111 1001 0011 xxxx xxxx 0000 00xx xxxx */
+ DECODE_EMULATEX (0xfe800fc0, 0xf8000000, t32_emulate_ldrstr,
+ REGS(NOPCX, NOSPPCX, 0, 0, NOSPPC)),
+
+ /* Other unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_1010___1111[] = {
+ /* Data-processing (register) */
+
+ /* ??? 1111 1010 011x xxxx 1111 xxxx 1xxx xxxx */
+ DECODE_REJECT (0xffe0f080, 0xfa60f080),
+
+ /* SXTH 1111 1010 0000 1111 1111 xxxx 1xxx xxxx */
+ /* UXTH 1111 1010 0001 1111 1111 xxxx 1xxx xxxx */
+ /* SXTB16 1111 1010 0010 1111 1111 xxxx 1xxx xxxx */
+ /* UXTB16 1111 1010 0011 1111 1111 xxxx 1xxx xxxx */
+ /* SXTB 1111 1010 0100 1111 1111 xxxx 1xxx xxxx */
+ /* UXTB 1111 1010 0101 1111 1111 xxxx 1xxx xxxx */
+ DECODE_EMULATEX (0xff8ff080, 0xfa0ff080, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(0, 0, NOSPPC, 0, NOSPPC)),
+
+
+ /* ??? 1111 1010 1xxx xxxx 1111 xxxx 0x11 xxxx */
+ DECODE_REJECT (0xff80f0b0, 0xfa80f030),
+ /* ??? 1111 1010 1x11 xxxx 1111 xxxx 0xxx xxxx */
+ DECODE_REJECT (0xffb0f080, 0xfab0f000),
+
+ /* SADD16 1111 1010 1001 xxxx 1111 xxxx 0000 xxxx */
+ /* SASX 1111 1010 1010 xxxx 1111 xxxx 0000 xxxx */
+ /* SSAX 1111 1010 1110 xxxx 1111 xxxx 0000 xxxx */
+ /* SSUB16 1111 1010 1101 xxxx 1111 xxxx 0000 xxxx */
+ /* SADD8 1111 1010 1000 xxxx 1111 xxxx 0000 xxxx */
+ /* SSUB8 1111 1010 1100 xxxx 1111 xxxx 0000 xxxx */
+
+ /* QADD16 1111 1010 1001 xxxx 1111 xxxx 0001 xxxx */
+ /* QASX 1111 1010 1010 xxxx 1111 xxxx 0001 xxxx */
+ /* QSAX 1111 1010 1110 xxxx 1111 xxxx 0001 xxxx */
+ /* QSUB16 1111 1010 1101 xxxx 1111 xxxx 0001 xxxx */
+ /* QADD8 1111 1010 1000 xxxx 1111 xxxx 0001 xxxx */
+ /* QSUB8 1111 1010 1100 xxxx 1111 xxxx 0001 xxxx */
+
+ /* SHADD16 1111 1010 1001 xxxx 1111 xxxx 0010 xxxx */
+ /* SHASX 1111 1010 1010 xxxx 1111 xxxx 0010 xxxx */
+ /* SHSAX 1111 1010 1110 xxxx 1111 xxxx 0010 xxxx */
+ /* SHSUB16 1111 1010 1101 xxxx 1111 xxxx 0010 xxxx */
+ /* SHADD8 1111 1010 1000 xxxx 1111 xxxx 0010 xxxx */
+ /* SHSUB8 1111 1010 1100 xxxx 1111 xxxx 0010 xxxx */
+
+ /* UADD16 1111 1010 1001 xxxx 1111 xxxx 0100 xxxx */
+ /* UASX 1111 1010 1010 xxxx 1111 xxxx 0100 xxxx */
+ /* USAX 1111 1010 1110 xxxx 1111 xxxx 0100 xxxx */
+ /* USUB16 1111 1010 1101 xxxx 1111 xxxx 0100 xxxx */
+ /* UADD8 1111 1010 1000 xxxx 1111 xxxx 0100 xxxx */
+ /* USUB8 1111 1010 1100 xxxx 1111 xxxx 0100 xxxx */
+
+ /* UQADD16 1111 1010 1001 xxxx 1111 xxxx 0101 xxxx */
+ /* UQASX 1111 1010 1010 xxxx 1111 xxxx 0101 xxxx */
+ /* UQSAX 1111 1010 1110 xxxx 1111 xxxx 0101 xxxx */
+ /* UQSUB16 1111 1010 1101 xxxx 1111 xxxx 0101 xxxx */
+ /* UQADD8 1111 1010 1000 xxxx 1111 xxxx 0101 xxxx */
+ /* UQSUB8 1111 1010 1100 xxxx 1111 xxxx 0101 xxxx */
+
+ /* UHADD16 1111 1010 1001 xxxx 1111 xxxx 0110 xxxx */
+ /* UHASX 1111 1010 1010 xxxx 1111 xxxx 0110 xxxx */
+ /* UHSAX 1111 1010 1110 xxxx 1111 xxxx 0110 xxxx */
+ /* UHSUB16 1111 1010 1101 xxxx 1111 xxxx 0110 xxxx */
+ /* UHADD8 1111 1010 1000 xxxx 1111 xxxx 0110 xxxx */
+ /* UHSUB8 1111 1010 1100 xxxx 1111 xxxx 0110 xxxx */
+ DECODE_OR (0xff80f080, 0xfa80f000),
+
+ /* SXTAH 1111 1010 0000 xxxx 1111 xxxx 1xxx xxxx */
+ /* UXTAH 1111 1010 0001 xxxx 1111 xxxx 1xxx xxxx */
+ /* SXTAB16 1111 1010 0010 xxxx 1111 xxxx 1xxx xxxx */
+ /* UXTAB16 1111 1010 0011 xxxx 1111 xxxx 1xxx xxxx */
+ /* SXTAB 1111 1010 0100 xxxx 1111 xxxx 1xxx xxxx */
+ /* UXTAB 1111 1010 0101 xxxx 1111 xxxx 1xxx xxxx */
+ DECODE_OR (0xff80f080, 0xfa00f080),
+
+ /* QADD 1111 1010 1000 xxxx 1111 xxxx 1000 xxxx */
+ /* QDADD 1111 1010 1000 xxxx 1111 xxxx 1001 xxxx */
+ /* QSUB 1111 1010 1000 xxxx 1111 xxxx 1010 xxxx */
+ /* QDSUB 1111 1010 1000 xxxx 1111 xxxx 1011 xxxx */
+ DECODE_OR (0xfff0f0c0, 0xfa80f080),
+
+ /* SEL 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
+ DECODE_OR (0xfff0f0f0, 0xfaa0f080),
+
+ /* LSL 1111 1010 000x xxxx 1111 xxxx 0000 xxxx */
+ /* LSR 1111 1010 001x xxxx 1111 xxxx 0000 xxxx */
+ /* ASR 1111 1010 010x xxxx 1111 xxxx 0000 xxxx */
+ /* ROR 1111 1010 011x xxxx 1111 xxxx 0000 xxxx */
+ DECODE_EMULATEX (0xff80f0f0, 0xfa00f000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
+
+ /* CLZ 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
+ DECODE_OR (0xfff0f0f0, 0xfab0f080),
+
+ /* REV 1111 1010 1001 xxxx 1111 xxxx 1000 xxxx */
+ /* REV16 1111 1010 1001 xxxx 1111 xxxx 1001 xxxx */
+ /* RBIT 1111 1010 1001 xxxx 1111 xxxx 1010 xxxx */
+ /* REVSH 1111 1010 1001 xxxx 1111 xxxx 1011 xxxx */
+ DECODE_EMULATEX (0xfff0f0c0, 0xfa90f080, t32_emulate_rd8rn16_noflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, SAMEAS16)),
+
+ /* Other unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_1011_0[] = {
+ /* Multiply, multiply accumulate, and absolute difference */
+
+ /* ??? 1111 1011 0000 xxxx 1111 xxxx 0001 xxxx */
+ DECODE_REJECT (0xfff0f0f0, 0xfb00f010),
+ /* ??? 1111 1011 0111 xxxx 1111 xxxx 0001 xxxx */
+ DECODE_REJECT (0xfff0f0f0, 0xfb70f010),
+
+ /* SMULxy 1111 1011 0001 xxxx 1111 xxxx 00xx xxxx */
+ DECODE_OR (0xfff0f0c0, 0xfb10f000),
+ /* MUL 1111 1011 0000 xxxx 1111 xxxx 0000 xxxx */
+ /* SMUAD{X} 1111 1011 0010 xxxx 1111 xxxx 000x xxxx */
+ /* SMULWy 1111 1011 0011 xxxx 1111 xxxx 000x xxxx */
+ /* SMUSD{X} 1111 1011 0100 xxxx 1111 xxxx 000x xxxx */
+ /* SMMUL{R} 1111 1011 0101 xxxx 1111 xxxx 000x xxxx */
+ /* USAD8 1111 1011 0111 xxxx 1111 xxxx 0000 xxxx */
+ DECODE_EMULATEX (0xff80f0e0, 0xfb00f000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
+
+ /* ??? 1111 1011 0111 xxxx xxxx xxxx 0001 xxxx */
+ DECODE_REJECT (0xfff000f0, 0xfb700010),
+
+ /* SMLAxy 1111 1011 0001 xxxx xxxx xxxx 00xx xxxx */
+ DECODE_OR (0xfff000c0, 0xfb100000),
+ /* MLA 1111 1011 0000 xxxx xxxx xxxx 0000 xxxx */
+ /* MLS 1111 1011 0000 xxxx xxxx xxxx 0001 xxxx */
+ /* SMLAD{X} 1111 1011 0010 xxxx xxxx xxxx 000x xxxx */
+ /* SMLAWy 1111 1011 0011 xxxx xxxx xxxx 000x xxxx */
+ /* SMLSD{X} 1111 1011 0100 xxxx xxxx xxxx 000x xxxx */
+ /* SMMLA{R} 1111 1011 0101 xxxx xxxx xxxx 000x xxxx */
+ /* SMMLS{R} 1111 1011 0110 xxxx xxxx xxxx 000x xxxx */
+ /* USADA8 1111 1011 0111 xxxx xxxx xxxx 0000 xxxx */
+ DECODE_EMULATEX (0xff8000c0, 0xfb000000, t32_emulate_rd8rn16rm0ra12_noflags,
+ REGS(NOSPPC, NOSPPCX, NOSPPC, 0, NOSPPC)),
+
+ /* Other unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_1011_1[] = {
+ /* Long multiply, long multiply accumulate, and divide */
+
+ /* UMAAL 1111 1011 1110 xxxx xxxx xxxx 0110 xxxx */
+ DECODE_OR (0xfff000f0, 0xfbe00060),
+ /* SMLALxy 1111 1011 1100 xxxx xxxx xxxx 10xx xxxx */
+ DECODE_OR (0xfff000c0, 0xfbc00080),
+ /* SMLALD{X} 1111 1011 1100 xxxx xxxx xxxx 110x xxxx */
+ /* SMLSLD{X} 1111 1011 1101 xxxx xxxx xxxx 110x xxxx */
+ DECODE_OR (0xffe000e0, 0xfbc000c0),
+ /* SMULL 1111 1011 1000 xxxx xxxx xxxx 0000 xxxx */
+ /* UMULL 1111 1011 1010 xxxx xxxx xxxx 0000 xxxx */
+ /* SMLAL 1111 1011 1100 xxxx xxxx xxxx 0000 xxxx */
+ /* UMLAL 1111 1011 1110 xxxx xxxx xxxx 0000 xxxx */
+ DECODE_EMULATEX (0xff9000f0, 0xfb800000, t32_emulate_rdlo12rdhi8rn16rm0_noflags,
+ REGS(NOSPPC, NOSPPC, NOSPPC, 0, NOSPPC)),
+
+ /* SDIV 1111 1011 1001 xxxx xxxx xxxx 1111 xxxx */
+ /* UDIV 1111 1011 1011 xxxx xxxx xxxx 1111 xxxx */
+ /* Other unallocated instructions... */
+ DECODE_END
+};
+
+const union decode_item kprobe_decode_thumb32_table[] = {
+
+ /*
+ * Load/store multiple instructions
+ * 1110 100x x0xx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfe400000, 0xe8000000, t32_table_1110_100x_x0xx),
+
+ /*
+ * Load/store dual, load/store exclusive, table branch
+ * 1110 100x x1xx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfe400000, 0xe8400000, t32_table_1110_100x_x1xx),
+
+ /*
+ * Data-processing (shifted register)
+ * 1110 101x xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfe000000, 0xea000000, t32_table_1110_101x),
+
+ /*
+ * Coprocessor instructions
+ * 1110 11xx xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_REJECT (0xfc000000, 0xec000000),
+
+ /*
+ * Data-processing (modified immediate)
+ * 1111 0x0x xxxx xxxx 0xxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfa008000, 0xf0000000, t32_table_1111_0x0x___0),
+
+ /*
+ * Data-processing (plain binary immediate)
+ * 1111 0x1x xxxx xxxx 0xxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfa008000, 0xf2000000, t32_table_1111_0x1x___0),
+
+ /*
+ * Branches and miscellaneous control
+ * 1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xf8008000, 0xf0008000, t32_table_1111_0xxx___1),
+
+ /*
+ * Advanced SIMD element or structure load/store instructions
+ * 1111 1001 xxx0 xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_REJECT (0xff100000, 0xf9000000),
+
+ /*
+ * Memory hints
+ * 1111 100x x0x1 xxxx 1111 xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfe50f000, 0xf810f000, t32_table_1111_100x_x0x1__1111),
+
+ /*
+ * Store single data item
+ * 1111 1000 xxx0 xxxx xxxx xxxx xxxx xxxx
+ * Load single data items
+ * 1111 100x xxx1 xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfe000000, 0xf8000000, t32_table_1111_100x),
+
+ /*
+ * Data-processing (register)
+ * 1111 1010 xxxx xxxx 1111 xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xff00f000, 0xfa00f000, t32_table_1111_1010___1111),
+
+ /*
+ * Multiply, multiply accumulate, and absolute difference
+ * 1111 1011 0xxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xff800000, 0xfb000000, t32_table_1111_1011_0),
+
+ /*
+ * Long multiply, long multiply accumulate, and divide
+ * 1111 1011 1xxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xff800000, 0xfb800000, t32_table_1111_1011_1),
+
+ /*
+ * Coprocessor instructions
+ * 1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_END
+};
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_thumb32_table);
+#endif
+
+static void __kprobes
+t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+ int rm = (insn >> 3) & 0xf;
+ unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
+
+ if (insn & (1 << 7)) /* BLX ? */
+ regs->ARM_lr = (unsigned long)p->addr + 2;
+
+ bx_write_pc(rmv, regs);
+}
+
+static void __kprobes
+t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3);
+ long index = insn & 0xff;
+ int rt = (insn >> 8) & 0x7;
+ regs->uregs[rt] = base[index];
+}
+
+static void __kprobes
+t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long* base = (unsigned long *)regs->ARM_sp;
+ long index = insn & 0xff;
+ int rt = (insn >> 8) & 0x7;
+ if (insn & 0x800) /* LDR */
+ regs->uregs[rt] = base[index];
+ else /* STR */
+ base[index] = regs->uregs[rt];
+}
+
+static void __kprobes
+t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long base = (insn & 0x800) ? regs->ARM_sp
+ : (thumb_probe_pc(p) & ~3);
+ long offset = insn & 0xff;
+ int rt = (insn >> 8) & 0x7;
+ regs->uregs[rt] = base + offset * 4;
+}
+
+static void __kprobes
+t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ long imm = insn & 0x7f;
+ if (insn & 0x80) /* SUB */
+ regs->ARM_sp -= imm * 4;
+ else /* ADD */
+ regs->ARM_sp += imm * 4;
+}
+
+static void __kprobes
+t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rn = insn & 0x7;
+ kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
+ if (nonzero & 0x800) {
+ long i = insn & 0x200;
+ long imm5 = insn & 0xf8;
+ unsigned long pc = thumb_probe_pc(p);
+ regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
+ }
+}
+
+static void __kprobes
+t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
+{
+ /*
+ * The 8 IT state bits are split into two parts in CPSR:
+ * ITSTATE<1:0> are in CPSR<26:25>
+ * ITSTATE<7:2> are in CPSR<15:10>
+ * The new IT state is in the lower byte of insn.
+ */
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long cpsr = regs->ARM_cpsr;
+ cpsr &= ~PSR_IT_MASK;
+ cpsr |= (insn & 0xfc) << 8;
+ cpsr |= (insn & 0x03) << 25;
+ regs->ARM_cpsr = cpsr;
+}
+
+static void __kprobes
+t16_singlestep_it(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->ARM_pc += 2;
+ t16_simulate_it(p, regs);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ asi->insn_singlestep = t16_singlestep_it;
+ return INSN_GOOD_NO_SLOT;
+}
+
+static void __kprobes
+t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+ long offset = insn & 0x7f;
+ offset -= insn & 0x80; /* Apply sign bit */
+ regs->ARM_pc = pc + (offset * 2);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ int cc = (insn >> 8) & 0xf;
+ asi->insn_check_cc = kprobe_condition_checks[cc];
+ asi->insn_handler = t16_simulate_cond_branch;
+ return INSN_GOOD_NO_SLOT;
+}
+
+static void __kprobes
+t16_simulate_branch(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+ long offset = insn & 0x3ff;
+ offset -= insn & 0x400; /* Apply sign bit */
+ regs->ARM_pc = pc + (offset * 2);
+}
+
+static unsigned long __kprobes
+t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
+{
+ unsigned long oldcpsr = regs->ARM_cpsr;
+ unsigned long newcpsr;
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[oldcpsr] \n\t"
+ "ldmia %[regs], {r0-r7} \n\t"
+ "blx %[fn] \n\t"
+ "stmia %[regs], {r0-r7} \n\t"
+ "mrs %[newcpsr], cpsr \n\t"
+ : [newcpsr] "=r" (newcpsr)
+ : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
+ [fn] "r" (p->ainsn.insn_fn)
+ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "lr", "memory", "cc"
+ );
+
+ return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
+}
+
+static void __kprobes
+t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->ARM_cpsr = t16_emulate_loregs(p, regs);
+}
+
+static void __kprobes
+t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs)
+{
+ unsigned long cpsr = t16_emulate_loregs(p, regs);
+ if (!in_it_block(cpsr))
+ regs->ARM_cpsr = cpsr;
+}
+
+static void __kprobes
+t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+ int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
+ int rm = (insn >> 3) & 0xf;
+
+ register unsigned long rdnv asm("r1");
+ register unsigned long rmv asm("r0");
+ unsigned long cpsr = regs->ARM_cpsr;
+
+ rdnv = (rdn == 15) ? pc : regs->uregs[rdn];
+ rmv = (rm == 15) ? pc : regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[cpsr] \n\t"
+ "blx %[fn] \n\t"
+ "mrs %[cpsr], cpsr \n\t"
+ : "=r" (rdnv), [cpsr] "=r" (cpsr)
+ : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ if (rdn == 15)
+ rdnv &= ~1;
+
+ regs->uregs[rdn] = rdnv;
+ regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ insn &= ~0x00ff;
+ insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
+ ((u16 *)asi->insn)[0] = insn;
+ asi->insn_handler = t16_emulate_hiregs;
+ return INSN_GOOD;
+}
+
+static void __kprobes
+t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
+{
+ __asm__ __volatile__ (
+ "ldr r9, [%[regs], #13*4] \n\t"
+ "ldr r8, [%[regs], #14*4] \n\t"
+ "ldmia %[regs], {r0-r7} \n\t"
+ "blx %[fn] \n\t"
+ "str r9, [%[regs], #13*4] \n\t"
+ :
+ : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+ "lr", "memory", "cc"
+ );
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ /*
+ * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}"
+ * and call it with R9=SP and LR in the register list represented
+ * by R8.
+ */
+ ((u16 *)asi->insn)[0] = 0xe929; /* 1st half STMDB R9!,{} */
+ ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */
+ asi->insn_handler = t16_emulate_push;
+ return INSN_GOOD;
+}
+
+static void __kprobes
+t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+ __asm__ __volatile__ (
+ "ldr r9, [%[regs], #13*4] \n\t"
+ "ldmia %[regs], {r0-r7} \n\t"
+ "blx %[fn] \n\t"
+ "stmia %[regs], {r0-r7} \n\t"
+ "str r9, [%[regs], #13*4] \n\t"
+ :
+ : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
+ "lr", "memory", "cc"
+ );
+}
+
+static void __kprobes
+t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
+{
+ register unsigned long pc asm("r8");
+
+ __asm__ __volatile__ (
+ "ldr r9, [%[regs], #13*4] \n\t"
+ "ldmia %[regs], {r0-r7} \n\t"
+ "blx %[fn] \n\t"
+ "stmia %[regs], {r0-r7} \n\t"
+ "str r9, [%[regs], #13*4] \n\t"
+ : "=r" (pc)
+ : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
+ "lr", "memory", "cc"
+ );
+
+ bx_write_pc(pc, regs);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ /*
+ * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}"
+ * and call it with R9=SP and PC in the register list represented
+ * by R8.
+ */
+ ((u16 *)asi->insn)[0] = 0xe8b9; /* 1st half LDMIA R9!,{} */
+ ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */
+ asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc
+ : t16_emulate_pop_nopc;
+ return INSN_GOOD;
+}
+
+static const union decode_item t16_table_1011[] = {
+ /* Miscellaneous 16-bit instructions */
+
+ /* ADD (SP plus immediate) 1011 0000 0xxx xxxx */
+ /* SUB (SP minus immediate) 1011 0000 1xxx xxxx */
+ DECODE_SIMULATE (0xff00, 0xb000, t16_simulate_add_sp_imm),
+
+ /* CBZ 1011 00x1 xxxx xxxx */
+ /* CBNZ 1011 10x1 xxxx xxxx */
+ DECODE_SIMULATE (0xf500, 0xb100, t16_simulate_cbz),
+
+ /* SXTH 1011 0010 00xx xxxx */
+ /* SXTB 1011 0010 01xx xxxx */
+ /* UXTH 1011 0010 10xx xxxx */
+ /* UXTB 1011 0010 11xx xxxx */
+ /* REV 1011 1010 00xx xxxx */
+ /* REV16 1011 1010 01xx xxxx */
+ /* ??? 1011 1010 10xx xxxx */
+ /* REVSH 1011 1010 11xx xxxx */
+ DECODE_REJECT (0xffc0, 0xba80),
+ DECODE_EMULATE (0xf500, 0xb000, t16_emulate_loregs_rwflags),
+
+ /* PUSH 1011 010x xxxx xxxx */
+ DECODE_CUSTOM (0xfe00, 0xb400, t16_decode_push),
+ /* POP 1011 110x xxxx xxxx */
+ DECODE_CUSTOM (0xfe00, 0xbc00, t16_decode_pop),
+
+ /*
+ * If-Then, and hints
+ * 1011 1111 xxxx xxxx
+ */
+
+ /* YIELD 1011 1111 0001 0000 */
+ DECODE_OR (0xffff, 0xbf10),
+ /* SEV 1011 1111 0100 0000 */
+ DECODE_EMULATE (0xffff, 0xbf40, kprobe_emulate_none),
+ /* NOP 1011 1111 0000 0000 */
+ /* WFE 1011 1111 0010 0000 */
+ /* WFI 1011 1111 0011 0000 */
+ DECODE_SIMULATE (0xffcf, 0xbf00, kprobe_simulate_nop),
+ /* Unassigned hints 1011 1111 xxxx 0000 */
+ DECODE_REJECT (0xff0f, 0xbf00),
+ /* IT 1011 1111 xxxx xxxx */
+ DECODE_CUSTOM (0xff00, 0xbf00, t16_decode_it),
+
+ /* SETEND 1011 0110 010x xxxx */
+ /* CPS 1011 0110 011x xxxx */
+ /* BKPT 1011 1110 xxxx xxxx */
+ /* And unallocated instructions... */
+ DECODE_END
+};
+
+const union decode_item kprobe_decode_thumb16_table[] = {
+
+ /*
+ * Shift (immediate), add, subtract, move, and compare
+ * 00xx xxxx xxxx xxxx
+ */
+
+ /* CMP (immediate) 0010 1xxx xxxx xxxx */
+ DECODE_EMULATE (0xf800, 0x2800, t16_emulate_loregs_rwflags),
+
+ /* ADD (register) 0001 100x xxxx xxxx */
+ /* SUB (register) 0001 101x xxxx xxxx */
+ /* LSL (immediate) 0000 0xxx xxxx xxxx */
+ /* LSR (immediate) 0000 1xxx xxxx xxxx */
+ /* ASR (immediate) 0001 0xxx xxxx xxxx */
+ /* ADD (immediate, Thumb) 0001 110x xxxx xxxx */
+ /* SUB (immediate, Thumb) 0001 111x xxxx xxxx */
+ /* MOV (immediate) 0010 0xxx xxxx xxxx */
+ /* ADD (immediate, Thumb) 0011 0xxx xxxx xxxx */
+ /* SUB (immediate, Thumb) 0011 1xxx xxxx xxxx */
+ DECODE_EMULATE (0xc000, 0x0000, t16_emulate_loregs_noitrwflags),
+
+ /*
+ * 16-bit Thumb data-processing instructions
+ * 0100 00xx xxxx xxxx
+ */
+
+ /* TST (register) 0100 0010 00xx xxxx */
+ DECODE_EMULATE (0xffc0, 0x4200, t16_emulate_loregs_rwflags),
+ /* CMP (register) 0100 0010 10xx xxxx */
+ /* CMN (register) 0100 0010 11xx xxxx */
+ DECODE_EMULATE (0xff80, 0x4280, t16_emulate_loregs_rwflags),
+ /* AND (register) 0100 0000 00xx xxxx */
+ /* EOR (register) 0100 0000 01xx xxxx */
+ /* LSL (register) 0100 0000 10xx xxxx */
+ /* LSR (register) 0100 0000 11xx xxxx */
+ /* ASR (register) 0100 0001 00xx xxxx */
+ /* ADC (register) 0100 0001 01xx xxxx */
+ /* SBC (register) 0100 0001 10xx xxxx */
+ /* ROR (register) 0100 0001 11xx xxxx */
+ /* RSB (immediate) 0100 0010 01xx xxxx */
+ /* ORR (register) 0100 0011 00xx xxxx */
+ /* MUL 0100 0011 00xx xxxx */
+ /* BIC (register) 0100 0011 10xx xxxx */
+ /* MVN (register) 0100 0011 10xx xxxx */
+ DECODE_EMULATE (0xfc00, 0x4000, t16_emulate_loregs_noitrwflags),
+
+ /*
+ * Special data instructions and branch and exchange
+ * 0100 01xx xxxx xxxx
+ */
+
+ /* BLX pc 0100 0111 1111 1xxx */
+ DECODE_REJECT (0xfff8, 0x47f8),
+
+ /* BX (register) 0100 0111 0xxx xxxx */
+ /* BLX (register) 0100 0111 1xxx xxxx */
+ DECODE_SIMULATE (0xff00, 0x4700, t16_simulate_bxblx),
+
+ /* ADD pc, pc 0100 0100 1111 1111 */
+ DECODE_REJECT (0xffff, 0x44ff),
+
+ /* ADD (register) 0100 0100 xxxx xxxx */
+ /* CMP (register) 0100 0101 xxxx xxxx */
+ /* MOV (register) 0100 0110 xxxx xxxx */
+ DECODE_CUSTOM (0xfc00, 0x4400, t16_decode_hiregs),
+
+ /*
+ * Load from Literal Pool
+ * LDR (literal) 0100 1xxx xxxx xxxx
+ */
+ DECODE_SIMULATE (0xf800, 0x4800, t16_simulate_ldr_literal),
+
+ /*
+ * 16-bit Thumb Load/store instructions
+ * 0101 xxxx xxxx xxxx
+ * 011x xxxx xxxx xxxx
+ * 100x xxxx xxxx xxxx
+ */
+
+ /* STR (register) 0101 000x xxxx xxxx */
+ /* STRH (register) 0101 001x xxxx xxxx */
+ /* STRB (register) 0101 010x xxxx xxxx */
+ /* LDRSB (register) 0101 011x xxxx xxxx */
+ /* LDR (register) 0101 100x xxxx xxxx */
+ /* LDRH (register) 0101 101x xxxx xxxx */
+ /* LDRB (register) 0101 110x xxxx xxxx */
+ /* LDRSH (register) 0101 111x xxxx xxxx */
+ /* STR (immediate, Thumb) 0110 0xxx xxxx xxxx */
+ /* LDR (immediate, Thumb) 0110 1xxx xxxx xxxx */
+ /* STRB (immediate, Thumb) 0111 0xxx xxxx xxxx */
+ /* LDRB (immediate, Thumb) 0111 1xxx xxxx xxxx */
+ DECODE_EMULATE (0xc000, 0x4000, t16_emulate_loregs_rwflags),
+ /* STRH (immediate, Thumb) 1000 0xxx xxxx xxxx */
+ /* LDRH (immediate, Thumb) 1000 1xxx xxxx xxxx */
+ DECODE_EMULATE (0xf000, 0x8000, t16_emulate_loregs_rwflags),
+ /* STR (immediate, Thumb) 1001 0xxx xxxx xxxx */
+ /* LDR (immediate, Thumb) 1001 1xxx xxxx xxxx */
+ DECODE_SIMULATE (0xf000, 0x9000, t16_simulate_ldrstr_sp_relative),
+
+ /*
+ * Generate PC-/SP-relative address
+ * ADR (literal) 1010 0xxx xxxx xxxx
+ * ADD (SP plus immediate) 1010 1xxx xxxx xxxx
+ */
+ DECODE_SIMULATE (0xf000, 0xa000, t16_simulate_reladr),
+
+ /*
+ * Miscellaneous 16-bit instructions
+ * 1011 xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xf000, 0xb000, t16_table_1011),
+
+ /* STM 1100 0xxx xxxx xxxx */
+ /* LDM 1100 1xxx xxxx xxxx */
+ DECODE_EMULATE (0xf000, 0xc000, t16_emulate_loregs_rwflags),
+
+ /*
+ * Conditional branch, and Supervisor Call
+ */
+
+ /* Permanently UNDEFINED 1101 1110 xxxx xxxx */
+ /* SVC 1101 1111 xxxx xxxx */
+ DECODE_REJECT (0xfe00, 0xde00),
+
+ /* Conditional branch 1101 xxxx xxxx xxxx */
+ DECODE_CUSTOM (0xf000, 0xd000, t16_decode_cond_branch),
+
+ /*
+ * Unconditional branch
+ * B 1110 0xxx xxxx xxxx
+ */
+ DECODE_SIMULATE (0xf800, 0xe000, t16_simulate_branch),
+
+ DECODE_END
+};
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table);
+#endif
+
+static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
+{
+ if (unlikely(in_it_block(cpsr)))
+ return kprobe_condition_checks[current_cond(cpsr)](cpsr);
+ return true;
+}
+
+static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->ARM_pc += 2;
+ p->ainsn.insn_handler(p, regs);
+ regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
+}
+
+static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->ARM_pc += 4;
+ p->ainsn.insn_handler(p, regs);
+ regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
+}
+
+enum kprobe_insn __kprobes
+thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ asi->insn_singlestep = thumb16_singlestep;
+ asi->insn_check_cc = thumb_check_cc;
+ return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true);
+}
+
+enum kprobe_insn __kprobes
+thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ asi->insn_singlestep = thumb32_singlestep;
+ asi->insn_check_cc = thumb_check_cc;
+ return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true);
+}
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
new file mode 100644
index 0000000..38945f7
--- /dev/null
+++ b/arch/arm/kernel/kprobes.h
@@ -0,0 +1,428 @@
+/*
+ * arch/arm/kernel/kprobes.h
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * Some contents moved here from arch/arm/include/asm/kprobes.h which is
+ * Copyright (C) 2006, 2007 Motorola Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _ARM_KERNEL_KPROBES_H
+#define _ARM_KERNEL_KPROBES_H
+
+/*
+ * These undefined instructions must be unique and
+ * reserved solely for kprobes' use.
+ */
+#define KPROBE_ARM_BREAKPOINT_INSTRUCTION 0x07f001f8
+#define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18
+#define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018
+
+
+enum kprobe_insn {
+ INSN_REJECTED,
+ INSN_GOOD,
+ INSN_GOOD_NO_SLOT
+};
+
+typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
+ struct arch_specific_insn *);
+
+#ifdef CONFIG_THUMB2_KERNEL
+
+enum kprobe_insn thumb16_kprobe_decode_insn(kprobe_opcode_t,
+ struct arch_specific_insn *);
+enum kprobe_insn thumb32_kprobe_decode_insn(kprobe_opcode_t,
+ struct arch_specific_insn *);
+
+#else /* !CONFIG_THUMB2_KERNEL */
+
+enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
+ struct arch_specific_insn *);
+#endif
+
+void __init arm_kprobe_decode_init(void);
+
+extern kprobe_check_cc * const kprobe_condition_checks[16];
+
+
+#if __LINUX_ARM_ARCH__ >= 7
+
+/* str_pc_offset is architecturally defined from ARMv7 onwards */
+#define str_pc_offset 8
+#define find_str_pc_offset()
+
+#else /* __LINUX_ARM_ARCH__ < 7 */
+
+/* We need a run-time check to determine str_pc_offset */
+extern int str_pc_offset;
+void __init find_str_pc_offset(void);
+
+#endif
+
+
+/*
+ * Update ITSTATE after normal execution of an IT block instruction.
+ *
+ * The 8 IT state bits are split into two parts in CPSR:
+ * ITSTATE<1:0> are in CPSR<26:25>
+ * ITSTATE<7:2> are in CPSR<15:10>
+ */
+static inline unsigned long it_advance(unsigned long cpsr)
+ {
+ if ((cpsr & 0x06000400) == 0) {
+ /* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */
+ cpsr &= ~PSR_IT_MASK;
+ } else {
+ /* We need to shift left ITSTATE<4:0> */
+ const unsigned long mask = 0x06001c00; /* Mask ITSTATE<4:0> */
+ unsigned long it = cpsr & mask;
+ it <<= 1;
+ it |= it >> (27 - 10); /* Carry ITSTATE<2> to correct place */
+ it &= mask;
+ cpsr &= ~mask;
+ cpsr |= it;
+ }
+ return cpsr;
+}
+
+static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs)
+{
+ long cpsr = regs->ARM_cpsr;
+ if (pcv & 0x1) {
+ cpsr |= PSR_T_BIT;
+ pcv &= ~0x1;
+ } else {
+ cpsr &= ~PSR_T_BIT;
+ pcv &= ~0x2; /* Avoid UNPREDICTABLE address allignment */
+ }
+ regs->ARM_cpsr = cpsr;
+ regs->ARM_pc = pcv;
+}
+
+
+#if __LINUX_ARM_ARCH__ >= 6
+
+/* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */
+#define load_write_pc_interworks true
+#define test_load_write_pc_interworking()
+
+#else /* __LINUX_ARM_ARCH__ < 6 */
+
+/* We need run-time testing to determine if load_write_pc() should interwork. */
+extern bool load_write_pc_interworks;
+void __init test_load_write_pc_interworking(void);
+
+#endif
+
+static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs)
+{
+ if (load_write_pc_interworks)
+ bx_write_pc(pcv, regs);
+ else
+ regs->ARM_pc = pcv;
+}
+
+
+#if __LINUX_ARM_ARCH__ >= 7
+
+#define alu_write_pc_interworks true
+#define test_alu_write_pc_interworking()
+
+#elif __LINUX_ARM_ARCH__ <= 5
+
+/* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */
+#define alu_write_pc_interworks false
+#define test_alu_write_pc_interworking()
+
+#else /* __LINUX_ARM_ARCH__ == 6 */
+
+/* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */
+extern bool alu_write_pc_interworks;
+void __init test_alu_write_pc_interworking(void);
+
+#endif /* __LINUX_ARM_ARCH__ == 6 */
+
+static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs)
+{
+ if (alu_write_pc_interworks)
+ bx_write_pc(pcv, regs);
+ else
+ regs->ARM_pc = pcv;
+}
+
+
+void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
+void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
+
+enum kprobe_insn __kprobes
+kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi);
+
+/*
+ * Test if load/store instructions writeback the address register.
+ * if P (bit 24) == 0 or W (bit 21) == 1
+ */
+#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
+
+/*
+ * The following definitions and macros are used to build instruction
+ * decoding tables for use by kprobe_decode_insn.
+ *
+ * These tables are a concatenation of entries each of which consist of one of
+ * the decode_* structs. All of the fields in every type of decode structure
+ * are of the union type decode_item, therefore the entire decode table can be
+ * viewed as an array of these and declared like:
+ *
+ * static const union decode_item table_name[] = {};
+ *
+ * In order to construct each entry in the table, macros are used to
+ * initialise a number of sequential decode_item values in a layout which
+ * matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct
+ * decode_simulate by initialising four decode_item objects like this...
+ *
+ * {.bits = _type},
+ * {.bits = _mask},
+ * {.bits = _value},
+ * {.handler = _handler},
+ *
+ * Initialising a specified member of the union means that the compiler
+ * will produce a warning if the argument is of an incorrect type.
+ *
+ * Below is a list of each of the macros used to initialise entries and a
+ * description of the action performed when that entry is matched to an
+ * instruction. A match is found when (instruction & mask) == value.
+ *
+ * DECODE_TABLE(mask, value, table)
+ * Instruction decoding jumps to parsing the new sub-table 'table'.
+ *
+ * DECODE_CUSTOM(mask, value, decoder)
+ * The custom function 'decoder' is called to the complete decoding
+ * of an instruction.
+ *
+ * DECODE_SIMULATE(mask, value, handler)
+ * Set the probes instruction handler to 'handler', this will be used
+ * to simulate the instruction when the probe is hit. Decoding returns
+ * with INSN_GOOD_NO_SLOT.
+ *
+ * DECODE_EMULATE(mask, value, handler)
+ * Set the probes instruction handler to 'handler', this will be used
+ * to emulate the instruction when the probe is hit. The modified
+ * instruction (see below) is placed in the probes instruction slot so it
+ * may be called by the emulation code. Decoding returns with INSN_GOOD.
+ *
+ * DECODE_REJECT(mask, value)
+ * Instruction decoding fails with INSN_REJECTED
+ *
+ * DECODE_OR(mask, value)
+ * This allows the mask/value test of multiple table entries to be
+ * logically ORed. Once an 'or' entry is matched the decoding action to
+ * be performed is that of the next entry which isn't an 'or'. E.g.
+ *
+ * DECODE_OR (mask1, value1)
+ * DECODE_OR (mask2, value2)
+ * DECODE_SIMULATE (mask3, value3, simulation_handler)
+ *
+ * This means that if any of the three mask/value pairs match the
+ * instruction being decoded, then 'simulation_handler' will be used
+ * for it.
+ *
+ * Both the SIMULATE and EMULATE macros have a second form which take an
+ * additional 'regs' argument.
+ *
+ * DECODE_SIMULATEX(mask, value, handler, regs)
+ * DECODE_EMULATEX (mask, value, handler, regs)
+ *
+ * These are used to specify what kind of CPU register is encoded in each of the
+ * least significant 5 nibbles of the instruction being decoded. The regs value
+ * is specified using the REGS macro, this takes any of the REG_TYPE_* values
+ * from enum decode_reg_type as arguments; only the '*' part of the name is
+ * given. E.g.
+ *
+ * REGS(0, ANY, NOPC, 0, ANY)
+ *
+ * This indicates an instruction is encoded like:
+ *
+ * bits 19..16 ignore
+ * bits 15..12 any register allowed here
+ * bits 11.. 8 any register except PC allowed here
+ * bits 7.. 4 ignore
+ * bits 3.. 0 any register allowed here
+ *
+ * This register specification is checked after a decode table entry is found to
+ * match an instruction (through the mask/value test). Any invalid register then
+ * found in the instruction will cause decoding to fail with INSN_REJECTED. In
+ * the above example this would happen if bits 11..8 of the instruction were
+ * 1111, indicating R15 or PC.
+ *
+ * As well as checking for legal combinations of registers, this data is also
+ * used to modify the registers encoded in the instructions so that an
+ * emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.)
+ *
+ * Here is a real example which matches ARM instructions of the form
+ * "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>"
+ *
+ * DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
+ * REGS(ANY, ANY, NOPC, 0, ANY)),
+ * ^ ^ ^ ^
+ * Rn Rd Rs Rm
+ *
+ * Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because
+ * Rs == R15
+ *
+ * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the
+ * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into
+ * the kprobes instruction slot. This can then be called later by the handler
+ * function emulate_rd12rn16rm0rs8_rwflags in order to simulate the instruction.
+ */
+
+enum decode_type {
+ DECODE_TYPE_END,
+ DECODE_TYPE_TABLE,
+ DECODE_TYPE_CUSTOM,
+ DECODE_TYPE_SIMULATE,
+ DECODE_TYPE_EMULATE,
+ DECODE_TYPE_OR,
+ DECODE_TYPE_REJECT,
+ NUM_DECODE_TYPES /* Must be last enum */
+};
+
+#define DECODE_TYPE_BITS 4
+#define DECODE_TYPE_MASK ((1 << DECODE_TYPE_BITS) - 1)
+
+enum decode_reg_type {
+ REG_TYPE_NONE = 0, /* Not a register, ignore */
+ REG_TYPE_ANY, /* Any register allowed */
+ REG_TYPE_SAMEAS16, /* Register should be same as that at bits 19..16 */
+ REG_TYPE_SP, /* Register must be SP */
+ REG_TYPE_PC, /* Register must be PC */
+ REG_TYPE_NOSP, /* Register must not be SP */
+ REG_TYPE_NOSPPC, /* Register must not be SP or PC */
+ REG_TYPE_NOPC, /* Register must not be PC */
+ REG_TYPE_NOPCWB, /* No PC if load/store write-back flag also set */
+
+ /* The following types are used when the encoding for PC indicates
+ * another instruction form. This distiction only matters for test
+ * case coverage checks.
+ */
+ REG_TYPE_NOPCX, /* Register must not be PC */
+ REG_TYPE_NOSPPCX, /* Register must not be SP or PC */
+
+ /* Alias to allow '0' arg to be used in REGS macro. */
+ REG_TYPE_0 = REG_TYPE_NONE
+};
+
+#define REGS(r16, r12, r8, r4, r0) \
+ ((REG_TYPE_##r16) << 16) + \
+ ((REG_TYPE_##r12) << 12) + \
+ ((REG_TYPE_##r8) << 8) + \
+ ((REG_TYPE_##r4) << 4) + \
+ (REG_TYPE_##r0)
+
+union decode_item {
+ u32 bits;
+ const union decode_item *table;
+ kprobe_insn_handler_t *handler;
+ kprobe_decode_insn_t *decoder;
+};
+
+
+#define DECODE_END \
+ {.bits = DECODE_TYPE_END}
+
+
+struct decode_header {
+ union decode_item type_regs;
+ union decode_item mask;
+ union decode_item value;
+};
+
+#define DECODE_HEADER(_type, _mask, _value, _regs) \
+ {.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)}, \
+ {.bits = (_mask)}, \
+ {.bits = (_value)}
+
+
+struct decode_table {
+ struct decode_header header;
+ union decode_item table;
+};
+
+#define DECODE_TABLE(_mask, _value, _table) \
+ DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0), \
+ {.table = (_table)}
+
+
+struct decode_custom {
+ struct decode_header header;
+ union decode_item decoder;
+};
+
+#define DECODE_CUSTOM(_mask, _value, _decoder) \
+ DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \
+ {.decoder = (_decoder)}
+
+
+struct decode_simulate {
+ struct decode_header header;
+ union decode_item handler;
+};
+
+#define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \
+ DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \
+ {.handler = (_handler)}
+
+#define DECODE_SIMULATE(_mask, _value, _handler) \
+ DECODE_SIMULATEX(_mask, _value, _handler, 0)
+
+
+struct decode_emulate {
+ struct decode_header header;
+ union decode_item handler;
+};
+
+#define DECODE_EMULATEX(_mask, _value, _handler, _regs) \
+ DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \
+ {.handler = (_handler)}
+
+#define DECODE_EMULATE(_mask, _value, _handler) \
+ DECODE_EMULATEX(_mask, _value, _handler, 0)
+
+
+struct decode_or {
+ struct decode_header header;
+};
+
+#define DECODE_OR(_mask, _value) \
+ DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0)
+
+
+struct decode_reject {
+ struct decode_header header;
+};
+
+#define DECODE_REJECT(_mask, _value) \
+ DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
+
+
+#ifdef CONFIG_THUMB2_KERNEL
+extern const union decode_item kprobe_decode_thumb16_table[];
+extern const union decode_item kprobe_decode_thumb32_table[];
+#else
+extern const union decode_item kprobe_decode_arm_table[];
+#endif
+
+
+int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ const union decode_item *table, bool thumb16);
+
+
+#endif /* _ARM_KERNEL_KPROBES_H */
diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c
new file mode 100644
index 0000000..93a22d2
--- /dev/null
+++ b/arch/arm/kernel/suspend.c
@@ -0,0 +1,72 @@
+#include <linux/init.h>
+
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/memory.h>
+#include <asm/suspend.h>
+#include <asm/tlbflush.h>
+
+static pgd_t *suspend_pgd;
+
+extern int __cpu_suspend(unsigned long, int (*)(unsigned long));
+extern void cpu_resume_mmu(void);
+
+/*
+ * This is called by __cpu_suspend() to save the state, and do whatever
+ * flushing is required to ensure that when the CPU goes to sleep we have
+ * the necessary data available when the caches are not searched.
+ */
+void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
+{
+ *save_ptr = virt_to_phys(ptr);
+
+ /* This must correspond to the LDM in cpu_resume() assembly */
+ *ptr++ = virt_to_phys(suspend_pgd);
+ *ptr++ = sp;
+ *ptr++ = virt_to_phys(cpu_do_resume);
+
+ cpu_do_suspend(ptr);
+
+ flush_cache_all();
+ outer_clean_range(*save_ptr, *save_ptr + ptrsz);
+ outer_clean_range(virt_to_phys(save_ptr),
+ virt_to_phys(save_ptr) + sizeof(*save_ptr));
+}
+
+/*
+ * Hide the first two arguments to __cpu_suspend - these are an implementation
+ * detail which platform code shouldn't have to know about.
+ */
+int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
+{
+ struct mm_struct *mm = current->active_mm;
+ int ret;
+
+ if (!suspend_pgd)
+ return -EINVAL;
+
+ /*
+ * Provide a temporary page table with an identity mapping for
+ * the MMU-enable code, required for resuming. On successful
+ * resume (indicated by a zero return code), we need to switch
+ * back to the correct page tables.
+ */
+ ret = __cpu_suspend(arg, fn);
+ if (ret == 0) {
+ cpu_switch_mm(mm->pgd, mm);
+ local_flush_tlb_all();
+ }
+
+ return ret;
+}
+
+static int __init cpu_suspend_init(void)
+{
+ suspend_pgd = pgd_alloc(&init_mm);
+ if (suspend_pgd) {
+ unsigned long addr = virt_to_phys(cpu_resume_mmu);
+ identity_mapping_add(suspend_pgd, addr, addr + SECTION_SIZE);
+ }
+ return suspend_pgd ? 0 : -ENOMEM;
+}
+core_initcall(cpu_suspend_init);
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
new file mode 100644
index 0000000..140c817
--- /dev/null
+++ b/arch/arm/kernel/topology.c
@@ -0,0 +1,150 @@
+/*
+ * arch/arm/kernel/topology.c
+ *
+ * Copyright (C) 2011 Linaro Limited.
+ * Written by: Vincent Guittot
+ *
+ * based on arch/sh/kernel/topology.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+#include <linux/sched.h>
+
+#include <asm/cputype.h>
+#include <asm/topology.h>
+
+#define MPIDR_SMP_BITMASK (0x3 << 30)
+#define MPIDR_SMP_VALUE (0x2 << 30)
+
+#define MPIDR_MT_BITMASK (0x1 << 24)
+
+/*
+ * These masks reflect the current use of the affinity levels.
+ * The affinity level can be up to 16 bits according to ARM ARM
+ */
+
+#define MPIDR_LEVEL0_MASK 0x3
+#define MPIDR_LEVEL0_SHIFT 0
+
+#define MPIDR_LEVEL1_MASK 0xF
+#define MPIDR_LEVEL1_SHIFT 8
+
+#define MPIDR_LEVEL2_MASK 0xFF
+#define MPIDR_LEVEL2_SHIFT 16
+
+struct cputopo_arm cpu_topology[NR_CPUS];
+EXPORT_SYMBOL_GPL(cpu_topology);
+
+const struct cpumask *cpu_coregroup_mask(int cpu)
+{
+ return &cpu_topology[cpu].core_sibling;
+}
+
+/*
+ * store_cpu_topology is called at boot when only one cpu is running
+ * and with the mutex cpu_hotplug.lock locked, when several cpus have booted,
+ * which prevents simultaneous write access to cpu_topology array
+ */
+void store_cpu_topology(unsigned int cpuid)
+{
+ struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid];
+ unsigned int mpidr;
+ unsigned int cpu;
+
+ /* If the cpu topology has been already set, just return */
+ if (cpuid_topo->core_id != -1)
+ return;
+
+ mpidr = read_cpuid_mpidr();
+
+ /* create cpu topology mapping */
+ if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) {
+ /*
+ * This is a multiprocessor system
+ * multiprocessor format & multiprocessor mode field are set
+ */
+
+ if (mpidr & MPIDR_MT_BITMASK) {
+ /* core performance interdependency */
+ cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT)
+ & MPIDR_LEVEL0_MASK;
+ cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT)
+ & MPIDR_LEVEL1_MASK;
+ cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT)
+ & MPIDR_LEVEL2_MASK;
+ } else {
+ /* largely independent cores */
+ cpuid_topo->thread_id = -1;
+ cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT)
+ & MPIDR_LEVEL0_MASK;
+ cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT)
+ & MPIDR_LEVEL1_MASK;
+ }
+ } else {
+ /*
+ * This is an uniprocessor system
+ * we are in multiprocessor format but uniprocessor system
+ * or in the old uniprocessor format
+ */
+ cpuid_topo->thread_id = -1;
+ cpuid_topo->core_id = 0;
+ cpuid_topo->socket_id = -1;
+ }
+
+ /* update core and thread sibling masks */
+ for_each_possible_cpu(cpu) {
+ struct cputopo_arm *cpu_topo = &cpu_topology[cpu];
+
+ if (cpuid_topo->socket_id == cpu_topo->socket_id) {
+ cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
+ if (cpu != cpuid)
+ cpumask_set_cpu(cpu,
+ &cpuid_topo->core_sibling);
+
+ if (cpuid_topo->core_id == cpu_topo->core_id) {
+ cpumask_set_cpu(cpuid,
+ &cpu_topo->thread_sibling);
+ if (cpu != cpuid)
+ cpumask_set_cpu(cpu,
+ &cpuid_topo->thread_sibling);
+ }
+ }
+ }
+ smp_wmb();
+
+ printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n",
+ cpuid, cpu_topology[cpuid].thread_id,
+ cpu_topology[cpuid].core_id,
+ cpu_topology[cpuid].socket_id, mpidr);
+}
+
+/*
+ * init_cpu_topology is called at boot when only one cpu is running
+ * which prevent simultaneous write access to cpu_topology array
+ */
+void init_cpu_topology(void)
+{
+ unsigned int cpu;
+
+ /* init core mask */
+ for_each_possible_cpu(cpu) {
+ struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]);
+
+ cpu_topo->thread_id = -1;
+ cpu_topo->core_id = -1;
+ cpu_topo->socket_id = -1;
+ cpumask_clear(&cpu_topo->core_sibling);
+ cpumask_clear(&cpu_topo->thread_sibling);
+ }
+ smp_wmb();
+}
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
new file mode 100644
index 0000000..0b7d327
--- /dev/null
+++ b/arch/arm/mach-at91/board-dt.c
@@ -0,0 +1,123 @@
+/*
+ * Setup code for AT91SAM Evaluation Kits with Device Tree support
+ *
+ * Covers: * AT91SAM9G45-EKES board
+ * * AT91SAM9M10-EKES board
+ * * AT91SAM9M10G45-EK board
+ *
+ * Copyright (C) 2011 Atmel,
+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/system_rev.h>
+#include <mach/at91sam9_smc.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+
+static void __init ek_init_early(void)
+{
+ /* Initialize processor: 12.000 MHz crystal */
+ at91_initialize(12000000);
+
+ /* DGBU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* set serial console to ttyS0 (ie, DBGU) */
+ at91_set_serial_console(0);
+}
+
+/* det_pin is not connected */
+static struct atmel_nand_data __initdata ek_nand_data = {
+ .ale = 21,
+ .cle = 22,
+ .rdy_pin = AT91_PIN_PC8,
+ .enable_pin = AT91_PIN_PC14,
+};
+
+static struct sam9_smc_config __initdata ek_nand_smc_config = {
+ .ncs_read_setup = 0,
+ .nrd_setup = 2,
+ .ncs_write_setup = 0,
+ .nwe_setup = 2,
+
+ .ncs_read_pulse = 4,
+ .nrd_pulse = 4,
+ .ncs_write_pulse = 4,
+ .nwe_pulse = 4,
+
+ .read_cycle = 7,
+ .write_cycle = 7,
+
+ .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
+ .tdf_cycles = 3,
+};
+
+static void __init ek_add_device_nand(void)
+{
+ ek_nand_data.bus_width_16 = board_have_nand_16bit();
+ /* setup bus-width (8 or 16) */
+ if (ek_nand_data.bus_width_16)
+ ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
+ else
+ ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
+
+ /* configure chip-select 3 (NAND) */
+ sam9_smc_configure(3, &ek_nand_smc_config);
+
+ at91_add_device_nand(&ek_nand_data);
+}
+
+static const struct of_device_id aic_of_match[] __initconst = {
+ { .compatible = "atmel,at91rm9200-aic", },
+ {},
+};
+
+static void __init at91_dt_init_irq(void)
+{
+ irq_domain_generate_simple(aic_of_match, 0xfffff000, 0);
+ at91_init_irq_default();
+}
+
+static void __init at91_dt_device_init(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+ /* NAND */
+ ek_add_device_nand();
+}
+
+static const char *at91_dt_board_compat[] __initdata = {
+ "atmel,at91sam9m10g45ek",
+ "calao,usb-a9g20",
+ NULL
+};
+
+DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
+ /* Maintainer: Atmel */
+ .timer = &at91sam926x_timer,
+ .map_io = at91_map_io,
+ .init_early = ek_init_early,
+ .init_irq = at91_dt_init_irq,
+ .init_machine = at91_dt_device_init,
+ .dt_compat = at91_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c
new file mode 100644
index 0000000..e927df0
--- /dev/null
+++ b/arch/arm/mach-at91/board-rsi-ews.c
@@ -0,0 +1,233 @@
+/*
+ * board-rsi-ews.c
+ *
+ * Copyright (C)
+ * 2005 SAN People,
+ * 2008-2011 R-S-I Elektrotechnik GmbH & Co. KG
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+
+#include <linux/gpio.h>
+
+#include "generic.h"
+
+static void __init rsi_ews_init_early(void)
+{
+ /* Initialize processor: 18.432 MHz crystal */
+ at91_initialize(18432000);
+
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB6, AT91_PIN_PB9);
+
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ /* This one is for debugging */
+ at91_register_uart(0, 0, 0);
+
+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ /* Dialin/-out modem interface */
+ at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
+
+ /* USART3 on ttyS4. (Rx, Tx, RTS) */
+ /* RS485 communication */
+ at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_RTS);
+
+ /* set serial console to ttyS0 (ie, DBGU) */
+ at91_set_serial_console(0);
+}
+
+/*
+ * Ethernet
+ */
+static struct at91_eth_data rsi_ews_eth_data __initdata = {
+ .phy_irq_pin = AT91_PIN_PC4,
+ .is_rmii = 1,
+};
+
+/*
+ * USB Host
+ */
+static struct at91_usbh_data rsi_ews_usbh_data __initdata = {
+ .ports = 1,
+};
+
+/*
+ * SD/MC
+ */
+static struct at91_mmc_data rsi_ews_mmc_data __initdata = {
+ .slot_b = 0,
+ .wire4 = 1,
+ .det_pin = AT91_PIN_PB27,
+ .wp_pin = AT91_PIN_PB29,
+};
+
+/*
+ * I2C
+ */
+static struct i2c_board_info rsi_ews_i2c_devices[] __initdata = {
+ {
+ I2C_BOARD_INFO("ds1337", 0x68),
+ },
+ {
+ I2C_BOARD_INFO("24c01", 0x50),
+ }
+};
+
+/*
+ * LEDs
+ */
+static struct gpio_led rsi_ews_leds[] = {
+ {
+ .name = "led0",
+ .gpio = AT91_PIN_PB6,
+ .active_low = 0,
+ },
+ {
+ .name = "led1",
+ .gpio = AT91_PIN_PB7,
+ .active_low = 0,
+ },
+ {
+ .name = "led2",
+ .gpio = AT91_PIN_PB8,
+ .active_low = 0,
+ },
+ {
+ .name = "led3",
+ .gpio = AT91_PIN_PB9,
+ .active_low = 0,
+ },
+};
+
+/*
+ * DataFlash
+ */
+static struct spi_board_info rsi_ews_spi_devices[] = {
+ { /* DataFlash chip 1*/
+ .modalias = "mtd_dataflash",
+ .chip_select = 0,
+ .max_speed_hz = 5 * 1000 * 1000,
+ },
+ { /* DataFlash chip 2*/
+ .modalias = "mtd_dataflash",
+ .chip_select = 1,
+ .max_speed_hz = 5 * 1000 * 1000,
+ },
+};
+
+/*
+ * NOR flash
+ */
+static struct mtd_partition rsiews_nor_partitions[] = {
+ {
+ .name = "boot",
+ .offset = 0,
+ .size = 3 * SZ_128K,
+ .mask_flags = MTD_WRITEABLE
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_2M - (3 * SZ_128K)
+ },
+ {
+ .name = "root",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_8M
+ },
+ {
+ .name = "kernelupd",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 3 * SZ_512K,
+ .mask_flags = MTD_WRITEABLE
+ },
+ {
+ .name = "rootupd",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 9 * SZ_512K,
+ .mask_flags = MTD_WRITEABLE
+ },
+};
+
+static struct physmap_flash_data rsiews_nor_data = {
+ .width = 2,
+ .parts = rsiews_nor_partitions,
+ .nr_parts = ARRAY_SIZE(rsiews_nor_partitions),
+};
+
+#define NOR_BASE AT91_CHIPSELECT_0
+#define NOR_SIZE SZ_16M
+
+static struct resource nor_flash_resources[] = {
+ {
+ .start = NOR_BASE,
+ .end = NOR_BASE + NOR_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device rsiews_nor_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &rsiews_nor_data,
+ },
+ .resource = nor_flash_resources,
+ .num_resources = ARRAY_SIZE(nor_flash_resources),
+};
+
+/*
+ * Init Func
+ */
+static void __init rsi_ews_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ at91_set_gpio_output(AT91_PIN_PA21, 0);
+ /* Ethernet */
+ at91_add_device_eth(&rsi_ews_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&rsi_ews_usbh_data);
+ /* I2C */
+ at91_add_device_i2c(rsi_ews_i2c_devices,
+ ARRAY_SIZE(rsi_ews_i2c_devices));
+ /* SPI */
+ at91_add_device_spi(rsi_ews_spi_devices,
+ ARRAY_SIZE(rsi_ews_spi_devices));
+ /* MMC */
+ at91_add_device_mmc(0, &rsi_ews_mmc_data);
+ /* NOR Flash */
+ platform_device_register(&rsiews_nor_flash);
+ /* LEDs */
+ at91_gpio_leds(rsi_ews_leds, ARRAY_SIZE(rsi_ews_leds));
+}
+
+MACHINE_START(RSI_EWS, "RSI EWS")
+ /* Maintainer: Josef Holzmayr <holzmayr@rsi-elektrotechnik.de> */
+ .timer = &at91rm9200_timer,
+ .map_io = at91_map_io,
+ .init_early = rsi_ews_init_early,
+ .init_irq = at91_init_irq_default,
+ .init_machine = rsi_ews_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c
new file mode 100644
index 0000000..0a20bab
--- /dev/null
+++ b/arch/arm/mach-at91/board-usb-a926x.c
@@ -0,0 +1,378 @@
+/*
+ * linux/arch/arm/mach-at91/board-usb-a926x.c
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2007 Atmel Corporation.
+ * Copyright (C) 2007 Calao-systems
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/spi/mmc_spi.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/at91sam9_smc.h>
+#include <mach/at91_shdwc.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+
+static void __init ek_init_early(void)
+{
+ /* Initialize processor: 12.00 MHz crystal */
+ at91_initialize(12000000);
+
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* set serial console to ttyS0 (ie, DBGU) */
+ at91_set_serial_console(0);
+}
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+ .ports = 2,
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+ .vbus_pin = AT91_PIN_PB11,
+ .pullup_pin = 0, /* pull-up driven by UDC */
+};
+
+static void __init ek_add_device_udc(void)
+{
+ if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+ ek_udc_data.vbus_pin = AT91_PIN_PC5;
+
+ at91_add_device_udc(&ek_udc_data);
+}
+
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+#define MMC_SPI_CARD_DETECT_INT AT91_PIN_PC4
+static int at91_mmc_spi_init(struct device *dev,
+ irqreturn_t (*detect_int)(int, void *), void *data)
+{
+ /* Configure Interrupt pin as input, no pull-up */
+ at91_set_gpio_input(MMC_SPI_CARD_DETECT_INT, 0);
+ return request_irq(gpio_to_irq(MMC_SPI_CARD_DETECT_INT), detect_int,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ "mmc-spi-detect", data);
+}
+
+static void at91_mmc_spi_exit(struct device *dev, void *data)
+{
+ free_irq(gpio_to_irq(MMC_SPI_CARD_DETECT_INT), data);
+}
+
+static struct mmc_spi_platform_data at91_mmc_spi_pdata = {
+ .init = at91_mmc_spi_init,
+ .exit = at91_mmc_spi_exit,
+ .detect_delay = 100, /* msecs */
+};
+#endif
+
+/*
+ * SPI devices.
+ */
+static struct spi_board_info usb_a9263_spi_devices[] = {
+#if !defined(CONFIG_MMC_AT91)
+ { /* DataFlash chip */
+ .modalias = "mtd_dataflash",
+ .chip_select = 0,
+ .max_speed_hz = 15 * 1000 * 1000,
+ .bus_num = 0,
+ }
+#endif
+};
+
+static struct spi_board_info usb_a9g20_spi_devices[] = {
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+ {
+ .modalias = "mmc_spi",
+ .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 0,
+ .platform_data = &at91_mmc_spi_pdata,
+ .mode = SPI_MODE_3,
+ },
+#endif
+};
+
+static void __init ek_add_device_spi(void)
+{
+ if (machine_is_usb_a9263())
+ at91_add_device_spi(usb_a9263_spi_devices, ARRAY_SIZE(usb_a9263_spi_devices));
+ else if (machine_is_usb_a9g20())
+ at91_add_device_spi(usb_a9g20_spi_devices, ARRAY_SIZE(usb_a9g20_spi_devices));
+}
+
+/*
+ * MACB Ethernet device
+ */
+static struct at91_eth_data __initdata ek_macb_data = {
+ .phy_irq_pin = AT91_PIN_PE31,
+ .is_rmii = 1,
+};
+
+static void __init ek_add_device_eth(void)
+{
+ if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+ ek_macb_data.phy_irq_pin = AT91_PIN_PA31;
+
+ at91_add_device_eth(&ek_macb_data);
+}
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+ {
+ .name = "barebox",
+ .offset = 0,
+ .size = 3 * SZ_128K,
+ }, {
+ .name = "bareboxenv",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_128K,
+ }, {
+ .name = "bareboxenv2",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_128K,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 4 * SZ_1M,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 120 * SZ_1M,
+ }, {
+ .name = "data",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL,
+ }
+};
+
+static struct atmel_nand_data __initdata ek_nand_data = {
+ .ale = 21,
+ .cle = 22,
+// .det_pin = ... not connected
+ .rdy_pin = AT91_PIN_PA22,
+ .enable_pin = AT91_PIN_PD15,
+ .parts = ek_nand_partition,
+ .num_parts = ARRAY_SIZE(ek_nand_partition),
+};
+
+static struct sam9_smc_config __initdata usb_a9260_nand_smc_config = {
+ .ncs_read_setup = 0,
+ .nrd_setup = 1,
+ .ncs_write_setup = 0,
+ .nwe_setup = 1,
+
+ .ncs_read_pulse = 3,
+ .nrd_pulse = 3,
+ .ncs_write_pulse = 3,
+ .nwe_pulse = 3,
+
+ .read_cycle = 5,
+ .write_cycle = 5,
+
+ .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
+ .tdf_cycles = 2,
+};
+
+static struct sam9_smc_config __initdata usb_a9g20_nand_smc_config = {
+ .ncs_read_setup = 0,
+ .nrd_setup = 2,
+ .ncs_write_setup = 0,
+ .nwe_setup = 2,
+
+ .ncs_read_pulse = 4,
+ .nrd_pulse = 4,
+ .ncs_write_pulse = 4,
+ .nwe_pulse = 4,
+
+ .read_cycle = 7,
+ .write_cycle = 7,
+
+ .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
+ .tdf_cycles = 3,
+};
+
+static void __init ek_add_device_nand(void)
+{
+ if (machine_is_usb_a9260() || machine_is_usb_a9g20()) {
+ ek_nand_data.rdy_pin = AT91_PIN_PC13;
+ ek_nand_data.enable_pin = AT91_PIN_PC14;
+ }
+
+ /* configure chip-select 3 (NAND) */
+ if (machine_is_usb_a9g20())
+ sam9_smc_configure(3, &usb_a9g20_nand_smc_config);
+ else
+ sam9_smc_configure(3, &usb_a9260_nand_smc_config);
+
+ at91_add_device_nand(&ek_nand_data);
+}
+
+
+/*
+ * GPIO Buttons
+ */
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button ek_buttons[] = {
+ { /* USER PUSH BUTTON */
+ .code = KEY_ENTER,
+ .gpio = AT91_PIN_PB10,
+ .active_low = 1,
+ .desc = "user_pb",
+ .wakeup = 1,
+ }
+};
+
+static struct gpio_keys_platform_data ek_button_data = {
+ .buttons = ek_buttons,
+ .nbuttons = ARRAY_SIZE(ek_buttons),
+};
+
+static struct platform_device ek_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &ek_button_data,
+ }
+};
+
+static void __init ek_add_device_buttons(void)
+{
+ at91_set_GPIO_periph(AT91_PIN_PB10, 1); /* user push button, pull up enabled */
+ at91_set_deglitch(AT91_PIN_PB10, 1);
+
+ platform_device_register(&ek_button_device);
+}
+#else
+static void __init ek_add_device_buttons(void) {}
+#endif
+
+/*
+ * LEDs
+ */
+static struct gpio_led ek_leds[] = {
+ { /* user_led (green) */
+ .name = "user_led",
+ .gpio = AT91_PIN_PB21,
+ .active_low = 1,
+ .default_trigger = "heartbeat",
+ }
+};
+
+static struct i2c_board_info __initdata ek_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("rv3029c2", 0x56),
+ },
+};
+
+static void __init ek_add_device_leds(void)
+{
+ if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+ ek_leds[0].active_low = 0;
+
+ at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+}
+
+static void __init ek_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* USB Host */
+ at91_add_device_usbh(&ek_usbh_data);
+ /* USB Device */
+ ek_add_device_udc();
+ /* SPI */
+ ek_add_device_spi();
+ /* Ethernet */
+ ek_add_device_eth();
+ /* NAND */
+ ek_add_device_nand();
+ /* Push Buttons */
+ ek_add_device_buttons();
+ /* LEDs */
+ ek_add_device_leds();
+
+ if (machine_is_usb_a9g20()) {
+ /* I2C */
+ at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
+ } else {
+ /* I2C */
+ at91_add_device_i2c(NULL, 0);
+ /* shutdown controller, wakeup button (5 msec low) */
+ at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10)
+ | AT91_SHDW_WKMODE0_LOW
+ | AT91_SHDW_RTTWKEN);
+ }
+}
+
+MACHINE_START(USB_A9263, "CALAO USB_A9263")
+ /* Maintainer: calao-systems */
+ .timer = &at91sam926x_timer,
+ .map_io = at91_map_io,
+ .init_early = ek_init_early,
+ .init_irq = at91_init_irq_default,
+ .init_machine = ek_board_init,
+MACHINE_END
+
+MACHINE_START(USB_A9260, "CALAO USB_A9260")
+ /* Maintainer: calao-systems */
+ .timer = &at91sam926x_timer,
+ .map_io = at91_map_io,
+ .init_early = ek_init_early,
+ .init_irq = at91_init_irq_default,
+ .init_machine = ek_board_init,
+MACHINE_END
+
+MACHINE_START(USB_A9G20, "CALAO USB_A92G0")
+ /* Maintainer: Jean-Christophe PLAGNIOL-VILLARD */
+ .timer = &at91sam926x_timer,
+ .map_io = at91_map_io,
+ .init_early = ek_init_early,
+ .init_irq = at91_init_irq_default,
+ .init_machine = ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
new file mode 100644
index 0000000..0d264bf
--- /dev/null
+++ b/arch/arm/mach-at91/setup.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2007 Atmel Corporation.
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Under GPLv2
+ */
+
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/cpu.h>
+#include <mach/at91_dbgu.h>
+#include <mach/at91_pmc.h>
+
+#include "soc.h"
+#include "generic.h"
+
+struct at91_init_soc __initdata at91_boot_soc;
+
+struct at91_socinfo at91_soc_initdata;
+EXPORT_SYMBOL(at91_soc_initdata);
+
+void __init at91rm9200_set_type(int type)
+{
+ if (type == ARCH_REVISON_9200_PQFP)
+ at91_soc_initdata.subtype = AT91_SOC_RM9200_PQFP;
+ else
+ at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
+
+ pr_info("AT91: filled in soc subtype: %s\n",
+ at91_get_soc_subtype(&at91_soc_initdata));
+}
+
+void __init at91_init_irq_default(void)
+{
+ at91_init_interrupts(at91_boot_soc.default_irq_priority);
+}
+
+void __init at91_init_interrupts(unsigned int *priority)
+{
+ /* Initialize the AIC interrupt controller */
+ at91_aic_init(priority);
+
+ /* Enable GPIO interrupts */
+ at91_gpio_irq_setup();
+}
+
+static struct map_desc sram_desc[2] __initdata;
+
+void __init at91_init_sram(int bank, unsigned long base, unsigned int length)
+{
+ struct map_desc *desc = &sram_desc[bank];
+
+ desc->virtual = AT91_IO_VIRT_BASE - length;
+ if (bank > 0)
+ desc->virtual -= sram_desc[bank - 1].length;
+
+ desc->pfn = __phys_to_pfn(base);
+ desc->length = length;
+ desc->type = MT_DEVICE;
+
+ pr_info("AT91: sram at 0x%lx of 0x%x mapped at 0x%lx\n",
+ base, length, desc->virtual);
+
+ iotable_init(desc, 1);
+}
+
+static struct map_desc at91_io_desc __initdata = {
+ .virtual = AT91_VA_BASE_SYS,
+ .pfn = __phys_to_pfn(AT91_BASE_SYS),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+};
+
+void __iomem *at91_ioremap(unsigned long p, size_t size, unsigned int type)
+{
+ if (p >= AT91_BASE_SYS && p <= (AT91_BASE_SYS + SZ_16K - 1))
+ return (void __iomem *)AT91_IO_P2V(p);
+
+ return __arm_ioremap_caller(p, size, type, __builtin_return_address(0));
+}
+EXPORT_SYMBOL(at91_ioremap);
+
+void at91_iounmap(volatile void __iomem *addr)
+{
+ unsigned long virt = (unsigned long)addr;
+
+ if (virt >= VMALLOC_START && virt < VMALLOC_END)
+ __iounmap(addr);
+}
+EXPORT_SYMBOL(at91_iounmap);
+
+#define AT91_DBGU0 0xfffff200
+#define AT91_DBGU1 0xffffee00
+
+static void __init soc_detect(u32 dbgu_base)
+{
+ u32 cidr, socid;
+
+ cidr = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_CIDR);
+ socid = cidr & ~AT91_CIDR_VERSION;
+
+ switch (socid) {
+ case ARCH_ID_AT91CAP9: {
+#ifdef CONFIG_AT91_PMC_UNIT
+ u32 pmc_ver = at91_sys_read(AT91_PMC_VER);
+
+ if (pmc_ver == ARCH_REVISION_CAP9_B)
+ at91_soc_initdata.subtype = AT91_SOC_CAP9_REV_B;
+ else if (pmc_ver == ARCH_REVISION_CAP9_C)
+ at91_soc_initdata.subtype = AT91_SOC_CAP9_REV_C;
+#endif
+ at91_soc_initdata.type = AT91_SOC_CAP9;
+ at91_boot_soc = at91cap9_soc;
+ break;
+ }
+
+ case ARCH_ID_AT91RM9200:
+ at91_soc_initdata.type = AT91_SOC_RM9200;
+ at91_boot_soc = at91rm9200_soc;
+ break;
+
+ case ARCH_ID_AT91SAM9260:
+ at91_soc_initdata.type = AT91_SOC_SAM9260;
+ at91_boot_soc = at91sam9260_soc;
+ break;
+
+ case ARCH_ID_AT91SAM9261:
+ at91_soc_initdata.type = AT91_SOC_SAM9261;
+ at91_boot_soc = at91sam9261_soc;
+ break;
+
+ case ARCH_ID_AT91SAM9263:
+ at91_soc_initdata.type = AT91_SOC_SAM9263;
+ at91_boot_soc = at91sam9263_soc;
+ break;
+
+ case ARCH_ID_AT91SAM9G20:
+ at91_soc_initdata.type = AT91_SOC_SAM9G20;
+ at91_boot_soc = at91sam9260_soc;
+ break;
+
+ case ARCH_ID_AT91SAM9G45:
+ at91_soc_initdata.type = AT91_SOC_SAM9G45;
+ if (cidr == ARCH_ID_AT91SAM9G45ES)
+ at91_soc_initdata.subtype = AT91_SOC_SAM9G45ES;
+ at91_boot_soc = at91sam9g45_soc;
+ break;
+
+ case ARCH_ID_AT91SAM9RL64:
+ at91_soc_initdata.type = AT91_SOC_SAM9RL;
+ at91_boot_soc = at91sam9rl_soc;
+ break;
+
+ case ARCH_ID_AT91SAM9X5:
+ at91_soc_initdata.type = AT91_SOC_SAM9X5;
+ at91_boot_soc = at91sam9x5_soc;
+ break;
+ }
+
+ /* at91sam9g10 */
+ if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
+ at91_soc_initdata.type = AT91_SOC_SAM9G10;
+ at91_boot_soc = at91sam9261_soc;
+ }
+ /* at91sam9xe */
+ else if ((cidr & AT91_CIDR_ARCH) == ARCH_FAMILY_AT91SAM9XE) {
+ at91_soc_initdata.type = AT91_SOC_SAM9260;
+ at91_soc_initdata.subtype = AT91_SOC_SAM9XE;
+ at91_boot_soc = at91sam9260_soc;
+ }
+
+ if (!at91_soc_is_detected())
+ return;
+
+ at91_soc_initdata.cidr = cidr;
+
+ /* sub version of soc */
+ at91_soc_initdata.exid = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_EXID);
+
+ if (at91_soc_initdata.type == AT91_SOC_SAM9G45) {
+ switch (at91_soc_initdata.exid) {
+ case ARCH_EXID_AT91SAM9M10:
+ at91_soc_initdata.subtype = AT91_SOC_SAM9M10;
+ break;
+ case ARCH_EXID_AT91SAM9G46:
+ at91_soc_initdata.subtype = AT91_SOC_SAM9G46;
+ break;
+ case ARCH_EXID_AT91SAM9M11:
+ at91_soc_initdata.subtype = AT91_SOC_SAM9M11;
+ break;
+ }
+ }
+
+ if (at91_soc_initdata.type == AT91_SOC_SAM9X5) {
+ switch (at91_soc_initdata.exid) {
+ case ARCH_EXID_AT91SAM9G15:
+ at91_soc_initdata.subtype = AT91_SOC_SAM9G15;
+ break;
+ case ARCH_EXID_AT91SAM9G35:
+ at91_soc_initdata.subtype = AT91_SOC_SAM9G35;
+ break;
+ case ARCH_EXID_AT91SAM9X35:
+ at91_soc_initdata.subtype = AT91_SOC_SAM9X35;
+ break;
+ case ARCH_EXID_AT91SAM9G25:
+ at91_soc_initdata.subtype = AT91_SOC_SAM9G25;
+ break;
+ case ARCH_EXID_AT91SAM9X25:
+ at91_soc_initdata.subtype = AT91_SOC_SAM9X25;
+ break;
+ }
+ }
+}
+
+static const char *soc_name[] = {
+ [AT91_SOC_RM9200] = "at91rm9200",
+ [AT91_SOC_CAP9] = "at91cap9",
+ [AT91_SOC_SAM9260] = "at91sam9260",
+ [AT91_SOC_SAM9261] = "at91sam9261",
+ [AT91_SOC_SAM9263] = "at91sam9263",
+ [AT91_SOC_SAM9G10] = "at91sam9g10",
+ [AT91_SOC_SAM9G20] = "at91sam9g20",
+ [AT91_SOC_SAM9G45] = "at91sam9g45",
+ [AT91_SOC_SAM9RL] = "at91sam9rl",
+ [AT91_SOC_SAM9X5] = "at91sam9x5",
+ [AT91_SOC_NONE] = "Unknown"
+};
+
+const char *at91_get_soc_type(struct at91_socinfo *c)
+{
+ return soc_name[c->type];
+}
+EXPORT_SYMBOL(at91_get_soc_type);
+
+static const char *soc_subtype_name[] = {
+ [AT91_SOC_RM9200_BGA] = "at91rm9200 BGA",
+ [AT91_SOC_RM9200_PQFP] = "at91rm9200 PQFP",
+ [AT91_SOC_CAP9_REV_B] = "at91cap9 revB",
+ [AT91_SOC_CAP9_REV_C] = "at91cap9 revC",
+ [AT91_SOC_SAM9XE] = "at91sam9xe",
+ [AT91_SOC_SAM9G45ES] = "at91sam9g45es",
+ [AT91_SOC_SAM9M10] = "at91sam9m10",
+ [AT91_SOC_SAM9G46] = "at91sam9g46",
+ [AT91_SOC_SAM9M11] = "at91sam9m11",
+ [AT91_SOC_SAM9G15] = "at91sam9g15",
+ [AT91_SOC_SAM9G35] = "at91sam9g35",
+ [AT91_SOC_SAM9X35] = "at91sam9x35",
+ [AT91_SOC_SAM9G25] = "at91sam9g25",
+ [AT91_SOC_SAM9X25] = "at91sam9x25",
+ [AT91_SOC_SUBTYPE_NONE] = "Unknown"
+};
+
+const char *at91_get_soc_subtype(struct at91_socinfo *c)
+{
+ return soc_subtype_name[c->subtype];
+}
+EXPORT_SYMBOL(at91_get_soc_subtype);
+
+void __init at91_map_io(void)
+{
+ /* Map peripherals */
+ iotable_init(&at91_io_desc, 1);
+
+ at91_soc_initdata.type = AT91_SOC_NONE;
+ at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE;
+
+ soc_detect(AT91_DBGU0);
+ if (!at91_soc_is_detected())
+ soc_detect(AT91_DBGU1);
+
+ if (!at91_soc_is_detected())
+ panic("AT91: Impossible to detect the SOC type");
+
+ pr_info("AT91: Detected soc type: %s\n",
+ at91_get_soc_type(&at91_soc_initdata));
+ pr_info("AT91: Detected soc subtype: %s\n",
+ at91_get_soc_subtype(&at91_soc_initdata));
+
+ if (!at91_soc_is_enabled())
+ panic("AT91: Soc not enabled");
+
+ if (at91_boot_soc.map_io)
+ at91_boot_soc.map_io();
+}
+
+void __init at91_initialize(unsigned long main_clock)
+{
+ /* Init clock subsystem */
+ at91_clock_init(main_clock);
+
+ /* Register the processor-specific clocks */
+ at91_boot_soc.register_clocks();
+
+ at91_boot_soc.init();
+}
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
new file mode 100644
index 0000000..21ed881
--- /dev/null
+++ b/arch/arm/mach-at91/soc.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Under GPLv2
+ */
+
+struct at91_init_soc {
+ unsigned int *default_irq_priority;
+ void (*map_io)(void);
+ void (*register_clocks)(void);
+ void (*init)(void);
+};
+
+extern struct at91_init_soc at91_boot_soc;
+extern struct at91_init_soc at91cap9_soc;
+extern struct at91_init_soc at91rm9200_soc;
+extern struct at91_init_soc at91sam9260_soc;
+extern struct at91_init_soc at91sam9261_soc;
+extern struct at91_init_soc at91sam9263_soc;
+extern struct at91_init_soc at91sam9g45_soc;
+extern struct at91_init_soc at91sam9rl_soc;
+extern struct at91_init_soc at91sam9x5_soc;
+
+static inline int at91_soc_is_enabled(void)
+{
+ return at91_boot_soc.init != NULL;
+}
+
+#if !defined(CONFIG_ARCH_AT91CAP9)
+#define at91cap9_soc at91_boot_soc
+#endif
+
+#if !defined(CONFIG_ARCH_AT91RM9200)
+#define at91rm9200_soc at91_boot_soc
+#endif
+
+#if !(defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20))
+#define at91sam9260_soc at91_boot_soc
+#endif
+
+#if !(defined(CONFIG_ARCH_AT91SAM9261) || defined(CONFIG_ARCH_AT91SAM9G10))
+#define at91sam9261_soc at91_boot_soc
+#endif
+
+#if !defined(CONFIG_ARCH_AT91SAM9263)
+#define at91sam9263_soc at91_boot_soc
+#endif
+
+#if !defined(CONFIG_ARCH_AT91SAM9G45)
+#define at91sam9g45_soc at91_boot_soc
+#endif
+
+#if !defined(CONFIG_ARCH_AT91SAM9RL)
+#define at91sam9rl_soc at91_boot_soc
+#endif
+
+#if !defined(CONFIG_ARCH_AT91SAM9X5)
+#define at91sam9x5_soc at91_boot_soc
+#endif
diff --git a/arch/arm/mach-davinci/include/mach/ddr2.h b/arch/arm/mach-davinci/include/mach/ddr2.h
new file mode 100644
index 0000000..c19e047
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/ddr2.h
@@ -0,0 +1,4 @@
+#define DDR2_SDRCR_OFFSET 0xc
+#define DDR2_SRPD_BIT (1 << 23)
+#define DDR2_MCLKSTOPEN_BIT (1 << 30)
+#define DDR2_LPMODEN_BIT (1 << 31)
diff --git a/arch/arm/mach-davinci/include/mach/gpio-davinci.h b/arch/arm/mach-davinci/include/mach/gpio-davinci.h
new file mode 100644
index 0000000..1fdd1fd
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/gpio-davinci.h
@@ -0,0 +1,91 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __DAVINCI_DAVINCI_GPIO_H
+#define __DAVINCI_DAVINCI_GPIO_H
+
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <asm-generic/gpio.h>
+
+#include <mach/irqs.h>
+#include <mach/common.h>
+
+#define DAVINCI_GPIO_BASE 0x01C67000
+
+enum davinci_gpio_type {
+ GPIO_TYPE_DAVINCI = 0,
+ GPIO_TYPE_TNETV107X,
+};
+
+/*
+ * basic gpio routines
+ *
+ * board-specific init should be done by arch/.../.../board-XXX.c (maybe
+ * initializing banks together) rather than boot loaders; kexec() won't
+ * go through boot loaders.
+ *
+ * the gpio clock will be turned on when gpios are used, and you may also
+ * need to pay attention to PINMUX registers to be sure those pins are
+ * used as gpios, not with other peripherals.
+ *
+ * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation,
+ * and maybe for later updates, code may write GPIO(N). These may be
+ * all 1.8V signals, all 3.3V ones, or a mix of the two. A given chip
+ * may not support all the GPIOs in that range.
+ *
+ * GPIOs can also be on external chips, numbered after the ones built-in
+ * to the DaVinci chip. For now, they won't be usable as IRQ sources.
+ */
+#define GPIO(X) (X) /* 0 <= X <= (DAVINCI_N_GPIO - 1) */
+
+/* Convert GPIO signal to GPIO pin number */
+#define GPIO_TO_PIN(bank, gpio) (16 * (bank) + (gpio))
+
+struct davinci_gpio_controller {
+ struct gpio_chip chip;
+ int irq_base;
+ spinlock_t lock;
+ void __iomem *regs;
+ void __iomem *set_data;
+ void __iomem *clr_data;
+ void __iomem *in_data;
+};
+
+/* The __gpio_to_controller() and __gpio_mask() functions inline to constants
+ * with constant parameters; or in outlined code they execute at runtime.
+ *
+ * You'd access the controller directly when reading or writing more than
+ * one gpio value at a time, and to support wired logic where the value
+ * being driven by the cpu need not match the value read back.
+ *
+ * These are NOT part of the cross-platform GPIO interface
+ */
+static inline struct davinci_gpio_controller *
+__gpio_to_controller(unsigned gpio)
+{
+ struct davinci_gpio_controller *ctlrs = davinci_soc_info.gpio_ctlrs;
+ int index = gpio / 32;
+
+ if (!ctlrs || index >= davinci_soc_info.gpio_ctlrs_num)
+ return NULL;
+
+ return ctlrs + index;
+}
+
+static inline u32 __gpio_mask(unsigned gpio)
+{
+ return 1 << (gpio % 32);
+}
+
+#endif /* __DAVINCI_DAVINCI_GPIO_H */
diff --git a/arch/arm/mach-ep93xx/dma.c b/arch/arm/mach-ep93xx/dma.c
new file mode 100644
index 0000000..5a25708
--- /dev/null
+++ b/arch/arm/mach-ep93xx/dma.c
@@ -0,0 +1,108 @@
+/*
+ * arch/arm/mach-ep93xx/dma.c
+ *
+ * Platform support code for the EP93xx dmaengine driver.
+ *
+ * Copyright (C) 2011 Mika Westerberg
+ *
+ * This work is based on the original dma-m2p implementation with
+ * following copyrights:
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2006 Applied Data Systems
+ * Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <mach/dma.h>
+#include <mach/hardware.h>
+
+#define DMA_CHANNEL(_name, _base, _irq) \
+ { .name = (_name), .base = (_base), .irq = (_irq) }
+
+/*
+ * DMA M2P channels.
+ *
+ * On the EP93xx chip the following peripherals my be allocated to the 10
+ * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
+ *
+ * I2S contains 3 Tx and 3 Rx DMA Channels
+ * AAC contains 3 Tx and 3 Rx DMA Channels
+ * UART1 contains 1 Tx and 1 Rx DMA Channels
+ * UART2 contains 1 Tx and 1 Rx DMA Channels
+ * UART3 contains 1 Tx and 1 Rx DMA Channels
+ * IrDA contains 1 Tx and 1 Rx DMA Channels
+ *
+ * Registers are mapped statically in ep93xx_map_io().
+ */
+static struct ep93xx_dma_chan_data ep93xx_dma_m2p_channels[] = {
+ DMA_CHANNEL("m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0),
+ DMA_CHANNEL("m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1),
+ DMA_CHANNEL("m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2),
+ DMA_CHANNEL("m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3),
+ DMA_CHANNEL("m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4),
+ DMA_CHANNEL("m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5),
+ DMA_CHANNEL("m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6),
+ DMA_CHANNEL("m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7),
+ DMA_CHANNEL("m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8),
+ DMA_CHANNEL("m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9),
+};
+
+static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = {
+ .channels = ep93xx_dma_m2p_channels,
+ .num_channels = ARRAY_SIZE(ep93xx_dma_m2p_channels),
+};
+
+static struct platform_device ep93xx_dma_m2p_device = {
+ .name = "ep93xx-dma-m2p",
+ .id = -1,
+ .dev = {
+ .platform_data = &ep93xx_dma_m2p_data,
+ },
+};
+
+/*
+ * DMA M2M channels.
+ *
+ * There are 2 M2M channels which support memcpy/memset and in addition simple
+ * hardware requests from/to SSP and IDE. We do not implement an external
+ * hardware requests.
+ *
+ * Registers are mapped statically in ep93xx_map_io().
+ */
+static struct ep93xx_dma_chan_data ep93xx_dma_m2m_channels[] = {
+ DMA_CHANNEL("m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0),
+ DMA_CHANNEL("m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1),
+};
+
+static struct ep93xx_dma_platform_data ep93xx_dma_m2m_data = {
+ .channels = ep93xx_dma_m2m_channels,
+ .num_channels = ARRAY_SIZE(ep93xx_dma_m2m_channels),
+};
+
+static struct platform_device ep93xx_dma_m2m_device = {
+ .name = "ep93xx-dma-m2m",
+ .id = -1,
+ .dev = {
+ .platform_data = &ep93xx_dma_m2m_data,
+ },
+};
+
+static int __init ep93xx_dma_init(void)
+{
+ platform_device_register(&ep93xx_dma_m2p_device);
+ platform_device_register(&ep93xx_dma_m2m_device);
+ return 0;
+}
+arch_initcall(ep93xx_dma_init);
diff --git a/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h b/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h
new file mode 100644
index 0000000..8aff2ea
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h
@@ -0,0 +1,100 @@
+/* Include file for the EP93XX GPIO controller machine specifics */
+
+#ifndef __GPIO_EP93XX_H
+#define __GPIO_EP93XX_H
+
+/* GPIO port A. */
+#define EP93XX_GPIO_LINE_A(x) ((x) + 0)
+#define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0)
+#define EP93XX_GPIO_LINE_EGPIO1 EP93XX_GPIO_LINE_A(1)
+#define EP93XX_GPIO_LINE_EGPIO2 EP93XX_GPIO_LINE_A(2)
+#define EP93XX_GPIO_LINE_EGPIO3 EP93XX_GPIO_LINE_A(3)
+#define EP93XX_GPIO_LINE_EGPIO4 EP93XX_GPIO_LINE_A(4)
+#define EP93XX_GPIO_LINE_EGPIO5 EP93XX_GPIO_LINE_A(5)
+#define EP93XX_GPIO_LINE_EGPIO6 EP93XX_GPIO_LINE_A(6)
+#define EP93XX_GPIO_LINE_EGPIO7 EP93XX_GPIO_LINE_A(7)
+
+/* GPIO port B. */
+#define EP93XX_GPIO_LINE_B(x) ((x) + 8)
+#define EP93XX_GPIO_LINE_EGPIO8 EP93XX_GPIO_LINE_B(0)
+#define EP93XX_GPIO_LINE_EGPIO9 EP93XX_GPIO_LINE_B(1)
+#define EP93XX_GPIO_LINE_EGPIO10 EP93XX_GPIO_LINE_B(2)
+#define EP93XX_GPIO_LINE_EGPIO11 EP93XX_GPIO_LINE_B(3)
+#define EP93XX_GPIO_LINE_EGPIO12 EP93XX_GPIO_LINE_B(4)
+#define EP93XX_GPIO_LINE_EGPIO13 EP93XX_GPIO_LINE_B(5)
+#define EP93XX_GPIO_LINE_EGPIO14 EP93XX_GPIO_LINE_B(6)
+#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7)
+
+/* GPIO port C. */
+#define EP93XX_GPIO_LINE_C(x) ((x) + 40)
+#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0)
+#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1)
+#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2)
+#define EP93XX_GPIO_LINE_ROW3 EP93XX_GPIO_LINE_C(3)
+#define EP93XX_GPIO_LINE_ROW4 EP93XX_GPIO_LINE_C(4)
+#define EP93XX_GPIO_LINE_ROW5 EP93XX_GPIO_LINE_C(5)
+#define EP93XX_GPIO_LINE_ROW6 EP93XX_GPIO_LINE_C(6)
+#define EP93XX_GPIO_LINE_ROW7 EP93XX_GPIO_LINE_C(7)
+
+/* GPIO port D. */
+#define EP93XX_GPIO_LINE_D(x) ((x) + 24)
+#define EP93XX_GPIO_LINE_COL0 EP93XX_GPIO_LINE_D(0)
+#define EP93XX_GPIO_LINE_COL1 EP93XX_GPIO_LINE_D(1)
+#define EP93XX_GPIO_LINE_COL2 EP93XX_GPIO_LINE_D(2)
+#define EP93XX_GPIO_LINE_COL3 EP93XX_GPIO_LINE_D(3)
+#define EP93XX_GPIO_LINE_COL4 EP93XX_GPIO_LINE_D(4)
+#define EP93XX_GPIO_LINE_COL5 EP93XX_GPIO_LINE_D(5)
+#define EP93XX_GPIO_LINE_COL6 EP93XX_GPIO_LINE_D(6)
+#define EP93XX_GPIO_LINE_COL7 EP93XX_GPIO_LINE_D(7)
+
+/* GPIO port E. */
+#define EP93XX_GPIO_LINE_E(x) ((x) + 32)
+#define EP93XX_GPIO_LINE_GRLED EP93XX_GPIO_LINE_E(0)
+#define EP93XX_GPIO_LINE_RDLED EP93XX_GPIO_LINE_E(1)
+#define EP93XX_GPIO_LINE_DIORn EP93XX_GPIO_LINE_E(2)
+#define EP93XX_GPIO_LINE_IDECS1n EP93XX_GPIO_LINE_E(3)
+#define EP93XX_GPIO_LINE_IDECS2n EP93XX_GPIO_LINE_E(4)
+#define EP93XX_GPIO_LINE_IDEDA0 EP93XX_GPIO_LINE_E(5)
+#define EP93XX_GPIO_LINE_IDEDA1 EP93XX_GPIO_LINE_E(6)
+#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7)
+
+/* GPIO port F. */
+#define EP93XX_GPIO_LINE_F(x) ((x) + 16)
+#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0)
+#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1)
+#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2)
+#define EP93XX_GPIO_LINE_MCBVD1 EP93XX_GPIO_LINE_F(3)
+#define EP93XX_GPIO_LINE_MCBVD2 EP93XX_GPIO_LINE_F(4)
+#define EP93XX_GPIO_LINE_VS1 EP93XX_GPIO_LINE_F(5)
+#define EP93XX_GPIO_LINE_READY EP93XX_GPIO_LINE_F(6)
+#define EP93XX_GPIO_LINE_VS2 EP93XX_GPIO_LINE_F(7)
+
+/* GPIO port G. */
+#define EP93XX_GPIO_LINE_G(x) ((x) + 48)
+#define EP93XX_GPIO_LINE_EECLK EP93XX_GPIO_LINE_G(0)
+#define EP93XX_GPIO_LINE_EEDAT EP93XX_GPIO_LINE_G(1)
+#define EP93XX_GPIO_LINE_SLA0 EP93XX_GPIO_LINE_G(2)
+#define EP93XX_GPIO_LINE_SLA1 EP93XX_GPIO_LINE_G(3)
+#define EP93XX_GPIO_LINE_DD12 EP93XX_GPIO_LINE_G(4)
+#define EP93XX_GPIO_LINE_DD13 EP93XX_GPIO_LINE_G(5)
+#define EP93XX_GPIO_LINE_DD14 EP93XX_GPIO_LINE_G(6)
+#define EP93XX_GPIO_LINE_DD15 EP93XX_GPIO_LINE_G(7)
+
+/* GPIO port H. */
+#define EP93XX_GPIO_LINE_H(x) ((x) + 56)
+#define EP93XX_GPIO_LINE_DD0 EP93XX_GPIO_LINE_H(0)
+#define EP93XX_GPIO_LINE_DD1 EP93XX_GPIO_LINE_H(1)
+#define EP93XX_GPIO_LINE_DD2 EP93XX_GPIO_LINE_H(2)
+#define EP93XX_GPIO_LINE_DD3 EP93XX_GPIO_LINE_H(3)
+#define EP93XX_GPIO_LINE_DD4 EP93XX_GPIO_LINE_H(4)
+#define EP93XX_GPIO_LINE_DD5 EP93XX_GPIO_LINE_H(5)
+#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6)
+#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for gpio line identifiers */
+#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for irq capable line identifiers */
+#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7)
+
+#endif /* __GPIO_EP93XX_H */
diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c
new file mode 100644
index 0000000..d96e4db
--- /dev/null
+++ b/arch/arm/mach-ep93xx/vision_ep9307.c
@@ -0,0 +1,364 @@
+/*
+ * arch/arm/mach-ep93xx/vision_ep9307.c
+ * Vision Engraving Systems EP9307 SoM support.
+ *
+ * Copyright (C) 2008-2011 Vision Engraving Systems
+ * H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/mtd/partitions.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/mmc/host.h>
+
+#include <mach/hardware.h>
+#include <mach/fb.h>
+#include <mach/ep93xx_spi.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+/*************************************************************************
+ * Static I/O mappings for the FPGA
+ *************************************************************************/
+#define VISION_PHYS_BASE EP93XX_CS7_PHYS_BASE
+#define VISION_VIRT_BASE 0xfebff000
+
+static struct map_desc vision_io_desc[] __initdata = {
+ {
+ .virtual = VISION_VIRT_BASE,
+ .pfn = __phys_to_pfn(VISION_PHYS_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
+static void __init vision_map_io(void)
+{
+ ep93xx_map_io();
+
+ iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc));
+}
+
+/*************************************************************************
+ * Ethernet
+ *************************************************************************/
+static struct ep93xx_eth_data vision_eth_data __initdata = {
+ .phy_id = 1,
+};
+
+/*************************************************************************
+ * Framebuffer
+ *************************************************************************/
+#define VISION_LCD_ENABLE EP93XX_GPIO_LINE_EGPIO1
+
+static int vision_lcd_setup(struct platform_device *pdev)
+{
+ int err;
+
+ err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_INIT_HIGH,
+ dev_name(&pdev->dev));
+ if (err)
+ return err;
+
+ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS |
+ EP93XX_SYSCON_DEVCFG_RASONP3 |
+ EP93XX_SYSCON_DEVCFG_EXVC);
+
+ return 0;
+}
+
+static void vision_lcd_teardown(struct platform_device *pdev)
+{
+ gpio_free(VISION_LCD_ENABLE);
+}
+
+static void vision_lcd_blank(int blank_mode, struct fb_info *info)
+{
+ if (blank_mode)
+ gpio_set_value(VISION_LCD_ENABLE, 0);
+ else
+ gpio_set_value(VISION_LCD_ENABLE, 1);
+}
+
+static struct ep93xxfb_mach_info ep93xxfb_info __initdata = {
+ .num_modes = EP93XXFB_USE_MODEDB,
+ .bpp = 16,
+ .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
+ .setup = vision_lcd_setup,
+ .teardown = vision_lcd_teardown,
+ .blank = vision_lcd_blank,
+};
+
+
+/*************************************************************************
+ * GPIO Expanders
+ *************************************************************************/
+#define PCA9539_74_GPIO_BASE (EP93XX_GPIO_LINE_MAX + 1)
+#define PCA9539_75_GPIO_BASE (PCA9539_74_GPIO_BASE + 16)
+#define PCA9539_76_GPIO_BASE (PCA9539_75_GPIO_BASE + 16)
+#define PCA9539_77_GPIO_BASE (PCA9539_76_GPIO_BASE + 16)
+
+static struct pca953x_platform_data pca953x_74_gpio_data = {
+ .gpio_base = PCA9539_74_GPIO_BASE,
+ .irq_base = EP93XX_BOARD_IRQ(0),
+};
+
+static struct pca953x_platform_data pca953x_75_gpio_data = {
+ .gpio_base = PCA9539_75_GPIO_BASE,
+ .irq_base = -1,
+};
+
+static struct pca953x_platform_data pca953x_76_gpio_data = {
+ .gpio_base = PCA9539_76_GPIO_BASE,
+ .irq_base = -1,
+};
+
+static struct pca953x_platform_data pca953x_77_gpio_data = {
+ .gpio_base = PCA9539_77_GPIO_BASE,
+ .irq_base = -1,
+};
+
+/*************************************************************************
+ * I2C Bus
+ *************************************************************************/
+static struct i2c_gpio_platform_data vision_i2c_gpio_data __initdata = {
+ .sda_pin = EP93XX_GPIO_LINE_EEDAT,
+ .scl_pin = EP93XX_GPIO_LINE_EECLK,
+};
+
+static struct i2c_board_info vision_i2c_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("isl1208", 0x6f),
+ .irq = IRQ_EP93XX_EXT1,
+ }, {
+ I2C_BOARD_INFO("pca9539", 0x74),
+ .platform_data = &pca953x_74_gpio_data,
+ .irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7)),
+ }, {
+ I2C_BOARD_INFO("pca9539", 0x75),
+ .platform_data = &pca953x_75_gpio_data,
+ }, {
+ I2C_BOARD_INFO("pca9539", 0x76),
+ .platform_data = &pca953x_76_gpio_data,
+ }, {
+ I2C_BOARD_INFO("pca9539", 0x77),
+ .platform_data = &pca953x_77_gpio_data,
+ },
+};
+
+/*************************************************************************
+ * SPI Flash
+ *************************************************************************/
+#define VISION_SPI_FLASH_CS EP93XX_GPIO_LINE_EGPIO7
+
+static struct mtd_partition vision_spi_flash_partitions[] = {
+ {
+ .name = "SPI bootstrap",
+ .offset = 0,
+ .size = SZ_4K,
+ }, {
+ .name = "Bootstrap config",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4K,
+ }, {
+ .name = "System config",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data vision_spi_flash_data = {
+ .name = "SPI Flash",
+ .parts = vision_spi_flash_partitions,
+ .nr_parts = ARRAY_SIZE(vision_spi_flash_partitions),
+};
+
+static int vision_spi_flash_hw_setup(struct spi_device *spi)
+{
+ return gpio_request_one(VISION_SPI_FLASH_CS, GPIOF_INIT_HIGH,
+ spi->modalias);
+}
+
+static void vision_spi_flash_hw_cleanup(struct spi_device *spi)
+{
+ gpio_free(VISION_SPI_FLASH_CS);
+}
+
+static void vision_spi_flash_hw_cs_control(struct spi_device *spi, int value)
+{
+ gpio_set_value(VISION_SPI_FLASH_CS, value);
+}
+
+static struct ep93xx_spi_chip_ops vision_spi_flash_hw = {
+ .setup = vision_spi_flash_hw_setup,
+ .cleanup = vision_spi_flash_hw_cleanup,
+ .cs_control = vision_spi_flash_hw_cs_control,
+};
+
+/*************************************************************************
+ * SPI SD/MMC host
+ *************************************************************************/
+#define VISION_SPI_MMC_CS EP93XX_GPIO_LINE_G(2)
+#define VISION_SPI_MMC_WP EP93XX_GPIO_LINE_F(0)
+#define VISION_SPI_MMC_CD EP93XX_GPIO_LINE_EGPIO15
+
+static struct gpio vision_spi_mmc_gpios[] = {
+ { VISION_SPI_MMC_WP, GPIOF_DIR_IN, "mmc_spi:wp" },
+ { VISION_SPI_MMC_CD, GPIOF_DIR_IN, "mmc_spi:cd" },
+};
+
+static int vision_spi_mmc_init(struct device *pdev,
+ irqreturn_t (*func)(int, void *), void *pdata)
+{
+ int err;
+
+ err = gpio_request_array(vision_spi_mmc_gpios,
+ ARRAY_SIZE(vision_spi_mmc_gpios));
+ if (err)
+ return err;
+
+ err = gpio_set_debounce(VISION_SPI_MMC_CD, 1);
+ if (err)
+ goto exit_err;
+
+ err = request_irq(gpio_to_irq(VISION_SPI_MMC_CD), func,
+ IRQ_TYPE_EDGE_BOTH, "mmc_spi:cd", pdata);
+ if (err)
+ goto exit_err;
+
+ return 0;
+
+exit_err:
+ gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
+ return err;
+
+}
+
+static void vision_spi_mmc_exit(struct device *pdev, void *pdata)
+{
+ free_irq(gpio_to_irq(VISION_SPI_MMC_CD), pdata);
+ gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
+}
+
+static int vision_spi_mmc_get_ro(struct device *pdev)
+{
+ return !!gpio_get_value(VISION_SPI_MMC_WP);
+}
+
+static int vision_spi_mmc_get_cd(struct device *pdev)
+{
+ return !gpio_get_value(VISION_SPI_MMC_CD);
+}
+
+static struct mmc_spi_platform_data vision_spi_mmc_data = {
+ .init = vision_spi_mmc_init,
+ .exit = vision_spi_mmc_exit,
+ .get_ro = vision_spi_mmc_get_ro,
+ .get_cd = vision_spi_mmc_get_cd,
+ .detect_delay = 100,
+ .powerup_msecs = 100,
+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+static int vision_spi_mmc_hw_setup(struct spi_device *spi)
+{
+ return gpio_request_one(VISION_SPI_MMC_CS, GPIOF_INIT_HIGH,
+ spi->modalias);
+}
+
+static void vision_spi_mmc_hw_cleanup(struct spi_device *spi)
+{
+ gpio_free(VISION_SPI_MMC_CS);
+}
+
+static void vision_spi_mmc_hw_cs_control(struct spi_device *spi, int value)
+{
+ gpio_set_value(VISION_SPI_MMC_CS, value);
+}
+
+static struct ep93xx_spi_chip_ops vision_spi_mmc_hw = {
+ .setup = vision_spi_mmc_hw_setup,
+ .cleanup = vision_spi_mmc_hw_cleanup,
+ .cs_control = vision_spi_mmc_hw_cs_control,
+};
+
+/*************************************************************************
+ * SPI Bus
+ *************************************************************************/
+static struct spi_board_info vision_spi_board_info[] __initdata = {
+ {
+ .modalias = "sst25l",
+ .platform_data = &vision_spi_flash_data,
+ .controller_data = &vision_spi_flash_hw,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ }, {
+ .modalias = "mmc_spi",
+ .platform_data = &vision_spi_mmc_data,
+ .controller_data = &vision_spi_mmc_hw,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .mode = SPI_MODE_3,
+ },
+};
+
+static struct ep93xx_spi_info vision_spi_master __initdata = {
+ .num_chipselect = ARRAY_SIZE(vision_spi_board_info),
+};
+
+/*************************************************************************
+ * Machine Initialization
+ *************************************************************************/
+static void __init vision_init_machine(void)
+{
+ ep93xx_init_devices();
+ ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_64M);
+ ep93xx_register_eth(&vision_eth_data, 1);
+ ep93xx_register_fb(&ep93xxfb_info);
+ ep93xx_register_pwm(1, 0);
+
+ /*
+ * Request the gpio expander's interrupt gpio line now to prevent
+ * the kernel from doing a WARN in gpiolib:gpio_ensure_requested().
+ */
+ if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_DIR_IN,
+ "pca9539:74"))
+ pr_warn("cannot request interrupt gpio for pca9539:74\n");
+
+ ep93xx_register_i2c(&vision_i2c_gpio_data, vision_i2c_info,
+ ARRAY_SIZE(vision_i2c_info));
+ ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
+ ARRAY_SIZE(vision_spi_board_info));
+}
+
+MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307")
+ /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+ .atag_offset = 0x100,
+ .map_io = vision_map_io,
+ .init_irq = ep93xx_init_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = vision_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-exynos/clock.c b/arch/arm/mach-exynos/clock.c
new file mode 100644
index 0000000..2894f0a
--- /dev/null
+++ b/arch/arm/mach-exynos/clock.c
@@ -0,0 +1,1491 @@
+/* linux/arch/arm/mach-exynos4/clock.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS4 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/exynos4.h>
+#include <plat/pm.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4_clock_save[] = {
+ SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
+ SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
+ SAVE_ITEM(S5P_CLKDIV_RIGHTBUS),
+ SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS),
+ SAVE_ITEM(S5P_CLKSRC_TOP0),
+ SAVE_ITEM(S5P_CLKSRC_TOP1),
+ SAVE_ITEM(S5P_CLKSRC_CAM),
+ SAVE_ITEM(S5P_CLKSRC_TV),
+ SAVE_ITEM(S5P_CLKSRC_MFC),
+ SAVE_ITEM(S5P_CLKSRC_G3D),
+ SAVE_ITEM(S5P_CLKSRC_LCD0),
+ SAVE_ITEM(S5P_CLKSRC_MAUDIO),
+ SAVE_ITEM(S5P_CLKSRC_FSYS),
+ SAVE_ITEM(S5P_CLKSRC_PERIL0),
+ SAVE_ITEM(S5P_CLKSRC_PERIL1),
+ SAVE_ITEM(S5P_CLKDIV_CAM),
+ SAVE_ITEM(S5P_CLKDIV_TV),
+ SAVE_ITEM(S5P_CLKDIV_MFC),
+ SAVE_ITEM(S5P_CLKDIV_G3D),
+ SAVE_ITEM(S5P_CLKDIV_LCD0),
+ SAVE_ITEM(S5P_CLKDIV_MAUDIO),
+ SAVE_ITEM(S5P_CLKDIV_FSYS0),
+ SAVE_ITEM(S5P_CLKDIV_FSYS1),
+ SAVE_ITEM(S5P_CLKDIV_FSYS2),
+ SAVE_ITEM(S5P_CLKDIV_FSYS3),
+ SAVE_ITEM(S5P_CLKDIV_PERIL0),
+ SAVE_ITEM(S5P_CLKDIV_PERIL1),
+ SAVE_ITEM(S5P_CLKDIV_PERIL2),
+ SAVE_ITEM(S5P_CLKDIV_PERIL3),
+ SAVE_ITEM(S5P_CLKDIV_PERIL4),
+ SAVE_ITEM(S5P_CLKDIV_PERIL5),
+ SAVE_ITEM(S5P_CLKDIV_TOP),
+ SAVE_ITEM(S5P_CLKSRC_MASK_TOP),
+ SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
+ SAVE_ITEM(S5P_CLKSRC_MASK_TV),
+ SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
+ SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO),
+ SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
+ SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
+ SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
+ SAVE_ITEM(S5P_CLKDIV2_RATIO),
+ SAVE_ITEM(S5P_CLKGATE_SCLKCAM),
+ SAVE_ITEM(S5P_CLKGATE_IP_CAM),
+ SAVE_ITEM(S5P_CLKGATE_IP_TV),
+ SAVE_ITEM(S5P_CLKGATE_IP_MFC),
+ SAVE_ITEM(S5P_CLKGATE_IP_G3D),
+ SAVE_ITEM(S5P_CLKGATE_IP_LCD0),
+ SAVE_ITEM(S5P_CLKGATE_IP_FSYS),
+ SAVE_ITEM(S5P_CLKGATE_IP_GPS),
+ SAVE_ITEM(S5P_CLKGATE_IP_PERIL),
+ SAVE_ITEM(S5P_CLKGATE_BLOCK),
+ SAVE_ITEM(S5P_CLKSRC_MASK_DMC),
+ SAVE_ITEM(S5P_CLKSRC_DMC),
+ SAVE_ITEM(S5P_CLKDIV_DMC0),
+ SAVE_ITEM(S5P_CLKDIV_DMC1),
+ SAVE_ITEM(S5P_CLKGATE_IP_DMC),
+ SAVE_ITEM(S5P_CLKSRC_CPU),
+ SAVE_ITEM(S5P_CLKDIV_CPU),
+ SAVE_ITEM(S5P_CLKDIV_CPU + 0x4),
+ SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
+ SAVE_ITEM(S5P_CLKGATE_IP_CPU),
+};
+
+struct clk clk_sclk_hdmi27m = {
+ .name = "sclk_hdmi27m",
+ .rate = 27000000,
+};
+
+struct clk clk_sclk_hdmiphy = {
+ .name = "sclk_hdmiphy",
+};
+
+struct clk clk_sclk_usbphy0 = {
+ .name = "sclk_usbphy0",
+ .rate = 27000000,
+};
+
+struct clk clk_sclk_usbphy1 = {
+ .name = "sclk_usbphy1",
+};
+
+static struct clk dummy_apb_pclk = {
+ .name = "apb_pclk",
+ .id = -1,
+};
+
+static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
+}
+
+static int exynos4_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKSRC_MASK_CAM, clk, enable);
+}
+
+static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable);
+}
+
+int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable);
+}
+
+static int exynos4_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable);
+}
+
+static int exynos4_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable);
+}
+
+static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable);
+}
+
+static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKSRC_MASK_TV, clk, enable);
+}
+
+static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
+}
+
+static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_TV, clk, enable);
+}
+
+static int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_IMAGE, clk, enable);
+}
+
+static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable);
+}
+
+int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable);
+}
+
+int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable);
+}
+
+static int exynos4_clk_ip_peril_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
+}
+
+static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
+}
+
+static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
+}
+
+static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
+}
+
+/* Core list of CMU_CPU side */
+
+static struct clksrc_clk clk_mout_apll = {
+ .clk = {
+ .name = "mout_apll",
+ },
+ .sources = &clk_src_apll,
+ .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
+};
+
+struct clksrc_clk clk_sclk_apll = {
+ .clk = {
+ .name = "sclk_apll",
+ .parent = &clk_mout_apll.clk,
+ },
+ .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
+};
+
+struct clksrc_clk clk_mout_epll = {
+ .clk = {
+ .name = "mout_epll",
+ },
+ .sources = &clk_src_epll,
+ .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
+};
+
+struct clksrc_clk clk_mout_mpll = {
+ .clk = {
+ .name = "mout_mpll",
+ },
+ .sources = &clk_src_mpll,
+
+ /* reg_src will be added in each SoCs' clock */
+};
+
+static struct clk *clkset_moutcore_list[] = {
+ [0] = &clk_mout_apll.clk,
+ [1] = &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_moutcore = {
+ .sources = clkset_moutcore_list,
+ .nr_sources = ARRAY_SIZE(clkset_moutcore_list),
+};
+
+static struct clksrc_clk clk_moutcore = {
+ .clk = {
+ .name = "moutcore",
+ },
+ .sources = &clkset_moutcore,
+ .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
+};
+
+static struct clksrc_clk clk_coreclk = {
+ .clk = {
+ .name = "core_clk",
+ .parent = &clk_moutcore.clk,
+ },
+ .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_armclk = {
+ .clk = {
+ .name = "armclk",
+ .parent = &clk_coreclk.clk,
+ },
+};
+
+static struct clksrc_clk clk_aclk_corem0 = {
+ .clk = {
+ .name = "aclk_corem0",
+ .parent = &clk_coreclk.clk,
+ },
+ .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_cores = {
+ .clk = {
+ .name = "aclk_cores",
+ .parent = &clk_coreclk.clk,
+ },
+ .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_corem1 = {
+ .clk = {
+ .name = "aclk_corem1",
+ .parent = &clk_coreclk.clk,
+ },
+ .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
+};
+
+static struct clksrc_clk clk_periphclk = {
+ .clk = {
+ .name = "periphclk",
+ .parent = &clk_coreclk.clk,
+ },
+ .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
+};
+
+/* Core list of CMU_CORE side */
+
+struct clk *clkset_corebus_list[] = {
+ [0] = &clk_mout_mpll.clk,
+ [1] = &clk_sclk_apll.clk,
+};
+
+struct clksrc_sources clkset_mout_corebus = {
+ .sources = clkset_corebus_list,
+ .nr_sources = ARRAY_SIZE(clkset_corebus_list),
+};
+
+static struct clksrc_clk clk_mout_corebus = {
+ .clk = {
+ .name = "mout_corebus",
+ },
+ .sources = &clkset_mout_corebus,
+ .reg_src = { .reg = S5P_CLKSRC_DMC, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_dmc = {
+ .clk = {
+ .name = "sclk_dmc",
+ .parent = &clk_mout_corebus.clk,
+ },
+ .reg_div = { .reg = S5P_CLKDIV_DMC0, .shift = 12, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_cored = {
+ .clk = {
+ .name = "aclk_cored",
+ .parent = &clk_sclk_dmc.clk,
+ },
+ .reg_div = { .reg = S5P_CLKDIV_DMC0, .shift = 16, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_corep = {
+ .clk = {
+ .name = "aclk_corep",
+ .parent = &clk_aclk_cored.clk,
+ },
+ .reg_div = { .reg = S5P_CLKDIV_DMC0, .shift = 20, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_acp = {
+ .clk = {
+ .name = "aclk_acp",
+ .parent = &clk_mout_corebus.clk,
+ },
+ .reg_div = { .reg = S5P_CLKDIV_DMC0, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_pclk_acp = {
+ .clk = {
+ .name = "pclk_acp",
+ .parent = &clk_aclk_acp.clk,
+ },
+ .reg_div = { .reg = S5P_CLKDIV_DMC0, .shift = 4, .size = 3 },
+};
+
+/* Core list of CMU_TOP side */
+
+struct clk *clkset_aclk_top_list[] = {
+ [0] = &clk_mout_mpll.clk,
+ [1] = &clk_sclk_apll.clk,
+};
+
+struct clksrc_sources clkset_aclk = {
+ .sources = clkset_aclk_top_list,
+ .nr_sources = ARRAY_SIZE(clkset_aclk_top_list),
+};
+
+static struct clksrc_clk clk_aclk_200 = {
+ .clk = {
+ .name = "aclk_200",
+ },
+ .sources = &clkset_aclk,
+ .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
+ .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_100 = {
+ .clk = {
+ .name = "aclk_100",
+ },
+ .sources = &clkset_aclk,
+ .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
+ .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 },
+};
+
+static struct clksrc_clk clk_aclk_160 = {
+ .clk = {
+ .name = "aclk_160",
+ },
+ .sources = &clkset_aclk,
+ .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
+ .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
+};
+
+struct clksrc_clk clk_aclk_133 = {
+ .clk = {
+ .name = "aclk_133",
+ },
+ .sources = &clkset_aclk,
+ .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
+ .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 },
+};
+
+static struct clk *clkset_vpllsrc_list[] = {
+ [0] = &clk_fin_vpll,
+ [1] = &clk_sclk_hdmi27m,
+};
+
+static struct clksrc_sources clkset_vpllsrc = {
+ .sources = clkset_vpllsrc_list,
+ .nr_sources = ARRAY_SIZE(clkset_vpllsrc_list),
+};
+
+static struct clksrc_clk clk_vpllsrc = {
+ .clk = {
+ .name = "vpll_src",
+ .enable = exynos4_clksrc_mask_top_ctrl,
+ .ctrlbit = (1 << 0),
+ },
+ .sources = &clkset_vpllsrc,
+ .reg_src = { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_vpll_list[] = {
+ [0] = &clk_vpllsrc.clk,
+ [1] = &clk_fout_vpll,
+};
+
+static struct clksrc_sources clkset_sclk_vpll = {
+ .sources = clkset_sclk_vpll_list,
+ .nr_sources = ARRAY_SIZE(clkset_sclk_vpll_list),
+};
+
+struct clksrc_clk clk_sclk_vpll = {
+ .clk = {
+ .name = "sclk_vpll",
+ },
+ .sources = &clkset_sclk_vpll,
+ .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
+};
+
+static struct clk init_clocks_off[] = {
+ {
+ .name = "timers",
+ .parent = &clk_aclk_100.clk,
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1<<24),
+ }, {
+ .name = "csis",
+ .devname = "s5p-mipi-csis.0",
+ .enable = exynos4_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 4),
+ }, {
+ .name = "csis",
+ .devname = "s5p-mipi-csis.1",
+ .enable = exynos4_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 5),
+ }, {
+ .name = "fimc",
+ .devname = "exynos4-fimc.0",
+ .enable = exynos4_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
+ .name = "fimc",
+ .devname = "exynos4-fimc.1",
+ .enable = exynos4_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 1),
+ }, {
+ .name = "fimc",
+ .devname = "exynos4-fimc.2",
+ .enable = exynos4_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 2),
+ }, {
+ .name = "fimc",
+ .devname = "exynos4-fimc.3",
+ .enable = exynos4_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 3),
+ }, {
+ .name = "fimd",
+ .devname = "exynos4-fb.0",
+ .enable = exynos4_clk_ip_lcd0_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
+ .name = "hsmmc",
+ .devname = "s3c-sdhci.0",
+ .parent = &clk_aclk_133.clk,
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 5),
+ }, {
+ .name = "hsmmc",
+ .devname = "s3c-sdhci.1",
+ .parent = &clk_aclk_133.clk,
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 6),
+ }, {
+ .name = "hsmmc",
+ .devname = "s3c-sdhci.2",
+ .parent = &clk_aclk_133.clk,
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 7),
+ }, {
+ .name = "hsmmc",
+ .devname = "s3c-sdhci.3",
+ .parent = &clk_aclk_133.clk,
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 8),
+ }, {
+ .name = "dwmmc",
+ .parent = &clk_aclk_133.clk,
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 9),
+ }, {
+ .name = "dac",
+ .devname = "s5p-sdo",
+ .enable = exynos4_clk_ip_tv_ctrl,
+ .ctrlbit = (1 << 2),
+ }, {
+ .name = "mixer",
+ .devname = "s5p-mixer",
+ .enable = exynos4_clk_ip_tv_ctrl,
+ .ctrlbit = (1 << 1),
+ }, {
+ .name = "vp",
+ .devname = "s5p-mixer",
+ .enable = exynos4_clk_ip_tv_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
+ .name = "hdmi",
+ .devname = "exynos4-hdmi",
+ .enable = exynos4_clk_ip_tv_ctrl,
+ .ctrlbit = (1 << 3),
+ }, {
+ .name = "hdmiphy",
+ .devname = "exynos4-hdmi",
+ .enable = exynos4_clk_hdmiphy_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
+ .name = "dacphy",
+ .devname = "s5p-sdo",
+ .enable = exynos4_clk_dac_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
+ .name = "dma",
+ .devname = "dma-pl330.0",
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
+ .name = "dma",
+ .devname = "dma-pl330.1",
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 1),
+ }, {
+ .name = "adc",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 15),
+ }, {
+ .name = "keypad",
+ .enable = exynos4_clk_ip_perir_ctrl,
+ .ctrlbit = (1 << 16),
+ }, {
+ .name = "rtc",
+ .enable = exynos4_clk_ip_perir_ctrl,
+ .ctrlbit = (1 << 15),
+ }, {
+ .name = "watchdog",
+ .parent = &clk_aclk_100.clk,
+ .enable = exynos4_clk_ip_perir_ctrl,
+ .ctrlbit = (1 << 14),
+ }, {
+ .name = "usbhost",
+ .enable = exynos4_clk_ip_fsys_ctrl ,
+ .ctrlbit = (1 << 12),
+ }, {
+ .name = "otg",
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 13),
+ }, {
+ .name = "spi",
+ .devname = "s3c64xx-spi.0",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 16),
+ }, {
+ .name = "spi",
+ .devname = "s3c64xx-spi.1",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 17),
+ }, {
+ .name = "spi",
+ .devname = "s3c64xx-spi.2",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 18),
+ }, {
+ .name = "iis",
+ .devname = "samsung-i2s.0",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 19),
+ }, {
+ .name = "iis",
+ .devname = "samsung-i2s.1",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 20),
+ }, {
+ .name = "iis",
+ .devname = "samsung-i2s.2",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 21),
+ }, {
+ .name = "ac97",
+ .devname = "samsung-ac97",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 27),
+ }, {
+ .name = "fimg2d",
+ .enable = exynos4_clk_ip_image_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
+ .name = "mfc",
+ .devname = "s5p-mfc",
+ .enable = exynos4_clk_ip_mfc_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
+ .name = "i2c",
+ .devname = "s3c2440-i2c.0",
+ .parent = &clk_aclk_100.clk,
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 6),
+ }, {
+ .name = "i2c",
+ .devname = "s3c2440-i2c.1",
+ .parent = &clk_aclk_100.clk,
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 7),
+ }, {
+ .name = "i2c",
+ .devname = "s3c2440-i2c.2",
+ .parent = &clk_aclk_100.clk,
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 8),
+ }, {
+ .name = "i2c",
+ .devname = "s3c2440-i2c.3",
+ .parent = &clk_aclk_100.clk,
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 9),
+ }, {
+ .name = "i2c",
+ .devname = "s3c2440-i2c.4",
+ .parent = &clk_aclk_100.clk,
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 10),
+ }, {
+ .name = "i2c",
+ .devname = "s3c2440-i2c.5",
+ .parent = &clk_aclk_100.clk,
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 11),
+ }, {
+ .name = "i2c",
+ .devname = "s3c2440-i2c.6",
+ .parent = &clk_aclk_100.clk,
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 12),
+ }, {
+ .name = "i2c",
+ .devname = "s3c2440-i2c.7",
+ .parent = &clk_aclk_100.clk,
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 13),
+ }, {
+ .name = "i2c",
+ .devname = "s3c2440-hdmiphy-i2c",
+ .parent = &clk_aclk_100.clk,
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 14),
+ }, {
+ .name = "SYSMMU_MDMA",
+ .enable = exynos4_clk_ip_image_ctrl,
+ .ctrlbit = (1 << 5),
+ }, {
+ .name = "SYSMMU_FIMC0",
+ .enable = exynos4_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 7),
+ }, {
+ .name = "SYSMMU_FIMC1",
+ .enable = exynos4_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 8),
+ }, {
+ .name = "SYSMMU_FIMC2",
+ .enable = exynos4_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 9),
+ }, {
+ .name = "SYSMMU_FIMC3",
+ .enable = exynos4_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 10),
+ }, {
+ .name = "SYSMMU_JPEG",
+ .enable = exynos4_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 11),
+ }, {
+ .name = "SYSMMU_FIMD0",
+ .enable = exynos4_clk_ip_lcd0_ctrl,
+ .ctrlbit = (1 << 4),
+ }, {
+ .name = "SYSMMU_FIMD1",
+ .enable = exynos4_clk_ip_lcd1_ctrl,
+ .ctrlbit = (1 << 4),
+ }, {
+ .name = "SYSMMU_PCIe",
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 18),
+ }, {
+ .name = "SYSMMU_G2D",
+ .enable = exynos4_clk_ip_image_ctrl,
+ .ctrlbit = (1 << 3),
+ }, {
+ .name = "SYSMMU_ROTATOR",
+ .enable = exynos4_clk_ip_image_ctrl,
+ .ctrlbit = (1 << 4),
+ }, {
+ .name = "SYSMMU_TV",
+ .enable = exynos4_clk_ip_tv_ctrl,
+ .ctrlbit = (1 << 4),
+ }, {
+ .name = "SYSMMU_MFC_L",
+ .enable = exynos4_clk_ip_mfc_ctrl,
+ .ctrlbit = (1 << 1),
+ }, {
+ .name = "SYSMMU_MFC_R",
+ .enable = exynos4_clk_ip_mfc_ctrl,
+ .ctrlbit = (1 << 2),
+ }
+};
+
+static struct clk init_clocks[] = {
+ {
+ .name = "uart",
+ .devname = "s5pv210-uart.0",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
+ .name = "uart",
+ .devname = "s5pv210-uart.1",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 1),
+ }, {
+ .name = "uart",
+ .devname = "s5pv210-uart.2",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 2),
+ }, {
+ .name = "uart",
+ .devname = "s5pv210-uart.3",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 3),
+ }, {
+ .name = "uart",
+ .devname = "s5pv210-uart.4",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 4),
+ }, {
+ .name = "uart",
+ .devname = "s5pv210-uart.5",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 5),
+ }
+};
+
+struct clk *clkset_group_list[] = {
+ [0] = &clk_ext_xtal_mux,
+ [1] = &clk_xusbxti,
+ [2] = &clk_sclk_hdmi27m,
+ [3] = &clk_sclk_usbphy0,
+ [4] = &clk_sclk_usbphy1,
+ [5] = &clk_sclk_hdmiphy,
+ [6] = &clk_mout_mpll.clk,
+ [7] = &clk_mout_epll.clk,
+ [8] = &clk_sclk_vpll.clk,
+};
+
+struct clksrc_sources clkset_group = {
+ .sources = clkset_group_list,
+ .nr_sources = ARRAY_SIZE(clkset_group_list),
+};
+
+static struct clk *clkset_mout_g2d0_list[] = {
+ [0] = &clk_mout_mpll.clk,
+ [1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_g2d0 = {
+ .sources = clkset_mout_g2d0_list,
+ .nr_sources = ARRAY_SIZE(clkset_mout_g2d0_list),
+};
+
+static struct clksrc_clk clk_mout_g2d0 = {
+ .clk = {
+ .name = "mout_g2d0",
+ },
+ .sources = &clkset_mout_g2d0,
+ .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_mout_g2d1_list[] = {
+ [0] = &clk_mout_epll.clk,
+ [1] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_mout_g2d1 = {
+ .sources = clkset_mout_g2d1_list,
+ .nr_sources = ARRAY_SIZE(clkset_mout_g2d1_list),
+};
+
+static struct clksrc_clk clk_mout_g2d1 = {
+ .clk = {
+ .name = "mout_g2d1",
+ },
+ .sources = &clkset_mout_g2d1,
+ .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 4, .size = 1 },
+};
+
+static struct clk *clkset_mout_g2d_list[] = {
+ [0] = &clk_mout_g2d0.clk,
+ [1] = &clk_mout_g2d1.clk,
+};
+
+static struct clksrc_sources clkset_mout_g2d = {
+ .sources = clkset_mout_g2d_list,
+ .nr_sources = ARRAY_SIZE(clkset_mout_g2d_list),
+};
+
+static struct clk *clkset_mout_mfc0_list[] = {
+ [0] = &clk_mout_mpll.clk,
+ [1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc0 = {
+ .sources = clkset_mout_mfc0_list,
+ .nr_sources = ARRAY_SIZE(clkset_mout_mfc0_list),
+};
+
+static struct clksrc_clk clk_mout_mfc0 = {
+ .clk = {
+ .name = "mout_mfc0",
+ },
+ .sources = &clkset_mout_mfc0,
+ .reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_mout_mfc1_list[] = {
+ [0] = &clk_mout_epll.clk,
+ [1] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc1 = {
+ .sources = clkset_mout_mfc1_list,
+ .nr_sources = ARRAY_SIZE(clkset_mout_mfc1_list),
+};
+
+static struct clksrc_clk clk_mout_mfc1 = {
+ .clk = {
+ .name = "mout_mfc1",
+ },
+ .sources = &clkset_mout_mfc1,
+ .reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 4, .size = 1 },
+};
+
+static struct clk *clkset_mout_mfc_list[] = {
+ [0] = &clk_mout_mfc0.clk,
+ [1] = &clk_mout_mfc1.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc = {
+ .sources = clkset_mout_mfc_list,
+ .nr_sources = ARRAY_SIZE(clkset_mout_mfc_list),
+};
+
+static struct clk *clkset_sclk_dac_list[] = {
+ [0] = &clk_sclk_vpll.clk,
+ [1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_dac = {
+ .sources = clkset_sclk_dac_list,
+ .nr_sources = ARRAY_SIZE(clkset_sclk_dac_list),
+};
+
+static struct clksrc_clk clk_sclk_dac = {
+ .clk = {
+ .name = "sclk_dac",
+ .enable = exynos4_clksrc_mask_tv_ctrl,
+ .ctrlbit = (1 << 8),
+ },
+ .sources = &clkset_sclk_dac,
+ .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 8, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_pixel = {
+ .clk = {
+ .name = "sclk_pixel",
+ .parent = &clk_sclk_vpll.clk,
+ },
+ .reg_div = { .reg = S5P_CLKDIV_TV, .shift = 0, .size = 4 },
+};
+
+static struct clk *clkset_sclk_hdmi_list[] = {
+ [0] = &clk_sclk_pixel.clk,
+ [1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_hdmi = {
+ .sources = clkset_sclk_hdmi_list,
+ .nr_sources = ARRAY_SIZE(clkset_sclk_hdmi_list),
+};
+
+static struct clksrc_clk clk_sclk_hdmi = {
+ .clk = {
+ .name = "sclk_hdmi",
+ .enable = exynos4_clksrc_mask_tv_ctrl,
+ .ctrlbit = (1 << 0),
+ },
+ .sources = &clkset_sclk_hdmi,
+ .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_mixer_list[] = {
+ [0] = &clk_sclk_dac.clk,
+ [1] = &clk_sclk_hdmi.clk,
+};
+
+static struct clksrc_sources clkset_sclk_mixer = {
+ .sources = clkset_sclk_mixer_list,
+ .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list),
+};
+
+static struct clksrc_clk clk_sclk_mixer = {
+ .clk = {
+ .name = "sclk_mixer",
+ .enable = exynos4_clksrc_mask_tv_ctrl,
+ .ctrlbit = (1 << 4),
+ },
+ .sources = &clkset_sclk_mixer,
+ .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk *sclk_tv[] = {
+ &clk_sclk_dac,
+ &clk_sclk_pixel,
+ &clk_sclk_hdmi,
+ &clk_sclk_mixer,
+};
+
+static struct clksrc_clk clk_dout_mmc0 = {
+ .clk = {
+ .name = "dout_mmc0",
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 0, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc1 = {
+ .clk = {
+ .name = "dout_mmc1",
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 4, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc2 = {
+ .clk = {
+ .name = "dout_mmc2",
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 8, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc3 = {
+ .clk = {
+ .name = "dout_mmc3",
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 12, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc4 = {
+ .clk = {
+ .name = "dout_mmc4",
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 16, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clksrcs[] = {
+ {
+ .clk = {
+ .name = "uclk1",
+ .devname = "s5pv210-uart.0",
+ .enable = exynos4_clksrc_mask_peril0_ctrl,
+ .ctrlbit = (1 << 0),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "uclk1",
+ .devname = "s5pv210-uart.1",
+ .enable = exynos4_clksrc_mask_peril0_ctrl,
+ .ctrlbit = (1 << 4),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
+ }, {
+ .clk = {
+ .name = "uclk1",
+ .devname = "s5pv210-uart.2",
+ .enable = exynos4_clksrc_mask_peril0_ctrl,
+ .ctrlbit = (1 << 8),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
+ }, {
+ .clk = {
+ .name = "uclk1",
+ .devname = "s5pv210-uart.3",
+ .enable = exynos4_clksrc_mask_peril0_ctrl,
+ .ctrlbit = (1 << 12),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_pwm",
+ .enable = exynos4_clksrc_mask_peril0_ctrl,
+ .ctrlbit = (1 << 24),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_csis",
+ .devname = "s5p-mipi-csis.0",
+ .enable = exynos4_clksrc_mask_cam_ctrl,
+ .ctrlbit = (1 << 24),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 24, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 24, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_csis",
+ .devname = "s5p-mipi-csis.1",
+ .enable = exynos4_clksrc_mask_cam_ctrl,
+ .ctrlbit = (1 << 28),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 28, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 28, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_cam0",
+ .enable = exynos4_clksrc_mask_cam_ctrl,
+ .ctrlbit = (1 << 16),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 16, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 16, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_cam1",
+ .enable = exynos4_clksrc_mask_cam_ctrl,
+ .ctrlbit = (1 << 20),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 20, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 20, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_fimc",
+ .devname = "exynos4-fimc.0",
+ .enable = exynos4_clksrc_mask_cam_ctrl,
+ .ctrlbit = (1 << 0),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 0, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_fimc",
+ .devname = "exynos4-fimc.1",
+ .enable = exynos4_clksrc_mask_cam_ctrl,
+ .ctrlbit = (1 << 4),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 4, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 4, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_fimc",
+ .devname = "exynos4-fimc.2",
+ .enable = exynos4_clksrc_mask_cam_ctrl,
+ .ctrlbit = (1 << 8),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 8, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 8, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_fimc",
+ .devname = "exynos4-fimc.3",
+ .enable = exynos4_clksrc_mask_cam_ctrl,
+ .ctrlbit = (1 << 12),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 12, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 12, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_fimd",
+ .devname = "exynos4-fb.0",
+ .enable = exynos4_clksrc_mask_lcd0_ctrl,
+ .ctrlbit = (1 << 0),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_LCD0, .shift = 0, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_spi",
+ .devname = "s3c64xx-spi.0",
+ .enable = exynos4_clksrc_mask_peril1_ctrl,
+ .ctrlbit = (1 << 16),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_spi",
+ .devname = "s3c64xx-spi.1",
+ .enable = exynos4_clksrc_mask_peril1_ctrl,
+ .ctrlbit = (1 << 20),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_spi",
+ .devname = "s3c64xx-spi.2",
+ .enable = exynos4_clksrc_mask_peril1_ctrl,
+ .ctrlbit = (1 << 24),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_fimg2d",
+ },
+ .sources = &clkset_mout_g2d,
+ .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 },
+ .reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_mfc",
+ .devname = "s5p-mfc",
+ },
+ .sources = &clkset_mout_mfc,
+ .reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 8, .size = 1 },
+ .reg_div = { .reg = S5P_CLKDIV_MFC, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_mmc",
+ .devname = "s3c-sdhci.0",
+ .parent = &clk_dout_mmc0.clk,
+ .enable = exynos4_clksrc_mask_fsys_ctrl,
+ .ctrlbit = (1 << 0),
+ },
+ .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 },
+ }, {
+ .clk = {
+ .name = "sclk_mmc",
+ .devname = "s3c-sdhci.1",
+ .parent = &clk_dout_mmc1.clk,
+ .enable = exynos4_clksrc_mask_fsys_ctrl,
+ .ctrlbit = (1 << 4),
+ },
+ .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 },
+ }, {
+ .clk = {
+ .name = "sclk_mmc",
+ .devname = "s3c-sdhci.2",
+ .parent = &clk_dout_mmc2.clk,
+ .enable = exynos4_clksrc_mask_fsys_ctrl,
+ .ctrlbit = (1 << 8),
+ },
+ .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 },
+ }, {
+ .clk = {
+ .name = "sclk_mmc",
+ .devname = "s3c-sdhci.3",
+ .parent = &clk_dout_mmc3.clk,
+ .enable = exynos4_clksrc_mask_fsys_ctrl,
+ .ctrlbit = (1 << 12),
+ },
+ .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
+ }, {
+ .clk = {
+ .name = "sclk_dwmmc",
+ .parent = &clk_dout_mmc4.clk,
+ .enable = exynos4_clksrc_mask_fsys_ctrl,
+ .ctrlbit = (1 << 16),
+ },
+ .reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 8, .size = 8 },
+ }
+};
+
+/* Clock initialization code */
+static struct clksrc_clk *sysclks[] = {
+ &clk_mout_apll,
+ &clk_sclk_apll,
+ &clk_mout_epll,
+ &clk_mout_mpll,
+ &clk_moutcore,
+ &clk_coreclk,
+ &clk_armclk,
+ &clk_aclk_corem0,
+ &clk_aclk_cores,
+ &clk_aclk_corem1,
+ &clk_periphclk,
+ &clk_mout_corebus,
+ &clk_sclk_dmc,
+ &clk_aclk_cored,
+ &clk_aclk_corep,
+ &clk_aclk_acp,
+ &clk_pclk_acp,
+ &clk_vpllsrc,
+ &clk_sclk_vpll,
+ &clk_aclk_200,
+ &clk_aclk_100,
+ &clk_aclk_160,
+ &clk_aclk_133,
+ &clk_dout_mmc0,
+ &clk_dout_mmc1,
+ &clk_dout_mmc2,
+ &clk_dout_mmc3,
+ &clk_dout_mmc4,
+ &clk_mout_mfc0,
+ &clk_mout_mfc1,
+};
+
+static int xtal_rate;
+
+static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
+{
+ if (soc_is_exynos4210())
+ return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0),
+ pll_4508);
+ else if (soc_is_exynos4212() || soc_is_exynos4412())
+ return s5p_get_pll35xx(xtal_rate, __raw_readl(S5P_APLL_CON0));
+ else
+ return 0;
+}
+
+static struct clk_ops exynos4_fout_apll_ops = {
+ .get_rate = exynos4_fout_apll_get_rate,
+};
+
+static u32 vpll_div[][8] = {
+ { 54000000, 3, 53, 3, 1024, 0, 17, 0 },
+ { 108000000, 3, 53, 2, 1024, 0, 17, 0 },
+};
+
+static unsigned long exynos4_vpll_get_rate(struct clk *clk)
+{
+ return clk->rate;
+}
+
+static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int vpll_con0, vpll_con1 = 0;
+ unsigned int i;
+
+ /* Return if nothing changed */
+ if (clk->rate == rate)
+ return 0;
+
+ vpll_con0 = __raw_readl(S5P_VPLL_CON0);
+ vpll_con0 &= ~(0x1 << 27 | \
+ PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \
+ PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
+ PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+ vpll_con1 = __raw_readl(S5P_VPLL_CON1);
+ vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT | \
+ PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT | \
+ PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
+
+ for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
+ if (vpll_div[i][0] == rate) {
+ vpll_con0 |= vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
+ vpll_con0 |= vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
+ vpll_con0 |= vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
+ vpll_con1 |= vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
+ vpll_con1 |= vpll_div[i][5] << PLL46XX_MFR_SHIFT;
+ vpll_con1 |= vpll_div[i][6] << PLL46XX_MRR_SHIFT;
+ vpll_con0 |= vpll_div[i][7] << 27;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(vpll_div)) {
+ printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ __raw_writel(vpll_con0, S5P_VPLL_CON0);
+ __raw_writel(vpll_con1, S5P_VPLL_CON1);
+
+ /* Wait for VPLL lock */
+ while (!(__raw_readl(S5P_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
+ continue;
+
+ clk->rate = rate;
+ return 0;
+}
+
+static struct clk_ops exynos4_vpll_ops = {
+ .get_rate = exynos4_vpll_get_rate,
+ .set_rate = exynos4_vpll_set_rate,
+};
+
+void __init_or_cpufreq exynos4_setup_clocks(void)
+{
+ struct clk *xtal_clk;
+ unsigned long apll = 0;
+ unsigned long mpll = 0;
+ unsigned long epll = 0;
+ unsigned long vpll = 0;
+ unsigned long vpllsrc;
+ unsigned long xtal;
+ unsigned long armclk;
+ unsigned long sclk_dmc;
+ unsigned long aclk_200;
+ unsigned long aclk_100;
+ unsigned long aclk_160;
+ unsigned long aclk_133;
+ unsigned int ptr;
+
+ printk(KERN_DEBUG "%s: registering clocks\n", __func__);
+
+ xtal_clk = clk_get(NULL, "xtal");
+ BUG_ON(IS_ERR(xtal_clk));
+
+ xtal = clk_get_rate(xtal_clk);
+
+ xtal_rate = xtal;
+
+ clk_put(xtal_clk);
+
+ printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
+
+ if (soc_is_exynos4210()) {
+ apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0),
+ pll_4508);
+ mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0),
+ pll_4508);
+ epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
+ __raw_readl(S5P_EPLL_CON1), pll_4600);
+
+ vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+ vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
+ __raw_readl(S5P_VPLL_CON1), pll_4650c);
+ } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
+ apll = s5p_get_pll35xx(xtal, __raw_readl(S5P_APLL_CON0));
+ mpll = s5p_get_pll35xx(xtal, __raw_readl(S5P_MPLL_CON0));
+ epll = s5p_get_pll36xx(xtal, __raw_readl(S5P_EPLL_CON0),
+ __raw_readl(S5P_EPLL_CON1));
+
+ vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+ vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
+ __raw_readl(S5P_VPLL_CON1));
+ } else {
+ /* nothing */
+ }
+
+ clk_fout_apll.ops = &exynos4_fout_apll_ops;
+ clk_fout_mpll.rate = mpll;
+ clk_fout_epll.rate = epll;
+ clk_fout_vpll.ops = &exynos4_vpll_ops;
+ clk_fout_vpll.rate = vpll;
+
+ printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
+ apll, mpll, epll, vpll);
+
+ armclk = clk_get_rate(&clk_armclk.clk);
+ sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk);
+
+ aclk_200 = clk_get_rate(&clk_aclk_200.clk);
+ aclk_100 = clk_get_rate(&clk_aclk_100.clk);
+ aclk_160 = clk_get_rate(&clk_aclk_160.clk);
+ aclk_133 = clk_get_rate(&clk_aclk_133.clk);
+
+ printk(KERN_INFO "EXYNOS4: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n"
+ "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n",
+ armclk, sclk_dmc, aclk_200,
+ aclk_100, aclk_160, aclk_133);
+
+ clk_f.rate = armclk;
+ clk_h.rate = sclk_dmc;
+ clk_p.rate = aclk_100;
+
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+ s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+static struct clk *clks[] __initdata = {
+ &clk_sclk_hdmi27m,
+ &clk_sclk_hdmiphy,
+ &clk_sclk_usbphy0,
+ &clk_sclk_usbphy1,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos4_clock_suspend(void)
+{
+ s3c_pm_do_save(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
+ return 0;
+}
+
+static void exynos4_clock_resume(void)
+{
+ s3c_pm_do_restore_core(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
+}
+
+#else
+#define exynos4_clock_suspend NULL
+#define exynos4_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4_clock_syscore_ops = {
+ .suspend = exynos4_clock_suspend,
+ .resume = exynos4_clock_resume,
+};
+
+void __init exynos4_register_clocks(void)
+{
+ int ptr;
+
+ s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+
+ for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+ s3c_register_clksrc(sysclks[ptr], 1);
+
+ for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
+ s3c_register_clksrc(sclk_tv[ptr], 1);
+
+ s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+ s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+ s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+ s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+
+ register_syscore_ops(&exynos4_clock_syscore_ops);
+ s3c24xx_register_clock(&dummy_apb_pclk);
+
+ s3c_pwmclk_init();
+}
diff --git a/arch/arm/mach-exynos/cpu.c b/arch/arm/mach-exynos/cpu.c
new file mode 100644
index 0000000..cc8d4bd
--- /dev/null
+++ b/arch/arm/mach-exynos/cpu.c
@@ -0,0 +1,293 @@
+/* linux/arch/arm/mach-exynos/cpu.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/sched.h>
+#include <linux/sysdev.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/proc-fns.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
+
+#include <plat/cpu.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/exynos4.h>
+#include <plat/adc-core.h>
+#include <plat/sdhci.h>
+#include <plat/fb-core.h>
+#include <plat/fimc-core.h>
+#include <plat/iic-core.h>
+#include <plat/reset.h>
+#include <plat/tv-core.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-pmu.h>
+
+unsigned int gic_bank_offset __read_mostly;
+
+extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
+ unsigned int irq_start);
+extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
+
+/* Initial IO mappings */
+static struct map_desc exynos_iodesc[] __initdata = {
+ {
+ .virtual = (unsigned long)S5P_VA_SYSTIMER,
+ .pfn = __phys_to_pfn(EXYNOS_PA_SYSTIMER),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_PMU,
+ .pfn = __phys_to_pfn(EXYNOS_PA_PMU),
+ .length = SZ_64K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_COMBINER_BASE,
+ .pfn = __phys_to_pfn(EXYNOS_PA_COMBINER),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_GIC_CPU,
+ .pfn = __phys_to_pfn(EXYNOS_PA_GIC_CPU),
+ .length = SZ_64K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_GIC_DIST,
+ .pfn = __phys_to_pfn(EXYNOS_PA_GIC_DIST),
+ .length = SZ_64K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S3C_VA_UART,
+ .pfn = __phys_to_pfn(S3C_PA_UART),
+ .length = SZ_512K,
+ .type = MT_DEVICE,
+ },
+};
+
+static struct map_desc exynos4_iodesc[] __initdata = {
+ {
+ .virtual = (unsigned long)S5P_VA_CMU,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
+ .length = SZ_128K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
+ .length = SZ_8K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_L2CC,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_L2CC),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_GPIO1,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_GPIO1),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_GPIO2,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_GPIO2),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_GPIO3,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_GPIO3),
+ .length = SZ_256,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_DMC0,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S3C_VA_USB_HSPHY,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
+static struct map_desc exynos4_iodesc0[] __initdata = {
+ {
+ .virtual = (unsigned long)S5P_VA_SYSRAM,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
+static struct map_desc exynos4_iodesc1[] __initdata = {
+ {
+ .virtual = (unsigned long)S5P_VA_SYSRAM,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
+static void exynos_idle(void)
+{
+ if (!need_resched())
+ cpu_do_idle();
+
+ local_irq_enable();
+}
+
+static void exynos4_sw_reset(void)
+{
+ __raw_writel(0x1, S5P_SWRESET);
+}
+
+/*
+ * exynos_map_io
+ *
+ * register the standard cpu IO areas
+ */
+void __init exynos4_map_io(void)
+{
+ iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc));
+ iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
+
+ if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0)
+ iotable_init(exynos4_iodesc0, ARRAY_SIZE(exynos4_iodesc0));
+ else
+ iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1));
+
+ /* initialize device information early */
+ exynos4_default_sdhci0();
+ exynos4_default_sdhci1();
+ exynos4_default_sdhci2();
+ exynos4_default_sdhci3();
+
+ s3c_adc_setname("samsung-adc-v3");
+
+ s3c_fimc_setname(0, "exynos4-fimc");
+ s3c_fimc_setname(1, "exynos4-fimc");
+ s3c_fimc_setname(2, "exynos4-fimc");
+ s3c_fimc_setname(3, "exynos4-fimc");
+
+ /* The I2C bus controllers are directly compatible with s3c2440 */
+ s3c_i2c0_setname("s3c2440-i2c");
+ s3c_i2c1_setname("s3c2440-i2c");
+ s3c_i2c2_setname("s3c2440-i2c");
+
+ s5p_fb_setname(0, "exynos4-fb");
+ s5p_hdmi_setname("exynos4-hdmi");
+}
+
+void __init exynos4_init_clocks(int xtal)
+{
+ printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+ s3c24xx_register_baseclocks(xtal);
+ s5p_register_clocks(xtal);
+
+ if (soc_is_exynos4210())
+ exynos4210_register_clocks();
+ else if (soc_is_exynos4212() || soc_is_exynos4412())
+ exynos4212_register_clocks();
+
+ exynos4_register_clocks();
+ exynos4_setup_clocks();
+}
+
+static void exynos4_gic_irq_fix_base(struct irq_data *d)
+{
+ struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+ gic_data->cpu_base = S5P_VA_GIC_CPU +
+ (gic_bank_offset * smp_processor_id());
+
+ gic_data->dist_base = S5P_VA_GIC_DIST +
+ (gic_bank_offset * smp_processor_id());
+}
+
+void __init exynos4_init_irq(void)
+{
+ int irq;
+
+ gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
+
+ gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+ gic_arch_extn.irq_eoi = exynos4_gic_irq_fix_base;
+ gic_arch_extn.irq_unmask = exynos4_gic_irq_fix_base;
+ gic_arch_extn.irq_mask = exynos4_gic_irq_fix_base;
+
+ for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
+
+ combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
+ COMBINER_IRQ(irq, 0));
+ combiner_cascade_irq(irq, IRQ_SPI(irq));
+ }
+
+ /* The parameters of s5p_init_irq() are for VIC init.
+ * Theses parameters should be NULL and 0 because EXYNOS4
+ * uses GIC instead of VIC.
+ */
+ s5p_init_irq(NULL, 0);
+}
+
+struct sysdev_class exynos4_sysclass = {
+ .name = "exynos4-core",
+};
+
+static struct sys_device exynos4_sysdev = {
+ .cls = &exynos4_sysclass,
+};
+
+static int __init exynos4_core_init(void)
+{
+ return sysdev_class_register(&exynos4_sysclass);
+}
+core_initcall(exynos4_core_init);
+
+#ifdef CONFIG_CACHE_L2X0
+static int __init exynos4_l2x0_cache_init(void)
+{
+ /* TAG, Data Latency Control: 2cycle */
+ __raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
+
+ if (soc_is_exynos4210())
+ __raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
+ else if (soc_is_exynos4212() || soc_is_exynos4412())
+ __raw_writel(0x120, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
+
+ /* L2X0 Prefetch Control */
+ __raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
+
+ /* L2X0 Power Control */
+ __raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
+ S5P_VA_L2CC + L2X0_POWER_CTRL);
+
+ l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
+
+ return 0;
+}
+
+early_initcall(exynos4_l2x0_cache_init);
+#endif
+
+int __init exynos_init(void)
+{
+ printk(KERN_INFO "EXYNOS: Initializing architecture\n");
+
+ /* set idle function */
+ pm_idle = exynos_idle;
+
+ /* set sw_reset function */
+ if (soc_is_exynos4210() || soc_is_exynos4212() || soc_is_exynos4412())
+ s5p_reset_hook = exynos4_sw_reset;
+
+ return sysdev_register(&exynos4_sysdev);
+}
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
new file mode 100644
index 0000000..4ebb382
--- /dev/null
+++ b/arch/arm/mach-exynos/cpuidle.c
@@ -0,0 +1,92 @@
+/* linux/arch/arm/mach-exynos4/cpuidle.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cpuidle.h>
+#include <linux/io.h>
+#include <linux/export.h>
+#include <linux/time.h>
+
+#include <asm/proc-fns.h>
+
+static int exynos4_enter_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index);
+
+static struct cpuidle_state exynos4_cpuidle_set[] = {
+ [0] = {
+ .enter = exynos4_enter_idle,
+ .exit_latency = 1,
+ .target_residency = 100000,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "IDLE",
+ .desc = "ARM clock gating(WFI)",
+ },
+};
+
+static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
+
+static struct cpuidle_driver exynos4_idle_driver = {
+ .name = "exynos4_idle",
+ .owner = THIS_MODULE,
+};
+
+static int exynos4_enter_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index)
+{
+ struct timeval before, after;
+ int idle_time;
+
+ local_irq_disable();
+ do_gettimeofday(&before);
+
+ cpu_do_idle();
+
+ do_gettimeofday(&after);
+ local_irq_enable();
+ idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+ (after.tv_usec - before.tv_usec);
+
+ dev->last_residency = idle_time;
+ return index;
+}
+
+static int __init exynos4_init_cpuidle(void)
+{
+ int i, max_cpuidle_state, cpu_id;
+ struct cpuidle_device *device;
+ struct cpuidle_driver *drv = &exynos4_idle_driver;
+
+ /* Setup cpuidle driver */
+ drv->state_count = (sizeof(exynos4_cpuidle_set) /
+ sizeof(struct cpuidle_state));
+ max_cpuidle_state = drv->state_count;
+ for (i = 0; i < max_cpuidle_state; i++) {
+ memcpy(&drv->states[i], &exynos4_cpuidle_set[i],
+ sizeof(struct cpuidle_state));
+ }
+ cpuidle_register_driver(&exynos4_idle_driver);
+
+ for_each_cpu(cpu_id, cpu_online_mask) {
+ device = &per_cpu(exynos4_cpuidle_device, cpu_id);
+ device->cpu = cpu_id;
+
+ device->state_count = drv->state_count;
+
+ if (cpuidle_register_device(device)) {
+ printk(KERN_ERR "CPUidle register device failed\n,");
+ return -EIO;
+ }
+ }
+ return 0;
+}
+device_initcall(exynos4_init_cpuidle);
diff --git a/arch/arm/mach-exynos/include/mach/exynos4-clock.h b/arch/arm/mach-exynos/include/mach/exynos4-clock.h
new file mode 100644
index 0000000..a07fcbf
--- /dev/null
+++ b/arch/arm/mach-exynos/include/mach/exynos4-clock.h
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/arm/mach-exynos4/include/mach/exynos4-clock.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Header file for exynos4 clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_CLOCK_H
+#define __ASM_ARCH_CLOCK_H __FILE__
+
+#include <linux/clk.h>
+
+extern struct clk clk_sclk_hdmi27m;
+extern struct clk clk_sclk_usbphy0;
+extern struct clk clk_sclk_usbphy1;
+extern struct clk clk_sclk_hdmiphy;
+
+extern struct clksrc_clk clk_sclk_apll;
+extern struct clksrc_clk clk_mout_mpll;
+extern struct clksrc_clk clk_aclk_133;
+extern struct clksrc_clk clk_mout_epll;
+extern struct clksrc_clk clk_sclk_vpll;
+
+extern struct clk *clkset_corebus_list[];
+extern struct clksrc_sources clkset_mout_corebus;
+
+extern struct clk *clkset_aclk_top_list[];
+extern struct clksrc_sources clkset_aclk;
+
+extern struct clk *clkset_group_list[];
+extern struct clksrc_sources clkset_group;
+
+extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable);
+extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable);
+extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable);
+
+#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
new file mode 100644
index 0000000..f80b563
--- /dev/null
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -0,0 +1,700 @@
+/* linux/arch/arm/mach-exynos4/mach-origen.c
+ *
+ * Copyright (c) 2011 Insignal Co., Ltd.
+ * http://www.insignal.co.kr/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/serial_core.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/input.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/max8997.h>
+#include <linux/lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <video/platform_lcd.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/sdhci.h>
+#include <plat/iic.h>
+#include <plat/ehci.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <plat/backlight.h>
+#include <plat/pd.h>
+#include <plat/fb.h>
+#include <plat/mfc.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define ORIGEN_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
+ S3C2410_UCON_RXILEVEL | \
+ S3C2410_UCON_TXIRQMODE | \
+ S3C2410_UCON_RXIRQMODE | \
+ S3C2410_UCON_RXFIFO_TOI | \
+ S3C2443_UCON_RXERR_IRQEN)
+
+#define ORIGEN_ULCON_DEFAULT S3C2410_LCON_CS8
+
+#define ORIGEN_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
+ S5PV210_UFCON_TXTRIG4 | \
+ S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = ORIGEN_UCON_DEFAULT,
+ .ulcon = ORIGEN_ULCON_DEFAULT,
+ .ufcon = ORIGEN_UFCON_DEFAULT,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = ORIGEN_UCON_DEFAULT,
+ .ulcon = ORIGEN_ULCON_DEFAULT,
+ .ufcon = ORIGEN_UFCON_DEFAULT,
+ },
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = ORIGEN_UCON_DEFAULT,
+ .ulcon = ORIGEN_ULCON_DEFAULT,
+ .ufcon = ORIGEN_UFCON_DEFAULT,
+ },
+ [3] = {
+ .hwport = 3,
+ .flags = 0,
+ .ucon = ORIGEN_UCON_DEFAULT,
+ .ulcon = ORIGEN_ULCON_DEFAULT,
+ .ufcon = ORIGEN_UFCON_DEFAULT,
+ },
+};
+
+static struct regulator_consumer_supply __initdata ldo3_consumer[] = {
+ REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+ REGULATOR_SUPPLY("vdd", "exynos4-hdmi"), /* HDMI */
+ REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"), /* HDMI */
+};
+static struct regulator_consumer_supply __initdata ldo6_consumer[] = {
+ REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata ldo7_consumer[] = {
+ REGULATOR_SUPPLY("avdd", "alc5625"), /* Realtek ALC5625 */
+};
+static struct regulator_consumer_supply __initdata ldo8_consumer[] = {
+ REGULATOR_SUPPLY("vdd", "s5p-adc"), /* ADC */
+ REGULATOR_SUPPLY("vdd_osc", "exynos4-hdmi"), /* HDMI */
+};
+static struct regulator_consumer_supply __initdata ldo9_consumer[] = {
+ REGULATOR_SUPPLY("dvdd", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata ldo11_consumer[] = {
+ REGULATOR_SUPPLY("dvdd", "alc5625"), /* Realtek ALC5625 */
+};
+static struct regulator_consumer_supply __initdata ldo14_consumer[] = {
+ REGULATOR_SUPPLY("avdd18", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata ldo17_consumer[] = {
+ REGULATOR_SUPPLY("vdd33", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata buck1_consumer[] = {
+ REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata buck2_consumer[] = {
+ REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata buck3_consumer[] = {
+ REGULATOR_SUPPLY("vdd_g3d", "mali_drm"), /* G3D */
+};
+static struct regulator_consumer_supply __initdata buck7_consumer[] = {
+ REGULATOR_SUPPLY("vcc", "platform-lcd"), /* LCD */
+};
+
+static struct regulator_init_data __initdata max8997_ldo1_data = {
+ .constraints = {
+ .name = "VDD_ABB_3.3V",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_ldo2_data = {
+ .constraints = {
+ .name = "VDD_ALIVE_1.1V",
+ .min_uV = 1100000,
+ .max_uV = 1100000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .enabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_ldo3_data = {
+ .constraints = {
+ .name = "VMIPI_1.1V",
+ .min_uV = 1100000,
+ .max_uV = 1100000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo3_consumer),
+ .consumer_supplies = ldo3_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo4_data = {
+ .constraints = {
+ .name = "VDD_RTC_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_ldo6_data = {
+ .constraints = {
+ .name = "VMIPI_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo6_consumer),
+ .consumer_supplies = ldo6_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo7_data = {
+ .constraints = {
+ .name = "VDD_AUD_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo7_consumer),
+ .consumer_supplies = ldo7_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo8_data = {
+ .constraints = {
+ .name = "VADC_3.3V",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo8_consumer),
+ .consumer_supplies = ldo8_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo9_data = {
+ .constraints = {
+ .name = "DVDD_SWB_2.8V",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo9_consumer),
+ .consumer_supplies = ldo9_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo10_data = {
+ .constraints = {
+ .name = "VDD_PLL_1.1V",
+ .min_uV = 1100000,
+ .max_uV = 1100000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_ldo11_data = {
+ .constraints = {
+ .name = "VDD_AUD_3V",
+ .min_uV = 3000000,
+ .max_uV = 3000000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo11_consumer),
+ .consumer_supplies = ldo11_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo14_data = {
+ .constraints = {
+ .name = "AVDD18_SWB_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo14_consumer),
+ .consumer_supplies = ldo14_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo17_data = {
+ .constraints = {
+ .name = "VDD_SWB_3.3V",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo17_consumer),
+ .consumer_supplies = ldo17_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo21_data = {
+ .constraints = {
+ .name = "VDD_MIF_1.2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_buck1_data = {
+ .constraints = {
+ .name = "VDD_ARM_1.2V",
+ .min_uV = 950000,
+ .max_uV = 1350000,
+ .always_on = 1,
+ .boot_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(buck1_consumer),
+ .consumer_supplies = buck1_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck2_data = {
+ .constraints = {
+ .name = "VDD_INT_1.1V",
+ .min_uV = 900000,
+ .max_uV = 1100000,
+ .always_on = 1,
+ .boot_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(buck2_consumer),
+ .consumer_supplies = buck2_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck3_data = {
+ .constraints = {
+ .name = "VDD_G3D_1.1V",
+ .min_uV = 900000,
+ .max_uV = 1100000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(buck3_consumer),
+ .consumer_supplies = buck3_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck5_data = {
+ .constraints = {
+ .name = "VDDQ_M1M2_1.2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_buck7_data = {
+ .constraints = {
+ .name = "VDD_LCD_3.3V",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .boot_on = 1,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(buck7_consumer),
+ .consumer_supplies = buck7_consumer,
+};
+
+static struct max8997_regulator_data __initdata origen_max8997_regulators[] = {
+ { MAX8997_LDO1, &max8997_ldo1_data },
+ { MAX8997_LDO2, &max8997_ldo2_data },
+ { MAX8997_LDO3, &max8997_ldo3_data },
+ { MAX8997_LDO4, &max8997_ldo4_data },
+ { MAX8997_LDO6, &max8997_ldo6_data },
+ { MAX8997_LDO7, &max8997_ldo7_data },
+ { MAX8997_LDO8, &max8997_ldo8_data },
+ { MAX8997_LDO9, &max8997_ldo9_data },
+ { MAX8997_LDO10, &max8997_ldo10_data },
+ { MAX8997_LDO11, &max8997_ldo11_data },
+ { MAX8997_LDO14, &max8997_ldo14_data },
+ { MAX8997_LDO17, &max8997_ldo17_data },
+ { MAX8997_LDO21, &max8997_ldo21_data },
+ { MAX8997_BUCK1, &max8997_buck1_data },
+ { MAX8997_BUCK2, &max8997_buck2_data },
+ { MAX8997_BUCK3, &max8997_buck3_data },
+ { MAX8997_BUCK5, &max8997_buck5_data },
+ { MAX8997_BUCK7, &max8997_buck7_data },
+};
+
+struct max8997_platform_data __initdata origen_max8997_pdata = {
+ .num_regulators = ARRAY_SIZE(origen_max8997_regulators),
+ .regulators = origen_max8997_regulators,
+
+ .wakeup = true,
+ .buck1_gpiodvs = false,
+ .buck2_gpiodvs = false,
+ .buck5_gpiodvs = false,
+ .irq_base = IRQ_GPIO_END + 1,
+
+ .ignore_gpiodvs_side_effect = true,
+ .buck125_default_idx = 0x0,
+
+ .buck125_gpios[0] = EXYNOS4_GPX0(0),
+ .buck125_gpios[1] = EXYNOS4_GPX0(1),
+ .buck125_gpios[2] = EXYNOS4_GPX0(2),
+
+ .buck1_voltage[0] = 1350000,
+ .buck1_voltage[1] = 1300000,
+ .buck1_voltage[2] = 1250000,
+ .buck1_voltage[3] = 1200000,
+ .buck1_voltage[4] = 1150000,
+ .buck1_voltage[5] = 1100000,
+ .buck1_voltage[6] = 1000000,
+ .buck1_voltage[7] = 950000,
+
+ .buck2_voltage[0] = 1100000,
+ .buck2_voltage[1] = 1100000,
+ .buck2_voltage[2] = 1100000,
+ .buck2_voltage[3] = 1100000,
+ .buck2_voltage[4] = 1000000,
+ .buck2_voltage[5] = 1000000,
+ .buck2_voltage[6] = 1000000,
+ .buck2_voltage[7] = 1000000,
+
+ .buck5_voltage[0] = 1200000,
+ .buck5_voltage[1] = 1200000,
+ .buck5_voltage[2] = 1200000,
+ .buck5_voltage[3] = 1200000,
+ .buck5_voltage[4] = 1200000,
+ .buck5_voltage[5] = 1200000,
+ .buck5_voltage[6] = 1200000,
+ .buck5_voltage[7] = 1200000,
+};
+
+/* I2C0 */
+static struct i2c_board_info i2c0_devs[] __initdata = {
+ {
+ I2C_BOARD_INFO("max8997", (0xCC >> 1)),
+ .platform_data = &origen_max8997_pdata,
+ .irq = IRQ_EINT(4),
+ },
+};
+
+static struct s3c_sdhci_platdata origen_hsmmc0_pdata __initdata = {
+ .cd_type = S3C_SDHCI_CD_INTERNAL,
+ .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
+ .cd_type = S3C_SDHCI_CD_INTERNAL,
+ .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+/* USB EHCI */
+static struct s5p_ehci_platdata origen_ehci_pdata;
+
+static void __init origen_ehci_init(void)
+{
+ struct s5p_ehci_platdata *pdata = &origen_ehci_pdata;
+
+ s5p_ehci_set_platdata(pdata);
+}
+
+static struct gpio_keys_button origen_gpio_keys_table[] = {
+ {
+ .code = KEY_MENU,
+ .gpio = EXYNOS4_GPX1(5),
+ .desc = "gpio-keys: KEY_MENU",
+ .type = EV_KEY,
+ .active_low = 1,
+ .wakeup = 1,
+ .debounce_interval = 1,
+ }, {
+ .code = KEY_HOME,
+ .gpio = EXYNOS4_GPX1(6),
+ .desc = "gpio-keys: KEY_HOME",
+ .type = EV_KEY,
+ .active_low = 1,
+ .wakeup = 1,
+ .debounce_interval = 1,
+ }, {
+ .code = KEY_BACK,
+ .gpio = EXYNOS4_GPX1(7),
+ .desc = "gpio-keys: KEY_BACK",
+ .type = EV_KEY,
+ .active_low = 1,
+ .wakeup = 1,
+ .debounce_interval = 1,
+ }, {
+ .code = KEY_UP,
+ .gpio = EXYNOS4_GPX2(0),
+ .desc = "gpio-keys: KEY_UP",
+ .type = EV_KEY,
+ .active_low = 1,
+ .wakeup = 1,
+ .debounce_interval = 1,
+ }, {
+ .code = KEY_DOWN,
+ .gpio = EXYNOS4_GPX2(1),
+ .desc = "gpio-keys: KEY_DOWN",
+ .type = EV_KEY,
+ .active_low = 1,
+ .wakeup = 1,
+ .debounce_interval = 1,
+ },
+};
+
+static struct gpio_keys_platform_data origen_gpio_keys_data = {
+ .buttons = origen_gpio_keys_table,
+ .nbuttons = ARRAY_SIZE(origen_gpio_keys_table),
+};
+
+static struct platform_device origen_device_gpiokeys = {
+ .name = "gpio-keys",
+ .dev = {
+ .platform_data = &origen_gpio_keys_data,
+ },
+};
+
+static void lcd_hv070wsa_set_power(struct plat_lcd_data *pd, unsigned int power)
+{
+ int ret;
+
+ if (power)
+ ret = gpio_request_one(EXYNOS4_GPE3(4),
+ GPIOF_OUT_INIT_HIGH, "GPE3_4");
+ else
+ ret = gpio_request_one(EXYNOS4_GPE3(4),
+ GPIOF_OUT_INIT_LOW, "GPE3_4");
+
+ gpio_free(EXYNOS4_GPE3(4));
+
+ if (ret)
+ pr_err("failed to request gpio for LCD power: %d\n", ret);
+}
+
+static struct plat_lcd_data origen_lcd_hv070wsa_data = {
+ .set_power = lcd_hv070wsa_set_power,
+};
+
+static struct platform_device origen_lcd_hv070wsa = {
+ .name = "platform-lcd",
+ .dev.parent = &s5p_device_fimd0.dev,
+ .dev.platform_data = &origen_lcd_hv070wsa_data,
+};
+
+static struct s3c_fb_pd_win origen_fb_win0 = {
+ .win_mode = {
+ .left_margin = 64,
+ .right_margin = 16,
+ .upper_margin = 64,
+ .lower_margin = 16,
+ .hsync_len = 48,
+ .vsync_len = 3,
+ .xres = 1024,
+ .yres = 600,
+ },
+ .max_bpp = 32,
+ .default_bpp = 24,
+};
+
+static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
+ .win[0] = &origen_fb_win0,
+ .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+ .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+ .setup_gpio = exynos4_fimd0_gpio_setup_24bpp,
+};
+
+static struct platform_device *origen_devices[] __initdata = {
+ &s3c_device_hsmmc2,
+ &s3c_device_hsmmc0,
+ &s3c_device_i2c0,
+ &s3c_device_rtc,
+ &s3c_device_wdt,
+ &s5p_device_ehci,
+ &s5p_device_fimc0,
+ &s5p_device_fimc1,
+ &s5p_device_fimc2,
+ &s5p_device_fimc3,
+ &s5p_device_fimd0,
+ &s5p_device_hdmi,
+ &s5p_device_i2c_hdmiphy,
+ &s5p_device_mfc,
+ &s5p_device_mfc_l,
+ &s5p_device_mfc_r,
+ &s5p_device_mixer,
+ &exynos4_device_pd[PD_LCD0],
+ &exynos4_device_pd[PD_TV],
+ &exynos4_device_pd[PD_G3D],
+ &exynos4_device_pd[PD_LCD1],
+ &exynos4_device_pd[PD_CAM],
+ &exynos4_device_pd[PD_GPS],
+ &exynos4_device_pd[PD_MFC],
+ &origen_device_gpiokeys,
+ &origen_lcd_hv070wsa,
+};
+
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info origen_bl_gpio_info = {
+ .no = EXYNOS4_GPD0(0),
+ .func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data origen_bl_data = {
+ .pwm_id = 0,
+ .pwm_period_ns = 1000,
+};
+
+static void s5p_tv_setup(void)
+{
+ /* Direct HPD to HDMI chip */
+ gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug");
+ s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+ s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+}
+
+static void __init origen_map_io(void)
+{
+ s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+ s3c24xx_init_clocks(24000000);
+ s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
+}
+
+static void __init origen_power_init(void)
+{
+ gpio_request(EXYNOS4_GPX0(4), "PMIC_IRQ");
+ s3c_gpio_cfgpin(EXYNOS4_GPX0(4), S3C_GPIO_SFN(0xf));
+ s3c_gpio_setpull(EXYNOS4_GPX0(4), S3C_GPIO_PULL_NONE);
+}
+
+static void __init origen_reserve(void)
+{
+ s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
+static void __init origen_machine_init(void)
+{
+ origen_power_init();
+
+ s3c_i2c0_set_platdata(NULL);
+ i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
+
+ /*
+ * Since sdhci instance 2 can contain a bootable media,
+ * sdhci instance 0 is registered after instance 2.
+ */
+ s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata);
+ s3c_sdhci0_set_platdata(&origen_hsmmc0_pdata);
+
+ origen_ehci_init();
+ clk_xusbxti.rate = 24000000;
+
+ s5p_tv_setup();
+ s5p_i2c_hdmiphy_set_platdata(NULL);
+
+ s5p_fimd0_set_platdata(&origen_lcd_pdata);
+
+ platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
+
+ s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+ s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+ s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+
+ s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+
+ samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
+}
+
+MACHINE_START(ORIGEN, "ORIGEN")
+ /* Maintainer: JeongHyeon Kim <jhkim@insignal.co.kr> */
+ .atag_offset = 0x100,
+ .init_irq = exynos4_init_irq,
+ .map_io = origen_map_io,
+ .init_machine = origen_machine_init,
+ .timer = &exynos4_timer,
+ .reserve = &origen_reserve,
+MACHINE_END
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
new file mode 100644
index 0000000..509a435
--- /dev/null
+++ b/arch/arm/mach-exynos/pm.c
@@ -0,0 +1,428 @@
+/* linux/arch/arm/mach-exynos4/pm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS4210 - Power Management support
+ *
+ * Based on arch/arm/mach-s3c2410/pm.c
+ * Copyright (c) 2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/syscore_ops.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/pll.h>
+#include <plat/regs-srom.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-pmu.h>
+#include <mach/pm-core.h>
+#include <mach/pmu.h>
+
+static struct sleep_save exynos4_set_clksrc[] = {
+ { .reg = S5P_CLKSRC_MASK_TOP , .val = 0x00000001, },
+ { .reg = S5P_CLKSRC_MASK_CAM , .val = 0x11111111, },
+ { .reg = S5P_CLKSRC_MASK_TV , .val = 0x00000111, },
+ { .reg = S5P_CLKSRC_MASK_LCD0 , .val = 0x00001111, },
+ { .reg = S5P_CLKSRC_MASK_MAUDIO , .val = 0x00000001, },
+ { .reg = S5P_CLKSRC_MASK_FSYS , .val = 0x01011111, },
+ { .reg = S5P_CLKSRC_MASK_PERIL0 , .val = 0x01111111, },
+ { .reg = S5P_CLKSRC_MASK_PERIL1 , .val = 0x01110111, },
+ { .reg = S5P_CLKSRC_MASK_DMC , .val = 0x00010000, },
+};
+
+static struct sleep_save exynos4210_set_clksrc[] = {
+ { .reg = S5P_CLKSRC_MASK_LCD1 , .val = 0x00001111, },
+};
+
+static struct sleep_save exynos4_epll_save[] = {
+ SAVE_ITEM(S5P_EPLL_CON0),
+ SAVE_ITEM(S5P_EPLL_CON1),
+};
+
+static struct sleep_save exynos4_vpll_save[] = {
+ SAVE_ITEM(S5P_VPLL_CON0),
+ SAVE_ITEM(S5P_VPLL_CON1),
+};
+
+static struct sleep_save exynos4_core_save[] = {
+ /* GIC side */
+ SAVE_ITEM(S5P_VA_GIC_CPU + 0x000),
+ SAVE_ITEM(S5P_VA_GIC_CPU + 0x004),
+ SAVE_ITEM(S5P_VA_GIC_CPU + 0x008),
+ SAVE_ITEM(S5P_VA_GIC_CPU + 0x00C),
+ SAVE_ITEM(S5P_VA_GIC_CPU + 0x014),
+ SAVE_ITEM(S5P_VA_GIC_CPU + 0x018),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x000),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x004),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x100),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x104),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x108),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x300),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x304),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x308),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x400),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x404),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x408),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x40C),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x410),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x414),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x418),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x41C),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x420),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x424),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x428),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x42C),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x430),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x434),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x438),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x43C),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x440),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x444),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x448),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x44C),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x450),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x454),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x458),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x45C),
+
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x800),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x804),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x808),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x80C),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x810),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x814),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x818),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x81C),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x820),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x824),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x828),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x82C),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x830),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x834),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x838),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x83C),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x840),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x844),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x848),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x84C),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x850),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x854),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x858),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0x85C),
+
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0xC00),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0xC04),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0xC08),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0xC0C),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0xC10),
+ SAVE_ITEM(S5P_VA_GIC_DIST + 0xC14),
+
+ SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x000),
+ SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x010),
+ SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x020),
+ SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x030),
+ SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x040),
+ SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x050),
+ SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x060),
+ SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070),
+ SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080),
+ SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090),
+
+ /* SROM side */
+ SAVE_ITEM(S5P_SROM_BW),
+ SAVE_ITEM(S5P_SROM_BC0),
+ SAVE_ITEM(S5P_SROM_BC1),
+ SAVE_ITEM(S5P_SROM_BC2),
+ SAVE_ITEM(S5P_SROM_BC3),
+};
+
+static struct sleep_save exynos4_l2cc_save[] = {
+ SAVE_ITEM(S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL),
+ SAVE_ITEM(S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL),
+ SAVE_ITEM(S5P_VA_L2CC + L2X0_PREFETCH_CTRL),
+ SAVE_ITEM(S5P_VA_L2CC + L2X0_POWER_CTRL),
+ SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),
+};
+
+/* For Cortex-A9 Diagnostic and Power control register */
+static unsigned int save_arm_register[2];
+
+static int exynos4_cpu_suspend(unsigned long arg)
+{
+ outer_flush_all();
+
+ /* issue the standby signal into the pm unit. */
+ cpu_do_idle();
+
+ /* we should never get past here */
+ panic("sleep resumed to originator?");
+}
+
+static void exynos4_pm_prepare(void)
+{
+ u32 tmp;
+
+ s3c_pm_do_save(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
+ s3c_pm_do_save(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
+ s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
+ s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
+
+ tmp = __raw_readl(S5P_INFORM1);
+
+ /* Set value of power down register for sleep mode */
+
+ exynos4_sys_powerdown_conf(SYS_SLEEP);
+ __raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
+
+ /* ensure at least INFORM0 has the resume address */
+
+ __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
+
+ /* Before enter central sequence mode, clock src register have to set */
+
+ s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
+
+ if (soc_is_exynos4210())
+ s3c_pm_do_restore_core(exynos4210_set_clksrc, ARRAY_SIZE(exynos4210_set_clksrc));
+
+}
+
+static int exynos4_pm_add(struct sys_device *sysdev)
+{
+ pm_cpu_prep = exynos4_pm_prepare;
+ pm_cpu_sleep = exynos4_cpu_suspend;
+
+ return 0;
+}
+
+/* This function copy from linux/arch/arm/kernel/smp_scu.c */
+
+void exynos4_scu_enable(void __iomem *scu_base)
+{
+ u32 scu_ctrl;
+
+ scu_ctrl = __raw_readl(scu_base);
+ /* already enabled? */
+ if (scu_ctrl & 1)
+ return;
+
+ scu_ctrl |= 1;
+ __raw_writel(scu_ctrl, scu_base);
+
+ /*
+ * Ensure that the data accessed by CPU0 before the SCU was
+ * initialised is visible to the other CPUs.
+ */
+ flush_cache_all();
+}
+
+static unsigned long pll_base_rate;
+
+static void exynos4_restore_pll(void)
+{
+ unsigned long pll_con, locktime, lockcnt;
+ unsigned long pll_in_rate;
+ unsigned int p_div, epll_wait = 0, vpll_wait = 0;
+
+ if (pll_base_rate == 0)
+ return;
+
+ pll_in_rate = pll_base_rate;
+
+ /* EPLL */
+ pll_con = exynos4_epll_save[0].val;
+
+ if (pll_con & (1 << 31)) {
+ pll_con &= (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT);
+ p_div = (pll_con >> PLL46XX_PDIV_SHIFT);
+
+ pll_in_rate /= 1000000;
+
+ locktime = (3000 / pll_in_rate) * p_div;
+ lockcnt = locktime * 10000 / (10000 / pll_in_rate);
+
+ __raw_writel(lockcnt, S5P_EPLL_LOCK);
+
+ s3c_pm_do_restore_core(exynos4_epll_save,
+ ARRAY_SIZE(exynos4_epll_save));
+ epll_wait = 1;
+ }
+
+ pll_in_rate = pll_base_rate;
+
+ /* VPLL */
+ pll_con = exynos4_vpll_save[0].val;
+
+ if (pll_con & (1 << 31)) {
+ pll_in_rate /= 1000000;
+ /* 750us */
+ locktime = 750;
+ lockcnt = locktime * 10000 / (10000 / pll_in_rate);
+
+ __raw_writel(lockcnt, S5P_VPLL_LOCK);
+
+ s3c_pm_do_restore_core(exynos4_vpll_save,
+ ARRAY_SIZE(exynos4_vpll_save));
+ vpll_wait = 1;
+ }
+
+ /* Wait PLL locking */
+
+ do {
+ if (epll_wait) {
+ pll_con = __raw_readl(S5P_EPLL_CON0);
+ if (pll_con & (1 << S5P_EPLLCON0_LOCKED_SHIFT))
+ epll_wait = 0;
+ }
+
+ if (vpll_wait) {
+ pll_con = __raw_readl(S5P_VPLL_CON0);
+ if (pll_con & (1 << S5P_VPLLCON0_LOCKED_SHIFT))
+ vpll_wait = 0;
+ }
+ } while (epll_wait || vpll_wait);
+}
+
+static struct sysdev_driver exynos4_pm_driver = {
+ .add = exynos4_pm_add,
+};
+
+static __init int exynos4_pm_drvinit(void)
+{
+ struct clk *pll_base;
+ unsigned int tmp;
+
+ s3c_pm_init();
+
+ /* All wakeup disable */
+
+ tmp = __raw_readl(S5P_WAKEUP_MASK);
+ tmp |= ((0xFF << 8) | (0x1F << 1));
+ __raw_writel(tmp, S5P_WAKEUP_MASK);
+
+ pll_base = clk_get(NULL, "xtal");
+
+ if (!IS_ERR(pll_base)) {
+ pll_base_rate = clk_get_rate(pll_base);
+ clk_put(pll_base);
+ }
+
+ return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
+}
+arch_initcall(exynos4_pm_drvinit);
+
+static int exynos4_pm_suspend(void)
+{
+ unsigned long tmp;
+
+ /* Setting Central Sequence Register for power down mode */
+
+ tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+ tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
+ __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+
+ if (soc_is_exynos4212()) {
+ tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
+ tmp &= ~(S5P_USE_STANDBYWFI_ISP_ARM |
+ S5P_USE_STANDBYWFE_ISP_ARM);
+ __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
+ }
+
+ /* Save Power control register */
+ asm ("mrc p15, 0, %0, c15, c0, 0"
+ : "=r" (tmp) : : "cc");
+ save_arm_register[0] = tmp;
+
+ /* Save Diagnostic register */
+ asm ("mrc p15, 0, %0, c15, c0, 1"
+ : "=r" (tmp) : : "cc");
+ save_arm_register[1] = tmp;
+
+ return 0;
+}
+
+static void exynos4_pm_resume(void)
+{
+ unsigned long tmp;
+
+ /*
+ * If PMU failed while entering sleep mode, WFI will be
+ * ignored by PMU and then exiting cpu_do_idle().
+ * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
+ * in this situation.
+ */
+ tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+ if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
+ tmp |= S5P_CENTRAL_LOWPWR_CFG;
+ __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+ /* No need to perform below restore code */
+ goto early_wakeup;
+ }
+ /* Restore Power control register */
+ tmp = save_arm_register[0];
+ asm volatile ("mcr p15, 0, %0, c15, c0, 0"
+ : : "r" (tmp)
+ : "cc");
+
+ /* Restore Diagnostic register */
+ tmp = save_arm_register[1];
+ asm volatile ("mcr p15, 0, %0, c15, c0, 1"
+ : : "r" (tmp)
+ : "cc");
+
+ /* For release retention */
+
+ __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
+ __raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
+ __raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
+ __raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
+ __raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
+ __raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
+ __raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
+
+ s3c_pm_do_restore_core(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
+
+ exynos4_restore_pll();
+
+ exynos4_scu_enable(S5P_VA_SCU);
+
+#ifdef CONFIG_CACHE_L2X0
+ s3c_pm_do_restore_core(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
+ outer_inv_all();
+ /* enable L2X0*/
+ writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
+#endif
+
+early_wakeup:
+ return;
+}
+
+static struct syscore_ops exynos4_pm_syscore_ops = {
+ .suspend = exynos4_pm_suspend,
+ .resume = exynos4_pm_resume,
+};
+
+static __init int exynos4_pm_syscore_init(void)
+{
+ register_syscore_ops(&exynos4_pm_syscore_ops);
+ return 0;
+}
+arch_initcall(exynos4_pm_syscore_init);
diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c
new file mode 100644
index 0000000..bba48f5
--- /dev/null
+++ b/arch/arm/mach-exynos/pmu.c
@@ -0,0 +1,230 @@
+/* linux/arch/arm/mach-exynos4/pmu.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * EXYNOS4210 - CPU PMU(Power Management Unit) support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+
+#include <mach/regs-clock.h>
+#include <mach/pmu.h>
+
+static struct exynos4_pmu_conf *exynos4_pmu_config;
+
+static struct exynos4_pmu_conf exynos4210_pmu_config[] = {
+ /* { .reg = address, .val = { AFTR, LPA, SLEEP } */
+ { S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } },
+ { S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } },
+ { S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } },
+ { S5P_ARM_CORE1_LOWPWR, { 0x0, 0x0, 0x2 } },
+ { S5P_DIS_IRQ_CORE1, { 0x0, 0x0, 0x0 } },
+ { S5P_DIS_IRQ_CENTRAL1, { 0x0, 0x0, 0x0 } },
+ { S5P_ARM_COMMON_LOWPWR, { 0x0, 0x0, 0x2 } },
+ { S5P_L2_0_LOWPWR, { 0x2, 0x2, 0x3 } },
+ { S5P_L2_1_LOWPWR, { 0x2, 0x2, 0x3 } },
+ { S5P_CMU_ACLKSTOP_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_SCLKSTOP_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_RESET_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_APLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_MPLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_VPLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_EPLL_SYSCLK_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_RESET_GPSALIVE_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_CLKSTOP_CAM_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_CLKSTOP_TV_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_CLKSTOP_MFC_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_CLKSTOP_G3D_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_CLKSTOP_LCD0_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_CLKSTOP_LCD1_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_CLKSTOP_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_CLKSTOP_GPS_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_RESET_CAM_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_RESET_TV_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_RESET_MFC_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_RESET_G3D_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_RESET_LCD0_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_RESET_LCD1_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_RESET_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_RESET_GPS_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_TOP_BUS_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_TOP_RETENTION_LOWPWR, { 0x1, 0x0, 0x1 } },
+ { S5P_TOP_PWR_LOWPWR, { 0x3, 0x0, 0x3 } },
+ { S5P_LOGIC_RESET_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_ONENAND_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_MODIMIF_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_G2D_ACP_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_USBOTG_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_HSMMC_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_CSSYS_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_SECSS_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_PCIE_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_SATA_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_DRAM_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_PAD_RETENTION_GPIO_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_UART_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_MMCA_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_MMCB_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_EBIA_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_EBIB_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_ISOLATION_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_ALV_SEL_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_XUSBXTI_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_XXTI_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_EXT_REGULATOR_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_GPIO_MODE_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_GPIO_MODE_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CAM_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_TV_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_MFC_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_G3D_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_LCD0_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_LCD1_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_MAUDIO_LOWPWR, { 0x7, 0x7, 0x0 } },
+ { S5P_GPS_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_GPS_ALIVE_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { PMU_TABLE_END,},
+};
+
+static struct exynos4_pmu_conf exynos4212_pmu_config[] = {
+ { S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } },
+ { S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } },
+ { S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } },
+ { S5P_ARM_CORE1_LOWPWR, { 0x0, 0x0, 0x2 } },
+ { S5P_DIS_IRQ_CORE1, { 0x0, 0x0, 0x0 } },
+ { S5P_DIS_IRQ_CENTRAL1, { 0x0, 0x0, 0x0 } },
+ { S5P_ISP_ARM_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR, { 0x0, 0x0, 0x0 } },
+ { S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR, { 0x0, 0x0, 0x0 } },
+ { S5P_ARM_COMMON_LOWPWR, { 0x0, 0x0, 0x2 } },
+ { S5P_L2_0_LOWPWR, { 0x0, 0x0, 0x3 } },
+ /* XXX_OPTION register should be set other field */
+ { S5P_ARM_L2_0_OPTION, { 0x10, 0x10, 0x0 } },
+ { S5P_L2_1_LOWPWR, { 0x0, 0x0, 0x3 } },
+ { S5P_ARM_L2_1_OPTION, { 0x10, 0x10, 0x0 } },
+ { S5P_CMU_ACLKSTOP_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_SCLKSTOP_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_RESET_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_DRAM_FREQ_DOWN_LOWPWR, { 0x1, 0x1, 0x1 } },
+ { S5P_DDRPHY_DLLOFF_LOWPWR, { 0x1, 0x1, 0x1 } },
+ { S5P_LPDDR_PHY_DLL_LOCK_LOWPWR, { 0x1, 0x1, 0x1 } },
+ { S5P_CMU_ACLKSTOP_COREBLK_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_SCLKSTOP_COREBLK_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_RESET_COREBLK_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_APLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_MPLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_VPLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_EPLL_SYSCLK_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_MPLLUSER_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_RESET_GPSALIVE_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_CLKSTOP_CAM_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_CLKSTOP_TV_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_CLKSTOP_MFC_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_CLKSTOP_G3D_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_CLKSTOP_LCD0_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_CLKSTOP_ISP_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_CLKSTOP_MAUDIO_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_CLKSTOP_GPS_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_RESET_CAM_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_RESET_TV_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_RESET_MFC_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_RESET_G3D_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_RESET_LCD0_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_RESET_ISP_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_RESET_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_CMU_RESET_GPS_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_TOP_BUS_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_TOP_RETENTION_LOWPWR, { 0x1, 0x0, 0x1 } },
+ { S5P_TOP_PWR_LOWPWR, { 0x3, 0x0, 0x3 } },
+ { S5P_TOP_BUS_COREBLK_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_TOP_RETENTION_COREBLK_LOWPWR, { 0x1, 0x0, 0x1 } },
+ { S5P_TOP_PWR_COREBLK_LOWPWR, { 0x3, 0x0, 0x3 } },
+ { S5P_LOGIC_RESET_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_OSCCLK_GATE_LOWPWR, { 0x1, 0x0, 0x1 } },
+ { S5P_LOGIC_RESET_COREBLK_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_OSCCLK_GATE_COREBLK_LOWPWR, { 0x1, 0x0, 0x1 } },
+ { S5P_ONENAND_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_ONENAND_MEM_OPTION, { 0x10, 0x10, 0x0 } },
+ { S5P_HSI_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_HSI_MEM_OPTION, { 0x10, 0x10, 0x0 } },
+ { S5P_G2D_ACP_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_G2D_ACP_MEM_OPTION, { 0x10, 0x10, 0x0 } },
+ { S5P_USBOTG_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_USBOTG_MEM_OPTION, { 0x10, 0x10, 0x0 } },
+ { S5P_HSMMC_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_HSMMC_MEM_OPTION, { 0x10, 0x10, 0x0 } },
+ { S5P_CSSYS_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_CSSYS_MEM_OPTION, { 0x10, 0x10, 0x0 } },
+ { S5P_SECSS_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_SECSS_MEM_OPTION, { 0x10, 0x10, 0x0 } },
+ { S5P_ROTATOR_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
+ { S5P_ROTATOR_MEM_OPTION, { 0x10, 0x10, 0x0 } },
+ { S5P_PAD_RETENTION_DRAM_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_PAD_RETENTION_GPIO_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_UART_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_MMCA_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_MMCB_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_EBIA_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_EBIB_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR,{ 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_ISOLATION_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_ISOLATION_COREBLK_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_PAD_RETENTION_ALV_SEL_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_XUSBXTI_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_XXTI_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_EXT_REGULATOR_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_GPIO_MODE_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_GPIO_MODE_COREBLK_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_GPIO_MODE_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
+ { S5P_TOP_ASB_RESET_LOWPWR, { 0x1, 0x1, 0x1 } },
+ { S5P_TOP_ASB_ISOLATION_LOWPWR, { 0x1, 0x0, 0x1 } },
+ { S5P_CAM_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_TV_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_MFC_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_G3D_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_LCD0_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_ISP_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_MAUDIO_LOWPWR, { 0x7, 0x7, 0x0 } },
+ { S5P_GPS_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_GPS_ALIVE_LOWPWR, { 0x7, 0x0, 0x0 } },
+ { S5P_CMU_SYSCLK_ISP_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { S5P_CMU_SYSCLK_GPS_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { PMU_TABLE_END,},
+};
+
+void exynos4_sys_powerdown_conf(enum sys_powerdown mode)
+{
+ unsigned int i;
+
+ for (i = 0; (exynos4_pmu_config[i].reg != PMU_TABLE_END) ; i++)
+ __raw_writel(exynos4_pmu_config[i].val[mode],
+ exynos4_pmu_config[i].reg);
+}
+
+static int __init exynos4_pmu_init(void)
+{
+ exynos4_pmu_config = exynos4210_pmu_config;
+
+ if (soc_is_exynos4210()) {
+ exynos4_pmu_config = exynos4210_pmu_config;
+ pr_info("EXYNOS4210 PMU Initialize\n");
+ } else if (soc_is_exynos4212()) {
+ exynos4_pmu_config = exynos4212_pmu_config;
+ pr_info("EXYNOS4212 PMU Initialize\n");
+ } else {
+ pr_info("EXYNOS4: PMU not supported\n");
+ }
+
+ return 0;
+}
+arch_initcall(exynos4_pmu_init);
diff --git a/arch/arm/mach-exynos/setup-i2c4.c~HEAD b/arch/arm/mach-exynos/setup-i2c4.c~HEAD
new file mode 100644
index 0000000..234f21f
--- /dev/null
+++ b/arch/arm/mach-exynos/setup-i2c4.c~HEAD
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/arm/mach-exynos/setup-i2c4.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C4 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+#include <plat/cpu.h>
+
+void s3c_i2c4_cfg_gpio(struct platform_device *dev)
+{
+#if defined(CONFIG_MACH_U1_NA_USCC)
+s3c_gpio_cfgall_range(EXYNOS4_GPB(0), 1,
+ S3C_GPIO_OUTPUT, S3C_GPIO_PULL_NONE);
+#else
+ if (soc_is_exynos4210())
+ s3c_gpio_cfgall_range(EXYNOS4_GPB(2), 2,
+ S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+ else if (soc_is_exynos4212())
+ s3c_gpio_cfgall_range(EXYNOS4_GPB(0), 2,
+ S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+ else
+ s3c_gpio_cfgall_range(EXYNOS5_GPA2(0), 2,
+ S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+#endif
+}
diff --git a/arch/arm/mach-exynos/setup-i2c4.c~v3.2.72 b/arch/arm/mach-exynos/setup-i2c4.c~v3.2.72
new file mode 100644
index 0000000..9f3c048
--- /dev/null
+++ b/arch/arm/mach-exynos/setup-i2c4.c~v3.2.72
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c4.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C4 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c4_cfg_gpio(struct platform_device *dev)
+{
+ s3c_gpio_cfgall_range(EXYNOS4_GPB(2), 2,
+ S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-exynos/setup-i2c5.c~HEAD b/arch/arm/mach-exynos/setup-i2c5.c~HEAD
new file mode 100644
index 0000000..8253fc1
--- /dev/null
+++ b/arch/arm/mach-exynos/setup-i2c5.c~HEAD
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/arm/mach-exynos/setup-i2c5.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C5 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+#include <plat/cpu.h>
+
+void s3c_i2c5_cfg_gpio(struct platform_device *dev)
+{
+ if (soc_is_exynos4210())
+ s3c_gpio_cfgall_range(EXYNOS4_GPB(6), 2,
+ S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+ else if (soc_is_exynos4212())
+ s3c_gpio_cfgall_range(EXYNOS4_GPB(2), 2,
+ S3C_GPIO_SFN(3), S3C_GPIO_PULL_NONE);
+ else
+ s3c_gpio_cfgall_range(EXYNOS5_GPA2(2), 2,
+ S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-exynos/setup-i2c5.c~v3.2.72 b/arch/arm/mach-exynos/setup-i2c5.c~v3.2.72
new file mode 100644
index 0000000..77e1a1e
--- /dev/null
+++ b/arch/arm/mach-exynos/setup-i2c5.c~v3.2.72
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c5.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C5 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c5_cfg_gpio(struct platform_device *dev)
+{
+ s3c_gpio_cfgall_range(EXYNOS4_GPB(6), 2,
+ S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-highbank/Makefile b/arch/arm/mach-highbank/Makefile
new file mode 100644
index 0000000..986958a
--- /dev/null
+++ b/arch/arm/mach-highbank/Makefile
@@ -0,0 +1,6 @@
+obj-y := clock.o highbank.o system.o
+obj-$(CONFIG_DEBUG_HIGHBANK_UART) += lluart.o
+obj-$(CONFIG_SMP) += platsmp.o
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+obj-$(CONFIG_PM_SLEEP) += pm.o
diff --git a/arch/arm/mach-highbank/Makefile.boot b/arch/arm/mach-highbank/Makefile.boot
new file mode 100644
index 0000000..dae9661
--- /dev/null
+++ b/arch/arm/mach-highbank/Makefile.boot
@@ -0,0 +1 @@
+zreladdr-y := 0x00008000
diff --git a/arch/arm/mach-highbank/clock.c b/arch/arm/mach-highbank/clock.c
new file mode 100644
index 0000000..c25a2ae
--- /dev/null
+++ b/arch/arm/mach-highbank/clock.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+
+struct clk {
+ unsigned long rate;
+};
+
+int clk_enable(struct clk *clk)
+{
+ return 0;
+}
+
+void clk_disable(struct clk *clk)
+{}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ return clk->rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ return 0;
+}
+
+static struct clk eclk = { .rate = 200000000 };
+static struct clk pclk = { .rate = 150000000 };
+
+static struct clk_lookup lookups[] = {
+ { .clk = &pclk, .con_id = "apb_pclk", },
+ { .clk = &pclk, .dev_id = "sp804", },
+ { .clk = &eclk, .dev_id = "ffe0e000.sdhci", },
+ { .clk = &pclk, .dev_id = "fff36000.serial", },
+};
+
+void __init highbank_clocks_init(void)
+{
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+}
diff --git a/arch/arm/mach-highbank/core.h b/arch/arm/mach-highbank/core.h
new file mode 100644
index 0000000..7e33fc9
--- /dev/null
+++ b/arch/arm/mach-highbank/core.h
@@ -0,0 +1,9 @@
+extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
+extern void highbank_clocks_init(void);
+extern void __iomem *scu_base_addr;
+#ifdef CONFIG_DEBUG_HIGHBANK_UART
+extern void highbank_lluart_map_io(void);
+#else
+static inline void highbank_lluart_map_io(void) {}
+#endif
+
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
new file mode 100644
index 0000000..88660d5
--- /dev/null
+++ b/arch/arm/mach-highbank/highbank.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+#include <asm/unified.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/arm_timer.h>
+#include <asm/hardware/timer-sp.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+void __iomem *sregs_base;
+
+#define HB_SCU_VIRT_BASE 0xfee00000
+void __iomem *scu_base_addr = ((void __iomem *)(HB_SCU_VIRT_BASE));
+
+static struct map_desc scu_io_desc __initdata = {
+ .virtual = HB_SCU_VIRT_BASE,
+ .pfn = 0, /* run-time */
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+};
+
+static void __init highbank_scu_map_io(void)
+{
+ unsigned long base;
+
+ /* Get SCU base */
+ asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+ scu_io_desc.pfn = __phys_to_pfn(base);
+ iotable_init(&scu_io_desc, 1);
+}
+
+static void __init highbank_map_io(void)
+{
+ highbank_scu_map_io();
+ highbank_lluart_map_io();
+}
+
+#define HB_JUMP_TABLE_PHYS(cpu) (0x40 + (0x10 * (cpu)))
+#define HB_JUMP_TABLE_VIRT(cpu) phys_to_virt(HB_JUMP_TABLE_PHYS(cpu))
+
+void highbank_set_cpu_jump(int cpu, void *jump_addr)
+{
+#ifdef CONFIG_SMP
+ cpu = cpu_logical_map(cpu);
+#endif
+ writel(BSYM(virt_to_phys(jump_addr)), HB_JUMP_TABLE_VIRT(cpu));
+ __cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
+ outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
+ HB_JUMP_TABLE_PHYS(cpu) + 15);
+}
+
+const static struct of_device_id irq_match[] = {
+ { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+ {}
+};
+
+static void __init highbank_init_irq(void)
+{
+ of_irq_init(irq_match);
+ l2x0_of_init(0, ~0UL);
+}
+
+static void __init highbank_timer_init(void)
+{
+ int irq;
+ struct device_node *np;
+ void __iomem *timer_base;
+
+ /* Map system registers */
+ np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
+ sregs_base = of_iomap(np, 0);
+ WARN_ON(!sregs_base);
+
+ np = of_find_compatible_node(NULL, NULL, "arm,sp804");
+ timer_base = of_iomap(np, 0);
+ WARN_ON(!timer_base);
+ irq = irq_of_parse_and_map(np, 0);
+
+ highbank_clocks_init();
+
+ sp804_clocksource_init(timer_base + 0x20, "timer1");
+ sp804_clockevents_init(timer_base, irq, "timer0");
+}
+
+static struct sys_timer highbank_timer = {
+ .init = highbank_timer_init,
+};
+
+static void highbank_power_off(void)
+{
+ hignbank_set_pwr_shutdown();
+ scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+
+ while (1)
+ cpu_do_idle();
+}
+
+static void __init highbank_init(void)
+{
+ pm_power_off = highbank_power_off;
+
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *highbank_match[] __initconst = {
+ "calxeda,highbank",
+ NULL,
+};
+
+DT_MACHINE_START(HIGHBANK, "Highbank")
+ .map_io = highbank_map_io,
+ .init_irq = highbank_init_irq,
+ .timer = &highbank_timer,
+ .init_machine = highbank_init,
+ .dt_compat = highbank_match,
+MACHINE_END
diff --git a/arch/arm/mach-highbank/hotplug.c b/arch/arm/mach-highbank/hotplug.c
new file mode 100644
index 0000000..977cebb
--- /dev/null
+++ b/arch/arm/mach-highbank/hotplug.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/smp_scu.h>
+#include <asm/cacheflush.h>
+
+#include "core.h"
+
+extern void secondary_startup(void);
+
+int platform_cpu_kill(unsigned int cpu)
+{
+ return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+ flush_cache_all();
+
+ highbank_set_cpu_jump(cpu, secondary_startup);
+ scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+
+ cpu_do_idle();
+
+ /* We should never return from idle */
+ panic("highbank: cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+ /*
+ * CPU0 should not be shut down via hotplug. cpu_idle can WFI
+ * or a proper shutdown or hibernate should be used.
+ */
+ return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-highbank/include/mach/debug-macro.S b/arch/arm/mach-highbank/include/mach/debug-macro.S
new file mode 100644
index 0000000..cb57fe5
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/debug-macro.S
@@ -0,0 +1,19 @@
+/*
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+ .macro addruart,rp,rv,tmp
+ movw \rv, #0x6000
+ movt \rv, #0xfee3
+ movw \rp, #0x6000
+ movt \rp, #0xfff3
+ .endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-highbank/include/mach/entry-macro.S b/arch/arm/mach-highbank/include/mach/entry-macro.S
new file mode 100644
index 0000000..73c1129
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/entry-macro.S
@@ -0,0 +1,7 @@
+#include <asm/hardware/entry-macro-gic.S>
+
+ .macro disable_fiq
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
diff --git a/arch/arm/mach-highbank/include/mach/gpio.h b/arch/arm/mach-highbank/include/mach/gpio.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/gpio.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-highbank/include/mach/io.h b/arch/arm/mach-highbank/include/mach/io.h
new file mode 100644
index 0000000..70cfa3b
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/io.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_IO_H
+#define __MACH_IO_H
+
+#define __io(a) ({ (void)(a); __typesafe_io(0); })
+#define __mem_pci(a) (a)
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/irqs.h b/arch/arm/mach-highbank/include/mach/irqs.h
new file mode 100644
index 0000000..9746aab
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/irqs.h
@@ -0,0 +1,6 @@
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define NR_IRQS 192
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/memory.h b/arch/arm/mach-highbank/include/mach/memory.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/memory.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-highbank/include/mach/system.h b/arch/arm/mach-highbank/include/mach/system.h
new file mode 100644
index 0000000..7e81922
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/system.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __MACH_SYSTEM_H
+#define __MACH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+ cpu_do_idle();
+}
+
+extern void arch_reset(char mode, const char *cmd);
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/timex.h b/arch/arm/mach-highbank/include/mach/timex.h
new file mode 100644
index 0000000..88dac7a
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/timex.h
@@ -0,0 +1,6 @@
+#ifndef __MACH_TIMEX_H
+#define __MACH_TIMEX_H
+
+#define CLOCK_TICK_RATE 1000000
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/uncompress.h b/arch/arm/mach-highbank/include/mach/uncompress.h
new file mode 100644
index 0000000..bbe20e6
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/uncompress.h
@@ -0,0 +1,9 @@
+#ifndef __MACH_UNCOMPRESS_H
+#define __MACH_UNCOMPRESS_H
+
+#define putc(c)
+#define flush()
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/vmalloc.h b/arch/arm/mach-highbank/include/mach/vmalloc.h
new file mode 100644
index 0000000..1969e95
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/vmalloc.h
@@ -0,0 +1 @@
+#define VMALLOC_END 0xFEE00000UL
diff --git a/arch/arm/mach-highbank/lluart.c b/arch/arm/mach-highbank/lluart.c
new file mode 100644
index 0000000..3715750
--- /dev/null
+++ b/arch/arm/mach-highbank/lluart.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <asm/page.h>
+#include <asm/sizes.h>
+#include <asm/mach/map.h>
+
+#define HB_DEBUG_LL_PHYS_BASE 0xfff36000
+#define HB_DEBUG_LL_VIRT_BASE 0xfee36000
+
+static struct map_desc lluart_io_desc __initdata = {
+ .virtual = HB_DEBUG_LL_VIRT_BASE,
+ .pfn = __phys_to_pfn(HB_DEBUG_LL_PHYS_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+};
+
+void __init highbank_lluart_map_io(void)
+{
+ iotable_init(&lluart_io_desc, 1);
+}
diff --git a/arch/arm/mach-highbank/localtimer.c b/arch/arm/mach-highbank/localtimer.c
new file mode 100644
index 0000000..5a00e79
--- /dev/null
+++ b/arch/arm/mach-highbank/localtimer.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Based on localtimer.c, Copyright (C) 2002 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/smp_twd.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
+ if (!twd_base) {
+ twd_base = of_iomap(np, 0);
+ WARN_ON(!twd_base);
+ }
+ evt->irq = irq_of_parse_and_map(np, 0);
+ twd_timer_setup(evt);
+ return 0;
+}
diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c
new file mode 100644
index 0000000..d01364c
--- /dev/null
+++ b/arch/arm/mach-highbank/platsmp.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.h>
+
+#include "core.h"
+
+extern void secondary_startup(void);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+ gic_secondary_init(0);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ gic_raise_softirq(cpumask_of(cpu), 0);
+ return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+ unsigned int i, ncores;
+
+ ncores = scu_get_core_count(scu_base_addr);
+
+ /* sanity check */
+ if (ncores > NR_CPUS) {
+ printk(KERN_WARNING
+ "highbank: no. of cores (%d) greater than configured "
+ "maximum of %d - clipping\n",
+ ncores, NR_CPUS);
+ ncores = NR_CPUS;
+ }
+
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+
+ set_smp_cross_call(gic_raise_softirq);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+ int i;
+
+ scu_enable(scu_base_addr);
+
+ /*
+ * Write the address of secondary startup into the jump table
+ * The cores are in wfi and wait until they receive a soft interrupt
+ * and a non-zero value to jump to. Then the secondary CPU branches
+ * to this address.
+ */
+ for (i = 1; i < max_cpus; i++)
+ highbank_set_cpu_jump(i, secondary_startup);
+}
diff --git a/arch/arm/mach-highbank/pm.c b/arch/arm/mach-highbank/pm.c
new file mode 100644
index 0000000..33b3beb
--- /dev/null
+++ b/arch/arm/mach-highbank/pm.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+
+#include <asm/proc-fns.h>
+#include <asm/smp_scu.h>
+#include <asm/suspend.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+static int highbank_suspend_finish(unsigned long val)
+{
+ cpu_do_idle();
+ return 0;
+}
+
+static int highbank_pm_enter(suspend_state_t state)
+{
+ hignbank_set_pwr_suspend();
+ highbank_set_cpu_jump(0, cpu_resume);
+
+ scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+ cpu_suspend(0, highbank_suspend_finish);
+
+ return 0;
+}
+
+static const struct platform_suspend_ops highbank_pm_ops = {
+ .enter = highbank_pm_enter,
+ .valid = suspend_valid_only_mem,
+};
+
+static int __init highbank_pm_init(void)
+{
+ suspend_set_ops(&highbank_pm_ops);
+ return 0;
+}
+module_init(highbank_pm_init);
diff --git a/arch/arm/mach-highbank/sysregs.h b/arch/arm/mach-highbank/sysregs.h
new file mode 100644
index 0000000..0e91338
--- /dev/null
+++ b/arch/arm/mach-highbank/sysregs.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _MACH_HIGHBANK__SYSREGS_H_
+#define _MACH_HIGHBANK__SYSREGS_H_
+
+#include <linux/io.h>
+
+extern void __iomem *sregs_base;
+
+#define HB_SREG_A9_PWR_REQ 0xf00
+#define HB_SREG_A9_BOOT_STAT 0xf04
+#define HB_SREG_A9_BOOT_DATA 0xf08
+
+#define HB_PWR_SUSPEND 0
+#define HB_PWR_SOFT_RESET 1
+#define HB_PWR_HARD_RESET 2
+#define HB_PWR_SHUTDOWN 3
+
+static inline void hignbank_set_pwr_suspend(void)
+{
+ writel(HB_PWR_SUSPEND, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_shutdown(void)
+{
+ writel(HB_PWR_SHUTDOWN, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_soft_reset(void)
+{
+ writel(HB_PWR_SOFT_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_hard_reset(void)
+{
+ writel(HB_PWR_HARD_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+#endif
diff --git a/arch/arm/mach-highbank/system.c b/arch/arm/mach-highbank/system.c
new file mode 100644
index 0000000..53f0c4c
--- /dev/null
+++ b/arch/arm/mach-highbank/system.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/io.h>
+#include <asm/smp_scu.h>
+#include <asm/proc-fns.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+void arch_reset(char mode, const char *cmd)
+{
+ if (mode == 'h')
+ hignbank_set_pwr_hard_reset();
+ else
+ hignbank_set_pwr_soft_reset();
+
+ scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+ cpu_do_idle();
+}
+
diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c
new file mode 100644
index 0000000..039a7ab
--- /dev/null
+++ b/arch/arm/mach-imx/clock-imx6q.c
@@ -0,0 +1,2030 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/div64.h>
+#include <asm/mach/map.h>
+#include <mach/clock.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+#define PLL_BASE IMX_IO_ADDRESS(MX6Q_ANATOP_BASE_ADDR)
+#define PLL1_SYS (PLL_BASE + 0x000)
+#define PLL2_BUS (PLL_BASE + 0x030)
+#define PLL3_USB_OTG (PLL_BASE + 0x010)
+#define PLL4_AUDIO (PLL_BASE + 0x070)
+#define PLL5_VIDEO (PLL_BASE + 0x0a0)
+#define PLL6_MLB (PLL_BASE + 0x0d0)
+#define PLL7_USB_HOST (PLL_BASE + 0x020)
+#define PLL8_ENET (PLL_BASE + 0x0e0)
+#define PFD_480 (PLL_BASE + 0x0f0)
+#define PFD_528 (PLL_BASE + 0x100)
+#define PLL_NUM_OFFSET 0x010
+#define PLL_DENOM_OFFSET 0x020
+
+#define PFD0 7
+#define PFD1 15
+#define PFD2 23
+#define PFD3 31
+#define PFD_FRAC_MASK 0x3f
+
+#define BM_PLL_BYPASS (0x1 << 16)
+#define BM_PLL_ENABLE (0x1 << 13)
+#define BM_PLL_POWER_DOWN (0x1 << 12)
+#define BM_PLL_LOCK (0x1 << 31)
+#define BP_PLL_SYS_DIV_SELECT 0
+#define BM_PLL_SYS_DIV_SELECT (0x7f << 0)
+#define BP_PLL_BUS_DIV_SELECT 0
+#define BM_PLL_BUS_DIV_SELECT (0x1 << 0)
+#define BP_PLL_USB_DIV_SELECT 0
+#define BM_PLL_USB_DIV_SELECT (0x3 << 0)
+#define BP_PLL_AV_DIV_SELECT 0
+#define BM_PLL_AV_DIV_SELECT (0x7f << 0)
+#define BP_PLL_ENET_DIV_SELECT 0
+#define BM_PLL_ENET_DIV_SELECT (0x3 << 0)
+#define BM_PLL_ENET_EN_PCIE (0x1 << 19)
+#define BM_PLL_ENET_EN_SATA (0x1 << 20)
+
+#define CCM_BASE IMX_IO_ADDRESS(MX6Q_CCM_BASE_ADDR)
+#define CCR (CCM_BASE + 0x00)
+#define CCDR (CCM_BASE + 0x04)
+#define CSR (CCM_BASE + 0x08)
+#define CCSR (CCM_BASE + 0x0c)
+#define CACRR (CCM_BASE + 0x10)
+#define CBCDR (CCM_BASE + 0x14)
+#define CBCMR (CCM_BASE + 0x18)
+#define CSCMR1 (CCM_BASE + 0x1c)
+#define CSCMR2 (CCM_BASE + 0x20)
+#define CSCDR1 (CCM_BASE + 0x24)
+#define CS1CDR (CCM_BASE + 0x28)
+#define CS2CDR (CCM_BASE + 0x2c)
+#define CDCDR (CCM_BASE + 0x30)
+#define CHSCCDR (CCM_BASE + 0x34)
+#define CSCDR2 (CCM_BASE + 0x38)
+#define CSCDR3 (CCM_BASE + 0x3c)
+#define CSCDR4 (CCM_BASE + 0x40)
+#define CWDR (CCM_BASE + 0x44)
+#define CDHIPR (CCM_BASE + 0x48)
+#define CDCR (CCM_BASE + 0x4c)
+#define CTOR (CCM_BASE + 0x50)
+#define CLPCR (CCM_BASE + 0x54)
+#define CISR (CCM_BASE + 0x58)
+#define CIMR (CCM_BASE + 0x5c)
+#define CCOSR (CCM_BASE + 0x60)
+#define CGPR (CCM_BASE + 0x64)
+#define CCGR0 (CCM_BASE + 0x68)
+#define CCGR1 (CCM_BASE + 0x6c)
+#define CCGR2 (CCM_BASE + 0x70)
+#define CCGR3 (CCM_BASE + 0x74)
+#define CCGR4 (CCM_BASE + 0x78)
+#define CCGR5 (CCM_BASE + 0x7c)
+#define CCGR6 (CCM_BASE + 0x80)
+#define CCGR7 (CCM_BASE + 0x84)
+#define CMEOR (CCM_BASE + 0x88)
+
+#define CG0 0
+#define CG1 2
+#define CG2 4
+#define CG3 6
+#define CG4 8
+#define CG5 10
+#define CG6 12
+#define CG7 14
+#define CG8 16
+#define CG9 18
+#define CG10 20
+#define CG11 22
+#define CG12 24
+#define CG13 26
+#define CG14 28
+#define CG15 30
+
+#define BM_CCSR_PLL1_SW_SEL (0x1 << 2)
+#define BM_CCSR_STEP_SEL (0x1 << 8)
+
+#define BP_CACRR_ARM_PODF 0
+#define BM_CACRR_ARM_PODF (0x7 << 0)
+
+#define BP_CBCDR_PERIPH2_CLK2_PODF 0
+#define BM_CBCDR_PERIPH2_CLK2_PODF (0x7 << 0)
+#define BP_CBCDR_MMDC_CH1_AXI_PODF 3
+#define BM_CBCDR_MMDC_CH1_AXI_PODF (0x7 << 3)
+#define BP_CBCDR_AXI_SEL 6
+#define BM_CBCDR_AXI_SEL (0x3 << 6)
+#define BP_CBCDR_IPG_PODF 8
+#define BM_CBCDR_IPG_PODF (0x3 << 8)
+#define BP_CBCDR_AHB_PODF 10
+#define BM_CBCDR_AHB_PODF (0x7 << 10)
+#define BP_CBCDR_AXI_PODF 16
+#define BM_CBCDR_AXI_PODF (0x7 << 16)
+#define BP_CBCDR_MMDC_CH0_AXI_PODF 19
+#define BM_CBCDR_MMDC_CH0_AXI_PODF (0x7 << 19)
+#define BP_CBCDR_PERIPH_CLK_SEL 25
+#define BM_CBCDR_PERIPH_CLK_SEL (0x1 << 25)
+#define BP_CBCDR_PERIPH2_CLK_SEL 26
+#define BM_CBCDR_PERIPH2_CLK_SEL (0x1 << 26)
+#define BP_CBCDR_PERIPH_CLK2_PODF 27
+#define BM_CBCDR_PERIPH_CLK2_PODF (0x7 << 27)
+
+#define BP_CBCMR_GPU2D_AXI_SEL 0
+#define BM_CBCMR_GPU2D_AXI_SEL (0x1 << 0)
+#define BP_CBCMR_GPU3D_AXI_SEL 1
+#define BM_CBCMR_GPU3D_AXI_SEL (0x1 << 1)
+#define BP_CBCMR_GPU3D_CORE_SEL 4
+#define BM_CBCMR_GPU3D_CORE_SEL (0x3 << 4)
+#define BP_CBCMR_GPU3D_SHADER_SEL 8
+#define BM_CBCMR_GPU3D_SHADER_SEL (0x3 << 8)
+#define BP_CBCMR_PCIE_AXI_SEL 10
+#define BM_CBCMR_PCIE_AXI_SEL (0x1 << 10)
+#define BP_CBCMR_VDO_AXI_SEL 11
+#define BM_CBCMR_VDO_AXI_SEL (0x1 << 11)
+#define BP_CBCMR_PERIPH_CLK2_SEL 12
+#define BM_CBCMR_PERIPH_CLK2_SEL (0x3 << 12)
+#define BP_CBCMR_VPU_AXI_SEL 14
+#define BM_CBCMR_VPU_AXI_SEL (0x3 << 14)
+#define BP_CBCMR_GPU2D_CORE_SEL 16
+#define BM_CBCMR_GPU2D_CORE_SEL (0x3 << 16)
+#define BP_CBCMR_PRE_PERIPH_CLK_SEL 18
+#define BM_CBCMR_PRE_PERIPH_CLK_SEL (0x3 << 18)
+#define BP_CBCMR_PERIPH2_CLK2_SEL 20
+#define BM_CBCMR_PERIPH2_CLK2_SEL (0x1 << 20)
+#define BP_CBCMR_PRE_PERIPH2_CLK_SEL 21
+#define BM_CBCMR_PRE_PERIPH2_CLK_SEL (0x3 << 21)
+#define BP_CBCMR_GPU2D_CORE_PODF 23
+#define BM_CBCMR_GPU2D_CORE_PODF (0x7 << 23)
+#define BP_CBCMR_GPU3D_CORE_PODF 26
+#define BM_CBCMR_GPU3D_CORE_PODF (0x7 << 26)
+#define BP_CBCMR_GPU3D_SHADER_PODF 29
+#define BM_CBCMR_GPU3D_SHADER_PODF (0x7 << 29)
+
+#define BP_CSCMR1_PERCLK_PODF 0
+#define BM_CSCMR1_PERCLK_PODF (0x3f << 0)
+#define BP_CSCMR1_SSI1_SEL 10
+#define BM_CSCMR1_SSI1_SEL (0x3 << 10)
+#define BP_CSCMR1_SSI2_SEL 12
+#define BM_CSCMR1_SSI2_SEL (0x3 << 12)
+#define BP_CSCMR1_SSI3_SEL 14
+#define BM_CSCMR1_SSI3_SEL (0x3 << 14)
+#define BP_CSCMR1_USDHC1_SEL 16
+#define BM_CSCMR1_USDHC1_SEL (0x1 << 16)
+#define BP_CSCMR1_USDHC2_SEL 17
+#define BM_CSCMR1_USDHC2_SEL (0x1 << 17)
+#define BP_CSCMR1_USDHC3_SEL 18
+#define BM_CSCMR1_USDHC3_SEL (0x1 << 18)
+#define BP_CSCMR1_USDHC4_SEL 19
+#define BM_CSCMR1_USDHC4_SEL (0x1 << 19)
+#define BP_CSCMR1_EMI_PODF 20
+#define BM_CSCMR1_EMI_PODF (0x7 << 20)
+#define BP_CSCMR1_EMI_SLOW_PODF 23
+#define BM_CSCMR1_EMI_SLOW_PODF (0x7 << 23)
+#define BP_CSCMR1_EMI_SEL 27
+#define BM_CSCMR1_EMI_SEL (0x3 << 27)
+#define BP_CSCMR1_EMI_SLOW_SEL 29
+#define BM_CSCMR1_EMI_SLOW_SEL (0x3 << 29)
+
+#define BP_CSCMR2_CAN_PODF 2
+#define BM_CSCMR2_CAN_PODF (0x3f << 2)
+#define BM_CSCMR2_LDB_DI0_IPU_DIV (0x1 << 10)
+#define BM_CSCMR2_LDB_DI1_IPU_DIV (0x1 << 11)
+#define BP_CSCMR2_ESAI_SEL 19
+#define BM_CSCMR2_ESAI_SEL (0x3 << 19)
+
+#define BP_CSCDR1_UART_PODF 0
+#define BM_CSCDR1_UART_PODF (0x3f << 0)
+#define BP_CSCDR1_USDHC1_PODF 11
+#define BM_CSCDR1_USDHC1_PODF (0x7 << 11)
+#define BP_CSCDR1_USDHC2_PODF 16
+#define BM_CSCDR1_USDHC2_PODF (0x7 << 16)
+#define BP_CSCDR1_USDHC3_PODF 19
+#define BM_CSCDR1_USDHC3_PODF (0x7 << 19)
+#define BP_CSCDR1_USDHC4_PODF 22
+#define BM_CSCDR1_USDHC4_PODF (0x7 << 22)
+#define BP_CSCDR1_VPU_AXI_PODF 25
+#define BM_CSCDR1_VPU_AXI_PODF (0x7 << 25)
+
+#define BP_CS1CDR_SSI1_PODF 0
+#define BM_CS1CDR_SSI1_PODF (0x3f << 0)
+#define BP_CS1CDR_SSI1_PRED 6
+#define BM_CS1CDR_SSI1_PRED (0x7 << 6)
+#define BP_CS1CDR_ESAI_PRED 9
+#define BM_CS1CDR_ESAI_PRED (0x7 << 9)
+#define BP_CS1CDR_SSI3_PODF 16
+#define BM_CS1CDR_SSI3_PODF (0x3f << 16)
+#define BP_CS1CDR_SSI3_PRED 22
+#define BM_CS1CDR_SSI3_PRED (0x7 << 22)
+#define BP_CS1CDR_ESAI_PODF 25
+#define BM_CS1CDR_ESAI_PODF (0x7 << 25)
+
+#define BP_CS2CDR_SSI2_PODF 0
+#define BM_CS2CDR_SSI2_PODF (0x3f << 0)
+#define BP_CS2CDR_SSI2_PRED 6
+#define BM_CS2CDR_SSI2_PRED (0x7 << 6)
+#define BP_CS2CDR_LDB_DI0_SEL 9
+#define BM_CS2CDR_LDB_DI0_SEL (0x7 << 9)
+#define BP_CS2CDR_LDB_DI1_SEL 12
+#define BM_CS2CDR_LDB_DI1_SEL (0x7 << 12)
+#define BP_CS2CDR_ENFC_SEL 16
+#define BM_CS2CDR_ENFC_SEL (0x3 << 16)
+#define BP_CS2CDR_ENFC_PRED 18
+#define BM_CS2CDR_ENFC_PRED (0x7 << 18)
+#define BP_CS2CDR_ENFC_PODF 21
+#define BM_CS2CDR_ENFC_PODF (0x3f << 21)
+
+#define BP_CDCDR_ASRC_SERIAL_SEL 7
+#define BM_CDCDR_ASRC_SERIAL_SEL (0x3 << 7)
+#define BP_CDCDR_ASRC_SERIAL_PODF 9
+#define BM_CDCDR_ASRC_SERIAL_PODF (0x7 << 9)
+#define BP_CDCDR_ASRC_SERIAL_PRED 12
+#define BM_CDCDR_ASRC_SERIAL_PRED (0x7 << 12)
+#define BP_CDCDR_SPDIF_SEL 20
+#define BM_CDCDR_SPDIF_SEL (0x3 << 20)
+#define BP_CDCDR_SPDIF_PODF 22
+#define BM_CDCDR_SPDIF_PODF (0x7 << 22)
+#define BP_CDCDR_SPDIF_PRED 25
+#define BM_CDCDR_SPDIF_PRED (0x7 << 25)
+#define BP_CDCDR_HSI_TX_PODF 29
+#define BM_CDCDR_HSI_TX_PODF (0x7 << 29)
+#define BP_CDCDR_HSI_TX_SEL 28
+#define BM_CDCDR_HSI_TX_SEL (0x1 << 28)
+
+#define BP_CHSCCDR_IPU1_DI0_SEL 0
+#define BM_CHSCCDR_IPU1_DI0_SEL (0x7 << 0)
+#define BP_CHSCCDR_IPU1_DI0_PRE_PODF 3
+#define BM_CHSCCDR_IPU1_DI0_PRE_PODF (0x7 << 3)
+#define BP_CHSCCDR_IPU1_DI0_PRE_SEL 6
+#define BM_CHSCCDR_IPU1_DI0_PRE_SEL (0x7 << 6)
+#define BP_CHSCCDR_IPU1_DI1_SEL 9
+#define BM_CHSCCDR_IPU1_DI1_SEL (0x7 << 9)
+#define BP_CHSCCDR_IPU1_DI1_PRE_PODF 12
+#define BM_CHSCCDR_IPU1_DI1_PRE_PODF (0x7 << 12)
+#define BP_CHSCCDR_IPU1_DI1_PRE_SEL 15
+#define BM_CHSCCDR_IPU1_DI1_PRE_SEL (0x7 << 15)
+
+#define BP_CSCDR2_IPU2_DI0_SEL 0
+#define BM_CSCDR2_IPU2_DI0_SEL (0x7)
+#define BP_CSCDR2_IPU2_DI0_PRE_PODF 3
+#define BM_CSCDR2_IPU2_DI0_PRE_PODF (0x7 << 3)
+#define BP_CSCDR2_IPU2_DI0_PRE_SEL 6
+#define BM_CSCDR2_IPU2_DI0_PRE_SEL (0x7 << 6)
+#define BP_CSCDR2_IPU2_DI1_SEL 9
+#define BM_CSCDR2_IPU2_DI1_SEL (0x7 << 9)
+#define BP_CSCDR2_IPU2_DI1_PRE_PODF 12
+#define BM_CSCDR2_IPU2_DI1_PRE_PODF (0x7 << 12)
+#define BP_CSCDR2_IPU2_DI1_PRE_SEL 15
+#define BM_CSCDR2_IPU2_DI1_PRE_SEL (0x7 << 15)
+#define BP_CSCDR2_ECSPI_CLK_PODF 19
+#define BM_CSCDR2_ECSPI_CLK_PODF (0x3f << 19)
+
+#define BP_CSCDR3_IPU1_HSP_SEL 9
+#define BM_CSCDR3_IPU1_HSP_SEL (0x3 << 9)
+#define BP_CSCDR3_IPU1_HSP_PODF 11
+#define BM_CSCDR3_IPU1_HSP_PODF (0x7 << 11)
+#define BP_CSCDR3_IPU2_HSP_SEL 14
+#define BM_CSCDR3_IPU2_HSP_SEL (0x3 << 14)
+#define BP_CSCDR3_IPU2_HSP_PODF 16
+#define BM_CSCDR3_IPU2_HSP_PODF (0x7 << 16)
+
+#define BM_CDHIPR_AXI_PODF_BUSY (0x1 << 0)
+#define BM_CDHIPR_AHB_PODF_BUSY (0x1 << 1)
+#define BM_CDHIPR_MMDC_CH1_PODF_BUSY (0x1 << 2)
+#define BM_CDHIPR_PERIPH2_SEL_BUSY (0x1 << 3)
+#define BM_CDHIPR_MMDC_CH0_PODF_BUSY (0x1 << 4)
+#define BM_CDHIPR_PERIPH_SEL_BUSY (0x1 << 5)
+#define BM_CDHIPR_ARM_PODF_BUSY (0x1 << 16)
+
+#define BP_CLPCR_LPM 0
+#define BM_CLPCR_LPM (0x3 << 0)
+#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
+#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
+#define BM_CLPCR_SBYOS (0x1 << 6)
+#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
+#define BM_CLPCR_VSTBY (0x1 << 8)
+#define BP_CLPCR_STBY_COUNT 9
+#define BM_CLPCR_STBY_COUNT (0x3 << 9)
+#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
+#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
+#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
+#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
+#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
+#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
+#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
+#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
+#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
+#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
+#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
+
+#define FREQ_480M 480000000
+#define FREQ_528M 528000000
+#define FREQ_594M 594000000
+#define FREQ_650M 650000000
+#define FREQ_1300M 1300000000
+
+static struct clk pll1_sys;
+static struct clk pll2_bus;
+static struct clk pll3_usb_otg;
+static struct clk pll4_audio;
+static struct clk pll5_video;
+static struct clk pll6_mlb;
+static struct clk pll7_usb_host;
+static struct clk pll8_enet;
+static struct clk apbh_dma_clk;
+static struct clk arm_clk;
+static struct clk ipg_clk;
+static struct clk ahb_clk;
+static struct clk axi_clk;
+static struct clk mmdc_ch0_axi_clk;
+static struct clk mmdc_ch1_axi_clk;
+static struct clk periph_clk;
+static struct clk periph_pre_clk;
+static struct clk periph_clk2_clk;
+static struct clk periph2_clk;
+static struct clk periph2_pre_clk;
+static struct clk periph2_clk2_clk;
+static struct clk gpu2d_core_clk;
+static struct clk gpu3d_core_clk;
+static struct clk gpu3d_shader_clk;
+static struct clk ipg_perclk;
+static struct clk emi_clk;
+static struct clk emi_slow_clk;
+static struct clk can1_clk;
+static struct clk uart_clk;
+static struct clk usdhc1_clk;
+static struct clk usdhc2_clk;
+static struct clk usdhc3_clk;
+static struct clk usdhc4_clk;
+static struct clk vpu_clk;
+static struct clk hsi_tx_clk;
+static struct clk ipu1_di0_pre_clk;
+static struct clk ipu1_di1_pre_clk;
+static struct clk ipu2_di0_pre_clk;
+static struct clk ipu2_di1_pre_clk;
+static struct clk ipu1_clk;
+static struct clk ipu2_clk;
+static struct clk ssi1_clk;
+static struct clk ssi3_clk;
+static struct clk esai_clk;
+static struct clk ssi2_clk;
+static struct clk spdif_clk;
+static struct clk asrc_serial_clk;
+static struct clk gpu2d_axi_clk;
+static struct clk gpu3d_axi_clk;
+static struct clk pcie_clk;
+static struct clk vdo_axi_clk;
+static struct clk ldb_di0_clk;
+static struct clk ldb_di1_clk;
+static struct clk ipu1_di0_clk;
+static struct clk ipu1_di1_clk;
+static struct clk ipu2_di0_clk;
+static struct clk ipu2_di1_clk;
+static struct clk enfc_clk;
+static struct clk dummy_clk = {};
+
+static unsigned long external_high_reference;
+static unsigned long external_low_reference;
+static unsigned long oscillator_reference;
+
+static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
+{
+ return oscillator_reference;
+}
+
+static unsigned long get_high_reference_clock_rate(struct clk *clk)
+{
+ return external_high_reference;
+}
+
+static unsigned long get_low_reference_clock_rate(struct clk *clk)
+{
+ return external_low_reference;
+}
+
+static struct clk ckil_clk = {
+ .get_rate = get_low_reference_clock_rate,
+};
+
+static struct clk ckih_clk = {
+ .get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+ .get_rate = get_oscillator_reference_clock_rate,
+};
+
+static inline void __iomem *pll_get_reg_addr(struct clk *pll)
+{
+ if (pll == &pll1_sys)
+ return PLL1_SYS;
+ else if (pll == &pll2_bus)
+ return PLL2_BUS;
+ else if (pll == &pll3_usb_otg)
+ return PLL3_USB_OTG;
+ else if (pll == &pll4_audio)
+ return PLL4_AUDIO;
+ else if (pll == &pll5_video)
+ return PLL5_VIDEO;
+ else if (pll == &pll6_mlb)
+ return PLL6_MLB;
+ else if (pll == &pll7_usb_host)
+ return PLL7_USB_HOST;
+ else if (pll == &pll8_enet)
+ return PLL8_ENET;
+ else
+ BUG();
+
+ return NULL;
+}
+
+static int pll_enable(struct clk *clk)
+{
+ int timeout = 0x100000;
+ void __iomem *reg;
+ u32 val;
+
+ reg = pll_get_reg_addr(clk);
+ val = readl_relaxed(reg);
+ val &= ~BM_PLL_BYPASS;
+ val &= ~BM_PLL_POWER_DOWN;
+ /* 480MHz PLLs have the opposite definition for power bit */
+ if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
+ val |= BM_PLL_POWER_DOWN;
+ writel_relaxed(val, reg);
+
+ /* Wait for PLL to lock */
+ while (!(readl_relaxed(reg) & BM_PLL_LOCK) && --timeout)
+ cpu_relax();
+
+ if (unlikely(!timeout))
+ return -EBUSY;
+
+ /* Enable the PLL output now */
+ val = readl_relaxed(reg);
+ val |= BM_PLL_ENABLE;
+ writel_relaxed(val, reg);
+
+ return 0;
+}
+
+static void pll_disable(struct clk *clk)
+{
+ void __iomem *reg;
+ u32 val;
+
+ reg = pll_get_reg_addr(clk);
+ val = readl_relaxed(reg);
+ val &= ~BM_PLL_ENABLE;
+ val |= BM_PLL_BYPASS;
+ val |= BM_PLL_POWER_DOWN;
+ if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
+ val &= ~BM_PLL_POWER_DOWN;
+ writel_relaxed(val, reg);
+}
+
+static unsigned long pll1_sys_get_rate(struct clk *clk)
+{
+ u32 div = (readl_relaxed(PLL1_SYS) & BM_PLL_SYS_DIV_SELECT) >>
+ BP_PLL_SYS_DIV_SELECT;
+
+ return clk_get_rate(clk->parent) * div / 2;
+}
+
+static int pll1_sys_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 val, div;
+
+ if (rate < FREQ_650M || rate > FREQ_1300M)
+ return -EINVAL;
+
+ div = rate * 2 / clk_get_rate(clk->parent);
+ val = readl_relaxed(PLL1_SYS);
+ val &= ~BM_PLL_SYS_DIV_SELECT;
+ val |= div << BP_PLL_SYS_DIV_SELECT;
+ writel_relaxed(val, PLL1_SYS);
+
+ return 0;
+}
+
+static unsigned long pll8_enet_get_rate(struct clk *clk)
+{
+ u32 div = (readl_relaxed(PLL8_ENET) & BM_PLL_ENET_DIV_SELECT) >>
+ BP_PLL_ENET_DIV_SELECT;
+
+ switch (div) {
+ case 0:
+ return 25000000;
+ case 1:
+ return 50000000;
+ case 2:
+ return 100000000;
+ case 3:
+ return 125000000;
+ }
+
+ return 0;
+}
+
+static int pll8_enet_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 val, div;
+
+ switch (rate) {
+ case 25000000:
+ div = 0;
+ break;
+ case 50000000:
+ div = 1;
+ break;
+ case 100000000:
+ div = 2;
+ break;
+ case 125000000:
+ div = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ val = readl_relaxed(PLL8_ENET);
+ val &= ~BM_PLL_ENET_DIV_SELECT;
+ val |= div << BP_PLL_ENET_DIV_SELECT;
+ writel_relaxed(val, PLL8_ENET);
+
+ return 0;
+}
+
+static unsigned long pll_av_get_rate(struct clk *clk)
+{
+ void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ u32 mfn = readl_relaxed(reg + PLL_NUM_OFFSET);
+ u32 mfd = readl_relaxed(reg + PLL_DENOM_OFFSET);
+ u32 div = (readl_relaxed(reg) & BM_PLL_AV_DIV_SELECT) >>
+ BP_PLL_AV_DIV_SELECT;
+
+ return (parent_rate * div) + ((parent_rate / mfd) * mfn);
+}
+
+static int pll_av_set_rate(struct clk *clk, unsigned long rate)
+{
+ void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
+ unsigned int parent_rate = clk_get_rate(clk->parent);
+ u32 val, div;
+ u32 mfn, mfd = 1000000;
+ s64 temp64;
+
+ if (rate < FREQ_650M || rate > FREQ_1300M)
+ return -EINVAL;
+
+ div = rate / parent_rate;
+ temp64 = (u64) (rate - div * parent_rate);
+ temp64 *= mfd;
+ do_div(temp64, parent_rate);
+ mfn = temp64;
+
+ val = readl_relaxed(reg);
+ val &= ~BM_PLL_AV_DIV_SELECT;
+ val |= div << BP_PLL_AV_DIV_SELECT;
+ writel_relaxed(val, reg);
+ writel_relaxed(mfn, reg + PLL_NUM_OFFSET);
+ writel_relaxed(mfd, reg + PLL_DENOM_OFFSET);
+
+ return 0;
+}
+
+static void __iomem *pll_get_div_reg_bit(struct clk *clk, u32 *bp, u32 *bm)
+{
+ void __iomem *reg;
+
+ if (clk == &pll2_bus) {
+ reg = PLL2_BUS;
+ *bp = BP_PLL_BUS_DIV_SELECT;
+ *bm = BM_PLL_BUS_DIV_SELECT;
+ } else if (clk == &pll3_usb_otg) {
+ reg = PLL3_USB_OTG;
+ *bp = BP_PLL_USB_DIV_SELECT;
+ *bm = BM_PLL_USB_DIV_SELECT;
+ } else if (clk == &pll7_usb_host) {
+ reg = PLL7_USB_HOST;
+ *bp = BP_PLL_USB_DIV_SELECT;
+ *bm = BM_PLL_USB_DIV_SELECT;
+ } else {
+ BUG();
+ }
+
+ return reg;
+}
+
+static unsigned long pll_get_rate(struct clk *clk)
+{
+ void __iomem *reg;
+ u32 div, bp, bm;
+
+ reg = pll_get_div_reg_bit(clk, &bp, &bm);
+ div = (readl_relaxed(reg) & bm) >> bp;
+
+ return (div == 1) ? clk_get_rate(clk->parent) * 22 :
+ clk_get_rate(clk->parent) * 20;
+}
+
+static int pll_set_rate(struct clk *clk, unsigned long rate)
+{
+ void __iomem *reg;
+ u32 val, div, bp, bm;
+
+ if (rate == FREQ_528M)
+ div = 1;
+ else if (rate == FREQ_480M)
+ div = 0;
+ else
+ return -EINVAL;
+
+ reg = pll_get_div_reg_bit(clk, &bp, &bm);
+ val = readl_relaxed(reg);
+ val &= ~bm;
+ val |= div << bp;
+ writel_relaxed(val, reg);
+
+ return 0;
+}
+
+#define pll2_bus_get_rate pll_get_rate
+#define pll2_bus_set_rate pll_set_rate
+#define pll3_usb_otg_get_rate pll_get_rate
+#define pll3_usb_otg_set_rate pll_set_rate
+#define pll7_usb_host_get_rate pll_get_rate
+#define pll7_usb_host_set_rate pll_set_rate
+#define pll4_audio_get_rate pll_av_get_rate
+#define pll4_audio_set_rate pll_av_set_rate
+#define pll5_video_get_rate pll_av_get_rate
+#define pll5_video_set_rate pll_av_set_rate
+#define pll6_mlb_get_rate NULL
+#define pll6_mlb_set_rate NULL
+
+#define DEF_PLL(name) \
+ static struct clk name = { \
+ .enable = pll_enable, \
+ .disable = pll_disable, \
+ .get_rate = name##_get_rate, \
+ .set_rate = name##_set_rate, \
+ .parent = &osc_clk, \
+ }
+
+DEF_PLL(pll1_sys);
+DEF_PLL(pll2_bus);
+DEF_PLL(pll3_usb_otg);
+DEF_PLL(pll4_audio);
+DEF_PLL(pll5_video);
+DEF_PLL(pll6_mlb);
+DEF_PLL(pll7_usb_host);
+DEF_PLL(pll8_enet);
+
+static unsigned long pfd_get_rate(struct clk *clk)
+{
+ u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
+ u32 frac, bp_frac;
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+
+ bp_frac = clk->enable_shift - 7;
+ frac = readl_relaxed(clk->enable_reg) >> bp_frac & PFD_FRAC_MASK;
+ do_div(tmp, frac);
+
+ return tmp;
+}
+
+static int pfd_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 val, frac, bp_frac;
+ u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+
+ /*
+ * Round up the divider so that we don't set a rate
+ * higher than what is requested
+ */
+ tmp += rate / 2;
+ do_div(tmp, rate);
+ frac = tmp;
+ frac = (frac < 12) ? 12 : frac;
+ frac = (frac > 35) ? 35 : frac;
+
+ /*
+ * The frac field always starts from 7 bits lower
+ * position of enable bit
+ */
+ bp_frac = clk->enable_shift - 7;
+ val = readl_relaxed(clk->enable_reg);
+ val &= ~(PFD_FRAC_MASK << bp_frac);
+ val |= frac << bp_frac;
+ writel_relaxed(val, clk->enable_reg);
+
+ tmp = (u64) clk_get_rate(clk->parent) * 18;
+ do_div(tmp, frac);
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.disable(&apbh_dma_clk);
+
+ return 0;
+}
+
+static unsigned long pfd_round_rate(struct clk *clk, unsigned long rate)
+{
+ u32 frac;
+ u64 tmp;
+
+ tmp = (u64) clk_get_rate(clk->parent) * 18;
+ tmp += rate / 2;
+ do_div(tmp, rate);
+ frac = tmp;
+ frac = (frac < 12) ? 12 : frac;
+ frac = (frac > 35) ? 35 : frac;
+ tmp = (u64) clk_get_rate(clk->parent) * 18;
+ do_div(tmp, frac);
+
+ return tmp;
+}
+
+static int pfd_enable(struct clk *clk)
+{
+ u32 val;
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+
+ val = readl_relaxed(clk->enable_reg);
+ val &= ~(1 << clk->enable_shift);
+ writel_relaxed(val, clk->enable_reg);
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.disable(&apbh_dma_clk);
+
+ return 0;
+}
+
+static void pfd_disable(struct clk *clk)
+{
+ u32 val;
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+
+ val = readl_relaxed(clk->enable_reg);
+ val |= 1 << clk->enable_shift;
+ writel_relaxed(val, clk->enable_reg);
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.disable(&apbh_dma_clk);
+}
+
+#define DEF_PFD(name, er, es, p) \
+ static struct clk name = { \
+ .enable_reg = er, \
+ .enable_shift = es, \
+ .enable = pfd_enable, \
+ .disable = pfd_disable, \
+ .get_rate = pfd_get_rate, \
+ .set_rate = pfd_set_rate, \
+ .round_rate = pfd_round_rate, \
+ .parent = p, \
+ }
+
+DEF_PFD(pll2_pfd_352m, PFD_528, PFD0, &pll2_bus);
+DEF_PFD(pll2_pfd_594m, PFD_528, PFD1, &pll2_bus);
+DEF_PFD(pll2_pfd_400m, PFD_528, PFD2, &pll2_bus);
+DEF_PFD(pll3_pfd_720m, PFD_480, PFD0, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_540m, PFD_480, PFD1, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_508m, PFD_480, PFD2, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_454m, PFD_480, PFD3, &pll3_usb_otg);
+
+static unsigned long pll2_200m_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk pll2_200m = {
+ .parent = &pll2_pfd_400m,
+ .get_rate = pll2_200m_get_rate,
+};
+
+static unsigned long pll3_120m_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 4;
+}
+
+static struct clk pll3_120m = {
+ .parent = &pll3_usb_otg,
+ .get_rate = pll3_120m_get_rate,
+};
+
+static unsigned long pll3_80m_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 6;
+}
+
+static struct clk pll3_80m = {
+ .parent = &pll3_usb_otg,
+ .get_rate = pll3_80m_get_rate,
+};
+
+static unsigned long pll3_60m_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 8;
+}
+
+static struct clk pll3_60m = {
+ .parent = &pll3_usb_otg,
+ .get_rate = pll3_60m_get_rate,
+};
+
+static int pll1_sw_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 val = readl_relaxed(CCSR);
+
+ if (parent == &pll1_sys) {
+ val &= ~BM_CCSR_PLL1_SW_SEL;
+ val &= ~BM_CCSR_STEP_SEL;
+ } else if (parent == &osc_clk) {
+ val |= BM_CCSR_PLL1_SW_SEL;
+ val &= ~BM_CCSR_STEP_SEL;
+ } else if (parent == &pll2_pfd_400m) {
+ val |= BM_CCSR_PLL1_SW_SEL;
+ val |= BM_CCSR_STEP_SEL;
+ } else {
+ return -EINVAL;
+ }
+
+ writel_relaxed(val, CCSR);
+
+ return 0;
+}
+
+static struct clk pll1_sw_clk = {
+ .parent = &pll1_sys,
+ .set_parent = pll1_sw_clk_set_parent,
+};
+
+static void calc_pred_podf_dividers(u32 div, u32 *pred, u32 *podf)
+{
+ u32 min_pred, temp_pred, old_err, err;
+
+ if (div >= 512) {
+ *pred = 8;
+ *podf = 64;
+ } else if (div >= 8) {
+ min_pred = (div - 1) / 64 + 1;
+ old_err = 8;
+ for (temp_pred = 8; temp_pred >= min_pred; temp_pred--) {
+ err = div % temp_pred;
+ if (err == 0) {
+ *pred = temp_pred;
+ break;
+ }
+ err = temp_pred - err;
+ if (err < old_err) {
+ old_err = err;
+ *pred = temp_pred;
+ }
+ }
+ *podf = (div + *pred - 1) / *pred;
+ } else if (div < 8) {
+ *pred = div;
+ *podf = 1;
+ }
+}
+
+static int _clk_enable(struct clk *clk)
+{
+ u32 reg;
+ reg = readl_relaxed(clk->enable_reg);
+ reg |= 0x3 << clk->enable_shift;
+ writel_relaxed(reg, clk->enable_reg);
+
+ return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+ u32 reg;
+ reg = readl_relaxed(clk->enable_reg);
+ reg &= ~(0x3 << clk->enable_shift);
+ writel_relaxed(reg, clk->enable_reg);
+}
+
+struct divider {
+ struct clk *clk;
+ void __iomem *reg;
+ u32 bp_pred;
+ u32 bm_pred;
+ u32 bp_podf;
+ u32 bm_podf;
+};
+
+#define DEF_CLK_DIV1(d, c, r, b) \
+ static struct divider d = { \
+ .clk = c, \
+ .reg = r, \
+ .bp_podf = BP_##r##_##b##_PODF, \
+ .bm_podf = BM_##r##_##b##_PODF, \
+ }
+
+DEF_CLK_DIV1(arm_div, &arm_clk, CACRR, ARM);
+DEF_CLK_DIV1(ipg_div, &ipg_clk, CBCDR, IPG);
+DEF_CLK_DIV1(ahb_div, &ahb_clk, CBCDR, AHB);
+DEF_CLK_DIV1(axi_div, &axi_clk, CBCDR, AXI);
+DEF_CLK_DIV1(mmdc_ch0_axi_div, &mmdc_ch0_axi_clk, CBCDR, MMDC_CH0_AXI);
+DEF_CLK_DIV1(mmdc_ch1_axi_div, &mmdc_ch1_axi_clk, CBCDR, MMDC_CH1_AXI);
+DEF_CLK_DIV1(periph_clk2_div, &periph_clk2_clk, CBCDR, PERIPH_CLK2);
+DEF_CLK_DIV1(periph2_clk2_div, &periph2_clk2_clk, CBCDR, PERIPH2_CLK2);
+DEF_CLK_DIV1(gpu2d_core_div, &gpu2d_core_clk, CBCMR, GPU2D_CORE);
+DEF_CLK_DIV1(gpu3d_core_div, &gpu3d_core_clk, CBCMR, GPU3D_CORE);
+DEF_CLK_DIV1(gpu3d_shader_div, &gpu3d_shader_clk, CBCMR, GPU3D_SHADER);
+DEF_CLK_DIV1(ipg_perclk_div, &ipg_perclk, CSCMR1, PERCLK);
+DEF_CLK_DIV1(emi_div, &emi_clk, CSCMR1, EMI);
+DEF_CLK_DIV1(emi_slow_div, &emi_slow_clk, CSCMR1, EMI_SLOW);
+DEF_CLK_DIV1(can_div, &can1_clk, CSCMR2, CAN);
+DEF_CLK_DIV1(uart_div, &uart_clk, CSCDR1, UART);
+DEF_CLK_DIV1(usdhc1_div, &usdhc1_clk, CSCDR1, USDHC1);
+DEF_CLK_DIV1(usdhc2_div, &usdhc2_clk, CSCDR1, USDHC2);
+DEF_CLK_DIV1(usdhc3_div, &usdhc3_clk, CSCDR1, USDHC3);
+DEF_CLK_DIV1(usdhc4_div, &usdhc4_clk, CSCDR1, USDHC4);
+DEF_CLK_DIV1(vpu_div, &vpu_clk, CSCDR1, VPU_AXI);
+DEF_CLK_DIV1(hsi_tx_div, &hsi_tx_clk, CDCDR, HSI_TX);
+DEF_CLK_DIV1(ipu1_di0_pre_div, &ipu1_di0_pre_clk, CHSCCDR, IPU1_DI0_PRE);
+DEF_CLK_DIV1(ipu1_di1_pre_div, &ipu1_di1_pre_clk, CHSCCDR, IPU1_DI1_PRE);
+DEF_CLK_DIV1(ipu2_di0_pre_div, &ipu2_di0_pre_clk, CSCDR2, IPU2_DI0_PRE);
+DEF_CLK_DIV1(ipu2_di1_pre_div, &ipu2_di1_pre_clk, CSCDR2, IPU2_DI1_PRE);
+DEF_CLK_DIV1(ipu1_div, &ipu1_clk, CSCDR3, IPU1_HSP);
+DEF_CLK_DIV1(ipu2_div, &ipu2_clk, CSCDR3, IPU2_HSP);
+
+#define DEF_CLK_DIV2(d, c, r, b) \
+ static struct divider d = { \
+ .clk = c, \
+ .reg = r, \
+ .bp_pred = BP_##r##_##b##_PRED, \
+ .bm_pred = BM_##r##_##b##_PRED, \
+ .bp_podf = BP_##r##_##b##_PODF, \
+ .bm_podf = BM_##r##_##b##_PODF, \
+ }
+
+DEF_CLK_DIV2(ssi1_div, &ssi1_clk, CS1CDR, SSI1);
+DEF_CLK_DIV2(ssi3_div, &ssi3_clk, CS1CDR, SSI3);
+DEF_CLK_DIV2(esai_div, &esai_clk, CS1CDR, ESAI);
+DEF_CLK_DIV2(ssi2_div, &ssi2_clk, CS2CDR, SSI2);
+DEF_CLK_DIV2(enfc_div, &enfc_clk, CS2CDR, ENFC);
+DEF_CLK_DIV2(spdif_div, &spdif_clk, CDCDR, SPDIF);
+DEF_CLK_DIV2(asrc_serial_div, &asrc_serial_clk, CDCDR, ASRC_SERIAL);
+
+static struct divider *dividers[] = {
+ &arm_div,
+ &ipg_div,
+ &ahb_div,
+ &axi_div,
+ &mmdc_ch0_axi_div,
+ &mmdc_ch1_axi_div,
+ &periph_clk2_div,
+ &periph2_clk2_div,
+ &gpu2d_core_div,
+ &gpu3d_core_div,
+ &gpu3d_shader_div,
+ &ipg_perclk_div,
+ &emi_div,
+ &emi_slow_div,
+ &can_div,
+ &uart_div,
+ &usdhc1_div,
+ &usdhc2_div,
+ &usdhc3_div,
+ &usdhc4_div,
+ &vpu_div,
+ &hsi_tx_div,
+ &ipu1_di0_pre_div,
+ &ipu1_di1_pre_div,
+ &ipu2_di0_pre_div,
+ &ipu2_di1_pre_div,
+ &ipu1_div,
+ &ipu2_div,
+ &ssi1_div,
+ &ssi3_div,
+ &esai_div,
+ &ssi2_div,
+ &enfc_div,
+ &spdif_div,
+ &asrc_serial_div,
+};
+
+static unsigned long ldb_di_clk_get_rate(struct clk *clk)
+{
+ u32 val = readl_relaxed(CSCMR2);
+
+ val &= (clk == &ldb_di0_clk) ? BM_CSCMR2_LDB_DI0_IPU_DIV :
+ BM_CSCMR2_LDB_DI1_IPU_DIV;
+ if (val)
+ return clk_get_rate(clk->parent) / 7;
+ else
+ return clk_get_rate(clk->parent) * 2 / 7;
+}
+
+static int ldb_di_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ u32 val = readl_relaxed(CSCMR2);
+
+ if (rate * 7 <= parent_rate + parent_rate / 20)
+ val |= BM_CSCMR2_LDB_DI0_IPU_DIV;
+ else
+ val &= ~BM_CSCMR2_LDB_DI0_IPU_DIV;
+
+ writel_relaxed(val, CSCMR2);
+
+ return 0;
+}
+
+static unsigned long ldb_di_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+
+ if (rate * 7 <= parent_rate + parent_rate / 20)
+ return parent_rate / 7;
+ else
+ return 2 * parent_rate / 7;
+}
+
+static unsigned long _clk_get_rate(struct clk *clk)
+{
+ struct divider *d;
+ u32 val, pred, podf;
+ int i, num;
+
+ if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+ return ldb_di_clk_get_rate(clk);
+
+ num = ARRAY_SIZE(dividers);
+ for (i = 0; i < num; i++)
+ if (dividers[i]->clk == clk) {
+ d = dividers[i];
+ break;
+ }
+ if (i == num)
+ return clk_get_rate(clk->parent);
+
+ val = readl_relaxed(d->reg);
+ pred = ((val & d->bm_pred) >> d->bp_pred) + 1;
+ podf = ((val & d->bm_podf) >> d->bp_podf) + 1;
+
+ return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int clk_busy_wait(struct clk *clk)
+{
+ int timeout = 0x100000;
+ u32 bm;
+
+ if (clk == &axi_clk)
+ bm = BM_CDHIPR_AXI_PODF_BUSY;
+ else if (clk == &ahb_clk)
+ bm = BM_CDHIPR_AHB_PODF_BUSY;
+ else if (clk == &mmdc_ch0_axi_clk)
+ bm = BM_CDHIPR_MMDC_CH0_PODF_BUSY;
+ else if (clk == &periph_clk)
+ bm = BM_CDHIPR_PERIPH_SEL_BUSY;
+ else if (clk == &arm_clk)
+ bm = BM_CDHIPR_ARM_PODF_BUSY;
+ else
+ return -EINVAL;
+
+ while ((readl_relaxed(CDHIPR) & bm) && --timeout)
+ cpu_relax();
+
+ if (unlikely(!timeout))
+ return -EBUSY;
+
+ return 0;
+}
+
+static int _clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ struct divider *d;
+ u32 val, div, max_div, pred = 0, podf;
+ int i, num;
+
+ if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+ return ldb_di_clk_set_rate(clk, rate);
+
+ num = ARRAY_SIZE(dividers);
+ for (i = 0; i < num; i++)
+ if (dividers[i]->clk == clk) {
+ d = dividers[i];
+ break;
+ }
+ if (i == num)
+ return -EINVAL;
+
+ max_div = ((d->bm_pred >> d->bp_pred) + 1) *
+ ((d->bm_podf >> d->bp_podf) + 1);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+
+ if ((parent_rate / div != rate) || div > max_div)
+ return -EINVAL;
+
+ if (d->bm_pred) {
+ calc_pred_podf_dividers(div, &pred, &podf);
+ } else {
+ pred = 1;
+ podf = div;
+ }
+
+ val = readl_relaxed(d->reg);
+ val &= ~(d->bm_pred | d->bm_podf);
+ val |= (pred - 1) << d->bp_pred | (podf - 1) << d->bp_podf;
+ writel_relaxed(val, d->reg);
+
+ if (clk == &axi_clk || clk == &ahb_clk ||
+ clk == &mmdc_ch0_axi_clk || clk == &arm_clk)
+ return clk_busy_wait(clk);
+
+ return 0;
+}
+
+static unsigned long _clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+ u32 div_max, pred = 0, podf;
+ struct divider *d;
+ int i, num;
+
+ if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+ return ldb_di_clk_round_rate(clk, rate);
+
+ num = ARRAY_SIZE(dividers);
+ for (i = 0; i < num; i++)
+ if (dividers[i]->clk == clk) {
+ d = dividers[i];
+ break;
+ }
+ if (i == num)
+ return -EINVAL;
+
+ if (div == 0 || parent_rate % rate)
+ div++;
+
+ if (d->bm_pred) {
+ calc_pred_podf_dividers(div, &pred, &podf);
+ div = pred * podf;
+ } else {
+ div_max = (d->bm_podf >> d->bp_podf) + 1;
+ if (div > div_max)
+ div = div_max;
+ }
+
+ return parent_rate / div;
+}
+
+struct multiplexer {
+ struct clk *clk;
+ void __iomem *reg;
+ u32 bp;
+ u32 bm;
+ int pnum;
+ struct clk *parents[];
+};
+
+static struct multiplexer axi_mux = {
+ .clk = &axi_clk,
+ .reg = CBCDR,
+ .bp = BP_CBCDR_AXI_SEL,
+ .bm = BM_CBCDR_AXI_SEL,
+ .parents = {
+ &periph_clk,
+ &pll2_pfd_400m,
+ &pll3_pfd_540m,
+ NULL
+ },
+};
+
+static struct multiplexer periph_mux = {
+ .clk = &periph_clk,
+ .reg = CBCDR,
+ .bp = BP_CBCDR_PERIPH_CLK_SEL,
+ .bm = BM_CBCDR_PERIPH_CLK_SEL,
+ .parents = {
+ &periph_pre_clk,
+ &periph_clk2_clk,
+ NULL
+ },
+};
+
+static struct multiplexer periph_pre_mux = {
+ .clk = &periph_pre_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_PRE_PERIPH_CLK_SEL,
+ .bm = BM_CBCMR_PRE_PERIPH_CLK_SEL,
+ .parents = {
+ &pll2_bus,
+ &pll2_pfd_400m,
+ &pll2_pfd_352m,
+ &pll2_200m,
+ NULL
+ },
+};
+
+static struct multiplexer periph_clk2_mux = {
+ .clk = &periph_clk2_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_PERIPH_CLK2_SEL,
+ .bm = BM_CBCMR_PERIPH_CLK2_SEL,
+ .parents = {
+ &pll3_usb_otg,
+ &osc_clk,
+ NULL
+ },
+};
+
+static struct multiplexer periph2_mux = {
+ .clk = &periph2_clk,
+ .reg = CBCDR,
+ .bp = BP_CBCDR_PERIPH2_CLK_SEL,
+ .bm = BM_CBCDR_PERIPH2_CLK_SEL,
+ .parents = {
+ &periph2_pre_clk,
+ &periph2_clk2_clk,
+ NULL
+ },
+};
+
+static struct multiplexer periph2_pre_mux = {
+ .clk = &periph2_pre_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_PRE_PERIPH2_CLK_SEL,
+ .bm = BM_CBCMR_PRE_PERIPH2_CLK_SEL,
+ .parents = {
+ &pll2_bus,
+ &pll2_pfd_400m,
+ &pll2_pfd_352m,
+ &pll2_200m,
+ NULL
+ },
+};
+
+static struct multiplexer periph2_clk2_mux = {
+ .clk = &periph2_clk2_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_PERIPH2_CLK2_SEL,
+ .bm = BM_CBCMR_PERIPH2_CLK2_SEL,
+ .parents = {
+ &pll3_usb_otg,
+ &osc_clk,
+ NULL
+ },
+};
+
+static struct multiplexer gpu2d_axi_mux = {
+ .clk = &gpu2d_axi_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_GPU2D_AXI_SEL,
+ .bm = BM_CBCMR_GPU2D_AXI_SEL,
+ .parents = {
+ &axi_clk,
+ &ahb_clk,
+ NULL
+ },
+};
+
+static struct multiplexer gpu3d_axi_mux = {
+ .clk = &gpu3d_axi_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_GPU3D_AXI_SEL,
+ .bm = BM_CBCMR_GPU3D_AXI_SEL,
+ .parents = {
+ &axi_clk,
+ &ahb_clk,
+ NULL
+ },
+};
+
+static struct multiplexer gpu3d_core_mux = {
+ .clk = &gpu3d_core_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_GPU3D_CORE_SEL,
+ .bm = BM_CBCMR_GPU3D_CORE_SEL,
+ .parents = {
+ &mmdc_ch0_axi_clk,
+ &pll3_usb_otg,
+ &pll2_pfd_594m,
+ &pll2_pfd_400m,
+ NULL
+ },
+};
+
+static struct multiplexer gpu3d_shader_mux = {
+ .clk = &gpu3d_shader_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_GPU3D_SHADER_SEL,
+ .bm = BM_CBCMR_GPU3D_SHADER_SEL,
+ .parents = {
+ &mmdc_ch0_axi_clk,
+ &pll3_usb_otg,
+ &pll2_pfd_594m,
+ &pll3_pfd_720m,
+ NULL
+ },
+};
+
+static struct multiplexer pcie_axi_mux = {
+ .clk = &pcie_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_PCIE_AXI_SEL,
+ .bm = BM_CBCMR_PCIE_AXI_SEL,
+ .parents = {
+ &axi_clk,
+ &ahb_clk,
+ NULL
+ },
+};
+
+static struct multiplexer vdo_axi_mux = {
+ .clk = &vdo_axi_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_VDO_AXI_SEL,
+ .bm = BM_CBCMR_VDO_AXI_SEL,
+ .parents = {
+ &axi_clk,
+ &ahb_clk,
+ NULL
+ },
+};
+
+static struct multiplexer vpu_axi_mux = {
+ .clk = &vpu_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_VPU_AXI_SEL,
+ .bm = BM_CBCMR_VPU_AXI_SEL,
+ .parents = {
+ &axi_clk,
+ &pll2_pfd_400m,
+ &pll2_pfd_352m,
+ NULL
+ },
+};
+
+static struct multiplexer gpu2d_core_mux = {
+ .clk = &gpu2d_core_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_GPU2D_CORE_SEL,
+ .bm = BM_CBCMR_GPU2D_CORE_SEL,
+ .parents = {
+ &axi_clk,
+ &pll3_usb_otg,
+ &pll2_pfd_352m,
+ &pll2_pfd_400m,
+ NULL
+ },
+};
+
+#define DEF_SSI_MUX(id) \
+ static struct multiplexer ssi##id##_mux = { \
+ .clk = &ssi##id##_clk, \
+ .reg = CSCMR1, \
+ .bp = BP_CSCMR1_SSI##id##_SEL, \
+ .bm = BM_CSCMR1_SSI##id##_SEL, \
+ .parents = { \
+ &pll3_pfd_508m, \
+ &pll3_pfd_454m, \
+ &pll4_audio, \
+ NULL \
+ }, \
+ }
+
+DEF_SSI_MUX(1);
+DEF_SSI_MUX(2);
+DEF_SSI_MUX(3);
+
+#define DEF_USDHC_MUX(id) \
+ static struct multiplexer usdhc##id##_mux = { \
+ .clk = &usdhc##id##_clk, \
+ .reg = CSCMR1, \
+ .bp = BP_CSCMR1_USDHC##id##_SEL, \
+ .bm = BM_CSCMR1_USDHC##id##_SEL, \
+ .parents = { \
+ &pll2_pfd_400m, \
+ &pll2_pfd_352m, \
+ NULL \
+ }, \
+ }
+
+DEF_USDHC_MUX(1);
+DEF_USDHC_MUX(2);
+DEF_USDHC_MUX(3);
+DEF_USDHC_MUX(4);
+
+static struct multiplexer emi_mux = {
+ .clk = &emi_clk,
+ .reg = CSCMR1,
+ .bp = BP_CSCMR1_EMI_SEL,
+ .bm = BM_CSCMR1_EMI_SEL,
+ .parents = {
+ &axi_clk,
+ &pll3_usb_otg,
+ &pll2_pfd_400m,
+ &pll2_pfd_352m,
+ NULL
+ },
+};
+
+static struct multiplexer emi_slow_mux = {
+ .clk = &emi_slow_clk,
+ .reg = CSCMR1,
+ .bp = BP_CSCMR1_EMI_SLOW_SEL,
+ .bm = BM_CSCMR1_EMI_SLOW_SEL,
+ .parents = {
+ &axi_clk,
+ &pll3_usb_otg,
+ &pll2_pfd_400m,
+ &pll2_pfd_352m,
+ NULL
+ },
+};
+
+static struct multiplexer esai_mux = {
+ .clk = &esai_clk,
+ .reg = CSCMR2,
+ .bp = BP_CSCMR2_ESAI_SEL,
+ .bm = BM_CSCMR2_ESAI_SEL,
+ .parents = {
+ &pll4_audio,
+ &pll3_pfd_508m,
+ &pll3_pfd_454m,
+ &pll3_usb_otg,
+ NULL
+ },
+};
+
+#define DEF_LDB_DI_MUX(id) \
+ static struct multiplexer ldb_di##id##_mux = { \
+ .clk = &ldb_di##id##_clk, \
+ .reg = CS2CDR, \
+ .bp = BP_CS2CDR_LDB_DI##id##_SEL, \
+ .bm = BM_CS2CDR_LDB_DI##id##_SEL, \
+ .parents = { \
+ &pll5_video, \
+ &pll2_pfd_352m, \
+ &pll2_pfd_400m, \
+ &pll3_pfd_540m, \
+ &pll3_usb_otg, \
+ NULL \
+ }, \
+ }
+
+DEF_LDB_DI_MUX(0);
+DEF_LDB_DI_MUX(1);
+
+static struct multiplexer enfc_mux = {
+ .clk = &enfc_clk,
+ .reg = CS2CDR,
+ .bp = BP_CS2CDR_ENFC_SEL,
+ .bm = BM_CS2CDR_ENFC_SEL,
+ .parents = {
+ &pll2_pfd_352m,
+ &pll2_bus,
+ &pll3_usb_otg,
+ &pll2_pfd_400m,
+ NULL
+ },
+};
+
+static struct multiplexer spdif_mux = {
+ .clk = &spdif_clk,
+ .reg = CDCDR,
+ .bp = BP_CDCDR_SPDIF_SEL,
+ .bm = BM_CDCDR_SPDIF_SEL,
+ .parents = {
+ &pll4_audio,
+ &pll3_pfd_508m,
+ &pll3_pfd_454m,
+ &pll3_usb_otg,
+ NULL
+ },
+};
+
+static struct multiplexer asrc_serial_mux = {
+ .clk = &asrc_serial_clk,
+ .reg = CDCDR,
+ .bp = BP_CDCDR_ASRC_SERIAL_SEL,
+ .bm = BM_CDCDR_ASRC_SERIAL_SEL,
+ .parents = {
+ &pll4_audio,
+ &pll3_pfd_508m,
+ &pll3_pfd_454m,
+ &pll3_usb_otg,
+ NULL
+ },
+};
+
+static struct multiplexer hsi_tx_mux = {
+ .clk = &hsi_tx_clk,
+ .reg = CDCDR,
+ .bp = BP_CDCDR_HSI_TX_SEL,
+ .bm = BM_CDCDR_HSI_TX_SEL,
+ .parents = {
+ &pll3_120m,
+ &pll2_pfd_400m,
+ NULL
+ },
+};
+
+#define DEF_IPU_DI_PRE_MUX(r, i, d) \
+ static struct multiplexer ipu##i##_di##d##_pre_mux = { \
+ .clk = &ipu##i##_di##d##_pre_clk, \
+ .reg = r, \
+ .bp = BP_##r##_IPU##i##_DI##d##_PRE_SEL, \
+ .bm = BM_##r##_IPU##i##_DI##d##_PRE_SEL, \
+ .parents = { \
+ &mmdc_ch0_axi_clk, \
+ &pll3_usb_otg, \
+ &pll5_video, \
+ &pll2_pfd_352m, \
+ &pll2_pfd_400m, \
+ &pll3_pfd_540m, \
+ NULL \
+ }, \
+ }
+
+DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 0);
+DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 1);
+DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 0);
+DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 1);
+
+#define DEF_IPU_DI_MUX(r, i, d) \
+ static struct multiplexer ipu##i##_di##d##_mux = { \
+ .clk = &ipu##i##_di##d##_clk, \
+ .reg = r, \
+ .bp = BP_##r##_IPU##i##_DI##d##_SEL, \
+ .bm = BM_##r##_IPU##i##_DI##d##_SEL, \
+ .parents = { \
+ &ipu##i##_di##d##_pre_clk, \
+ &dummy_clk, \
+ &dummy_clk, \
+ &ldb_di0_clk, \
+ &ldb_di1_clk, \
+ NULL \
+ }, \
+ }
+
+DEF_IPU_DI_MUX(CHSCCDR, 1, 0);
+DEF_IPU_DI_MUX(CHSCCDR, 1, 1);
+DEF_IPU_DI_MUX(CSCDR2, 2, 0);
+DEF_IPU_DI_MUX(CSCDR2, 2, 1);
+
+#define DEF_IPU_MUX(id) \
+ static struct multiplexer ipu##id##_mux = { \
+ .clk = &ipu##id##_clk, \
+ .reg = CSCDR3, \
+ .bp = BP_CSCDR3_IPU##id##_HSP_SEL, \
+ .bm = BM_CSCDR3_IPU##id##_HSP_SEL, \
+ .parents = { \
+ &mmdc_ch0_axi_clk, \
+ &pll2_pfd_400m, \
+ &pll3_120m, \
+ &pll3_pfd_540m, \
+ NULL \
+ }, \
+ }
+
+DEF_IPU_MUX(1);
+DEF_IPU_MUX(2);
+
+static struct multiplexer *multiplexers[] = {
+ &axi_mux,
+ &periph_mux,
+ &periph_pre_mux,
+ &periph_clk2_mux,
+ &periph2_mux,
+ &periph2_pre_mux,
+ &periph2_clk2_mux,
+ &gpu2d_axi_mux,
+ &gpu3d_axi_mux,
+ &gpu3d_core_mux,
+ &gpu3d_shader_mux,
+ &pcie_axi_mux,
+ &vdo_axi_mux,
+ &vpu_axi_mux,
+ &gpu2d_core_mux,
+ &ssi1_mux,
+ &ssi2_mux,
+ &ssi3_mux,
+ &usdhc1_mux,
+ &usdhc2_mux,
+ &usdhc3_mux,
+ &usdhc4_mux,
+ &emi_mux,
+ &emi_slow_mux,
+ &esai_mux,
+ &ldb_di0_mux,
+ &ldb_di1_mux,
+ &enfc_mux,
+ &spdif_mux,
+ &asrc_serial_mux,
+ &hsi_tx_mux,
+ &ipu1_di0_pre_mux,
+ &ipu1_di0_mux,
+ &ipu1_di1_pre_mux,
+ &ipu1_di1_mux,
+ &ipu2_di0_pre_mux,
+ &ipu2_di0_mux,
+ &ipu2_di1_pre_mux,
+ &ipu2_di1_mux,
+ &ipu1_mux,
+ &ipu2_mux,
+};
+
+static int _clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct multiplexer *m;
+ int i, num;
+ u32 val;
+
+ num = ARRAY_SIZE(multiplexers);
+ for (i = 0; i < num; i++)
+ if (multiplexers[i]->clk == clk) {
+ m = multiplexers[i];
+ break;
+ }
+ if (i == num)
+ return -EINVAL;
+
+ i = 0;
+ while (m->parents[i]) {
+ if (parent == m->parents[i])
+ break;
+ i++;
+ }
+ if (!m->parents[i])
+ return -EINVAL;
+
+ val = readl_relaxed(m->reg);
+ val &= ~m->bm;
+ val |= i << m->bp;
+ writel_relaxed(val, m->reg);
+
+ if (clk == &periph_clk)
+ return clk_busy_wait(clk);
+
+ return 0;
+}
+
+#define DEF_NG_CLK(name, p) \
+ static struct clk name = { \
+ .get_rate = _clk_get_rate, \
+ .set_rate = _clk_set_rate, \
+ .round_rate = _clk_round_rate, \
+ .set_parent = _clk_set_parent, \
+ .parent = p, \
+ }
+
+DEF_NG_CLK(periph_clk2_clk, &osc_clk);
+DEF_NG_CLK(periph_pre_clk, &pll2_bus);
+DEF_NG_CLK(periph_clk, &periph_pre_clk);
+DEF_NG_CLK(periph2_clk2_clk, &osc_clk);
+DEF_NG_CLK(periph2_pre_clk, &pll2_bus);
+DEF_NG_CLK(periph2_clk, &periph2_pre_clk);
+DEF_NG_CLK(axi_clk, &periph_clk);
+DEF_NG_CLK(emi_clk, &axi_clk);
+DEF_NG_CLK(arm_clk, &pll1_sw_clk);
+DEF_NG_CLK(ahb_clk, &periph_clk);
+DEF_NG_CLK(ipg_clk, &ahb_clk);
+DEF_NG_CLK(ipg_perclk, &ipg_clk);
+DEF_NG_CLK(ipu1_di0_pre_clk, &pll3_pfd_540m);
+DEF_NG_CLK(ipu1_di1_pre_clk, &pll3_pfd_540m);
+DEF_NG_CLK(ipu2_di0_pre_clk, &pll3_pfd_540m);
+DEF_NG_CLK(ipu2_di1_pre_clk, &pll3_pfd_540m);
+DEF_NG_CLK(asrc_serial_clk, &pll3_usb_otg);
+
+#define DEF_CLK(name, er, es, p, s) \
+ static struct clk name = { \
+ .enable_reg = er, \
+ .enable_shift = es, \
+ .enable = _clk_enable, \
+ .disable = _clk_disable, \
+ .get_rate = _clk_get_rate, \
+ .set_rate = _clk_set_rate, \
+ .round_rate = _clk_round_rate, \
+ .set_parent = _clk_set_parent, \
+ .parent = p, \
+ .secondary = s, \
+ }
+
+DEF_CLK(aips_tz1_clk, CCGR0, CG0, &ahb_clk, NULL);
+DEF_CLK(aips_tz2_clk, CCGR0, CG1, &ahb_clk, NULL);
+DEF_CLK(apbh_dma_clk, CCGR0, CG2, &ahb_clk, NULL);
+DEF_CLK(asrc_clk, CCGR0, CG3, &pll4_audio, NULL);
+DEF_CLK(can1_serial_clk, CCGR0, CG8, &pll3_usb_otg, NULL);
+DEF_CLK(can1_clk, CCGR0, CG7, &pll3_usb_otg, &can1_serial_clk);
+DEF_CLK(can2_serial_clk, CCGR0, CG10, &pll3_usb_otg, NULL);
+DEF_CLK(can2_clk, CCGR0, CG9, &pll3_usb_otg, &can2_serial_clk);
+DEF_CLK(ecspi1_clk, CCGR1, CG0, &pll3_60m, NULL);
+DEF_CLK(ecspi2_clk, CCGR1, CG1, &pll3_60m, NULL);
+DEF_CLK(ecspi3_clk, CCGR1, CG2, &pll3_60m, NULL);
+DEF_CLK(ecspi4_clk, CCGR1, CG3, &pll3_60m, NULL);
+DEF_CLK(ecspi5_clk, CCGR1, CG4, &pll3_60m, NULL);
+DEF_CLK(enet_clk, CCGR1, CG5, &ipg_clk, NULL);
+DEF_CLK(esai_clk, CCGR1, CG8, &pll3_usb_otg, NULL);
+DEF_CLK(gpt_serial_clk, CCGR1, CG11, &ipg_perclk, NULL);
+DEF_CLK(gpt_clk, CCGR1, CG10, &ipg_perclk, &gpt_serial_clk);
+DEF_CLK(gpu2d_core_clk, CCGR1, CG12, &pll2_pfd_352m, &gpu2d_axi_clk);
+DEF_CLK(gpu3d_core_clk, CCGR1, CG13, &pll2_pfd_594m, &gpu3d_axi_clk);
+DEF_CLK(gpu3d_shader_clk, CCGR1, CG13, &pll3_pfd_720m, &gpu3d_axi_clk);
+DEF_CLK(hdmi_iahb_clk, CCGR2, CG0, &ahb_clk, NULL);
+DEF_CLK(hdmi_isfr_clk, CCGR2, CG2, &pll3_pfd_540m, &hdmi_iahb_clk);
+DEF_CLK(i2c1_clk, CCGR2, CG3, &ipg_perclk, NULL);
+DEF_CLK(i2c2_clk, CCGR2, CG4, &ipg_perclk, NULL);
+DEF_CLK(i2c3_clk, CCGR2, CG5, &ipg_perclk, NULL);
+DEF_CLK(iim_clk, CCGR2, CG6, &ipg_clk, NULL);
+DEF_CLK(enfc_clk, CCGR2, CG7, &pll2_pfd_352m, NULL);
+DEF_CLK(ipu1_clk, CCGR3, CG0, &mmdc_ch0_axi_clk, NULL);
+DEF_CLK(ipu1_di0_clk, CCGR3, CG1, &ipu1_di0_pre_clk, NULL);
+DEF_CLK(ipu1_di1_clk, CCGR3, CG2, &ipu1_di1_pre_clk, NULL);
+DEF_CLK(ipu2_clk, CCGR3, CG3, &mmdc_ch0_axi_clk, NULL);
+DEF_CLK(ipu2_di0_clk, CCGR3, CG4, &ipu2_di0_pre_clk, NULL);
+DEF_CLK(ipu2_di1_clk, CCGR3, CG5, &ipu2_di1_pre_clk, NULL);
+DEF_CLK(ldb_di0_clk, CCGR3, CG6, &pll3_pfd_540m, NULL);
+DEF_CLK(ldb_di1_clk, CCGR3, CG7, &pll3_pfd_540m, NULL);
+DEF_CLK(hsi_tx_clk, CCGR3, CG8, &pll2_pfd_400m, NULL);
+DEF_CLK(mlb_clk, CCGR3, CG9, &pll6_mlb, NULL);
+DEF_CLK(mmdc_ch0_ipg_clk, CCGR3, CG12, &ipg_clk, NULL);
+DEF_CLK(mmdc_ch0_axi_clk, CCGR3, CG10, &periph_clk, &mmdc_ch0_ipg_clk);
+DEF_CLK(mmdc_ch1_ipg_clk, CCGR3, CG13, &ipg_clk, NULL);
+DEF_CLK(mmdc_ch1_axi_clk, CCGR3, CG11, &periph2_clk, &mmdc_ch1_ipg_clk);
+DEF_CLK(openvg_axi_clk, CCGR3, CG13, &axi_clk, NULL);
+DEF_CLK(pwm1_clk, CCGR4, CG8, &ipg_perclk, NULL);
+DEF_CLK(pwm2_clk, CCGR4, CG9, &ipg_perclk, NULL);
+DEF_CLK(pwm3_clk, CCGR4, CG10, &ipg_perclk, NULL);
+DEF_CLK(pwm4_clk, CCGR4, CG11, &ipg_perclk, NULL);
+DEF_CLK(gpmi_bch_apb_clk, CCGR4, CG12, &usdhc3_clk, NULL);
+DEF_CLK(gpmi_bch_clk, CCGR4, CG13, &usdhc4_clk, &gpmi_bch_apb_clk);
+DEF_CLK(gpmi_apb_clk, CCGR4, CG15, &usdhc3_clk, &gpmi_bch_clk);
+DEF_CLK(gpmi_io_clk, CCGR4, CG14, &enfc_clk, &gpmi_apb_clk);
+DEF_CLK(sdma_clk, CCGR5, CG3, &ahb_clk, NULL);
+DEF_CLK(spba_clk, CCGR5, CG6, &ipg_clk, NULL);
+DEF_CLK(spdif_clk, CCGR5, CG7, &pll3_usb_otg, &spba_clk);
+DEF_CLK(ssi1_clk, CCGR5, CG9, &pll3_pfd_508m, NULL);
+DEF_CLK(ssi2_clk, CCGR5, CG10, &pll3_pfd_508m, NULL);
+DEF_CLK(ssi3_clk, CCGR5, CG11, &pll3_pfd_508m, NULL);
+DEF_CLK(uart_serial_clk, CCGR5, CG13, &pll3_usb_otg, NULL);
+DEF_CLK(uart_clk, CCGR5, CG12, &pll3_80m, &uart_serial_clk);
+DEF_CLK(usboh3_clk, CCGR6, CG0, &ipg_clk, NULL);
+DEF_CLK(usdhc1_clk, CCGR6, CG1, &pll2_pfd_400m, NULL);
+DEF_CLK(usdhc2_clk, CCGR6, CG2, &pll2_pfd_400m, NULL);
+DEF_CLK(usdhc3_clk, CCGR6, CG3, &pll2_pfd_400m, NULL);
+DEF_CLK(usdhc4_clk, CCGR6, CG4, &pll2_pfd_400m, NULL);
+DEF_CLK(emi_slow_clk, CCGR6, CG5, &axi_clk, NULL);
+DEF_CLK(vdo_axi_clk, CCGR6, CG6, &axi_clk, NULL);
+DEF_CLK(vpu_clk, CCGR6, CG7, &axi_clk, NULL);
+
+static int pcie_clk_enable(struct clk *clk)
+{
+ u32 val;
+
+ val = readl_relaxed(PLL8_ENET);
+ val |= BM_PLL_ENET_EN_PCIE;
+ writel_relaxed(val, PLL8_ENET);
+
+ return _clk_enable(clk);
+}
+
+static void pcie_clk_disable(struct clk *clk)
+{
+ u32 val;
+
+ _clk_disable(clk);
+
+ val = readl_relaxed(PLL8_ENET);
+ val &= BM_PLL_ENET_EN_PCIE;
+ writel_relaxed(val, PLL8_ENET);
+}
+
+static struct clk pcie_clk = {
+ .enable_reg = CCGR4,
+ .enable_shift = CG0,
+ .enable = pcie_clk_enable,
+ .disable = pcie_clk_disable,
+ .set_parent = _clk_set_parent,
+ .parent = &axi_clk,
+ .secondary = &pll8_enet,
+};
+
+static int sata_clk_enable(struct clk *clk)
+{
+ u32 val;
+
+ val = readl_relaxed(PLL8_ENET);
+ val |= BM_PLL_ENET_EN_SATA;
+ writel_relaxed(val, PLL8_ENET);
+
+ return _clk_enable(clk);
+}
+
+static void sata_clk_disable(struct clk *clk)
+{
+ u32 val;
+
+ _clk_disable(clk);
+
+ val = readl_relaxed(PLL8_ENET);
+ val &= BM_PLL_ENET_EN_SATA;
+ writel_relaxed(val, PLL8_ENET);
+}
+
+static struct clk sata_clk = {
+ .enable_reg = CCGR5,
+ .enable_shift = CG2,
+ .enable = sata_clk_enable,
+ .disable = sata_clk_disable,
+ .parent = &ipg_clk,
+ .secondary = &pll8_enet,
+};
+
+#define _REGISTER_CLOCK(d, n, c) \
+ { \
+ .dev_id = d, \
+ .con_id = n, \
+ .clk = &c, \
+ }
+
+static struct clk_lookup lookups[] = {
+ _REGISTER_CLOCK("2020000.uart", NULL, uart_clk),
+ _REGISTER_CLOCK("21e8000.uart", NULL, uart_clk),
+ _REGISTER_CLOCK("21ec000.uart", NULL, uart_clk),
+ _REGISTER_CLOCK("21f0000.uart", NULL, uart_clk),
+ _REGISTER_CLOCK("21f4000.uart", NULL, uart_clk),
+ _REGISTER_CLOCK("2188000.enet", NULL, enet_clk),
+ _REGISTER_CLOCK("2190000.usdhc", NULL, usdhc1_clk),
+ _REGISTER_CLOCK("2194000.usdhc", NULL, usdhc2_clk),
+ _REGISTER_CLOCK("2198000.usdhc", NULL, usdhc3_clk),
+ _REGISTER_CLOCK("219c000.usdhc", NULL, usdhc4_clk),
+ _REGISTER_CLOCK("21a0000.i2c", NULL, i2c1_clk),
+ _REGISTER_CLOCK("21a4000.i2c", NULL, i2c2_clk),
+ _REGISTER_CLOCK("21a8000.i2c", NULL, i2c3_clk),
+ _REGISTER_CLOCK("2008000.ecspi", NULL, ecspi1_clk),
+ _REGISTER_CLOCK("200c000.ecspi", NULL, ecspi2_clk),
+ _REGISTER_CLOCK("2010000.ecspi", NULL, ecspi3_clk),
+ _REGISTER_CLOCK("2014000.ecspi", NULL, ecspi4_clk),
+ _REGISTER_CLOCK("2018000.ecspi", NULL, ecspi5_clk),
+ _REGISTER_CLOCK("20ec000.sdma", NULL, sdma_clk),
+ _REGISTER_CLOCK("20bc000.wdog", NULL, dummy_clk),
+ _REGISTER_CLOCK("20c0000.wdog", NULL, dummy_clk),
+ _REGISTER_CLOCK(NULL, "ckih", ckih_clk),
+ _REGISTER_CLOCK(NULL, "ckil_clk", ckil_clk),
+ _REGISTER_CLOCK(NULL, "aips_tz1_clk", aips_tz1_clk),
+ _REGISTER_CLOCK(NULL, "aips_tz2_clk", aips_tz2_clk),
+ _REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk),
+ _REGISTER_CLOCK(NULL, "can2_clk", can2_clk),
+ _REGISTER_CLOCK(NULL, "hdmi_isfr_clk", hdmi_isfr_clk),
+ _REGISTER_CLOCK(NULL, "iim_clk", iim_clk),
+ _REGISTER_CLOCK(NULL, "mlb_clk", mlb_clk),
+ _REGISTER_CLOCK(NULL, "openvg_axi_clk", openvg_axi_clk),
+ _REGISTER_CLOCK(NULL, "pwm1_clk", pwm1_clk),
+ _REGISTER_CLOCK(NULL, "pwm2_clk", pwm2_clk),
+ _REGISTER_CLOCK(NULL, "pwm3_clk", pwm3_clk),
+ _REGISTER_CLOCK(NULL, "pwm4_clk", pwm4_clk),
+ _REGISTER_CLOCK(NULL, "gpmi_io_clk", gpmi_io_clk),
+ _REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk),
+ _REGISTER_CLOCK(NULL, "sata_clk", sata_clk),
+};
+
+int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
+{
+ u32 val = readl_relaxed(CLPCR);
+
+ val &= ~BM_CLPCR_LPM;
+ switch (mode) {
+ case WAIT_CLOCKED:
+ break;
+ case WAIT_UNCLOCKED:
+ val |= 0x1 << BP_CLPCR_LPM;
+ break;
+ case STOP_POWER_ON:
+ val |= 0x2 << BP_CLPCR_LPM;
+ break;
+ case WAIT_UNCLOCKED_POWER_OFF:
+ val |= 0x1 << BP_CLPCR_LPM;
+ val &= ~BM_CLPCR_VSTBY;
+ val &= ~BM_CLPCR_SBYOS;
+ val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ break;
+ case STOP_POWER_OFF:
+ val |= 0x2 << BP_CLPCR_LPM;
+ val |= 0x3 << BP_CLPCR_STBY_COUNT;
+ val |= BM_CLPCR_VSTBY;
+ val |= BM_CLPCR_SBYOS;
+ val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ break;
+ default:
+ return -EINVAL;
+ }
+ writel_relaxed(val, CLPCR);
+
+ return 0;
+}
+
+static struct map_desc imx6q_clock_desc[] = {
+ imx_map_entry(MX6Q, CCM, MT_DEVICE),
+ imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
+};
+
+void __init imx6q_clock_map_io(void)
+{
+ iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc));
+}
+
+int __init mx6q_clocks_init(void)
+{
+ struct device_node *np;
+ void __iomem *base;
+ int i, irq;
+
+ /* retrieve the freqency of fixed clocks from device tree */
+ for_each_compatible_node(np, NULL, "fixed-clock") {
+ u32 rate;
+ if (of_property_read_u32(np, "clock-frequency", &rate))
+ continue;
+
+ if (of_device_is_compatible(np, "fsl,imx-ckil"))
+ external_low_reference = rate;
+ else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+ external_high_reference = rate;
+ else if (of_device_is_compatible(np, "fsl,imx-osc"))
+ oscillator_reference = rate;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ clkdev_add(&lookups[i]);
+
+ /* only keep necessary clocks on */
+ writel_relaxed(0x3 << CG0 | 0x3 << CG1 | 0x3 << CG2, CCGR0);
+ writel_relaxed(0x3 << CG8 | 0x3 << CG9 | 0x3 << CG10, CCGR2);
+ writel_relaxed(0x3 << CG10 | 0x3 << CG12, CCGR3);
+ writel_relaxed(0x3 << CG4 | 0x3 << CG6 | 0x3 << CG7, CCGR4);
+ writel_relaxed(0x3 << CG0, CCGR5);
+ writel_relaxed(0, CCGR6);
+ writel_relaxed(0, CCGR7);
+
+ clk_enable(&uart_clk);
+ clk_enable(&mmdc_ch0_axi_clk);
+
+ clk_set_rate(&pll4_audio, FREQ_650M);
+ clk_set_rate(&pll5_video, FREQ_650M);
+ clk_set_parent(&ipu1_di0_clk, &ipu1_di0_pre_clk);
+ clk_set_parent(&ipu1_di0_pre_clk, &pll5_video);
+ clk_set_parent(&gpu3d_shader_clk, &pll2_pfd_594m);
+ clk_set_rate(&gpu3d_shader_clk, FREQ_594M);
+ clk_set_parent(&gpu3d_core_clk, &mmdc_ch0_axi_clk);
+ clk_set_rate(&gpu3d_core_clk, FREQ_528M);
+ clk_set_parent(&asrc_serial_clk, &pll3_usb_otg);
+ clk_set_rate(&asrc_serial_clk, 1500000);
+ clk_set_rate(&enfc_clk, 11000000);
+
+ /*
+ * Before pinctrl API is available, we have to rely on the pad
+ * configuration set up by bootloader. For usdhc example here,
+ * u-boot sets up the pads for 49.5 MHz case, and we have to lower
+ * the usdhc clock from 198 to 49.5 MHz to match the pad configuration.
+ *
+ * FIXME: This is should be removed after pinctrl API is available.
+ * At that time, usdhc driver can call pinctrl API to change pad
+ * configuration dynamically per different usdhc clock settings.
+ */
+ clk_set_rate(&usdhc1_clk, 49500000);
+ clk_set_rate(&usdhc2_clk, 49500000);
+ clk_set_rate(&usdhc3_clk, 49500000);
+ clk_set_rate(&usdhc4_clk, 49500000);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+ irq = irq_of_parse_and_map(np, 0);
+ mxc_timer_init(&gpt_clk, base, irq);
+
+ return 0;
+}
diff --git a/arch/arm/mach-imx/cpu-imx25.c b/arch/arm/mach-imx/cpu-imx25.c
new file mode 100644
index 0000000..6914bcb
--- /dev/null
+++ b/arch/arm/mach-imx/cpu-imx25.c
@@ -0,0 +1,41 @@
+/*
+ * MX25 CPU type detection
+ *
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/iim.h>
+
+static int mx25_cpu_rev = -1;
+
+static int mx25_read_cpu_rev(void)
+{
+ u32 rev;
+
+ rev = __raw_readl(MX25_IO_ADDRESS(MX25_IIM_BASE_ADDR + MXC_IIMSREV));
+ switch (rev) {
+ case 0x00:
+ return IMX_CHIP_REVISION_1_0;
+ case 0x01:
+ return IMX_CHIP_REVISION_1_1;
+ default:
+ return IMX_CHIP_REVISION_UNKNOWN;
+ }
+}
+
+int mx25_revision(void)
+{
+ if (mx25_cpu_rev == -1)
+ mx25_cpu_rev = mx25_read_cpu_rev();
+
+ return mx25_cpu_rev;
+}
+EXPORT_SYMBOL(mx25_revision);
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
new file mode 100644
index 0000000..e1537f9
--- /dev/null
+++ b/arch/arm/mach-imx/gpc.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/hardware/gic.h>
+
+#define GPC_IMR1 0x008
+#define GPC_PGC_CPU_PDN 0x2a0
+
+#define IMR_NUM 4
+
+static void __iomem *gpc_base;
+static u32 gpc_wake_irqs[IMR_NUM];
+static u32 gpc_saved_imrs[IMR_NUM];
+
+void imx_gpc_pre_suspend(void)
+{
+ void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
+ int i;
+
+ /* Tell GPC to power off ARM core when suspend */
+ writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
+
+ for (i = 0; i < IMR_NUM; i++) {
+ gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
+ writel_relaxed(~gpc_wake_irqs[i], reg_imr1 + i * 4);
+ }
+}
+
+void imx_gpc_post_resume(void)
+{
+ void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
+ int i;
+
+ /* Keep ARM core powered on for other low-power modes */
+ writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
+
+ for (i = 0; i < IMR_NUM; i++)
+ writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
+}
+
+static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+ unsigned int idx = d->irq / 32 - 1;
+ u32 mask;
+
+ /* Sanity check for SPI irq */
+ if (d->irq < 32)
+ return -EINVAL;
+
+ mask = 1 << d->irq % 32;
+ gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
+ gpc_wake_irqs[idx] & ~mask;
+
+ return 0;
+}
+
+static void imx_gpc_irq_unmask(struct irq_data *d)
+{
+ void __iomem *reg;
+ u32 val;
+
+ /* Sanity check for SPI irq */
+ if (d->irq < 32)
+ return;
+
+ reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+ val = readl_relaxed(reg);
+ val &= ~(1 << d->irq % 32);
+ writel_relaxed(val, reg);
+}
+
+static void imx_gpc_irq_mask(struct irq_data *d)
+{
+ void __iomem *reg;
+ u32 val;
+
+ /* Sanity check for SPI irq */
+ if (d->irq < 32)
+ return;
+
+ reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+ val = readl_relaxed(reg);
+ val |= 1 << (d->irq % 32);
+ writel_relaxed(val, reg);
+}
+
+void __init imx_gpc_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
+ gpc_base = of_iomap(np, 0);
+ WARN_ON(!gpc_base);
+
+ /* Register GPC as the secondary interrupt controller behind GIC */
+ gic_arch_extn.irq_mask = imx_gpc_irq_mask;
+ gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
+ gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
+}
diff --git a/arch/arm/mach-imx/head-v7.S b/arch/arm/mach-imx/head-v7.S
new file mode 100644
index 0000000..6229efb
--- /dev/null
+++ b/arch/arm/mach-imx/head-v7.S
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/hardware/cache-l2x0.h>
+
+ .section ".text.head", "ax"
+ __CPUINIT
+
+/*
+ * The secondary kernel init calls v7_flush_dcache_all before it enables
+ * the L1; however, the L1 comes out of reset in an undefined state, so
+ * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
+ * of cache lines with uninitialized data and uninitialized tags to get
+ * written out to memory, which does really unpleasant things to the main
+ * processor. We fix this by performing an invalidate, rather than a
+ * clean + invalidate, before jumping into the kernel.
+ *
+ * This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs
+ * to be called for both secondary cores startup and primary core resume
+ * procedures. Ideally, it should be moved into arch/arm/mm/cache-v7.S.
+ */
+ENTRY(v7_invalidate_l1)
+ mov r0, #0
+ mcr p15, 2, r0, c0, c0, 0
+ mrc p15, 1, r0, c0, c0, 0
+
+ ldr r1, =0x7fff
+ and r2, r1, r0, lsr #13
+
+ ldr r1, =0x3ff
+
+ and r3, r1, r0, lsr #3 @ NumWays - 1
+ add r2, r2, #1 @ NumSets
+
+ and r0, r0, #0x7
+ add r0, r0, #4 @ SetShift
+
+ clz r1, r3 @ WayShift
+ add r4, r3, #1 @ NumWays
+1: sub r2, r2, #1 @ NumSets--
+ mov r3, r4 @ Temp = NumWays
+2: subs r3, r3, #1 @ Temp--
+ mov r5, r3, lsl r1
+ mov r6, r2, lsl r0
+ orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
+ mcr p15, 0, r5, c7, c6, 2
+ bgt 2b
+ cmp r2, #0
+ bgt 1b
+ dsb
+ isb
+ mov pc, lr
+ENDPROC(v7_invalidate_l1)
+
+#ifdef CONFIG_SMP
+ENTRY(v7_secondary_startup)
+ bl v7_invalidate_l1
+ b secondary_startup
+ENDPROC(v7_secondary_startup)
+#endif
+
+/*
+ * The following code is located into the .data section. This is to
+ * allow phys_l2x0_saved_regs to be accessed with a relative load
+ * as we are running on physical address here.
+ */
+ .data
+ .align
+
+ .macro pl310_resume
+ ldr r2, phys_l2x0_saved_regs
+ ldr r0, [r2, #L2X0_R_PHY_BASE] @ get physical base of l2x0
+ ldr r1, [r2, #L2X0_R_AUX_CTRL] @ get aux_ctrl value
+ str r1, [r0, #L2X0_AUX_CTRL] @ restore aux_ctrl
+ mov r1, #0x1
+ str r1, [r0, #L2X0_CTRL] @ re-enable L2
+ .endm
+
+ENTRY(v7_cpu_resume)
+ bl v7_invalidate_l1
+ pl310_resume
+ b cpu_resume
+ENDPROC(v7_cpu_resume)
+
+ .globl phys_l2x0_saved_regs
+phys_l2x0_saved_regs:
+ .long 0
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
new file mode 100644
index 0000000..f8f7437
--- /dev/null
+++ b/arch/arm/mach-imx/hotplug.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/errno.h>
+#include <asm/cacheflush.h>
+#include <asm/cp15.h>
+#include <mach/common.h>
+
+int platform_cpu_kill(unsigned int cpu)
+{
+ return 1;
+}
+
+static inline void cpu_enter_lowpower(void)
+{
+ unsigned int v;
+
+ flush_cache_all();
+ asm volatile(
+ "mcr p15, 0, %1, c7, c5, 0\n"
+ " mcr p15, 0, %1, c7, c10, 4\n"
+ /*
+ * Turn off coherency
+ */
+ " mrc p15, 0, %0, c1, c0, 1\n"
+ " bic %0, %0, %3\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ " mrc p15, 0, %0, c1, c0, 0\n"
+ " bic %0, %0, %2\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ : "=&r" (v)
+ : "r" (0), "Ir" (CR_C), "Ir" (0x40)
+ : "cc");
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+ cpu_enter_lowpower();
+ imx_enable_cpu(cpu, false);
+
+ /* spin here until hardware takes it down */
+ while (1)
+ ;
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+ /*
+ * we don't allow CPU 0 to be shutdown (it is still too special
+ * e.g. clock tick interrupts)
+ */
+ return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-imx/lluart.c b/arch/arm/mach-imx/lluart.c
new file mode 100644
index 0000000..d4ab6f2
--- /dev/null
+++ b/arch/arm/mach-imx/lluart.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <asm/page.h>
+#include <asm/sizes.h>
+#include <asm/mach/map.h>
+#include <mach/hardware.h>
+
+static struct map_desc imx_lluart_desc = {
+#ifdef CONFIG_DEBUG_IMX6Q_UART
+ .virtual = MX6Q_IO_P2V(MX6Q_UART4_BASE_ADDR),
+ .pfn = __phys_to_pfn(MX6Q_UART4_BASE_ADDR),
+ .length = MX6Q_UART4_SIZE,
+ .type = MT_DEVICE,
+#endif
+};
+
+void __init imx_lluart_map_io(void)
+{
+ if (imx_lluart_desc.virtual)
+ iotable_init(&imx_lluart_desc, 1);
+}
diff --git a/arch/arm/mach-imx/localtimer.c b/arch/arm/mach-imx/localtimer.c
new file mode 100644
index 0000000..3a16351
--- /dev/null
+++ b/arch/arm/mach-imx/localtimer.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/smp_twd.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
+ if (!twd_base) {
+ twd_base = of_iomap(np, 0);
+ WARN_ON(!twd_base);
+ }
+ evt->irq = irq_of_parse_and_map(np, 0);
+ twd_timer_setup(evt);
+
+ return 0;
+}
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
new file mode 100644
index 0000000..8deb012
--- /dev/null
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+static void __init imx6q_init_machine(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+ imx6q_pm_init();
+}
+
+static void __init imx6q_map_io(void)
+{
+ imx_lluart_map_io();
+ imx_scu_map_io();
+ imx6q_clock_map_io();
+}
+
+static int __init imx6q_gpio_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+ gpio_irq_base -= 32;
+ irq_domain_add_simple(np, gpio_irq_base);
+
+ return 0;
+}
+
+static const struct of_device_id imx6q_irq_match[] __initconst = {
+ { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+ { .compatible = "fsl,imx6q-gpio", .data = imx6q_gpio_add_irq_domain, },
+ { /* sentinel */ }
+};
+
+static void __init imx6q_init_irq(void)
+{
+ l2x0_of_init(0, ~0UL);
+ imx_src_init();
+ imx_gpc_init();
+ of_irq_init(imx6q_irq_match);
+}
+
+static void __init imx6q_timer_init(void)
+{
+ mx6q_clocks_init();
+}
+
+static struct sys_timer imx6q_timer = {
+ .init = imx6q_timer_init,
+};
+
+static const char *imx6q_dt_compat[] __initdata = {
+ "fsl,imx6q-sabreauto",
+ NULL,
+};
+
+DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
+ .map_io = imx6q_map_io,
+ .init_irq = imx6q_init_irq,
+ .handle_irq = imx6q_handle_irq,
+ .timer = &imx6q_timer,
+ .init_machine = imx6q_init_machine,
+ .dt_compat = imx6q_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c
new file mode 100644
index 0000000..31807d2
--- /dev/null
+++ b/arch/arm/mach-imx/mm-imx3.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 1999,2000 Arm Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ * Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * - add MX31 specific definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/err.h>
+
+#include <asm/pgtable.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/map.h>
+
+#include <mach/common.h>
+#include <mach/devices-common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-v3.h>
+#include <mach/irqs.h>
+
+static void imx3_idle(void)
+{
+ unsigned long reg = 0;
+
+ if (!need_resched())
+ __asm__ __volatile__(
+ /* disable I and D cache */
+ "mrc p15, 0, %0, c1, c0, 0\n"
+ "bic %0, %0, #0x00001000\n"
+ "bic %0, %0, #0x00000004\n"
+ "mcr p15, 0, %0, c1, c0, 0\n"
+ /* invalidate I cache */
+ "mov %0, #0\n"
+ "mcr p15, 0, %0, c7, c5, 0\n"
+ /* clear and invalidate D cache */
+ "mov %0, #0\n"
+ "mcr p15, 0, %0, c7, c14, 0\n"
+ /* WFI */
+ "mov %0, #0\n"
+ "mcr p15, 0, %0, c7, c0, 4\n"
+ "nop\n" "nop\n" "nop\n" "nop\n"
+ "nop\n" "nop\n" "nop\n"
+ /* enable I and D cache */
+ "mrc p15, 0, %0, c1, c0, 0\n"
+ "orr %0, %0, #0x00001000\n"
+ "orr %0, %0, #0x00000004\n"
+ "mcr p15, 0, %0, c1, c0, 0\n"
+ : "=r" (reg));
+ local_irq_enable();
+}
+
+static void __iomem *imx3_ioremap(unsigned long phys_addr, size_t size,
+ unsigned int mtype)
+{
+ if (mtype == MT_DEVICE) {
+ /*
+ * Access all peripherals below 0x80000000 as nonshared device
+ * on mx3, but leave l2cc alone. Otherwise cache corruptions
+ * can occur.
+ */
+ if (phys_addr < 0x80000000 &&
+ !addr_in_module(phys_addr, MX3x_L2CC))
+ mtype = MT_DEVICE_NONSHARED;
+ }
+
+ return __arm_ioremap(phys_addr, size, mtype);
+}
+
+void imx3_init_l2x0(void)
+{
+ void __iomem *l2x0_base;
+ void __iomem *clkctl_base;
+
+/*
+ * First of all, we must repair broken chip settings. There are some
+ * i.MX35 CPUs in the wild, comming with bogus L2 cache settings. These
+ * misconfigured CPUs will run amok immediately when the L2 cache gets enabled.
+ * Workaraound is to setup the correct register setting prior enabling the
+ * L2 cache. This should not hurt already working CPUs, as they are using the
+ * same value.
+ */
+#define L2_MEM_VAL 0x10
+
+ clkctl_base = ioremap(MX35_CLKCTL_BASE_ADDR, 4096);
+ if (clkctl_base != NULL) {
+ writel(0x00000515, clkctl_base + L2_MEM_VAL);
+ iounmap(clkctl_base);
+ } else {
+ pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
+ }
+
+ l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
+ if (IS_ERR(l2x0_base)) {
+ printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
+ PTR_ERR(l2x0_base));
+ return;
+ }
+
+ l2x0_init(l2x0_base, 0x00030024, 0x00000000);
+}
+
+#ifdef CONFIG_SOC_IMX31
+static struct map_desc mx31_io_desc[] __initdata = {
+ imx_map_entry(MX31, X_MEMC, MT_DEVICE),
+ imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
+ imx_map_entry(MX31, AIPS1, MT_DEVICE_NONSHARED),
+ imx_map_entry(MX31, AIPS2, MT_DEVICE_NONSHARED),
+ imx_map_entry(MX31, SPBA0, MT_DEVICE_NONSHARED),
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+void __init mx31_map_io(void)
+{
+ iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
+}
+
+void __init imx31_init_early(void)
+{
+ mxc_set_cpu_type(MXC_CPU_MX31);
+ mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
+ pm_idle = imx3_idle;
+ imx_ioremap = imx3_ioremap;
+}
+
+void __init mx31_init_irq(void)
+{
+ mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
+}
+
+static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
+ .per_2_per_addr = 1677,
+};
+
+static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
+ .ap_2_ap_addr = 423,
+ .ap_2_bp_addr = 829,
+ .bp_2_ap_addr = 1029,
+};
+
+static struct sdma_platform_data imx31_sdma_pdata __initdata = {
+ .fw_name = "sdma-imx31-to2.bin",
+ .script_addrs = &imx31_to2_sdma_script,
+};
+
+void __init imx31_soc_init(void)
+{
+ int to_version = mx31_revision() >> 4;
+
+ imx3_init_l2x0();
+
+ mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
+ mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
+ mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
+
+ if (to_version == 1) {
+ strncpy(imx31_sdma_pdata.fw_name, "sdma-imx31-to1.bin",
+ strlen(imx31_sdma_pdata.fw_name));
+ imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
+ }
+
+ imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
+}
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+static struct map_desc mx35_io_desc[] __initdata = {
+ imx_map_entry(MX35, X_MEMC, MT_DEVICE),
+ imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
+ imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
+ imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
+ imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
+};
+
+void __init mx35_map_io(void)
+{
+ iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
+}
+
+void __init imx35_init_early(void)
+{
+ mxc_set_cpu_type(MXC_CPU_MX35);
+ mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
+ mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
+ pm_idle = imx3_idle;
+ imx_ioremap = imx3_ioremap;
+}
+
+void __init mx35_init_irq(void)
+{
+ mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
+}
+
+static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
+ .ap_2_ap_addr = 642,
+ .uart_2_mcu_addr = 817,
+ .mcu_2_app_addr = 747,
+ .uartsh_2_mcu_addr = 1183,
+ .per_2_shp_addr = 1033,
+ .mcu_2_shp_addr = 961,
+ .ata_2_mcu_addr = 1333,
+ .mcu_2_ata_addr = 1252,
+ .app_2_mcu_addr = 683,
+ .shp_2_per_addr = 1111,
+ .shp_2_mcu_addr = 892,
+};
+
+static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
+ .ap_2_ap_addr = 729,
+ .uart_2_mcu_addr = 904,
+ .per_2_app_addr = 1597,
+ .mcu_2_app_addr = 834,
+ .uartsh_2_mcu_addr = 1270,
+ .per_2_shp_addr = 1120,
+ .mcu_2_shp_addr = 1048,
+ .ata_2_mcu_addr = 1429,
+ .mcu_2_ata_addr = 1339,
+ .app_2_per_addr = 1531,
+ .app_2_mcu_addr = 770,
+ .shp_2_per_addr = 1198,
+ .shp_2_mcu_addr = 979,
+};
+
+static struct sdma_platform_data imx35_sdma_pdata __initdata = {
+ .fw_name = "sdma-imx35-to2.bin",
+ .script_addrs = &imx35_to2_sdma_script,
+};
+
+void __init imx35_soc_init(void)
+{
+ int to_version = mx35_revision() >> 4;
+
+ imx3_init_l2x0();
+
+ /* i.mx35 has the i.mx31 type gpio */
+ mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
+ mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
+ mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
+
+ if (to_version == 1) {
+ strncpy(imx35_sdma_pdata.fw_name, "sdma-imx35-to1.bin",
+ strlen(imx35_sdma_pdata.fw_name));
+ imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
+ }
+
+ imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
+}
+#endif /* ifdef CONFIG_SOC_IMX35 */
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
new file mode 100644
index 0000000..c461e98
--- /dev/null
+++ b/arch/arm/mach-imx/mmdc.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+
+#define MMDC_MAPSR 0x404
+#define BP_MMDC_MAPSR_PSD 0
+#define BP_MMDC_MAPSR_PSS 4
+
+static int __devinit imx_mmdc_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ void __iomem *mmdc_base, *reg;
+ u32 val;
+ int timeout = 0x400;
+
+ mmdc_base = of_iomap(np, 0);
+ WARN_ON(!mmdc_base);
+
+ reg = mmdc_base + MMDC_MAPSR;
+
+ /* Enable automatic power saving */
+ val = readl_relaxed(reg);
+ val &= ~(1 << BP_MMDC_MAPSR_PSD);
+ writel_relaxed(val, reg);
+
+ /* Ensure it's successfully enabled */
+ while (!(readl_relaxed(reg) & 1 << BP_MMDC_MAPSR_PSS) && --timeout)
+ cpu_relax();
+
+ if (unlikely(!timeout)) {
+ pr_warn("%s: failed to enable automatic power saving\n",
+ __func__);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static struct of_device_id imx_mmdc_dt_ids[] = {
+ { .compatible = "fsl,imx6q-mmdc", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver imx_mmdc_driver = {
+ .driver = {
+ .name = "imx-mmdc",
+ .owner = THIS_MODULE,
+ .of_match_table = imx_mmdc_dt_ids,
+ },
+ .probe = imx_mmdc_probe,
+};
+
+static int __init imx_mmdc_init(void)
+{
+ return platform_driver_register(&imx_mmdc_driver);
+}
+postcore_initcall(imx_mmdc_init);
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
new file mode 100644
index 0000000..ab98c6f
--- /dev/null
+++ b/arch/arm/mach-imx/platsmp.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <asm/page.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+static void __iomem *scu_base;
+
+static struct map_desc scu_io_desc __initdata = {
+ /* .virtual and .pfn are run-time assigned */
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+};
+
+void __init imx_scu_map_io(void)
+{
+ unsigned long base;
+
+ /* Get SCU base */
+ asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+ scu_io_desc.virtual = IMX_IO_P2V(base);
+ scu_io_desc.pfn = __phys_to_pfn(base);
+ iotable_init(&scu_io_desc, 1);
+
+ scu_base = IMX_IO_ADDRESS(base);
+}
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+ /*
+ * if any interrupts are already enabled for the primary
+ * core (e.g. timer irq), then they will not have been enabled
+ * for us: do so
+ */
+ gic_secondary_init(0);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ imx_set_cpu_jump(cpu, v7_secondary_startup);
+ imx_enable_cpu(cpu, true);
+ return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+ int i, ncores;
+
+ ncores = scu_get_core_count(scu_base);
+
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+
+ set_smp_cross_call(gic_raise_softirq);
+}
+
+void imx_smp_prepare(void)
+{
+ scu_enable(scu_base);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+ imx_smp_prepare();
+}
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
new file mode 100644
index 0000000..f20f191
--- /dev/null
+++ b/arch/arm/mach-imx/pm-imx6q.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+extern unsigned long phys_l2x0_saved_regs;
+
+static int imx6q_suspend_finish(unsigned long val)
+{
+ cpu_do_idle();
+ return 0;
+}
+
+static int imx6q_pm_enter(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ imx6q_set_lpm(STOP_POWER_OFF);
+ imx_gpc_pre_suspend();
+ imx_set_cpu_jump(0, v7_cpu_resume);
+ /* Zzz ... */
+ cpu_suspend(0, imx6q_suspend_finish);
+ imx_smp_prepare();
+ imx_gpc_post_resume();
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct platform_suspend_ops imx6q_pm_ops = {
+ .enter = imx6q_pm_enter,
+ .valid = suspend_valid_only_mem,
+};
+
+void __init imx6q_pm_init(void)
+{
+ /*
+ * The l2x0 core code provides an infrastucture to save and restore
+ * l2x0 registers across suspend/resume cycle. But because imx6q
+ * retains L2 content during suspend and needs to resume L2 before
+ * MMU is enabled, it can only utilize register saving support and
+ * have to take care of restoring on its own. So we save physical
+ * address of the data structure used by l2x0 core to save registers,
+ * and later restore the necessary ones in imx6q resume entry.
+ */
+ phys_l2x0_saved_regs = __pa(&l2x0_saved_regs);
+
+ suspend_set_ops(&imx6q_pm_ops);
+}
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
new file mode 100644
index 0000000..a8e3368
--- /dev/null
+++ b/arch/arm/mach-imx/src.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+#include <asm/unified.h>
+
+#define SRC_SCR 0x000
+#define SRC_GPR1 0x020
+#define BP_SRC_SCR_CORE1_RST 14
+#define BP_SRC_SCR_CORE1_ENABLE 22
+
+static void __iomem *src_base;
+
+#ifndef CONFIG_SMP
+#define cpu_logical_map(cpu) 0
+#endif
+
+void imx_enable_cpu(int cpu, bool enable)
+{
+ u32 mask, val;
+
+ cpu = cpu_logical_map(cpu);
+ mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
+ val = readl_relaxed(src_base + SRC_SCR);
+ val = enable ? val | mask : val & ~mask;
+ writel_relaxed(val, src_base + SRC_SCR);
+}
+
+void imx_set_cpu_jump(int cpu, void *jump_addr)
+{
+ cpu = cpu_logical_map(cpu);
+ writel_relaxed(BSYM(virt_to_phys(jump_addr)),
+ src_base + SRC_GPR1 + cpu * 8);
+}
+
+void __init imx_src_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-src");
+ src_base = of_iomap(np, 0);
+ WARN_ON(!src_base);
+}
diff --git a/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h b/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h
new file mode 100644
index 0000000..af836c7
--- /dev/null
+++ b/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h
@@ -0,0 +1,48 @@
+/*
+ * arch/arm/mach-ixp2000/include/mach/gpio.h
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ *
+ * This program is free software, you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * IXP2000 GPIO in/out, edge/level detection for IRQs:
+ * IRQs are generated on Falling-edge, Rising-Edge, Level-low, Level-High
+ * or both Falling-edge and Rising-edge.
+ * This must be called *before* the corresponding IRQ is registerd.
+ * Use this instead of directly setting the GPIO registers.
+ * GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb)
+ */
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+#ifndef __ASSEMBLY__
+
+#define GPIO_IN 0
+#define GPIO_OUT 1
+
+#define IXP2000_GPIO_LOW 0
+#define IXP2000_GPIO_HIGH 1
+
+extern void gpio_line_config(int line, int direction);
+
+static inline int gpio_line_get(int line)
+{
+ return (((*IXP2000_GPIO_PLR) >> line) & 1);
+}
+
+static inline void gpio_line_set(int line, int value)
+{
+ if (value == IXP2000_GPIO_HIGH) {
+ ixp2000_reg_write(IXP2000_GPIO_POSR, 1 << line);
+ } else if (value == IXP2000_GPIO_LOW) {
+ ixp2000_reg_write(IXP2000_GPIO_POCR, 1 << line);
+ }
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* ASM_ARCH_IXP2000_GPIO_H_ */
diff --git a/arch/arm/mach-ixp4xx/miccpt-pci.c b/arch/arm/mach-ixp4xx/miccpt-pci.c
new file mode 100644
index 0000000..ca0bae7
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/miccpt-pci.c
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-ixp4xx/miccpt-pci.c
+ *
+ * MICCPT board-level PCI initialization
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * Copyright (C) 2006 OMICRON electronics GmbH
+ *
+ * Author: Michael Jochum <michael.jochum@omicron.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+
+#define MAX_DEV 4
+#define IRQ_LINES 4
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA 1
+#define INTB 2
+#define INTC 3
+#define INTD 4
+
+
+void __init miccpt_pci_preinit(void)
+{
+ irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+ irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+ irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+ irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+ ixp4xx_pci_preinit();
+}
+
+static int __init miccpt_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ static int pci_irq_table[IRQ_LINES] = {
+ IXP4XX_GPIO_IRQ(INTA),
+ IXP4XX_GPIO_IRQ(INTB),
+ IXP4XX_GPIO_IRQ(INTC),
+ IXP4XX_GPIO_IRQ(INTD)
+ };
+
+ if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
+ return pci_irq_table[(slot + pin - 2) % 4];
+
+ return -1;
+}
+
+struct hw_pci miccpt_pci __initdata = {
+ .nr_controllers = 1,
+ .preinit = miccpt_pci_preinit,
+ .swizzle = pci_std_swizzle,
+ .setup = ixp4xx_setup,
+ .scan = ixp4xx_scan_bus,
+ .map_irq = miccpt_map_irq,
+};
+
+int __init miccpt_pci_init(void)
+{
+ if (machine_is_miccpt())
+ pci_common_init(&miccpt_pci);
+ return 0;
+}
+
+subsys_initcall(miccpt_pci_init);
diff --git a/arch/arm/mach-ixp4xx/omixp-setup.c b/arch/arm/mach-ixp4xx/omixp-setup.c
new file mode 100644
index 0000000..3b6a81a
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/omixp-setup.c
@@ -0,0 +1,273 @@
+/*
+ * arch/arm/mach-ixp4xx/omixp-setup.c
+ *
+ * omicron ixp4xx board setup
+ * Copyright (C) 2009 OMICRON electronics GmbH
+ *
+ * based nslu2-setup.c, ixdp425-setup.c:
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#ifdef CONFIG_LEDS_CLASS
+#include <linux/leds.h>
+#endif
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct resource omixp_flash_resources[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ }, {
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct mtd_partition omixp_partitions[] = {
+ {
+ .name = "Recovery Bootloader",
+ .size = 0x00020000,
+ .offset = 0,
+ }, {
+ .name = "Calibration Data",
+ .size = 0x00020000,
+ .offset = 0x00020000,
+ }, {
+ .name = "Recovery FPGA",
+ .size = 0x00020000,
+ .offset = 0x00040000,
+ }, {
+ .name = "Release Bootloader",
+ .size = 0x00020000,
+ .offset = 0x00060000,
+ }, {
+ .name = "Release FPGA",
+ .size = 0x00020000,
+ .offset = 0x00080000,
+ }, {
+ .name = "Kernel",
+ .size = 0x00160000,
+ .offset = 0x000a0000,
+ }, {
+ .name = "Filesystem",
+ .size = 0x00C00000,
+ .offset = 0x00200000,
+ }, {
+ .name = "Persistent Storage",
+ .size = 0x00200000,
+ .offset = 0x00E00000,
+ },
+};
+
+static struct flash_platform_data omixp_flash_data[] = {
+ {
+ .map_name = "cfi_probe",
+ .parts = omixp_partitions,
+ .nr_parts = ARRAY_SIZE(omixp_partitions),
+ }, {
+ .map_name = "cfi_probe",
+ .parts = NULL,
+ .nr_parts = 0,
+ },
+};
+
+static struct platform_device omixp_flash_device[] = {
+ {
+ .name = "IXP4XX-Flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &omixp_flash_data[0],
+ },
+ .resource = &omixp_flash_resources[0],
+ .num_resources = 1,
+ }, {
+ .name = "IXP4XX-Flash",
+ .id = 1,
+ .dev = {
+ .platform_data = &omixp_flash_data[1],
+ },
+ .resource = &omixp_flash_resources[1],
+ .num_resources = 1,
+ },
+};
+
+/* Swap UART's - These boards have the console on UART2. The following
+ * configuration is used:
+ * ttyS0 .. UART2
+ * ttyS1 .. UART1
+ * This way standard images can be used with the kernel that expect
+ * the console on ttyS0.
+ */
+static struct resource omixp_uart_resources[] = {
+ {
+ .start = IXP4XX_UART2_BASE_PHYS,
+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IXP4XX_UART1_BASE_PHYS,
+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct plat_serial8250_port omixp_uart_data[] = {
+ {
+ .mapbase = IXP4XX_UART2_BASE_PHYS,
+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+ .irq = IRQ_IXP4XX_UART2,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+ }, {
+ .mapbase = IXP4XX_UART1_BASE_PHYS,
+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+ .irq = IRQ_IXP4XX_UART1,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+ }, {
+ /* list termination */
+ }
+};
+
+static struct platform_device omixp_uart = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev.platform_data = omixp_uart_data,
+ .num_resources = 2,
+ .resource = omixp_uart_resources,
+};
+
+static struct gpio_led mic256_led_pins[] = {
+ {
+ .name = "LED-A",
+ .gpio = 7,
+ },
+};
+
+static struct gpio_led_platform_data mic256_led_data = {
+ .num_leds = ARRAY_SIZE(mic256_led_pins),
+ .leds = mic256_led_pins,
+};
+
+static struct platform_device mic256_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev.platform_data = &mic256_led_data,
+};
+
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info ixdp425_plat_eth[] = {
+ {
+ .phy = 0,
+ .rxq = 3,
+ .txreadyq = 20,
+ }, {
+ .phy = 1,
+ .rxq = 4,
+ .txreadyq = 21,
+ },
+};
+
+static struct platform_device ixdp425_eth[] = {
+ {
+ .name = "ixp4xx_eth",
+ .id = IXP4XX_ETH_NPEB,
+ .dev.platform_data = ixdp425_plat_eth,
+ }, {
+ .name = "ixp4xx_eth",
+ .id = IXP4XX_ETH_NPEC,
+ .dev.platform_data = ixdp425_plat_eth + 1,
+ },
+};
+
+
+static struct platform_device *devixp_pldev[] __initdata = {
+ &omixp_uart,
+ &omixp_flash_device[0],
+ &ixdp425_eth[0],
+ &ixdp425_eth[1],
+};
+
+static struct platform_device *mic256_pldev[] __initdata = {
+ &omixp_uart,
+ &omixp_flash_device[0],
+ &mic256_leds,
+ &ixdp425_eth[0],
+ &ixdp425_eth[1],
+};
+
+static struct platform_device *miccpt_pldev[] __initdata = {
+ &omixp_uart,
+ &omixp_flash_device[0],
+ &omixp_flash_device[1],
+ &ixdp425_eth[0],
+ &ixdp425_eth[1],
+};
+
+static void __init omixp_init(void)
+{
+ ixp4xx_sys_init();
+
+ /* 16MiB Boot Flash */
+ omixp_flash_resources[0].start = IXP4XX_EXP_BUS_BASE(0);
+ omixp_flash_resources[0].end = IXP4XX_EXP_BUS_END(0);
+
+ /* 32 MiB Data Flash */
+ omixp_flash_resources[1].start = IXP4XX_EXP_BUS_BASE(2);
+ omixp_flash_resources[1].end = IXP4XX_EXP_BUS_END(2);
+
+ if (machine_is_devixp())
+ platform_add_devices(devixp_pldev, ARRAY_SIZE(devixp_pldev));
+ else if (machine_is_miccpt())
+ platform_add_devices(miccpt_pldev, ARRAY_SIZE(miccpt_pldev));
+ else if (machine_is_mic256())
+ platform_add_devices(mic256_pldev, ARRAY_SIZE(mic256_pldev));
+}
+
+#ifdef CONFIG_MACH_DEVIXP
+MACHINE_START(DEVIXP, "Omicron DEVIXP")
+ .atag_offset = 0x100,
+ .map_io = ixp4xx_map_io,
+ .init_irq = ixp4xx_init_irq,
+ .timer = &ixp4xx_timer,
+ .init_machine = omixp_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MICCPT
+MACHINE_START(MICCPT, "Omicron MICCPT")
+ .atag_offset = 0x100,
+ .map_io = ixp4xx_map_io,
+ .init_irq = ixp4xx_init_irq,
+ .timer = &ixp4xx_timer,
+ .init_machine = omixp_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MIC256
+MACHINE_START(MIC256, "Omicron MIC256")
+ .atag_offset = 0x100,
+ .map_io = ixp4xx_map_io,
+ .init_irq = ixp4xx_init_irq,
+ .timer = &ixp4xx_timer,
+ .init_machine = omixp_init,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h b/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h
new file mode 100644
index 0000000..6eb034d
--- /dev/null
+++ b/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2006 Andrew Victor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __MACH_KS8659_GPIO_H
+#define __MACH_KS8659_GPIO_H
+
+#include <linux/kernel.h>
+
+#define KS8695_GPIO_0 0
+#define KS8695_GPIO_1 1
+#define KS8695_GPIO_2 2
+#define KS8695_GPIO_3 3
+#define KS8695_GPIO_4 4
+#define KS8695_GPIO_5 5
+#define KS8695_GPIO_6 6
+#define KS8695_GPIO_7 7
+#define KS8695_GPIO_8 8
+#define KS8695_GPIO_9 9
+#define KS8695_GPIO_10 10
+#define KS8695_GPIO_11 11
+#define KS8695_GPIO_12 12
+#define KS8695_GPIO_13 13
+#define KS8695_GPIO_14 14
+#define KS8695_GPIO_15 15
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+extern int ks8695_gpio_interrupt(unsigned int pin, unsigned int type);
+
+/* Register the GPIOs */
+extern void ks8695_register_gpios(void);
+
+#endif /* __MACH_KS8659_GPIO_H */
diff --git a/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h b/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h
new file mode 100644
index 0000000..1816e22
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h
@@ -0,0 +1,50 @@
+/*
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_GPIO_LPC32XX_H
+#define __MACH_GPIO_LPC32XX_H
+
+/*
+ * Note!
+ * Muxed GP pins need to be setup to the GP state in the board level
+ * code prior to using this driver.
+ * GPI pins : 28xP3 group
+ * GPO pins : 24xP3 group
+ * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group
+ */
+
+#define LPC32XX_GPIO_P0_MAX 8
+#define LPC32XX_GPIO_P1_MAX 24
+#define LPC32XX_GPIO_P2_MAX 13
+#define LPC32XX_GPIO_P3_MAX 6
+#define LPC32XX_GPI_P3_MAX 28
+#define LPC32XX_GPO_P3_MAX 24
+
+#define LPC32XX_GPIO_P0_GRP 0
+#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
+#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
+#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
+#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
+#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
+
+/*
+ * A specific GPIO can be selected with this macro
+ * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
+ * See the LPC32x0 User's guide for GPIO group numbers
+ */
+#define LPC32XX_GPIO(x, y) ((x) + (y))
+
+#endif /* __MACH_GPIO_LPC32XX_H */
diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
new file mode 100644
index 0000000..4665767
--- /dev/null
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -0,0 +1,197 @@
+/*
+ * linux/arch/arm/mach-mmp/gplugd.c
+ *
+ * Support for the Marvell PXA168-based GuruPlug Display (gplugD) Platform.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <mach/pxa168.h>
+#include <mach/mfp-pxa168.h>
+
+#include "common.h"
+
+static unsigned long gplugd_pin_config[] __initdata = {
+ /* UART3 */
+ GPIO8_UART3_TXD,
+ GPIO9_UART3_RXD,
+ GPIO1O_UART3_CTS,
+ GPIO11_UART3_RTS,
+
+ /* USB OTG PEN */
+ GPIO18_GPIO,
+
+ /* MMC2 */
+ GPIO28_MMC2_CMD,
+ GPIO29_MMC2_CLK,
+ GPIO30_MMC2_DAT0,
+ GPIO31_MMC2_DAT1,
+ GPIO32_MMC2_DAT2,
+ GPIO33_MMC2_DAT3,
+
+ /* LCD & HDMI clock selection GPIO: 0: 74.176MHz, 1: 74.25 MHz */
+ GPIO35_GPIO,
+ GPIO36_GPIO, /* CEC Interrupt */
+
+ /* MMC1 */
+ GPIO43_MMC1_CLK,
+ GPIO49_MMC1_CMD,
+ GPIO41_MMC1_DAT0,
+ GPIO40_MMC1_DAT1,
+ GPIO52_MMC1_DAT2,
+ GPIO51_MMC1_DAT3,
+ GPIO53_MMC1_CD,
+
+ /* LCD */
+ GPIO56_LCD_FCLK_RD,
+ GPIO57_LCD_LCLK_A0,
+ GPIO58_LCD_PCLK_WR,
+ GPIO59_LCD_DENA_BIAS,
+ GPIO60_LCD_DD0,
+ GPIO61_LCD_DD1,
+ GPIO62_LCD_DD2,
+ GPIO63_LCD_DD3,
+ GPIO64_LCD_DD4,
+ GPIO65_LCD_DD5,
+ GPIO66_LCD_DD6,
+ GPIO67_LCD_DD7,
+ GPIO68_LCD_DD8,
+ GPIO69_LCD_DD9,
+ GPIO70_LCD_DD10,
+ GPIO71_LCD_DD11,
+ GPIO72_LCD_DD12,
+ GPIO73_LCD_DD13,
+ GPIO74_LCD_DD14,
+ GPIO75_LCD_DD15,
+ GPIO76_LCD_DD16,
+ GPIO77_LCD_DD17,
+ GPIO78_LCD_DD18,
+ GPIO79_LCD_DD19,
+ GPIO80_LCD_DD20,
+ GPIO81_LCD_DD21,
+ GPIO82_LCD_DD22,
+ GPIO83_LCD_DD23,
+
+ /* GPIO */
+ GPIO84_GPIO,
+ GPIO85_GPIO,
+
+ /* Fast-Ethernet*/
+ GPIO86_TX_CLK,
+ GPIO87_TX_EN,
+ GPIO88_TX_DQ3,
+ GPIO89_TX_DQ2,
+ GPIO90_TX_DQ1,
+ GPIO91_TX_DQ0,
+ GPIO92_MII_CRS,
+ GPIO93_MII_COL,
+ GPIO94_RX_CLK,
+ GPIO95_RX_ER,
+ GPIO96_RX_DQ3,
+ GPIO97_RX_DQ2,
+ GPIO98_RX_DQ1,
+ GPIO99_RX_DQ0,
+ GPIO100_MII_MDC,
+ GPIO101_MII_MDIO,
+ GPIO103_RX_DV,
+ GPIO104_GPIO, /* Reset PHY */
+
+ /* RTC interrupt */
+ GPIO102_GPIO,
+
+ /* I2C */
+ GPIO105_CI2C_SDA,
+ GPIO106_CI2C_SCL,
+
+ /* SPI NOR Flash on SSP2 */
+ GPIO107_SSP2_RXD,
+ GPIO108_SSP2_TXD,
+ GPIO110_GPIO, /* SPI_CSn */
+ GPIO111_SSP2_CLK,
+
+ /* Select JTAG */
+ GPIO109_GPIO,
+
+ /* I2S */
+ GPIO114_I2S_FRM,
+ GPIO115_I2S_BCLK,
+ GPIO116_I2S_TXD
+};
+
+static struct i2c_board_info gplugd_i2c_board_info[] = {
+ {
+ .type = "isl1208",
+ .addr = 0x6F,
+ }
+};
+
+/* Bring PHY out of reset by setting GPIO 104 */
+static int gplugd_eth_init(void)
+{
+ if (unlikely(gpio_request(104, "ETH_RESET_N"))) {
+ printk(KERN_ERR "Can't get hold of GPIO 104 to bring Ethernet "
+ "PHY out of reset\n");
+ return -EIO;
+ }
+
+ gpio_direction_output(104, 1);
+ gpio_free(104);
+ return 0;
+}
+
+struct pxa168_eth_platform_data gplugd_eth_platform_data = {
+ .port_number = 0,
+ .phy_addr = 0,
+ .speed = 0, /* Autonagotiation */
+ .init = gplugd_eth_init,
+};
+
+static void __init select_disp_freq(void)
+{
+ /* set GPIO 35 & clear GPIO 85 to set LCD External Clock to 74.25 MHz */
+ if (unlikely(gpio_request(35, "DISP_FREQ_SEL"))) {
+ printk(KERN_ERR "Can't get hold of GPIO 35 to select display "
+ "frequency\n");
+ } else {
+ gpio_direction_output(35, 1);
+ gpio_free(35);
+ }
+
+ if (unlikely(gpio_request(85, "DISP_FREQ_SEL_2"))) {
+ printk(KERN_ERR "Can't get hold of GPIO 85 to select display "
+ "frequency\n");
+ } else {
+ gpio_direction_output(85, 0);
+ gpio_free(85);
+ }
+}
+
+static void __init gplugd_init(void)
+{
+ mfp_config(ARRAY_AND_SIZE(gplugd_pin_config));
+
+ select_disp_freq();
+
+ /* on-chip devices */
+ pxa168_add_uart(3);
+ pxa168_add_ssp(1);
+ pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info));
+
+ pxa168_add_eth(&gplugd_eth_platform_data);
+}
+
+MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform")
+ .map_io = mmp_map_io,
+ .nr_irqs = IRQ_BOARD_START,
+ .init_irq = pxa168_init_irq,
+ .timer = &pxa168_timer,
+ .init_machine = gplugd_init,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/include/mach/gpio-pxa.h b/arch/arm/mach-mmp/include/mach/gpio-pxa.h
new file mode 100644
index 0000000..99b4ce1
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/gpio-pxa.h
@@ -0,0 +1,30 @@
+#ifndef __ASM_MACH_GPIO_PXA_H
+#define __ASM_MACH_GPIO_PXA_H
+
+#include <mach/addr-map.h>
+#include <mach/irqs.h>
+
+#define GPIO_REGS_VIRT (APB_VIRT_BASE + 0x19000)
+
+#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+#define GPIO_REG(x) (*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
+
+#define NR_BUILTIN_GPIO IRQ_GPIO_NUM
+
+#define gpio_to_bank(gpio) ((gpio) >> 5)
+
+/* NOTE: these macros are defined here to make optimization of
+ * gpio_{get,set}_value() to work when 'gpio' is a constant.
+ * Usage of these macros otherwise is no longer recommended,
+ * use generic GPIO API whenever possible.
+ */
+#define GPIO_bit(gpio) (1 << ((gpio) & 0x1f))
+
+#define GPLR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00)
+#define GPDR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c)
+#define GPSR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18)
+#define GPCR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24)
+
+#include <plat/gpio-pxa.h>
+
+#endif /* __ASM_MACH_GPIO_PXA_H */
diff --git a/arch/arm/mach-mmp/include/mach/sram.h b/arch/arm/mach-mmp/include/mach/sram.h
new file mode 100644
index 0000000..239e0fc
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/sram.h
@@ -0,0 +1,35 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/sram.h
+ *
+ * SRAM Memory Management
+ *
+ * Copyright (c) 2011 Marvell Semiconductors Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ASM_ARCH_SRAM_H
+#define __ASM_ARCH_SRAM_H
+
+#include <linux/genalloc.h>
+
+/* ARBITRARY: SRAM allocations are multiples of this 2^N size */
+#define SRAM_GRANULARITY 512
+
+enum sram_type {
+ MMP_SRAM_UNDEFINED = 0,
+ MMP_ASRAM,
+ MMP_ISRAM,
+};
+
+struct sram_platdata {
+ char *pool_name;
+ int granularity;
+};
+
+extern struct gen_pool *sram_get_gpool(char *pool_name);
+
+#endif /* __ASM_ARCH_SRAM_H */
diff --git a/arch/arm/mach-mmp/sram.c b/arch/arm/mach-mmp/sram.c
new file mode 100644
index 0000000..4304f95
--- /dev/null
+++ b/arch/arm/mach-mmp/sram.c
@@ -0,0 +1,168 @@
+/*
+ * linux/arch/arm/mach-mmp/sram.c
+ *
+ * based on mach-davinci/sram.c - DaVinci simple SRAM allocator
+ *
+ * Copyright (c) 2011 Marvell Semiconductors Inc.
+ * All Rights Reserved
+ *
+ * Add for mmp sram support - Leo Yan <leoy@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/genalloc.h>
+
+#include <mach/sram.h>
+
+struct sram_bank_info {
+ char *pool_name;
+ struct gen_pool *gpool;
+ int granularity;
+
+ phys_addr_t sram_phys;
+ void __iomem *sram_virt;
+ u32 sram_size;
+
+ struct list_head node;
+};
+
+static DEFINE_MUTEX(sram_lock);
+static LIST_HEAD(sram_bank_list);
+
+struct gen_pool *sram_get_gpool(char *pool_name)
+{
+ struct sram_bank_info *info = NULL;
+
+ if (!pool_name)
+ return NULL;
+
+ mutex_lock(&sram_lock);
+
+ list_for_each_entry(info, &sram_bank_list, node)
+ if (!strcmp(pool_name, info->pool_name))
+ break;
+
+ mutex_unlock(&sram_lock);
+
+ if (&info->node == &sram_bank_list)
+ return NULL;
+
+ return info->gpool;
+}
+EXPORT_SYMBOL(sram_get_gpool);
+
+static int __devinit sram_probe(struct platform_device *pdev)
+{
+ struct sram_platdata *pdata = pdev->dev.platform_data;
+ struct sram_bank_info *info;
+ struct resource *res;
+ int ret = 0;
+
+ if (!pdata && !pdata->pool_name)
+ return -ENODEV;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no memory resource defined\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (!resource_size(res))
+ return 0;
+
+ info->sram_phys = (phys_addr_t)res->start;
+ info->sram_size = resource_size(res);
+ info->sram_virt = ioremap(info->sram_phys, info->sram_size);
+ info->pool_name = kstrdup(pdata->pool_name, GFP_KERNEL);
+ info->granularity = pdata->granularity;
+
+ info->gpool = gen_pool_create(ilog2(info->granularity), -1);
+ if (!info->gpool) {
+ dev_err(&pdev->dev, "create pool failed\n");
+ ret = -ENOMEM;
+ goto create_pool_err;
+ }
+
+ ret = gen_pool_add_virt(info->gpool, (unsigned long)info->sram_virt,
+ info->sram_phys, info->sram_size, -1);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "add new chunk failed\n");
+ ret = -ENOMEM;
+ goto add_chunk_err;
+ }
+
+ mutex_lock(&sram_lock);
+ list_add(&info->node, &sram_bank_list);
+ mutex_unlock(&sram_lock);
+
+ platform_set_drvdata(pdev, info);
+
+ dev_info(&pdev->dev, "initialized\n");
+ return 0;
+
+add_chunk_err:
+ gen_pool_destroy(info->gpool);
+create_pool_err:
+ iounmap(info->sram_virt);
+ kfree(info->pool_name);
+out:
+ kfree(info);
+ return ret;
+}
+
+static int __devexit sram_remove(struct platform_device *pdev)
+{
+ struct sram_bank_info *info;
+
+ info = platform_get_drvdata(pdev);
+ if (info == NULL)
+ return -ENODEV;
+
+ mutex_lock(&sram_lock);
+ list_del(&info->node);
+ mutex_unlock(&sram_lock);
+
+ gen_pool_destroy(info->gpool);
+ iounmap(info->sram_virt);
+ kfree(info->pool_name);
+ kfree(info);
+ return 0;
+}
+
+static const struct platform_device_id sram_id_table[] = {
+ { "asram", MMP_ASRAM },
+ { "isram", MMP_ISRAM },
+ { }
+};
+
+static struct platform_driver sram_driver = {
+ .probe = sram_probe,
+ .remove = sram_remove,
+ .driver = {
+ .name = "mmp-sram",
+ },
+ .id_table = sram_id_table,
+};
+
+static int __init sram_init(void)
+{
+ return platform_driver_register(&sram_driver);
+}
+core_initcall(sram_init);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-msm/include/mach/msm_gpiomux.h b/arch/arm/mach-msm/include/mach/msm_gpiomux.h
new file mode 100644
index 0000000..0c7d393
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_gpiomux.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _LINUX_MSM_GPIOMUX_H
+#define _LINUX_MSM_GPIOMUX_H
+
+#ifdef CONFIG_MSM_GPIOMUX
+
+/* Increment a gpio's reference count, possibly activating the line. */
+int __must_check msm_gpiomux_get(unsigned gpio);
+
+/* Decrement a gpio's reference count, possibly suspending the line. */
+int msm_gpiomux_put(unsigned gpio);
+
+#else
+
+static inline int __must_check msm_gpiomux_get(unsigned gpio)
+{
+ return -ENOSYS;
+}
+
+static inline int msm_gpiomux_put(unsigned gpio)
+{
+ return -ENOSYS;
+}
+
+#endif
+
+#endif /* _LINUX_MSM_GPIOMUX_H */
diff --git a/arch/arm/mach-mx5/board-mx53_ard.c b/arch/arm/mach-mx5/board-mx53_ard.c
new file mode 100644
index 0000000..0d7f0ff
--- /dev/null
+++ b/arch/arm/mach-mx5/board-mx53_ard.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "crm_regs.h"
+#include "devices-imx53.h"
+
+#define ARD_ETHERNET_INT_B IMX_GPIO_NR(2, 31)
+#define ARD_SD1_CD IMX_GPIO_NR(1, 1)
+#define ARD_SD1_WP IMX_GPIO_NR(1, 9)
+#define ARD_I2CPORTEXP_B IMX_GPIO_NR(2, 3)
+#define ARD_VOLUMEDOWN IMX_GPIO_NR(4, 0)
+#define ARD_HOME IMX_GPIO_NR(5, 10)
+#define ARD_BACK IMX_GPIO_NR(5, 11)
+#define ARD_PROG IMX_GPIO_NR(5, 12)
+#define ARD_VOLUMEUP IMX_GPIO_NR(5, 13)
+
+static iomux_v3_cfg_t mx53_ard_pads[] = {
+ /* UART1 */
+ MX53_PAD_PATA_DIOW__UART1_TXD_MUX,
+ MX53_PAD_PATA_DMACK__UART1_RXD_MUX,
+ /* WEIM for CS1 */
+ MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */
+ MX53_PAD_EIM_D16__EMI_WEIM_D_16,
+ MX53_PAD_EIM_D17__EMI_WEIM_D_17,
+ MX53_PAD_EIM_D18__EMI_WEIM_D_18,
+ MX53_PAD_EIM_D19__EMI_WEIM_D_19,
+ MX53_PAD_EIM_D20__EMI_WEIM_D_20,
+ MX53_PAD_EIM_D21__EMI_WEIM_D_21,
+ MX53_PAD_EIM_D22__EMI_WEIM_D_22,
+ MX53_PAD_EIM_D23__EMI_WEIM_D_23,
+ MX53_PAD_EIM_D24__EMI_WEIM_D_24,
+ MX53_PAD_EIM_D25__EMI_WEIM_D_25,
+ MX53_PAD_EIM_D26__EMI_WEIM_D_26,
+ MX53_PAD_EIM_D27__EMI_WEIM_D_27,
+ MX53_PAD_EIM_D28__EMI_WEIM_D_28,
+ MX53_PAD_EIM_D29__EMI_WEIM_D_29,
+ MX53_PAD_EIM_D30__EMI_WEIM_D_30,
+ MX53_PAD_EIM_D31__EMI_WEIM_D_31,
+ MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0,
+ MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1,
+ MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2,
+ MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3,
+ MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4,
+ MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5,
+ MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6,
+ MX53_PAD_EIM_OE__EMI_WEIM_OE,
+ MX53_PAD_EIM_RW__EMI_WEIM_RW,
+ MX53_PAD_EIM_CS1__EMI_WEIM_CS_1,
+ /* SDHC1 */
+ MX53_PAD_SD1_CMD__ESDHC1_CMD,
+ MX53_PAD_SD1_CLK__ESDHC1_CLK,
+ MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+ MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+ MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+ MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+ MX53_PAD_PATA_DATA8__ESDHC1_DAT4,
+ MX53_PAD_PATA_DATA9__ESDHC1_DAT5,
+ MX53_PAD_PATA_DATA10__ESDHC1_DAT6,
+ MX53_PAD_PATA_DATA11__ESDHC1_DAT7,
+ MX53_PAD_GPIO_1__GPIO1_1,
+ MX53_PAD_GPIO_9__GPIO1_9,
+ /* I2C2 */
+ MX53_PAD_EIM_EB2__I2C2_SCL,
+ MX53_PAD_KEY_ROW3__I2C2_SDA,
+ /* I2C3 */
+ MX53_PAD_GPIO_3__I2C3_SCL,
+ MX53_PAD_GPIO_16__I2C3_SDA,
+ /* GPIO */
+ MX53_PAD_DISP0_DAT16__GPIO5_10, /* home */
+ MX53_PAD_DISP0_DAT17__GPIO5_11, /* back */
+ MX53_PAD_DISP0_DAT18__GPIO5_12, /* prog */
+ MX53_PAD_DISP0_DAT19__GPIO5_13, /* vol up */
+ MX53_PAD_GPIO_10__GPIO4_0, /* vol down */
+};
+
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \
+{ \
+ .gpio = gpio_num, \
+ .type = EV_KEY, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+ .wakeup = wake, \
+}
+
+static struct gpio_keys_button ard_buttons[] = {
+ GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0),
+ GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0),
+ GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0),
+ GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0),
+ GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static const struct gpio_keys_platform_data ard_button_data __initconst = {
+ .buttons = ard_buttons,
+ .nbuttons = ARRAY_SIZE(ard_buttons),
+};
+
+static struct resource ard_smsc911x_resources[] = {
+ {
+ .start = MX53_CS1_64MB_BASE_ADDR,
+ .end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+ .end = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct smsc911x_platform_config ard_smsc911x_config = {
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+ .flags = SMSC911X_USE_32BIT,
+};
+
+static struct platform_device ard_smsc_lan9220_device = {
+ .name = "smsc911x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ard_smsc911x_resources),
+ .resource = ard_smsc911x_resources,
+ .dev = {
+ .platform_data = &ard_smsc911x_config,
+ },
+};
+
+static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = {
+ .cd_gpio = ARD_SD1_CD,
+ .wp_gpio = ARD_SD1_WP,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c2_data = {
+ .bitrate = 50000,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c3_data = {
+ .bitrate = 400000,
+};
+
+static void __init mx53_ard_io_init(void)
+{
+ gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
+ gpio_direction_input(ARD_ETHERNET_INT_B);
+
+ gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst");
+ gpio_direction_output(ARD_I2CPORTEXP_B, 1);
+}
+
+/* Config CS1 settings for ethernet controller */
+static int weim_cs_config(void)
+{
+ u32 reg;
+ void __iomem *weim_base, *iomuxc_base;
+
+ weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K);
+ if (!weim_base)
+ return -ENOMEM;
+
+ iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
+ if (!iomuxc_base)
+ return -ENOMEM;
+
+ /* CS1 timings for LAN9220 */
+ writel(0x20001, (weim_base + 0x18));
+ writel(0x0, (weim_base + 0x1C));
+ writel(0x16000202, (weim_base + 0x20));
+ writel(0x00000002, (weim_base + 0x24));
+ writel(0x16002082, (weim_base + 0x28));
+ writel(0x00000000, (weim_base + 0x2C));
+ writel(0x00000000, (weim_base + 0x90));
+
+ /* specify 64 MB on CS1 and CS0 on GPR1 */
+ reg = readl(iomuxc_base + 0x4);
+ reg &= ~0x3F;
+ reg |= 0x1B;
+ writel(reg, (iomuxc_base + 0x4));
+
+ iounmap(iomuxc_base);
+ iounmap(weim_base);
+
+ return 0;
+}
+
+void __init imx53_ard_common_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
+ ARRAY_SIZE(mx53_ard_pads));
+ weim_cs_config();
+}
+
+static struct platform_device *devices[] __initdata = {
+ &ard_smsc_lan9220_device,
+};
+
+static void __init mx53_ard_board_init(void)
+{
+ imx53_soc_init();
+ imx53_add_imx_uart(0, NULL);
+
+ imx53_ard_common_init();
+ mx53_ard_io_init();
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+
+ imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
+ imx53_add_imx2_wdt(0, NULL);
+ imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
+ imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
+ imx_add_gpio_keys(&ard_button_data);
+ imx53_add_ahci_imx();
+}
+
+static void __init mx53_ard_timer_init(void)
+{
+ mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_ard_timer = {
+ .init = mx53_ard_timer_init,
+};
+
+MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
+ .map_io = mx53_map_io,
+ .init_early = imx53_init_early,
+ .init_irq = mx53_init_irq,
+ .handle_irq = imx53_handle_irq,
+ .timer = &mx53_ard_timer,
+ .init_machine = mx53_ard_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c
new file mode 100644
index 0000000..596edd9
--- /dev/null
+++ b/arch/arm/mach-mx5/imx51-dt.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx51.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate(). Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
+ OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+ { /* sentinel */ }
+};
+
+static int __init imx51_tzic_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ irq_domain_add_simple(np, 0);
+ return 0;
+}
+
+static int __init imx51_gpio_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+ gpio_irq_base -= 32;
+ irq_domain_add_simple(np, gpio_irq_base);
+
+ return 0;
+}
+
+static const struct of_device_id imx51_irq_match[] __initconst = {
+ { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
+ { .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
+ { /* sentinel */ }
+};
+
+static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
+ { .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
+ { /* sentinel */ }
+};
+
+static void __init imx51_dt_init(void)
+{
+ struct device_node *node;
+ const struct of_device_id *of_id;
+ void (*func)(void);
+
+ of_irq_init(imx51_irq_match);
+
+ node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
+ if (node) {
+ of_id = of_match_node(imx51_iomuxc_of_match, node);
+ func = of_id->data;
+ func();
+ of_node_put(node);
+ }
+
+ of_platform_populate(NULL, of_default_bus_match_table,
+ imx51_auxdata_lookup, NULL);
+}
+
+static void __init imx51_timer_init(void)
+{
+ mx51_clocks_init_dt();
+}
+
+static struct sys_timer imx51_timer = {
+ .init = imx51_timer_init,
+};
+
+static const char *imx51_dt_board_compat[] __initdata = {
+ "fsl,imx51-babbage",
+ NULL
+};
+
+DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
+ .map_io = mx51_map_io,
+ .init_early = imx51_init_early,
+ .init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
+ .timer = &imx51_timer,
+ .init_machine = imx51_dt_init,
+ .dt_compat = imx51_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/imx53-dt.c b/arch/arm/mach-mx5/imx53-dt.c
new file mode 100644
index 0000000..85bfd5f
--- /dev/null
+++ b/arch/arm/mach-mx5/imx53-dt.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx53.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate(). Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+ { /* sentinel */ }
+};
+
+static int __init imx53_tzic_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ irq_domain_add_simple(np, 0);
+ return 0;
+}
+
+static int __init imx53_gpio_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+ gpio_irq_base -= 32;
+ irq_domain_add_simple(np, gpio_irq_base);
+
+ return 0;
+}
+
+static const struct of_device_id imx53_irq_match[] __initconst = {
+ { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
+ { .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
+ { /* sentinel */ }
+};
+
+static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
+ { .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
+ { .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
+ { .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, },
+ { .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, },
+ { /* sentinel */ }
+};
+
+static void __init imx53_dt_init(void)
+{
+ struct device_node *node;
+ const struct of_device_id *of_id;
+ void (*func)(void);
+
+ of_irq_init(imx53_irq_match);
+
+ node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
+ if (node) {
+ of_id = of_match_node(imx53_iomuxc_of_match, node);
+ func = of_id->data;
+ func();
+ of_node_put(node);
+ }
+
+ of_platform_populate(NULL, of_default_bus_match_table,
+ imx53_auxdata_lookup, NULL);
+}
+
+static void __init imx53_timer_init(void)
+{
+ mx53_clocks_init_dt();
+}
+
+static struct sys_timer imx53_timer = {
+ .init = imx53_timer_init,
+};
+
+static const char *imx53_dt_board_compat[] __initdata = {
+ "fsl,imx53-ard",
+ "fsl,imx53-evk",
+ "fsl,imx53-qsb",
+ "fsl,imx53-smd",
+ NULL
+};
+
+DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
+ .map_io = mx53_map_io,
+ .init_early = imx53_init_early,
+ .init_irq = mx53_init_irq,
+ .handle_irq = imx53_handle_irq,
+ .timer = &imx53_timer,
+ .init_machine = imx53_dt_init,
+ .dt_compat = imx53_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/pm-imx5.c b/arch/arm/mach-mx5/pm-imx5.c
new file mode 100644
index 0000000..98052fc
--- /dev/null
+++ b/arch/arm/mach-mx5/pm-imx5.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/suspend.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include "crm_regs.h"
+
+static struct clk *gpc_dvfs_clk;
+
+static int mx5_suspend_prepare(void)
+{
+ return clk_enable(gpc_dvfs_clk);
+}
+
+static int mx5_suspend_enter(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ mx5_cpu_lp_set(STOP_POWER_OFF);
+ break;
+ case PM_SUSPEND_STANDBY:
+ mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (state == PM_SUSPEND_MEM) {
+ local_flush_tlb_all();
+ flush_cache_all();
+
+ /*clear the EMPGC0/1 bits */
+ __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
+ __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
+ }
+ cpu_do_idle();
+ return 0;
+}
+
+static void mx5_suspend_finish(void)
+{
+ clk_disable(gpc_dvfs_clk);
+}
+
+static int mx5_pm_valid(suspend_state_t state)
+{
+ return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
+}
+
+static const struct platform_suspend_ops mx5_suspend_ops = {
+ .valid = mx5_pm_valid,
+ .prepare = mx5_suspend_prepare,
+ .enter = mx5_suspend_enter,
+ .finish = mx5_suspend_finish,
+};
+
+static int __init mx5_pm_init(void)
+{
+ if (gpc_dvfs_clk == NULL)
+ gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+
+ if (!IS_ERR(gpc_dvfs_clk)) {
+ if (cpu_is_mx51())
+ suspend_set_ops(&mx5_suspend_ops);
+ } else
+ return -EPERM;
+
+ return 0;
+}
+device_initcall(mx5_pm_init);
diff --git a/arch/arm/mach-mxs/devices/platform-gpio-mxs.c b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c
new file mode 100644
index 0000000..ed0885e
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+struct platform_device *__init mxs_add_gpio(
+ int id, resource_size_t iobase, int irq)
+{
+ struct resource res[] = {
+ {
+ .start = iobase,
+ .end = iobase + SZ_8K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = irq,
+ .end = irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return platform_device_register_resndata(&mxs_apbh_bus,
+ "gpio-mxs", id, res, ARRAY_SIZE(res), NULL, 0);
+}
+
+static int __init mxs_add_mxs_gpio(void)
+{
+ if (cpu_is_mx23()) {
+ mxs_add_gpio(0, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO0);
+ mxs_add_gpio(1, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO1);
+ mxs_add_gpio(2, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO2);
+ }
+
+ if (cpu_is_mx28()) {
+ mxs_add_gpio(0, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO0);
+ mxs_add_gpio(1, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO1);
+ mxs_add_gpio(2, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO2);
+ mxs_add_gpio(3, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO3);
+ mxs_add_gpio(4, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO4);
+ }
+
+ return 0;
+}
+postcore_initcall(mxs_add_mxs_gpio);
diff --git a/arch/arm/mach-mxs/devices/platform-mxs-saif.c b/arch/arm/mach-mxs/devices/platform-mxs-saif.c
new file mode 100644
index 0000000..1ec965e
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-mxs-saif.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_saif_data_entry_single(soc, _id) \
+ { \
+ .id = _id, \
+ .iobase = soc ## _SAIF ## _id ## _BASE_ADDR, \
+ .irq = soc ## _INT_SAIF ## _id, \
+ .dma = soc ## _DMA_SAIF ## _id, \
+ .dmairq = soc ## _INT_SAIF ## _id ##_DMA, \
+ }
+
+#define mxs_saif_data_entry(soc, _id) \
+ [_id] = mxs_saif_data_entry_single(soc, _id)
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_saif_data mx28_saif_data[] __initconst = {
+ mxs_saif_data_entry(MX28, 0),
+ mxs_saif_data_entry(MX28, 1),
+};
+#endif
+
+struct platform_device *__init mxs_add_saif(const struct mxs_saif_data *data)
+{
+ struct resource res[] = {
+ {
+ .start = data->iobase,
+ .end = data->iobase + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .start = data->dma,
+ .end = data->dma,
+ .flags = IORESOURCE_DMA,
+ }, {
+ .start = data->dmairq,
+ .end = data->dmairq,
+ .flags = IORESOURCE_IRQ,
+ },
+
+ };
+
+ return mxs_add_platform_device("mxs-saif", data->id, res,
+ ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c b/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c
new file mode 100644
index 0000000..639eaee
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 Pengutronix, Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <asm/sizes.h>
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#ifdef CONFIG_SOC_IMX23
+struct platform_device *__init mx23_add_rtc_stmp3xxx(void)
+{
+ struct resource res[] = {
+ {
+ .start = MX23_RTC_BASE_ADDR,
+ .end = MX23_RTC_BASE_ADDR + SZ_8K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = MX23_INT_RTC_ALARM,
+ .end = MX23_INT_RTC_ALARM,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return mxs_add_platform_device("stmp3xxx-rtc", 0, res, ARRAY_SIZE(res),
+ NULL, 0);
+}
+#endif /* CONFIG_SOC_IMX23 */
+
+#ifdef CONFIG_SOC_IMX28
+struct platform_device *__init mx28_add_rtc_stmp3xxx(void)
+{
+ struct resource res[] = {
+ {
+ .start = MX28_RTC_BASE_ADDR,
+ .end = MX28_RTC_BASE_ADDR + SZ_8K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = MX28_INT_RTC_ALARM,
+ .end = MX28_INT_RTC_ALARM,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return mxs_add_platform_device("stmp3xxx-rtc", 0, res, ARRAY_SIZE(res),
+ NULL, 0);
+}
+#endif /* CONFIG_SOC_IMX28 */
diff --git a/arch/arm/mach-mxs/mach-m28evk.c b/arch/arm/mach-mxs/mach-m28evk.c
new file mode 100644
index 0000000..6b00577
--- /dev/null
+++ b/arch/arm/mach-mxs/mach-m28evk.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2011
+ * Stefano Babic, DENX Software Engineering, <sbabic@denx.de>
+ *
+ * based on: mach-mx28_evk.c
+ * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/iomux-mx28.h>
+
+#include "devices-mx28.h"
+
+#define M28EVK_GPIO_USERLED1 MXS_GPIO_NR(3, 16)
+#define M28EVK_GPIO_USERLED2 MXS_GPIO_NR(3, 17)
+
+#define MX28EVK_BL_ENABLE MXS_GPIO_NR(3, 18)
+#define M28EVK_LCD_ENABLE MXS_GPIO_NR(3, 28)
+
+#define MX28EVK_MMC0_WRITE_PROTECT MXS_GPIO_NR(2, 12)
+#define MX28EVK_MMC1_WRITE_PROTECT MXS_GPIO_NR(0, 28)
+
+static const iomux_cfg_t m28evk_pads[] __initconst = {
+ /* duart */
+ MX28_PAD_AUART0_CTS__DUART_RX | MXS_PAD_CTRL,
+ MX28_PAD_AUART0_RTS__DUART_TX | MXS_PAD_CTRL,
+
+ /* auart0 */
+ MX28_PAD_AUART0_RX__AUART0_RX | MXS_PAD_CTRL,
+ MX28_PAD_AUART0_TX__AUART0_TX | MXS_PAD_CTRL,
+
+ /* auart3 */
+ MX28_PAD_AUART3_RX__AUART3_RX | MXS_PAD_CTRL,
+ MX28_PAD_AUART3_TX__AUART3_TX | MXS_PAD_CTRL,
+ MX28_PAD_AUART3_CTS__AUART3_CTS | MXS_PAD_CTRL,
+ MX28_PAD_AUART3_RTS__AUART3_RTS | MXS_PAD_CTRL,
+
+#define MXS_PAD_FEC (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP)
+ /* fec0 */
+ MX28_PAD_ENET0_MDC__ENET0_MDC | MXS_PAD_FEC,
+ MX28_PAD_ENET0_MDIO__ENET0_MDIO | MXS_PAD_FEC,
+ MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MXS_PAD_FEC,
+ MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MXS_PAD_FEC,
+ MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MXS_PAD_FEC,
+ MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MXS_PAD_FEC,
+ MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MXS_PAD_FEC,
+ MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MXS_PAD_FEC,
+ MX28_PAD_ENET_CLK__CLKCTRL_ENET | MXS_PAD_FEC,
+ /* fec1 */
+ MX28_PAD_ENET0_CRS__ENET1_RX_EN | MXS_PAD_FEC,
+ MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MXS_PAD_FEC,
+ MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MXS_PAD_FEC,
+ MX28_PAD_ENET0_COL__ENET1_TX_EN | MXS_PAD_FEC,
+ MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MXS_PAD_FEC,
+ MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MXS_PAD_FEC,
+
+ /* flexcan0 */
+ MX28_PAD_GPMI_RDY2__CAN0_TX,
+ MX28_PAD_GPMI_RDY3__CAN0_RX,
+
+ /* flexcan1 */
+ MX28_PAD_GPMI_CE2N__CAN1_TX,
+ MX28_PAD_GPMI_CE3N__CAN1_RX,
+
+ /* I2C */
+ MX28_PAD_I2C0_SCL__I2C0_SCL,
+ MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+ /* mxsfb (lcdif) */
+ MX28_PAD_LCD_D00__LCD_D0 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D01__LCD_D1 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D02__LCD_D2 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D03__LCD_D3 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D04__LCD_D4 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D05__LCD_D5 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D06__LCD_D6 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D07__LCD_D7 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D08__LCD_D8 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D09__LCD_D9 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D18__LCD_D18 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D19__LCD_D19 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D20__LCD_D20 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D21__LCD_D21 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D22__LCD_D22 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D23__LCD_D23 | MXS_PAD_CTRL,
+
+ MX28_PAD_LCD_ENABLE__LCD_ENABLE | MXS_PAD_CTRL,
+ MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | MXS_PAD_CTRL,
+
+ /* mmc0 */
+ MX28_PAD_SSP0_DATA0__SSP0_D0 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA1__SSP0_D1 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA2__SSP0_D2 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA3__SSP0_D3 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA4__SSP0_D4 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA5__SSP0_D5 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA6__SSP0_D6 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA7__SSP0_D7 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_CMD__SSP0_CMD |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+ MX28_PAD_SSP0_SCK__SSP0_SCK |
+ (MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+ /* mmc1 */
+ MX28_PAD_GPMI_D00__SSP1_D0 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D01__SSP1_D1 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D02__SSP1_D2 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D03__SSP1_D3 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D04__SSP1_D4 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D05__SSP1_D5 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D06__SSP1_D6 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D07__SSP1_D7 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_RDY1__SSP1_CMD |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_WRN__SSP1_SCK |
+ (MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+ /* write protect */
+ MX28_PAD_GPMI_RESETN__GPIO_0_28 |
+ (MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+ /* slot power enable */
+ MX28_PAD_PWM4__GPIO_3_29 |
+ (MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+ /* led */
+ MX28_PAD_PWM0__GPIO_3_16 | MXS_PAD_CTRL,
+ MX28_PAD_PWM1__GPIO_3_17 | MXS_PAD_CTRL,
+
+ /* nand */
+ MX28_PAD_GPMI_D00__GPMI_D0 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D01__GPMI_D1 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D02__GPMI_D2 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D03__GPMI_D3 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D04__GPMI_D4 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D05__GPMI_D5 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D06__GPMI_D6 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D07__GPMI_D7 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_CE0N__GPMI_CE0N |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_RDY0__GPMI_READY0 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_RDN__GPMI_RDN |
+ (MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_WRN__GPMI_WRN |
+ (MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_ALE__GPMI_ALE |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_CLE__GPMI_CLE |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_RESETN__GPMI_RESETN |
+ (MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+
+ /* Backlight */
+ MX28_PAD_PWM3__GPIO_3_28 | MXS_PAD_CTRL,
+};
+
+/* led */
+static const struct gpio_led m28evk_leds[] __initconst = {
+ {
+ .name = "user-led1",
+ .default_trigger = "heartbeat",
+ .gpio = M28EVK_GPIO_USERLED1,
+ },
+ {
+ .name = "user-led2",
+ .default_trigger = "heartbeat",
+ .gpio = M28EVK_GPIO_USERLED2,
+ },
+};
+
+static const struct gpio_led_platform_data m28evk_led_data __initconst = {
+ .leds = m28evk_leds,
+ .num_leds = ARRAY_SIZE(m28evk_leds),
+};
+
+static struct fec_platform_data mx28_fec_pdata[] __initdata = {
+ {
+ /* fec0 */
+ .phy = PHY_INTERFACE_MODE_RMII,
+ }, {
+ /* fec1 */
+ .phy = PHY_INTERFACE_MODE_RMII,
+ },
+};
+
+static int __init m28evk_fec_get_mac(void)
+{
+ int i;
+ u32 val;
+ const u32 *ocotp = mxs_get_ocotp();
+
+ if (!ocotp) {
+ pr_err("%s: timeout when reading fec mac from OCOTP\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+
+ /*
+ * OCOTP only stores the last 4 octets for each mac address,
+ * so hard-code DENX OUI (C0:E5:4E) here.
+ */
+ for (i = 0; i < 2; i++) {
+ val = ocotp[i * 4];
+ mx28_fec_pdata[i].mac[0] = 0xC0;
+ mx28_fec_pdata[i].mac[1] = 0xE5;
+ mx28_fec_pdata[i].mac[2] = 0x4E;
+ mx28_fec_pdata[i].mac[3] = (val >> 16) & 0xff;
+ mx28_fec_pdata[i].mac[4] = (val >> 8) & 0xff;
+ mx28_fec_pdata[i].mac[5] = (val >> 0) & 0xff;
+ }
+
+ return 0;
+}
+
+/* mxsfb (lcdif) */
+static struct fb_videomode m28evk_video_modes[] = {
+ {
+ .name = "Ampire AM-800480R2TMQW-T01H",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = 30066, /* picosecond (33.26 MHz) */
+ .left_margin = 0,
+ .right_margin = 256,
+ .upper_margin = 0,
+ .lower_margin = 45,
+ .hsync_len = 1,
+ .vsync_len = 1,
+ .sync = FB_SYNC_DATA_ENABLE_HIGH_ACT,
+ },
+};
+
+static const struct mxsfb_platform_data m28evk_mxsfb_pdata __initconst = {
+ .mode_list = m28evk_video_modes,
+ .mode_count = ARRAY_SIZE(m28evk_video_modes),
+ .default_bpp = 16,
+ .ld_intf_width = STMLCDIF_18BIT,
+};
+
+static struct at24_platform_data m28evk_eeprom = {
+ .byte_len = 16384,
+ .page_size = 32,
+ .flags = AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info m28_stk5v3_i2c_boardinfo[] __initdata = {
+ {
+ I2C_BOARD_INFO("at24", 0x51), /* E0=1, E1=0, E2=0 */
+ .platform_data = &m28evk_eeprom,
+ },
+};
+
+static struct mxs_mmc_platform_data m28evk_mmc_pdata[] __initdata = {
+ {
+ /* mmc0 */
+ .wp_gpio = MX28EVK_MMC0_WRITE_PROTECT,
+ .flags = SLOTF_8_BIT_CAPABLE,
+ }, {
+ /* mmc1 */
+ .wp_gpio = MX28EVK_MMC1_WRITE_PROTECT,
+ .flags = SLOTF_8_BIT_CAPABLE,
+ },
+};
+
+static void __init m28evk_init(void)
+{
+ mxs_iomux_setup_multiple_pads(m28evk_pads, ARRAY_SIZE(m28evk_pads));
+
+ mx28_add_duart();
+ mx28_add_auart0();
+ mx28_add_auart3();
+
+ if (!m28evk_fec_get_mac()) {
+ mx28_add_fec(0, &mx28_fec_pdata[0]);
+ mx28_add_fec(1, &mx28_fec_pdata[1]);
+ }
+
+ mx28_add_flexcan(0, NULL);
+ mx28_add_flexcan(1, NULL);
+
+ mx28_add_mxsfb(&m28evk_mxsfb_pdata);
+
+ mx28_add_mxs_mmc(0, &m28evk_mmc_pdata[0]);
+ mx28_add_mxs_mmc(1, &m28evk_mmc_pdata[1]);
+
+ gpio_led_register_device(0, &m28evk_led_data);
+
+ /* I2C */
+ mx28_add_mxs_i2c(0);
+ i2c_register_board_info(0, m28_stk5v3_i2c_boardinfo,
+ ARRAY_SIZE(m28_stk5v3_i2c_boardinfo));
+}
+
+static void __init m28evk_timer_init(void)
+{
+ mx28_clocks_init();
+}
+
+static struct sys_timer m28evk_timer = {
+ .init = m28evk_timer_init,
+};
+
+MACHINE_START(M28EVK, "DENX M28 EVK")
+ .map_io = mx28_map_io,
+ .init_irq = mx28_init_irq,
+ .timer = &m28evk_timer,
+ .init_machine = m28evk_init,
+MACHINE_END
diff --git a/arch/arm/mach-mxs/mm.c b/arch/arm/mach-mxs/mm.c
new file mode 100644
index 0000000..50af5ce
--- /dev/null
+++ b/arch/arm/mach-mxs/mm.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Create static mapping between physical to virtual memory.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/common.h>
+#include <mach/iomux.h>
+
+/*
+ * Define the MX23 memory map.
+ */
+static struct map_desc mx23_io_desc[] __initdata = {
+ mxs_map_entry(MX23, OCRAM, MT_DEVICE),
+ mxs_map_entry(MX23, IO, MT_DEVICE),
+};
+
+/*
+ * Define the MX28 memory map.
+ */
+static struct map_desc mx28_io_desc[] __initdata = {
+ mxs_map_entry(MX28, OCRAM, MT_DEVICE),
+ mxs_map_entry(MX28, IO, MT_DEVICE),
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+void __init mx23_map_io(void)
+{
+ iotable_init(mx23_io_desc, ARRAY_SIZE(mx23_io_desc));
+}
+
+void __init mx23_init_irq(void)
+{
+ icoll_init_irq();
+}
+
+void __init mx28_map_io(void)
+{
+ iotable_init(mx28_io_desc, ARRAY_SIZE(mx28_io_desc));
+}
+
+void __init mx28_init_irq(void)
+{
+ icoll_init_irq();
+}
diff --git a/arch/arm/mach-omap1/timer.c b/arch/arm/mach-omap1/timer.c
new file mode 100644
index 0000000..fb202af
--- /dev/null
+++ b/arch/arm/mach-omap1/timer.c
@@ -0,0 +1,173 @@
+/**
+ * OMAP1 Dual-Mode Timers - platform device registration
+ *
+ * Contains first level initialization routines which internally
+ * generates timer device information and registers with linux
+ * device model. It also has low level function to chnage the timer
+ * input clock source.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+
+#include <plat/dmtimer.h>
+
+#define OMAP1610_GPTIMER1_BASE 0xfffb1400
+#define OMAP1610_GPTIMER2_BASE 0xfffb1c00
+#define OMAP1610_GPTIMER3_BASE 0xfffb2400
+#define OMAP1610_GPTIMER4_BASE 0xfffb2c00
+#define OMAP1610_GPTIMER5_BASE 0xfffb3400
+#define OMAP1610_GPTIMER6_BASE 0xfffb3c00
+#define OMAP1610_GPTIMER7_BASE 0xfffb7400
+#define OMAP1610_GPTIMER8_BASE 0xfffbd400
+
+#define OMAP1_DM_TIMER_COUNT 8
+
+static int omap1_dm_timer_set_src(struct platform_device *pdev,
+ int source)
+{
+ int n = (pdev->id - 1) << 1;
+ u32 l;
+
+ l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
+ l |= source << n;
+ omap_writel(l, MOD_CONF_CTRL_1);
+
+ return 0;
+}
+
+
+int __init omap1_dm_timer_init(void)
+{
+ int i;
+ int ret;
+ struct dmtimer_platform_data *pdata;
+ struct platform_device *pdev;
+
+ if (!cpu_is_omap16xx())
+ return 0;
+
+ for (i = 1; i <= OMAP1_DM_TIMER_COUNT; i++) {
+ struct resource res[2];
+ u32 base, irq;
+
+ switch (i) {
+ case 1:
+ base = OMAP1610_GPTIMER1_BASE;
+ irq = INT_1610_GPTIMER1;
+ break;
+ case 2:
+ base = OMAP1610_GPTIMER2_BASE;
+ irq = INT_1610_GPTIMER2;
+ break;
+ case 3:
+ base = OMAP1610_GPTIMER3_BASE;
+ irq = INT_1610_GPTIMER3;
+ break;
+ case 4:
+ base = OMAP1610_GPTIMER4_BASE;
+ irq = INT_1610_GPTIMER4;
+ break;
+ case 5:
+ base = OMAP1610_GPTIMER5_BASE;
+ irq = INT_1610_GPTIMER5;
+ break;
+ case 6:
+ base = OMAP1610_GPTIMER6_BASE;
+ irq = INT_1610_GPTIMER6;
+ break;
+ case 7:
+ base = OMAP1610_GPTIMER7_BASE;
+ irq = INT_1610_GPTIMER7;
+ break;
+ case 8:
+ base = OMAP1610_GPTIMER8_BASE;
+ irq = INT_1610_GPTIMER8;
+ break;
+ default:
+ /*
+ * not supposed to reach here.
+ * this is to remove warning.
+ */
+ return -EINVAL;
+ }
+
+ pdev = platform_device_alloc("omap_timer", i);
+ if (!pdev) {
+ pr_err("%s: Failed to device alloc for dmtimer%d\n",
+ __func__, i);
+ return -ENOMEM;
+ }
+
+ memset(res, 0, 2 * sizeof(struct resource));
+ res[0].start = base;
+ res[0].end = base + 0x46;
+ res[0].flags = IORESOURCE_MEM;
+ res[1].start = irq;
+ res[1].end = irq;
+ res[1].flags = IORESOURCE_IRQ;
+ ret = platform_device_add_resources(pdev, res,
+ ARRAY_SIZE(res));
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Failed to add resources.\n",
+ __func__);
+ goto err_free_pdev;
+ }
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&pdev->dev, "%s: Failed to allocate pdata.\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_free_pdata;
+ }
+
+ pdata->set_timer_src = omap1_dm_timer_set_src;
+ pdata->needs_manual_reset = 1;
+
+ ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Failed to add platform data.\n",
+ __func__);
+ goto err_free_pdata;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Failed to add platform device.\n",
+ __func__);
+ goto err_free_pdata;
+ }
+
+ dev_dbg(&pdev->dev, " Registered.\n");
+ }
+
+ return 0;
+
+err_free_pdata:
+ kfree(pdata);
+
+err_free_pdev:
+ platform_device_unregister(pdev);
+
+ return ret;
+}
+arch_initcall(omap1_dm_timer_init);
diff --git a/arch/arm/mach-omap2/clockdomains2420_data.c b/arch/arm/mach-omap2/clockdomains2420_data.c
new file mode 100644
index 0000000..0ab8e46
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains2420_data.c
@@ -0,0 +1,154 @@
+/*
+ * OMAP2420 clockdomains
+ *
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ *
+ * This file contains clockdomains and clockdomain wakeup dependencies
+ * for OMAP2420 chips. Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs must have a dep_bit assigned. So
+ * wkdep_srcs are really just software-controllable dependencies.
+ * Non-software-controllable dependencies do exist, but they are not
+ * encoded below (yet).
+ *
+ * 24xx does not support programmable sleep dependencies (SLEEPDEP)
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}. The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ * from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "prm-regbits-24xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* Wakeup dependency source arrays */
+
+/* 2420-specific possible wakeup dependencies */
+
+/* 2420 PM_WKDEP_MPU: CORE, DSP, WKUP */
+static struct clkdm_dep mpu_2420_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "dsp_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/* 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP */
+static struct clkdm_dep core_2420_wkdeps[] = {
+ { .clkdm_name = "dsp_clkdm" },
+ { .clkdm_name = "gfx_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/*
+ * 2420-only clockdomains
+ */
+
+static struct clockdomain mpu_2420_clkdm = {
+ .name = "mpu_clkdm",
+ .pwrdm = { .name = "mpu_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .wkdep_srcs = mpu_2420_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
+};
+
+static struct clockdomain iva1_2420_clkdm = {
+ .name = "iva1_clkdm",
+ .pwrdm = { .name = "dsp_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .dep_bit = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+ .wkdep_srcs = dsp_24xx_wkdeps,
+ .clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
+};
+
+static struct clockdomain dsp_2420_clkdm = {
+ .name = "dsp_clkdm",
+ .pwrdm = { .name = "dsp_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
+};
+
+static struct clockdomain gfx_2420_clkdm = {
+ .name = "gfx_clkdm",
+ .pwrdm = { .name = "gfx_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = gfx_24xx_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
+};
+
+static struct clockdomain core_l3_2420_clkdm = {
+ .name = "core_l3_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .wkdep_srcs = core_2420_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
+};
+
+static struct clockdomain core_l4_2420_clkdm = {
+ .name = "core_l4_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .wkdep_srcs = core_2420_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
+};
+
+static struct clockdomain dss_2420_clkdm = {
+ .name = "dss_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
+};
+
+static struct clockdomain *clockdomains_omap242x[] __initdata = {
+ &wkup_common_clkdm,
+ &cm_common_clkdm,
+ &prm_common_clkdm,
+ &mpu_2420_clkdm,
+ &iva1_2420_clkdm,
+ &dsp_2420_clkdm,
+ &gfx_2420_clkdm,
+ &core_l3_2420_clkdm,
+ &core_l4_2420_clkdm,
+ &dss_2420_clkdm,
+ NULL,
+};
+
+void __init omap242x_clockdomains_init(void)
+{
+ if (!cpu_is_omap242x())
+ return;
+
+ clkdm_register_platform_funcs(&omap2_clkdm_operations);
+ clkdm_register_clkdms(clockdomains_omap242x);
+ clkdm_complete_init();
+}
diff --git a/arch/arm/mach-omap2/clockdomains2430_data.c b/arch/arm/mach-omap2/clockdomains2430_data.c
new file mode 100644
index 0000000..3645ed0
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains2430_data.c
@@ -0,0 +1,181 @@
+/*
+ * OMAP2xxx clockdomains
+ *
+ * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ *
+ * This file contains clockdomains and clockdomain wakeup dependencies
+ * for OMAP2xxx chips. Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs must have a dep_bit assigned. So
+ * wkdep_srcs are really just software-controllable dependencies.
+ * Non-software-controllable dependencies do exist, but they are not
+ * encoded below (yet).
+ *
+ * 24xx does not support programmable sleep dependencies (SLEEPDEP)
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}. The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ * from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "prm-regbits-24xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* Wakeup dependency source arrays */
+
+/* 2430-specific possible wakeup dependencies */
+
+/* 2430 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP, MDM */
+static struct clkdm_dep core_2430_wkdeps[] = {
+ { .clkdm_name = "dsp_clkdm" },
+ { .clkdm_name = "gfx_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { .clkdm_name = "mdm_clkdm" },
+ { NULL },
+};
+
+/* 2430 PM_WKDEP_MPU: CORE, DSP, WKUP, MDM */
+static struct clkdm_dep mpu_2430_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "dsp_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { .clkdm_name = "mdm_clkdm" },
+ { NULL },
+};
+
+/* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
+static struct clkdm_dep mdm_2430_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/*
+ * 2430-only clockdomains
+ */
+
+static struct clockdomain mpu_2430_clkdm = {
+ .name = "mpu_clkdm",
+ .pwrdm = { .name = "mpu_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = mpu_2430_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
+};
+
+/* Another case of bit name collisions between several registers: EN_MDM */
+static struct clockdomain mdm_clkdm = {
+ .name = "mdm_clkdm",
+ .pwrdm = { .name = "mdm_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .dep_bit = OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
+ .wkdep_srcs = mdm_2430_wkdeps,
+ .clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
+};
+
+static struct clockdomain dsp_2430_clkdm = {
+ .name = "dsp_clkdm",
+ .pwrdm = { .name = "dsp_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .dep_bit = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+ .wkdep_srcs = dsp_24xx_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
+};
+
+static struct clockdomain gfx_2430_clkdm = {
+ .name = "gfx_clkdm",
+ .pwrdm = { .name = "gfx_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = gfx_24xx_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l3_2430_clkdm = {
+ .name = "core_l3_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .dep_bit = OMAP24XX_EN_CORE_SHIFT,
+ .wkdep_srcs = core_2430_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l4_2430_clkdm = {
+ .name = "core_l4_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .dep_bit = OMAP24XX_EN_CORE_SHIFT,
+ .wkdep_srcs = core_2430_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
+};
+
+static struct clockdomain dss_2430_clkdm = {
+ .name = "dss_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
+};
+
+static struct clockdomain *clockdomains_omap243x[] __initdata = {
+ &wkup_common_clkdm,
+ &cm_common_clkdm,
+ &prm_common_clkdm,
+ &mpu_2430_clkdm,
+ &mdm_clkdm,
+ &dsp_2430_clkdm,
+ &gfx_2430_clkdm,
+ &core_l3_2430_clkdm,
+ &core_l4_2430_clkdm,
+ &dss_2430_clkdm,
+ NULL,
+};
+
+void __init omap243x_clockdomains_init(void)
+{
+ if (!cpu_is_omap243x())
+ return;
+
+ clkdm_register_platform_funcs(&omap2_clkdm_operations);
+ clkdm_register_clkdms(clockdomains_omap243x);
+ clkdm_complete_init();
+}
+
diff --git a/arch/arm/mach-omap2/clockdomains3xxx_data.c b/arch/arm/mach-omap2/clockdomains3xxx_data.c
new file mode 100644
index 0000000..b84e138
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains3xxx_data.c
@@ -0,0 +1,398 @@
+/*
+ * OMAP3xxx clockdomains
+ *
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ *
+ * This file contains clockdomains and clockdomain wakeup/sleep
+ * dependencies for the OMAP3xxx chips. Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs or sleepdep_srcs array must have a
+ * dep_bit assigned. So wkdep_srcs/sleepdep_srcs are really just
+ * software-controllable dependencies. Non-software-controllable
+ * dependencies do exist, but they are not encoded below (yet).
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}. The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ * from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-34xx.h"
+#include "prm-regbits-34xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps/sleepdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* OMAP3-specific possible dependencies */
+
+/*
+ * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
+ * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
+ */
+static struct clkdm_dep gfx_sgx_3xxx_wkdeps[] = {
+ { .clkdm_name = "iva2_clkdm", },
+ { .clkdm_name = "mpu_clkdm", },
+ { .clkdm_name = "wkup_clkdm", },
+ { NULL },
+};
+
+/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
+static struct clkdm_dep per_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "iva2_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
+static struct clkdm_dep usbhost_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "iva2_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
+static struct clkdm_dep mpu_3xxx_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "iva2_clkdm" },
+ { .clkdm_name = "dss_clkdm" },
+ { .clkdm_name = "per_clkdm" },
+ { NULL },
+};
+
+/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
+static struct clkdm_dep iva2_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { .clkdm_name = "dss_clkdm" },
+ { .clkdm_name = "per_clkdm" },
+ { NULL },
+};
+
+/* 3430 PM_WKDEP_CAM: IVA2, MPU, WKUP */
+static struct clkdm_dep cam_wkdeps[] = {
+ { .clkdm_name = "iva2_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/* 3430 PM_WKDEP_DSS: IVA2, MPU, WKUP */
+static struct clkdm_dep dss_wkdeps[] = {
+ { .clkdm_name = "iva2_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/* 3430: PM_WKDEP_NEON: MPU */
+static struct clkdm_dep neon_wkdeps[] = {
+ { .clkdm_name = "mpu_clkdm" },
+ { NULL },
+};
+
+/* Sleep dependency source arrays for OMAP3-specific clkdms */
+
+/* 3430: CM_SLEEPDEP_DSS: MPU, IVA */
+static struct clkdm_dep dss_sleepdeps[] = {
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "iva2_clkdm" },
+ { NULL },
+};
+
+/* 3430: CM_SLEEPDEP_PER: MPU, IVA */
+static struct clkdm_dep per_sleepdeps[] = {
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "iva2_clkdm" },
+ { NULL },
+};
+
+/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
+static struct clkdm_dep usbhost_sleepdeps[] = {
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "iva2_clkdm" },
+ { NULL },
+};
+
+/* 3430: CM_SLEEPDEP_CAM: MPU */
+static struct clkdm_dep cam_sleepdeps[] = {
+ { .clkdm_name = "mpu_clkdm" },
+ { NULL },
+};
+
+/*
+ * 3430ES1: CM_SLEEPDEP_GFX: MPU
+ * 3430ES2: CM_SLEEPDEP_SGX: MPU
+ * These can share data since they will never be present simultaneously
+ * on the same device.
+ */
+static struct clkdm_dep gfx_sgx_sleepdeps[] = {
+ { .clkdm_name = "mpu_clkdm" },
+ { NULL },
+};
+
+/*
+ * OMAP3 clockdomains
+ */
+
+static struct clockdomain mpu_3xxx_clkdm = {
+ .name = "mpu_clkdm",
+ .pwrdm = { .name = "mpu_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
+ .dep_bit = OMAP3430_EN_MPU_SHIFT,
+ .wkdep_srcs = mpu_3xxx_wkdeps,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
+};
+
+static struct clockdomain neon_clkdm = {
+ .name = "neon_clkdm",
+ .pwrdm = { .name = "neon_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = neon_wkdeps,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
+};
+
+static struct clockdomain iva2_clkdm = {
+ .name = "iva2_clkdm",
+ .pwrdm = { .name = "iva2_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .dep_bit = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
+ .wkdep_srcs = iva2_wkdeps,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
+};
+
+static struct clockdomain gfx_3430es1_clkdm = {
+ .name = "gfx_clkdm",
+ .pwrdm = { .name = "gfx_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = gfx_sgx_3xxx_wkdeps,
+ .sleepdep_srcs = gfx_sgx_sleepdeps,
+ .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
+};
+
+static struct clockdomain sgx_clkdm = {
+ .name = "sgx_clkdm",
+ .pwrdm = { .name = "sgx_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = gfx_sgx_3xxx_wkdeps,
+ .sleepdep_srcs = gfx_sgx_sleepdeps,
+ .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
+};
+
+/*
+ * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
+ * then that information was removed from the 34xx ES2+ TRM. It is
+ * unclear whether the core is still there, but the clockdomain logic
+ * is there, and must be programmed to an appropriate state if the
+ * CORE clockdomain is to become inactive.
+ */
+static struct clockdomain d2d_clkdm = {
+ .name = "d2d_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l3_3xxx_clkdm = {
+ .name = "core_l3_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .dep_bit = OMAP3430_EN_CORE_SHIFT,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l4_3xxx_clkdm = {
+ .name = "core_l4_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .dep_bit = OMAP3430_EN_CORE_SHIFT,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
+};
+
+/* Another case of bit name collisions between several registers: EN_DSS */
+static struct clockdomain dss_3xxx_clkdm = {
+ .name = "dss_clkdm",
+ .pwrdm = { .name = "dss_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .dep_bit = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
+ .wkdep_srcs = dss_wkdeps,
+ .sleepdep_srcs = dss_sleepdeps,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
+};
+
+static struct clockdomain cam_clkdm = {
+ .name = "cam_clkdm",
+ .pwrdm = { .name = "cam_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = cam_wkdeps,
+ .sleepdep_srcs = cam_sleepdeps,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
+};
+
+static struct clockdomain usbhost_clkdm = {
+ .name = "usbhost_clkdm",
+ .pwrdm = { .name = "usbhost_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = usbhost_wkdeps,
+ .sleepdep_srcs = usbhost_sleepdeps,
+ .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
+};
+
+static struct clockdomain per_clkdm = {
+ .name = "per_clkdm",
+ .pwrdm = { .name = "per_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .dep_bit = OMAP3430_EN_PER_SHIFT,
+ .wkdep_srcs = per_wkdeps,
+ .sleepdep_srcs = per_sleepdeps,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
+};
+
+/*
+ * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
+ * switched of even if sdti is in use
+ */
+static struct clockdomain emu_clkdm = {
+ .name = "emu_clkdm",
+ .pwrdm = { .name = "emu_pwrdm" },
+ .flags = /* CLKDM_CAN_ENABLE_AUTO | */CLKDM_CAN_SWSUP,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
+};
+
+static struct clockdomain dpll1_clkdm = {
+ .name = "dpll1_clkdm",
+ .pwrdm = { .name = "dpll1_pwrdm" },
+};
+
+static struct clockdomain dpll2_clkdm = {
+ .name = "dpll2_clkdm",
+ .pwrdm = { .name = "dpll2_pwrdm" },
+};
+
+static struct clockdomain dpll3_clkdm = {
+ .name = "dpll3_clkdm",
+ .pwrdm = { .name = "dpll3_pwrdm" },
+};
+
+static struct clockdomain dpll4_clkdm = {
+ .name = "dpll4_clkdm",
+ .pwrdm = { .name = "dpll4_pwrdm" },
+};
+
+static struct clockdomain dpll5_clkdm = {
+ .name = "dpll5_clkdm",
+ .pwrdm = { .name = "dpll5_pwrdm" },
+};
+
+/*
+ * Clockdomain hwsup dependencies
+ */
+
+static struct clkdm_autodep clkdm_autodeps[] = {
+ {
+ .clkdm = { .name = "mpu_clkdm" },
+ },
+ {
+ .clkdm = { .name = "iva2_clkdm" },
+ },
+ {
+ .clkdm = { .name = NULL },
+ }
+};
+
+/*
+ *
+ */
+
+static struct clockdomain *clockdomains_omap3430_common[] __initdata = {
+ &wkup_common_clkdm,
+ &cm_common_clkdm,
+ &prm_common_clkdm,
+ &mpu_3xxx_clkdm,
+ &neon_clkdm,
+ &iva2_clkdm,
+ &d2d_clkdm,
+ &core_l3_3xxx_clkdm,
+ &core_l4_3xxx_clkdm,
+ &dss_3xxx_clkdm,
+ &cam_clkdm,
+ &per_clkdm,
+ &emu_clkdm,
+ &dpll1_clkdm,
+ &dpll2_clkdm,
+ &dpll3_clkdm,
+ &dpll4_clkdm,
+ NULL
+};
+
+static struct clockdomain *clockdomains_omap3430es1[] __initdata = {
+ &gfx_3430es1_clkdm,
+ NULL,
+};
+
+static struct clockdomain *clockdomains_omap3430es2plus[] __initdata = {
+ &sgx_clkdm,
+ &dpll5_clkdm,
+ &usbhost_clkdm,
+ NULL,
+};
+
+void __init omap3xxx_clockdomains_init(void)
+{
+ struct clockdomain **sc;
+
+ if (!cpu_is_omap34xx())
+ return;
+
+ clkdm_register_platform_funcs(&omap3_clkdm_operations);
+ clkdm_register_clkdms(clockdomains_omap3430_common);
+
+ sc = (omap_rev() == OMAP3430_REV_ES1_0) ? clockdomains_omap3430es1 :
+ clockdomains_omap3430es2plus;
+
+ clkdm_register_clkdms(sc);
+
+ clkdm_register_autodeps(clkdm_autodeps);
+ clkdm_complete_init();
+}
diff --git a/arch/arm/mach-omap2/display.h b/arch/arm/mach-omap2/display.h
new file mode 100644
index 0000000..b871b01
--- /dev/null
+++ b/arch/arm/mach-omap2/display.h
@@ -0,0 +1,29 @@
+/*
+ * display.h - OMAP2+ integration-specific DSS header
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_DISPLAY_H
+#define __ARCH_ARM_MACH_OMAP2_DISPLAY_H
+
+#include <linux/kernel.h>
+
+struct omap_dss_dispc_dev_attr {
+ u8 manager_count;
+ bool has_framedonetv_irq;
+};
+
+#endif
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
new file mode 100644
index 0000000..04637fa
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
@@ -0,0 +1,173 @@
+/*
+ * omap_hwmod_2xxx_3xxx_interconnect_data.c - common interconnect data, OMAP2/3
+ *
+ * Copyright (C) 2009-2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * XXX handle crossbar/shared link difference for L3?
+ * XXX these should be marked initdata for multi-OMAP kernels
+ */
+#include <asm/sizes.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/serial.h>
+
+#include "omap_hwmod_common_data.h"
+
+struct omap_hwmod_addr_space omap2430_mmc1_addr_space[] = {
+ {
+ .pa_start = 0x4809c000,
+ .pa_end = 0x4809c1ff,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2430_mmc2_addr_space[] = {
+ {
+ .pa_start = 0x480b4000,
+ .pa_end = 0x480b41ff,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_i2c1_addr_space[] = {
+ {
+ .pa_start = 0x48070000,
+ .pa_end = 0x48070000 + SZ_128 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_i2c2_addr_space[] = {
+ {
+ .pa_start = 0x48072000,
+ .pa_end = 0x48072000 + SZ_128 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_dss_addrs[] = {
+ {
+ .pa_start = 0x48050000,
+ .pa_end = 0x48050000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_dss_dispc_addrs[] = {
+ {
+ .pa_start = 0x48050400,
+ .pa_end = 0x48050400 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_dss_rfbi_addrs[] = {
+ {
+ .pa_start = 0x48050800,
+ .pa_end = 0x48050800 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_dss_venc_addrs[] = {
+ {
+ .pa_start = 0x48050C00,
+ .pa_end = 0x48050C00 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_timer10_addrs[] = {
+ {
+ .pa_start = 0x48086000,
+ .pa_end = 0x48086000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_timer11_addrs[] = {
+ {
+ .pa_start = 0x48088000,
+ .pa_end = 0x48088000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer12_addrs[] = {
+ {
+ .pa_start = 0x4808a000,
+ .pa_end = 0x4808a000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_mcspi1_addr_space[] = {
+ {
+ .pa_start = 0x48098000,
+ .pa_end = 0x48098000 + SZ_256 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_mcspi2_addr_space[] = {
+ {
+ .pa_start = 0x4809a000,
+ .pa_end = 0x4809a000 + SZ_256 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[] = {
+ {
+ .pa_start = 0x480b8000,
+ .pa_end = 0x480b8000 + SZ_256 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_dma_system_addrs[] = {
+ {
+ .pa_start = 0x48056000,
+ .pa_end = 0x48056000 + SZ_4K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_mailbox_addrs[] = {
+ {
+ .pa_start = 0x48094000,
+ .pa_end = 0x48094000 + SZ_512 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_mcbsp1_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x48074000,
+ .pa_end = 0x480740ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
new file mode 100644
index 0000000..c11273d
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
@@ -0,0 +1,325 @@
+/*
+ * omap_hwmod_2xxx_3xxx_ipblock_data.c - common IP block data for OMAP2/3
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <plat/omap_hwmod.h>
+#include <plat/serial.h>
+#include <plat/dma.h>
+#include <plat/common.h>
+
+#include <mach/irqs.h>
+
+#include "omap_hwmod_common_data.h"
+
+/* UART */
+
+static struct omap_hwmod_class_sysconfig omap2_uart_sysc = {
+ .rev_offs = 0x50,
+ .sysc_offs = 0x54,
+ .syss_offs = 0x58,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_uart_class = {
+ .name = "uart",
+ .sysc = &omap2_uart_sysc,
+};
+
+/*
+ * 'dss' class
+ * display sub-system
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_dss_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+ SYSS_HAS_RESET_STATUS),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_dss_hwmod_class = {
+ .name = "dss",
+ .sysc = &omap2_dss_sysc,
+ .reset = omap_dss_reset,
+};
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+ SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_dispc_hwmod_class = {
+ .name = "dispc",
+ .sysc = &omap2_dispc_sysc,
+};
+
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_rfbi_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_rfbi_hwmod_class = {
+ .name = "rfbi",
+ .sysc = &omap2_rfbi_sysc,
+};
+
+/*
+ * 'venc' class
+ * video encoder
+ */
+
+struct omap_hwmod_class omap2_venc_hwmod_class = {
+ .name = "venc",
+};
+
+
+/* Common DMA request line data */
+struct omap_hwmod_dma_info omap2_uart1_sdma_reqs[] = {
+ { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, },
+ { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_uart2_sdma_reqs[] = {
+ { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, },
+ { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_uart3_sdma_reqs[] = {
+ { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, },
+ { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_i2c1_sdma_reqs[] = {
+ { .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
+ { .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_i2c2_sdma_reqs[] = {
+ { .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
+ { .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcspi1_sdma_reqs[] = {
+ { .name = "tx0", .dma_req = 35 }, /* DMA_SPI1_TX0 */
+ { .name = "rx0", .dma_req = 36 }, /* DMA_SPI1_RX0 */
+ { .name = "tx1", .dma_req = 37 }, /* DMA_SPI1_TX1 */
+ { .name = "rx1", .dma_req = 38 }, /* DMA_SPI1_RX1 */
+ { .name = "tx2", .dma_req = 39 }, /* DMA_SPI1_TX2 */
+ { .name = "rx2", .dma_req = 40 }, /* DMA_SPI1_RX2 */
+ { .name = "tx3", .dma_req = 41 }, /* DMA_SPI1_TX3 */
+ { .name = "rx3", .dma_req = 42 }, /* DMA_SPI1_RX3 */
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcspi2_sdma_reqs[] = {
+ { .name = "tx0", .dma_req = 43 }, /* DMA_SPI2_TX0 */
+ { .name = "rx0", .dma_req = 44 }, /* DMA_SPI2_RX0 */
+ { .name = "tx1", .dma_req = 45 }, /* DMA_SPI2_TX1 */
+ { .name = "rx1", .dma_req = 46 }, /* DMA_SPI2_RX1 */
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcbsp1_sdma_reqs[] = {
+ { .name = "rx", .dma_req = 32 },
+ { .name = "tx", .dma_req = 31 },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcbsp2_sdma_reqs[] = {
+ { .name = "rx", .dma_req = 34 },
+ { .name = "tx", .dma_req = 33 },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcbsp3_sdma_reqs[] = {
+ { .name = "rx", .dma_req = 18 },
+ { .name = "tx", .dma_req = 17 },
+ { .dma_req = -1 }
+};
+
+/* Other IP block data */
+
+
+/*
+ * omap_hwmod class data
+ */
+
+struct omap_hwmod_class l3_hwmod_class = {
+ .name = "l3"
+};
+
+struct omap_hwmod_class l4_hwmod_class = {
+ .name = "l4"
+};
+
+struct omap_hwmod_class mpu_hwmod_class = {
+ .name = "mpu"
+};
+
+struct omap_hwmod_class iva_hwmod_class = {
+ .name = "iva"
+};
+
+/* Common MPU IRQ line data */
+
+struct omap_hwmod_irq_info omap2_timer1_mpu_irqs[] = {
+ { .irq = 37, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer2_mpu_irqs[] = {
+ { .irq = 38, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer3_mpu_irqs[] = {
+ { .irq = 39, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer4_mpu_irqs[] = {
+ { .irq = 40, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer5_mpu_irqs[] = {
+ { .irq = 41, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer6_mpu_irqs[] = {
+ { .irq = 42, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer7_mpu_irqs[] = {
+ { .irq = 43, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer8_mpu_irqs[] = {
+ { .irq = 44, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer9_mpu_irqs[] = {
+ { .irq = 45, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer10_mpu_irqs[] = {
+ { .irq = 46, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer11_mpu_irqs[] = {
+ { .irq = 47, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_uart1_mpu_irqs[] = {
+ { .irq = INT_24XX_UART1_IRQ, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_uart2_mpu_irqs[] = {
+ { .irq = INT_24XX_UART2_IRQ, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_uart3_mpu_irqs[] = {
+ { .irq = INT_24XX_UART3_IRQ, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_dispc_irqs[] = {
+ { .irq = 25 },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_i2c1_mpu_irqs[] = {
+ { .irq = INT_24XX_I2C1_IRQ, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_i2c2_mpu_irqs[] = {
+ { .irq = INT_24XX_I2C2_IRQ, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_gpio1_irqs[] = {
+ { .irq = 29 }, /* INT_24XX_GPIO_BANK1 */
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_gpio2_irqs[] = {
+ { .irq = 30 }, /* INT_24XX_GPIO_BANK2 */
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_gpio3_irqs[] = {
+ { .irq = 31 }, /* INT_24XX_GPIO_BANK3 */
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_gpio4_irqs[] = {
+ { .irq = 32 }, /* INT_24XX_GPIO_BANK4 */
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_dma_system_irqs[] = {
+ { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+ { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+ { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+ { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_mcspi1_mpu_irqs[] = {
+ { .irq = 65 },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_mcspi2_mpu_irqs[] = {
+ { .irq = 66 },
+ { .irq = -1 }
+};
+
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
new file mode 100644
index 0000000..4f3547c
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
@@ -0,0 +1,130 @@
+/*
+ * omap_hwmod_2xxx_interconnect_data.c - common interconnect data for OMAP2xxx
+ *
+ * Copyright (C) 2009-2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * XXX handle crossbar/shared link difference for L3?
+ * XXX these should be marked initdata for multi-OMAP kernels
+ */
+#include <asm/sizes.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/serial.h>
+
+#include "omap_hwmod_common_data.h"
+
+struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[] = {
+ {
+ .pa_start = OMAP2_UART1_BASE,
+ .pa_end = OMAP2_UART1_BASE + SZ_8K - 1,
+ .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[] = {
+ {
+ .pa_start = OMAP2_UART2_BASE,
+ .pa_end = OMAP2_UART2_BASE + SZ_1K - 1,
+ .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_uart3_addr_space[] = {
+ {
+ .pa_start = OMAP2_UART3_BASE,
+ .pa_end = OMAP2_UART3_BASE + SZ_1K - 1,
+ .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer2_addrs[] = {
+ {
+ .pa_start = 0x4802a000,
+ .pa_end = 0x4802a000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer3_addrs[] = {
+ {
+ .pa_start = 0x48078000,
+ .pa_end = 0x48078000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer4_addrs[] = {
+ {
+ .pa_start = 0x4807a000,
+ .pa_end = 0x4807a000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer5_addrs[] = {
+ {
+ .pa_start = 0x4807c000,
+ .pa_end = 0x4807c000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer6_addrs[] = {
+ {
+ .pa_start = 0x4807e000,
+ .pa_end = 0x4807e000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer7_addrs[] = {
+ {
+ .pa_start = 0x48080000,
+ .pa_end = 0x48080000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer8_addrs[] = {
+ {
+ .pa_start = 0x48082000,
+ .pa_end = 0x48082000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer9_addrs[] = {
+ {
+ .pa_start = 0x48084000,
+ .pa_end = 0x48084000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_mcbsp2_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x48076000,
+ .pa_end = 0x480760ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
new file mode 100644
index 0000000..177dee2
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -0,0 +1,150 @@
+/*
+ * omap_hwmod_2xxx_ipblock_data.c - common IP block data for OMAP2xxx
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <plat/omap_hwmod.h>
+#include <plat/serial.h>
+#include <plat/dma.h>
+#include <plat/dmtimer.h>
+#include <plat/mcspi.h>
+
+#include <mach/irqs.h>
+
+#include "omap_hwmod_common_data.h"
+#include "wd_timer.h"
+
+struct omap_hwmod_irq_info omap2xxx_timer12_mpu_irqs[] = {
+ { .irq = 48, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = {
+ { .name = "dispc", .dma_req = 5 },
+ { .dma_req = -1 }
+};
+/* OMAP2xxx Timer Common */
+static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+ SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_timer_hwmod_class = {
+ .name = "timer",
+ .sysc = &omap2xxx_timer_sysc,
+ .rev = OMAP_TIMER_IP_VERSION_1,
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_wd_timer_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_wd_timer_hwmod_class = {
+ .name = "wd_timer",
+ .sysc = &omap2xxx_wd_timer_sysc,
+ .pre_shutdown = &omap2_wd_timer_disable
+};
+
+/*
+ * 'gpio' class
+ * general purpose io module
+ */
+static struct omap_hwmod_class_sysconfig omap2xxx_gpio_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+ SYSS_HAS_RESET_STATUS),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_gpio_hwmod_class = {
+ .name = "gpio",
+ .sysc = &omap2xxx_gpio_sysc,
+ .rev = 0,
+};
+
+/* system dma */
+static struct omap_hwmod_class_sysconfig omap2xxx_dma_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x002c,
+ .syss_offs = 0x0028,
+ .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
+ SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
+ SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+ .idlemodes = (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_dma_hwmod_class = {
+ .name = "dma",
+ .sysc = &omap2xxx_dma_sysc,
+};
+
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors
+ * using a queued mailbox-interrupt mechanism.
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_mailbox_sysc = {
+ .rev_offs = 0x000,
+ .sysc_offs = 0x010,
+ .syss_offs = 0x014,
+ .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_mailbox_hwmod_class = {
+ .name = "mailbox",
+ .sysc = &omap2xxx_mailbox_sysc,
+};
+
+/*
+ * 'mcspi' class
+ * multichannel serial port interface (mcspi) / master/slave synchronous serial
+ * bus
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_mcspi_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_mcspi_class = {
+ .name = "mcspi",
+ .sysc = &omap2xxx_mcspi_sysc,
+ .rev = OMAP2_MCSPI_REV,
+};
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
new file mode 100644
index 0000000..037b0d7
--- /dev/null
+++ b/arch/arm/mach-omap2/timer.c
@@ -0,0 +1,503 @@
+/*
+ * linux/arch/arm/mach-omap2/timer.c
+ *
+ * OMAP2 GP timer support.
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Update to use new clocksource/clockevent layers
+ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (C) 2007 MontaVista Software, Inc.
+ *
+ * Original driver:
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Paul Mundt <paul.mundt@nokia.com>
+ * Juha Yrjölä <juha.yrjola@nokia.com>
+ * OMAP Dual-mode timer framework support by Timo Teras
+ *
+ * Some parts based off of TI's 24xx code:
+ *
+ * Copyright (C) 2004-2009 Texas Instruments, Inc.
+ *
+ * Roughly modelled after the OMAP1 MPU timer code.
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/slab.h>
+
+#include <asm/mach/time.h>
+#include <plat/dmtimer.h>
+#include <asm/localtimer.h>
+#include <asm/sched_clock.h>
+#include <plat/common.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#include "powerdomain.h"
+
+/* Parent clocks, eventually these will come from the clock framework */
+
+#define OMAP2_MPU_SOURCE "sys_ck"
+#define OMAP3_MPU_SOURCE OMAP2_MPU_SOURCE
+#define OMAP4_MPU_SOURCE "sys_clkin_ck"
+#define OMAP2_32K_SOURCE "func_32k_ck"
+#define OMAP3_32K_SOURCE "omap_32k_fck"
+#define OMAP4_32K_SOURCE "sys_32k_ck"
+
+#ifdef CONFIG_OMAP_32K_TIMER
+#define OMAP2_CLKEV_SOURCE OMAP2_32K_SOURCE
+#define OMAP3_CLKEV_SOURCE OMAP3_32K_SOURCE
+#define OMAP4_CLKEV_SOURCE OMAP4_32K_SOURCE
+#define OMAP3_SECURE_TIMER 12
+#else
+#define OMAP2_CLKEV_SOURCE OMAP2_MPU_SOURCE
+#define OMAP3_CLKEV_SOURCE OMAP3_MPU_SOURCE
+#define OMAP4_CLKEV_SOURCE OMAP4_MPU_SOURCE
+#define OMAP3_SECURE_TIMER 1
+#endif
+
+/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
+#define MAX_GPTIMER_ID 12
+
+static u32 sys_timer_reserved;
+
+/* Clockevent code */
+
+static struct omap_dm_timer clkev;
+static struct clock_event_device clockevent_gpt;
+
+static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &clockevent_gpt;
+
+ __omap_dm_timer_write_status(&clkev, OMAP_TIMER_INT_OVERFLOW);
+
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+}
+
+static struct irqaction omap2_gp_timer_irq = {
+ .name = "gp timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = omap2_gp_timer_interrupt,
+};
+
+static int omap2_gp_timer_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ __omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
+ 0xffffffff - cycles, 1);
+
+ return 0;
+}
+
+static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ u32 period;
+
+ __omap_dm_timer_stop(&clkev, 1, clkev.rate);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ period = clkev.rate / HZ;
+ period -= 1;
+ /* Looks like we need to first set the load value separately */
+ __omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG,
+ 0xffffffff - period, 1);
+ __omap_dm_timer_load_start(&clkev,
+ OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
+ 0xffffffff - period, 1);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
+}
+
+static struct clock_event_device clockevent_gpt = {
+ .name = "gp timer",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .set_next_event = omap2_gp_timer_set_next_event,
+ .set_mode = omap2_gp_timer_set_mode,
+};
+
+static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
+ int gptimer_id,
+ const char *fck_source)
+{
+ char name[10]; /* 10 = sizeof("gptXX_Xck0") */
+ struct omap_hwmod *oh;
+ size_t size;
+ int res = 0;
+
+ sprintf(name, "timer%d", gptimer_id);
+ omap_hwmod_setup_one(name);
+ oh = omap_hwmod_lookup(name);
+ if (!oh)
+ return -ENODEV;
+
+ timer->irq = oh->mpu_irqs[0].irq;
+ timer->phys_base = oh->slaves[0]->addr->pa_start;
+ size = oh->slaves[0]->addr->pa_end - timer->phys_base;
+
+ /* Static mapping, never released */
+ timer->io_base = ioremap(timer->phys_base, size);
+ if (!timer->io_base)
+ return -ENXIO;
+
+ /* After the dmtimer is using hwmod these clocks won't be needed */
+ sprintf(name, "gpt%d_fck", gptimer_id);
+ timer->fclk = clk_get(NULL, name);
+ if (IS_ERR(timer->fclk))
+ return -ENODEV;
+
+ sprintf(name, "gpt%d_ick", gptimer_id);
+ timer->iclk = clk_get(NULL, name);
+ if (IS_ERR(timer->iclk)) {
+ clk_put(timer->fclk);
+ return -ENODEV;
+ }
+
+ omap_hwmod_enable(oh);
+
+ sys_timer_reserved |= (1 << (gptimer_id - 1));
+
+ if (gptimer_id != 12) {
+ struct clk *src;
+
+ src = clk_get(NULL, fck_source);
+ if (IS_ERR(src)) {
+ res = -EINVAL;
+ } else {
+ res = __omap_dm_timer_set_source(timer->fclk, src);
+ if (IS_ERR_VALUE(res))
+ pr_warning("%s: timer%i cannot set source\n",
+ __func__, gptimer_id);
+ clk_put(src);
+ }
+ }
+ __omap_dm_timer_init_regs(timer);
+ __omap_dm_timer_reset(timer, 1, 1);
+ timer->posted = 1;
+
+ timer->rate = clk_get_rate(timer->fclk);
+
+ timer->reserved = 1;
+
+ return res;
+}
+
+static void __init omap2_gp_clockevent_init(int gptimer_id,
+ const char *fck_source)
+{
+ int res;
+
+ res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source);
+ BUG_ON(res);
+
+ omap2_gp_timer_irq.dev_id = (void *)&clkev;
+ setup_irq(clkev.irq, &omap2_gp_timer_irq);
+
+ __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
+
+ clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
+ clockevent_gpt.shift);
+ clockevent_gpt.max_delta_ns =
+ clockevent_delta2ns(0xffffffff, &clockevent_gpt);
+ clockevent_gpt.min_delta_ns =
+ clockevent_delta2ns(3, &clockevent_gpt);
+ /* Timer internal resynch latency. */
+
+ clockevent_gpt.cpumask = cpumask_of(0);
+ clockevents_register_device(&clockevent_gpt);
+
+ pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n",
+ gptimer_id, clkev.rate);
+}
+
+/* Clocksource code */
+
+#ifdef CONFIG_OMAP_32K_TIMER
+/*
+ * When 32k-timer is enabled, don't use GPTimer for clocksource
+ * instead, just leave default clocksource which uses the 32k
+ * sync counter. See clocksource setup in plat-omap/counter_32k.c
+ */
+
+static void __init omap2_gp_clocksource_init(int unused, const char *dummy)
+{
+ omap_init_clocksource_32k();
+}
+
+#else
+
+static struct omap_dm_timer clksrc;
+
+/*
+ * clocksource
+ */
+static DEFINE_CLOCK_DATA(cd);
+static cycle_t clocksource_read_cycles(struct clocksource *cs)
+{
+ return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1);
+}
+
+static struct clocksource clocksource_gpt = {
+ .name = "gp timer",
+ .rating = 300,
+ .read = clocksource_read_cycles,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void notrace dmtimer_update_sched_clock(void)
+{
+ u32 cyc;
+
+ cyc = __omap_dm_timer_read_counter(&clksrc, 1);
+
+ update_sched_clock(&cd, cyc, (u32)~0);
+}
+
+unsigned long long notrace sched_clock(void)
+{
+ u32 cyc = 0;
+
+ if (clksrc.reserved)
+ cyc = __omap_dm_timer_read_counter(&clksrc, 1);
+
+ return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+/* Setup free-running counter for clocksource */
+static void __init omap2_gp_clocksource_init(int gptimer_id,
+ const char *fck_source)
+{
+ int res;
+
+ res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source);
+ BUG_ON(res);
+
+ pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
+ gptimer_id, clksrc.rate);
+
+ __omap_dm_timer_load_start(&clksrc,
+ OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
+ init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);
+
+ if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
+ pr_err("Could not register clocksource %s\n",
+ clocksource_gpt.name);
+}
+#endif
+
+#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \
+ clksrc_nr, clksrc_src) \
+static void __init omap##name##_timer_init(void) \
+{ \
+ omap2_gp_clockevent_init((clkev_nr), clkev_src); \
+ omap2_gp_clocksource_init((clksrc_nr), clksrc_src); \
+}
+
+#define OMAP_SYS_TIMER(name) \
+struct sys_timer omap##name##_timer = { \
+ .init = omap##name##_timer_init, \
+};
+
+#ifdef CONFIG_ARCH_OMAP2
+OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, 2, OMAP2_MPU_SOURCE)
+OMAP_SYS_TIMER(2)
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, 2, OMAP3_MPU_SOURCE)
+OMAP_SYS_TIMER(3)
+OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE,
+ 2, OMAP3_MPU_SOURCE)
+OMAP_SYS_TIMER(3_secure)
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+static void __init omap4_timer_init(void)
+{
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
+ BUG_ON(!twd_base);
+#endif
+ omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE);
+ omap2_gp_clocksource_init(2, OMAP4_MPU_SOURCE);
+}
+OMAP_SYS_TIMER(4)
+#endif
+
+/**
+ * omap2_dm_timer_set_src - change the timer input clock source
+ * @pdev: timer platform device pointer
+ * @source: array index of parent clock source
+ */
+static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
+{
+ int ret;
+ struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
+ struct clk *fclk, *parent;
+ char *parent_name = NULL;
+
+ fclk = clk_get(&pdev->dev, "fck");
+ if (IS_ERR_OR_NULL(fclk)) {
+ dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ switch (source) {
+ case OMAP_TIMER_SRC_SYS_CLK:
+ parent_name = "sys_ck";
+ break;
+
+ case OMAP_TIMER_SRC_32_KHZ:
+ parent_name = "32k_ck";
+ break;
+
+ case OMAP_TIMER_SRC_EXT_CLK:
+ if (pdata->timer_ip_version == OMAP_TIMER_IP_VERSION_1) {
+ parent_name = "alt_ck";
+ break;
+ }
+ dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
+ __func__, __LINE__);
+ clk_put(fclk);
+ return -EINVAL;
+ }
+
+ parent = clk_get(&pdev->dev, parent_name);
+ if (IS_ERR_OR_NULL(parent)) {
+ dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
+ __func__, __LINE__, parent_name);
+ clk_put(fclk);
+ return -EINVAL;
+ }
+
+ ret = clk_set_parent(fclk, parent);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
+ __func__, parent_name);
+ ret = -EINVAL;
+ }
+
+ clk_put(parent);
+ clk_put(fclk);
+
+ return ret;
+}
+
+/**
+ * omap_timer_init - build and register timer device with an
+ * associated timer hwmod
+ * @oh: timer hwmod pointer to be used to build timer device
+ * @user: parameter that can be passed from calling hwmod API
+ *
+ * Called by omap_hwmod_for_each_by_class to register each of the timer
+ * devices present in the system. The number of timer devices is known
+ * by parsing through the hwmod database for a given class name. At the
+ * end of function call memory is allocated for timer device and it is
+ * registered to the framework ready to be proved by the driver.
+ */
+static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
+{
+ int id;
+ int ret = 0;
+ char *name = "omap_timer";
+ struct dmtimer_platform_data *pdata;
+ struct platform_device *pdev;
+ struct omap_timer_capability_dev_attr *timer_dev_attr;
+ struct powerdomain *pwrdm;
+
+ pr_debug("%s: %s\n", __func__, oh->name);
+
+ /* on secure device, do not register secure timer */
+ timer_dev_attr = oh->dev_attr;
+ if (omap_type() != OMAP2_DEVICE_TYPE_GP && timer_dev_attr)
+ if (timer_dev_attr->timer_capability == OMAP_TIMER_SECURE)
+ return ret;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("%s: No memory for [%s]\n", __func__, oh->name);
+ return -ENOMEM;
+ }
+
+ /*
+ * Extract the IDs from name field in hwmod database
+ * and use the same for constructing ids' for the
+ * timer devices. In a way, we are avoiding usage of
+ * static variable witin the function to do the same.
+ * CAUTION: We have to be careful and make sure the
+ * name in hwmod database does not change in which case
+ * we might either make corresponding change here or
+ * switch back static variable mechanism.
+ */
+ sscanf(oh->name, "timer%2d", &id);
+
+ pdata->set_timer_src = omap2_dm_timer_set_src;
+ pdata->timer_ip_version = oh->class->rev;
+
+ /* Mark clocksource and clockevent timers as reserved */
+ if ((sys_timer_reserved >> (id - 1)) & 0x1)
+ pdata->reserved = 1;
+
+ pwrdm = omap_hwmod_get_pwrdm(oh);
+ pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
+#ifdef CONFIG_PM
+ pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
+#endif
+ pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
+ NULL, 0, 0);
+
+ if (IS_ERR(pdev)) {
+ pr_err("%s: Can't build omap_device for %s: %s.\n",
+ __func__, name, oh->name);
+ ret = -EINVAL;
+ }
+
+ kfree(pdata);
+
+ return ret;
+}
+
+/**
+ * omap2_dm_timer_init - top level regular device initialization
+ *
+ * Uses dedicated hwmod api to parse through hwmod database for
+ * given class name and then build and register the timer device.
+ */
+static int __init omap2_dm_timer_init(void)
+{
+ int ret;
+
+ ret = omap_hwmod_for_each_by_class("timer", omap_timer_init, NULL);
+ if (unlikely(ret)) {
+ pr_err("%s: device registration failed.\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+arch_initcall(omap2_dm_timer_init);
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
new file mode 100644
index 0000000..10b20c6
--- /dev/null
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -0,0 +1,328 @@
+/*
+ * twl-common.c
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc..
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/i2c/twl.h>
+#include <linux/gpio.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+
+#include <plat/i2c.h>
+#include <plat/usb.h>
+
+#include "twl-common.h"
+#include "pm.h"
+
+static struct i2c_board_info __initdata pmic_i2c_board_info = {
+ .addr = 0x48,
+ .flags = I2C_CLIENT_WAKE,
+};
+
+void __init omap_pmic_init(int bus, u32 clkrate,
+ const char *pmic_type, int pmic_irq,
+ struct twl4030_platform_data *pmic_data)
+{
+ strncpy(pmic_i2c_board_info.type, pmic_type,
+ sizeof(pmic_i2c_board_info.type));
+ pmic_i2c_board_info.irq = pmic_irq;
+ pmic_i2c_board_info.platform_data = pmic_data;
+
+ omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
+}
+
+void __init omap_pmic_late_init(void)
+{
+ /* Init the OMAP TWL parameters (if PMIC has been registerd) */
+ if (!pmic_i2c_board_info.irq)
+ return;
+
+ omap3_twl_init();
+ omap4_twl_init();
+}
+
+#if defined(CONFIG_ARCH_OMAP3)
+static struct twl4030_usb_data omap3_usb_pdata = {
+ .usb_mode = T2_USB_MODE_ULPI,
+};
+
+static int omap3_batt_table[] = {
+/* 0 C */
+30800, 29500, 28300, 27100,
+26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
+17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
+11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310,
+8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830,
+5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170,
+4040, 3910, 3790, 3670, 3550
+};
+
+static struct twl4030_bci_platform_data omap3_bci_pdata = {
+ .battery_tmp_tbl = omap3_batt_table,
+ .tblsize = ARRAY_SIZE(omap3_batt_table),
+};
+
+static struct twl4030_madc_platform_data omap3_madc_pdata = {
+ .irq_line = 1,
+};
+
+static struct twl4030_codec_data omap3_codec;
+
+static struct twl4030_audio_data omap3_audio_pdata = {
+ .audio_mclk = 26000000,
+ .codec = &omap3_codec,
+};
+
+static struct regulator_consumer_supply omap3_vdda_dac_supplies[] = {
+ REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
+};
+
+static struct regulator_init_data omap3_vdac_idata = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap3_vdda_dac_supplies),
+ .consumer_supplies = omap3_vdda_dac_supplies,
+};
+
+static struct regulator_consumer_supply omap3_vpll2_supplies[] = {
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
+};
+
+static struct regulator_init_data omap3_vpll2_idata = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap3_vpll2_supplies),
+ .consumer_supplies = omap3_vpll2_supplies,
+};
+
+void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
+ u32 pdata_flags, u32 regulators_flags)
+{
+ if (!pmic_data->irq_base)
+ pmic_data->irq_base = TWL4030_IRQ_BASE;
+ if (!pmic_data->irq_end)
+ pmic_data->irq_end = TWL4030_IRQ_END;
+
+ /* Common platform data configurations */
+ if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
+ pmic_data->usb = &omap3_usb_pdata;
+
+ if (pdata_flags & TWL_COMMON_PDATA_BCI && !pmic_data->bci)
+ pmic_data->bci = &omap3_bci_pdata;
+
+ if (pdata_flags & TWL_COMMON_PDATA_MADC && !pmic_data->madc)
+ pmic_data->madc = &omap3_madc_pdata;
+
+ if (pdata_flags & TWL_COMMON_PDATA_AUDIO && !pmic_data->audio)
+ pmic_data->audio = &omap3_audio_pdata;
+
+ /* Common regulator configurations */
+ if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
+ pmic_data->vdac = &omap3_vdac_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VPLL2 && !pmic_data->vpll2)
+ pmic_data->vpll2 = &omap3_vpll2_idata;
+}
+#endif /* CONFIG_ARCH_OMAP3 */
+
+#if defined(CONFIG_ARCH_OMAP4)
+static struct twl4030_usb_data omap4_usb_pdata = {
+ .phy_init = omap4430_phy_init,
+ .phy_exit = omap4430_phy_exit,
+ .phy_power = omap4430_phy_power,
+ .phy_set_clock = omap4430_phy_set_clk,
+ .phy_suspend = omap4430_phy_suspend,
+};
+
+static struct regulator_init_data omap4_vdac_idata = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data omap4_vaux2_idata = {
+ .constraints = {
+ .min_uV = 1200000,
+ .max_uV = 2800000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data omap4_vaux3_idata = {
+ .constraints = {
+ .min_uV = 1000000,
+ .max_uV = 3000000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_consumer_supply omap4_vmmc_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
+
+/* VMMC1 for MMC1 card */
+static struct regulator_init_data omap4_vmmc_idata = {
+ .constraints = {
+ .min_uV = 1200000,
+ .max_uV = 3000000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap4_vmmc_supply),
+ .consumer_supplies = omap4_vmmc_supply,
+};
+
+static struct regulator_init_data omap4_vpp_idata = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 2500000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data omap4_vana_idata = {
+ .constraints = {
+ .min_uV = 2100000,
+ .max_uV = 2100000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_consumer_supply omap4_vcxio_supply[] = {
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dss"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.1"),
+};
+
+static struct regulator_init_data omap4_vcxio_idata = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ .always_on = true,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap4_vcxio_supply),
+ .consumer_supplies = omap4_vcxio_supply,
+};
+
+static struct regulator_init_data omap4_vusb_idata = {
+ .constraints = {
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data omap4_clk32kg_idata = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
+ u32 pdata_flags, u32 regulators_flags)
+{
+ if (!pmic_data->irq_base)
+ pmic_data->irq_base = TWL6030_IRQ_BASE;
+ if (!pmic_data->irq_end)
+ pmic_data->irq_end = TWL6030_IRQ_END;
+
+ /* Common platform data configurations */
+ if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
+ pmic_data->usb = &omap4_usb_pdata;
+
+ /* Common regulator configurations */
+ if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
+ pmic_data->vdac = &omap4_vdac_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VAUX2 && !pmic_data->vaux2)
+ pmic_data->vaux2 = &omap4_vaux2_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VAUX3 && !pmic_data->vaux3)
+ pmic_data->vaux3 = &omap4_vaux3_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VMMC && !pmic_data->vmmc)
+ pmic_data->vmmc = &omap4_vmmc_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VPP && !pmic_data->vpp)
+ pmic_data->vpp = &omap4_vpp_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VANA && !pmic_data->vana)
+ pmic_data->vana = &omap4_vana_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VCXIO && !pmic_data->vcxio)
+ pmic_data->vcxio = &omap4_vcxio_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VUSB && !pmic_data->vusb)
+ pmic_data->vusb = &omap4_vusb_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_CLK32KG &&
+ !pmic_data->clk32kg)
+ pmic_data->clk32kg = &omap4_clk32kg_idata;
+}
+#endif /* CONFIG_ARCH_OMAP4 */
diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h
new file mode 100644
index 0000000..275dde8
--- /dev/null
+++ b/arch/arm/mach-omap2/twl-common.h
@@ -0,0 +1,62 @@
+#ifndef __OMAP_PMIC_COMMON__
+#define __OMAP_PMIC_COMMON__
+
+#include <plat/irqs.h>
+
+#define TWL_COMMON_PDATA_USB (1 << 0)
+#define TWL_COMMON_PDATA_BCI (1 << 1)
+#define TWL_COMMON_PDATA_MADC (1 << 2)
+#define TWL_COMMON_PDATA_AUDIO (1 << 3)
+
+/* Common LDO regulators for TWL4030/TWL6030 */
+#define TWL_COMMON_REGULATOR_VDAC (1 << 0)
+#define TWL_COMMON_REGULATOR_VAUX1 (1 << 1)
+#define TWL_COMMON_REGULATOR_VAUX2 (1 << 2)
+#define TWL_COMMON_REGULATOR_VAUX3 (1 << 3)
+
+/* TWL6030 LDO regulators */
+#define TWL_COMMON_REGULATOR_VMMC (1 << 4)
+#define TWL_COMMON_REGULATOR_VPP (1 << 5)
+#define TWL_COMMON_REGULATOR_VUSIM (1 << 6)
+#define TWL_COMMON_REGULATOR_VANA (1 << 7)
+#define TWL_COMMON_REGULATOR_VCXIO (1 << 8)
+#define TWL_COMMON_REGULATOR_VUSB (1 << 9)
+#define TWL_COMMON_REGULATOR_CLK32KG (1 << 10)
+
+/* TWL4030 LDO regulators */
+#define TWL_COMMON_REGULATOR_VPLL1 (1 << 4)
+#define TWL_COMMON_REGULATOR_VPLL2 (1 << 5)
+
+
+struct twl4030_platform_data;
+
+void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq,
+ struct twl4030_platform_data *pmic_data);
+void omap_pmic_late_init(void);
+
+static inline void omap2_pmic_init(const char *pmic_type,
+ struct twl4030_platform_data *pmic_data)
+{
+ omap_pmic_init(2, 2600, pmic_type, INT_24XX_SYS_NIRQ, pmic_data);
+}
+
+static inline void omap3_pmic_init(const char *pmic_type,
+ struct twl4030_platform_data *pmic_data)
+{
+ omap_pmic_init(1, 2600, pmic_type, INT_34XX_SYS_NIRQ, pmic_data);
+}
+
+static inline void omap4_pmic_init(const char *pmic_type,
+ struct twl4030_platform_data *pmic_data)
+{
+ /* Phoenix Audio IC needs I2C1 to start with 400 KHz or less */
+ omap_pmic_init(1, 400, pmic_type, OMAP44XX_IRQ_SYS_1N, pmic_data);
+}
+
+void omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
+ u32 pdata_flags, u32 regulators_flags);
+
+void omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
+ u32 pdata_flags, u32 regulators_flags);
+
+#endif /* __OMAP_PMIC_COMMON__ */
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
new file mode 100644
index 0000000..031d116
--- /dev/null
+++ b/arch/arm/mach-omap2/vc.c
@@ -0,0 +1,367 @@
+/*
+ * OMAP Voltage Controller (VC) interface
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <plat/cpu.h>
+
+#include "voltage.h"
+#include "vc.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+
+/**
+ * struct omap_vc_channel_cfg - describe the cfg_channel bitfield
+ * @sa: bit for slave address
+ * @rav: bit for voltage configuration register
+ * @rac: bit for command configuration register
+ * @racen: enable bit for RAC
+ * @cmd: bit for command value set selection
+ *
+ * Channel configuration bits, common for OMAP3+
+ * OMAP3 register: PRM_VC_CH_CONF
+ * OMAP4 register: PRM_VC_CFG_CHANNEL
+ * OMAP5 register: PRM_VC_SMPS_<voltdm>_CONFIG
+ */
+struct omap_vc_channel_cfg {
+ u8 sa;
+ u8 rav;
+ u8 rac;
+ u8 racen;
+ u8 cmd;
+};
+
+static struct omap_vc_channel_cfg vc_default_channel_cfg = {
+ .sa = BIT(0),
+ .rav = BIT(1),
+ .rac = BIT(2),
+ .racen = BIT(3),
+ .cmd = BIT(4),
+};
+
+/*
+ * On OMAP3+, all VC channels have the above default bitfield
+ * configuration, except the OMAP4 MPU channel. This appears
+ * to be a freak accident as every other VC channel has the
+ * default configuration, thus creating a mutant channel config.
+ */
+static struct omap_vc_channel_cfg vc_mutant_channel_cfg = {
+ .sa = BIT(0),
+ .rav = BIT(2),
+ .rac = BIT(3),
+ .racen = BIT(4),
+ .cmd = BIT(1),
+};
+
+static struct omap_vc_channel_cfg *vc_cfg_bits;
+#define CFG_CHANNEL_MASK 0x1f
+
+/**
+ * omap_vc_config_channel - configure VC channel to PMIC mappings
+ * @voltdm: pointer to voltagdomain defining the desired VC channel
+ *
+ * Configures the VC channel to PMIC mappings for the following
+ * PMIC settings
+ * - i2c slave address (SA)
+ * - voltage configuration address (RAV)
+ * - command configuration address (RAC) and enable bit (RACEN)
+ * - command values for ON, ONLP, RET and OFF (CMD)
+ *
+ * This function currently only allows flexible configuration of the
+ * non-default channel. Starting with OMAP4, there are more than 2
+ * channels, with one defined as the default (on OMAP4, it's MPU.)
+ * Only the non-default channel can be configured.
+ */
+static int omap_vc_config_channel(struct voltagedomain *voltdm)
+{
+ struct omap_vc_channel *vc = voltdm->vc;
+
+ /*
+ * For default channel, the only configurable bit is RACEN.
+ * All others must stay at zero (see function comment above.)
+ */
+ if (vc->flags & OMAP_VC_CHANNEL_DEFAULT)
+ vc->cfg_channel &= vc_cfg_bits->racen;
+
+ voltdm->rmw(CFG_CHANNEL_MASK << vc->cfg_channel_sa_shift,
+ vc->cfg_channel << vc->cfg_channel_sa_shift,
+ vc->cfg_channel_reg);
+
+ return 0;
+}
+
+/* Voltage scale and accessory APIs */
+int omap_vc_pre_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt,
+ u8 *target_vsel, u8 *current_vsel)
+{
+ struct omap_vc_channel *vc = voltdm->vc;
+ u32 vc_cmdval;
+
+ /* Check if sufficient pmic info is available for this vdd */
+ if (!voltdm->pmic) {
+ pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
+ __func__, voltdm->name);
+ return -EINVAL;
+ }
+
+ if (!voltdm->pmic->uv_to_vsel) {
+ pr_err("%s: PMIC function to convert voltage in uV to"
+ "vsel not registered. Hence unable to scale voltage"
+ "for vdd_%s\n", __func__, voltdm->name);
+ return -ENODATA;
+ }
+
+ if (!voltdm->read || !voltdm->write) {
+ pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+ __func__, voltdm->name);
+ return -EINVAL;
+ }
+
+ *target_vsel = voltdm->pmic->uv_to_vsel(target_volt);
+ *current_vsel = voltdm->pmic->uv_to_vsel(voltdm->nominal_volt);
+
+ /* Setting the ON voltage to the new target voltage */
+ vc_cmdval = voltdm->read(vc->cmdval_reg);
+ vc_cmdval &= ~vc->common->cmd_on_mask;
+ vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift);
+ voltdm->write(vc_cmdval, vc->cmdval_reg);
+
+ omap_vp_update_errorgain(voltdm, target_volt);
+
+ return 0;
+}
+
+void omap_vc_post_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt,
+ u8 target_vsel, u8 current_vsel)
+{
+ u32 smps_steps = 0, smps_delay = 0;
+
+ smps_steps = abs(target_vsel - current_vsel);
+ /* SMPS slew rate / step size. 2us added as buffer. */
+ smps_delay = ((smps_steps * voltdm->pmic->step_size) /
+ voltdm->pmic->slew_rate) + 2;
+ udelay(smps_delay);
+}
+
+/* vc_bypass_scale - VC bypass method of voltage scaling */
+int omap_vc_bypass_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt)
+{
+ struct omap_vc_channel *vc = voltdm->vc;
+ u32 loop_cnt = 0, retries_cnt = 0;
+ u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
+ u8 target_vsel, current_vsel;
+ int ret;
+
+ ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
+ if (ret)
+ return ret;
+
+ vc_valid = vc->common->valid;
+ vc_bypass_val_reg = vc->common->bypass_val_reg;
+ vc_bypass_value = (target_vsel << vc->common->data_shift) |
+ (vc->volt_reg_addr << vc->common->regaddr_shift) |
+ (vc->i2c_slave_addr << vc->common->slaveaddr_shift);
+
+ voltdm->write(vc_bypass_value, vc_bypass_val_reg);
+ voltdm->write(vc_bypass_value | vc_valid, vc_bypass_val_reg);
+
+ vc_bypass_value = voltdm->read(vc_bypass_val_reg);
+ /*
+ * Loop till the bypass command is acknowledged from the SMPS.
+ * NOTE: This is legacy code. The loop count and retry count needs
+ * to be revisited.
+ */
+ while (!(vc_bypass_value & vc_valid)) {
+ loop_cnt++;
+
+ if (retries_cnt > 10) {
+ pr_warning("%s: Retry count exceeded\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ if (loop_cnt > 50) {
+ retries_cnt++;
+ loop_cnt = 0;
+ udelay(10);
+ }
+ vc_bypass_value = voltdm->read(vc_bypass_val_reg);
+ }
+
+ omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
+ return 0;
+}
+
+static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
+{
+ /*
+ * Voltage Manager FSM parameters init
+ * XXX This data should be passed in from the board file
+ */
+ voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET);
+ voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
+ voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
+}
+
+static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
+{
+ static bool is_initialized;
+
+ if (is_initialized)
+ return;
+
+ omap3_vfsm_init(voltdm);
+
+ is_initialized = true;
+}
+
+
+/* OMAP4 specific voltage init functions */
+static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
+{
+ static bool is_initialized;
+ u32 vc_val;
+
+ if (is_initialized)
+ return;
+
+ /* XXX These are magic numbers and do not belong! */
+ vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
+ voltdm->write(vc_val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
+
+ is_initialized = true;
+}
+
+/**
+ * omap_vc_i2c_init - initialize I2C interface to PMIC
+ * @voltdm: voltage domain containing VC data
+ *
+ * Use PMIC supplied seetings for I2C high-speed mode and
+ * master code (if set) and program the VC I2C configuration
+ * register.
+ *
+ * The VC I2C configuration is common to all VC channels,
+ * so this function only configures I2C for the first VC
+ * channel registers. All other VC channels will use the
+ * same configuration.
+ */
+static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
+{
+ struct omap_vc_channel *vc = voltdm->vc;
+ static bool initialized;
+ static bool i2c_high_speed;
+ u8 mcode;
+
+ if (initialized) {
+ if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
+ pr_warn("%s: I2C config for all channels must match.",
+ __func__);
+ return;
+ }
+
+ i2c_high_speed = voltdm->pmic->i2c_high_speed;
+ if (i2c_high_speed)
+ voltdm->rmw(vc->common->i2c_cfg_hsen_mask,
+ vc->common->i2c_cfg_hsen_mask,
+ vc->common->i2c_cfg_reg);
+
+ mcode = voltdm->pmic->i2c_mcode;
+ if (mcode)
+ voltdm->rmw(vc->common->i2c_mcode_mask,
+ mcode << __ffs(vc->common->i2c_mcode_mask),
+ vc->common->i2c_cfg_reg);
+
+ initialized = true;
+}
+
+void __init omap_vc_init_channel(struct voltagedomain *voltdm)
+{
+ struct omap_vc_channel *vc = voltdm->vc;
+ u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
+ u32 val;
+
+ if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
+ pr_err("%s: PMIC info requried to configure vc for"
+ "vdd_%s not populated.Hence cannot initialize vc\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ if (!voltdm->read || !voltdm->write) {
+ pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ vc->cfg_channel = 0;
+ if (vc->flags & OMAP_VC_CHANNEL_CFG_MUTANT)
+ vc_cfg_bits = &vc_mutant_channel_cfg;
+ else
+ vc_cfg_bits = &vc_default_channel_cfg;
+
+ /* get PMIC/board specific settings */
+ vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr;
+ vc->volt_reg_addr = voltdm->pmic->volt_reg_addr;
+ vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr;
+ vc->setup_time = voltdm->pmic->volt_setup_time;
+
+ /* Configure the i2c slave address for this VC */
+ voltdm->rmw(vc->smps_sa_mask,
+ vc->i2c_slave_addr << __ffs(vc->smps_sa_mask),
+ vc->smps_sa_reg);
+ vc->cfg_channel |= vc_cfg_bits->sa;
+
+ /*
+ * Configure the PMIC register addresses.
+ */
+ voltdm->rmw(vc->smps_volra_mask,
+ vc->volt_reg_addr << __ffs(vc->smps_volra_mask),
+ vc->smps_volra_reg);
+ vc->cfg_channel |= vc_cfg_bits->rav;
+
+ if (vc->cmd_reg_addr) {
+ voltdm->rmw(vc->smps_cmdra_mask,
+ vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask),
+ vc->smps_cmdra_reg);
+ vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen;
+ }
+
+ /* Set up the on, inactive, retention and off voltage */
+ on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt);
+ onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt);
+ ret_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->ret_volt);
+ off_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->off_volt);
+ val = ((on_vsel << vc->common->cmd_on_shift) |
+ (onlp_vsel << vc->common->cmd_onlp_shift) |
+ (ret_vsel << vc->common->cmd_ret_shift) |
+ (off_vsel << vc->common->cmd_off_shift));
+ voltdm->write(val, vc->cmdval_reg);
+ vc->cfg_channel |= vc_cfg_bits->cmd;
+
+ /* Channel configuration */
+ omap_vc_config_channel(voltdm);
+
+ /* Configure the setup times */
+ voltdm->rmw(voltdm->vfsm->voltsetup_mask,
+ vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
+ voltdm->vfsm->voltsetup_reg);
+
+ omap_vc_i2c_init(voltdm);
+
+ if (cpu_is_omap34xx())
+ omap3_vc_init_channel(voltdm);
+ else if (cpu_is_omap44xx())
+ omap4_vc_init_channel(voltdm);
+}
+
diff --git a/arch/arm/mach-omap2/voltagedomains2xxx_data.c b/arch/arm/mach-omap2/voltagedomains2xxx_data.c
new file mode 100644
index 0000000..7a41349
--- /dev/null
+++ b/arch/arm/mach-omap2/voltagedomains2xxx_data.c
@@ -0,0 +1,32 @@
+/*
+ * OMAP3 voltage domain data
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include "voltage.h"
+
+static struct voltagedomain omap2_voltdm_core = {
+ .name = "core",
+};
+
+static struct voltagedomain omap2_voltdm_wkup = {
+ .name = "wakeup",
+};
+
+static struct voltagedomain *voltagedomains_omap2[] __initdata = {
+ &omap2_voltdm_core,
+ &omap2_voltdm_wkup,
+ NULL,
+};
+
+void __init omap2xxx_voltagedomains_init(void)
+{
+ voltdm_init(voltagedomains_omap2);
+}
diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c
new file mode 100644
index 0000000..3b52027
--- /dev/null
+++ b/arch/arm/mach-omap2/vp.c
@@ -0,0 +1,283 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "voltage.h"
+#include "vp.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+
+static u32 _vp_set_init_voltage(struct voltagedomain *voltdm, u32 volt)
+{
+ struct omap_vp_instance *vp = voltdm->vp;
+ u32 vpconfig;
+ char vsel;
+
+ vsel = voltdm->pmic->uv_to_vsel(volt);
+
+ vpconfig = voltdm->read(vp->vpconfig);
+ vpconfig &= ~(vp->common->vpconfig_initvoltage_mask |
+ vp->common->vpconfig_forceupdate |
+ vp->common->vpconfig_initvdd);
+ vpconfig |= vsel << __ffs(vp->common->vpconfig_initvoltage_mask);
+ voltdm->write(vpconfig, vp->vpconfig);
+
+ /* Trigger initVDD value copy to voltage processor */
+ voltdm->write((vpconfig | vp->common->vpconfig_initvdd),
+ vp->vpconfig);
+
+ /* Clear initVDD copy trigger bit */
+ voltdm->write(vpconfig, vp->vpconfig);
+
+ return vpconfig;
+}
+
+/* Generic voltage init functions */
+void __init omap_vp_init(struct voltagedomain *voltdm)
+{
+ struct omap_vp_instance *vp = voltdm->vp;
+ u32 val, sys_clk_rate, timeout, waittime;
+ u32 vddmin, vddmax, vstepmin, vstepmax;
+
+ if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
+ pr_err("%s: No PMIC info for vdd_%s\n", __func__, voltdm->name);
+ return;
+ }
+
+ if (!voltdm->read || !voltdm->write) {
+ pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ vp->enabled = false;
+
+ /* Divide to avoid overflow */
+ sys_clk_rate = voltdm->sys_clk.rate / 1000;
+
+ timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000;
+ vddmin = voltdm->pmic->vp_vddmin;
+ vddmax = voltdm->pmic->vp_vddmax;
+
+ waittime = ((voltdm->pmic->step_size / voltdm->pmic->slew_rate) *
+ sys_clk_rate) / 1000;
+ vstepmin = voltdm->pmic->vp_vstepmin;
+ vstepmax = voltdm->pmic->vp_vstepmax;
+
+ /*
+ * VP_CONFIG: error gain is not set here, it will be updated
+ * on each scale, based on OPP.
+ */
+ val = (voltdm->pmic->vp_erroroffset <<
+ __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) |
+ vp->common->vpconfig_timeouten;
+ voltdm->write(val, vp->vpconfig);
+
+ /* VSTEPMIN */
+ val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) |
+ (vstepmin << vp->common->vstepmin_stepmin_shift);
+ voltdm->write(val, vp->vstepmin);
+
+ /* VSTEPMAX */
+ val = (vstepmax << vp->common->vstepmax_stepmax_shift) |
+ (waittime << vp->common->vstepmax_smpswaittimemax_shift);
+ voltdm->write(val, vp->vstepmax);
+
+ /* VLIMITTO */
+ val = (vddmax << vp->common->vlimitto_vddmax_shift) |
+ (vddmin << vp->common->vlimitto_vddmin_shift) |
+ (timeout << vp->common->vlimitto_timeout_shift);
+ voltdm->write(val, vp->vlimitto);
+}
+
+int omap_vp_update_errorgain(struct voltagedomain *voltdm,
+ unsigned long target_volt)
+{
+ struct omap_volt_data *volt_data;
+
+ if (!voltdm->vp)
+ return -EINVAL;
+
+ /* Get volt_data corresponding to target_volt */
+ volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
+ if (IS_ERR(volt_data))
+ return -EINVAL;
+
+ /* Setting vp errorgain based on the voltage */
+ voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask,
+ volt_data->vp_errgain <<
+ __ffs(voltdm->vp->common->vpconfig_errorgain_mask),
+ voltdm->vp->vpconfig);
+
+ return 0;
+}
+
+/* VP force update method of voltage scaling */
+int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt)
+{
+ struct omap_vp_instance *vp = voltdm->vp;
+ u32 vpconfig;
+ u8 target_vsel, current_vsel;
+ int ret, timeout = 0;
+
+ ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
+ if (ret)
+ return ret;
+
+ /*
+ * Clear all pending TransactionDone interrupt/status. Typical latency
+ * is <3us
+ */
+ while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+ vp->common->ops->clear_txdone(vp->id);
+ if (!vp->common->ops->check_txdone(vp->id))
+ break;
+ udelay(1);
+ }
+ if (timeout >= VP_TRANXDONE_TIMEOUT) {
+ pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
+ "Voltage change aborted", __func__, voltdm->name);
+ return -ETIMEDOUT;
+ }
+
+ vpconfig = _vp_set_init_voltage(voltdm, target_volt);
+
+ /* Force update of voltage */
+ voltdm->write(vpconfig | vp->common->vpconfig_forceupdate,
+ voltdm->vp->vpconfig);
+
+ /*
+ * Wait for TransactionDone. Typical latency is <200us.
+ * Depends on SMPSWAITTIMEMIN/MAX and voltage change
+ */
+ timeout = 0;
+ omap_test_timeout(vp->common->ops->check_txdone(vp->id),
+ VP_TRANXDONE_TIMEOUT, timeout);
+ if (timeout >= VP_TRANXDONE_TIMEOUT)
+ pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
+ "TRANXDONE never got set after the voltage update\n",
+ __func__, voltdm->name);
+
+ omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
+
+ /*
+ * Disable TransactionDone interrupt , clear all status, clear
+ * control registers
+ */
+ timeout = 0;
+ while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+ vp->common->ops->clear_txdone(vp->id);
+ if (!vp->common->ops->check_txdone(vp->id))
+ break;
+ udelay(1);
+ }
+
+ if (timeout >= VP_TRANXDONE_TIMEOUT)
+ pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
+ "to clear the TRANXDONE status\n",
+ __func__, voltdm->name);
+
+ /* Clear force bit */
+ voltdm->write(vpconfig, vp->vpconfig);
+
+ return 0;
+}
+
+/**
+ * omap_vp_enable() - API to enable a particular VP
+ * @voltdm: pointer to the VDD whose VP is to be enabled.
+ *
+ * This API enables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_vp_enable(struct voltagedomain *voltdm)
+{
+ struct omap_vp_instance *vp;
+ u32 vpconfig, volt;
+
+ if (!voltdm || IS_ERR(voltdm)) {
+ pr_warning("%s: VDD specified does not exist!\n", __func__);
+ return;
+ }
+
+ vp = voltdm->vp;
+ if (!voltdm->read || !voltdm->write) {
+ pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ /* If VP is already enabled, do nothing. Return */
+ if (vp->enabled)
+ return;
+
+ volt = voltdm_get_voltage(voltdm);
+ if (!volt) {
+ pr_warning("%s: unable to find current voltage for %s\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ vpconfig = _vp_set_init_voltage(voltdm, volt);
+
+ /* Enable VP */
+ vpconfig |= vp->common->vpconfig_vpenable;
+ voltdm->write(vpconfig, vp->vpconfig);
+
+ vp->enabled = true;
+}
+
+/**
+ * omap_vp_disable() - API to disable a particular VP
+ * @voltdm: pointer to the VDD whose VP is to be disabled.
+ *
+ * This API disables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_vp_disable(struct voltagedomain *voltdm)
+{
+ struct omap_vp_instance *vp;
+ u32 vpconfig;
+ int timeout;
+
+ if (!voltdm || IS_ERR(voltdm)) {
+ pr_warning("%s: VDD specified does not exist!\n", __func__);
+ return;
+ }
+
+ vp = voltdm->vp;
+ if (!voltdm->read || !voltdm->write) {
+ pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ /* If VP is already disabled, do nothing. Return */
+ if (!vp->enabled) {
+ pr_warning("%s: Trying to disable VP for vdd_%s when"
+ "it is already disabled\n", __func__, voltdm->name);
+ return;
+ }
+
+ /* Disable VP */
+ vpconfig = voltdm->read(vp->vpconfig);
+ vpconfig &= ~vp->common->vpconfig_vpenable;
+ voltdm->write(vpconfig, vp->vpconfig);
+
+ /*
+ * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
+ */
+ omap_test_timeout((voltdm->read(vp->vstatus)),
+ VP_IDLE_TIMEOUT, timeout);
+
+ if (timeout >= VP_IDLE_TIMEOUT)
+ pr_warning("%s: vdd_%s idle timedout\n",
+ __func__, voltdm->name);
+
+ vp->enabled = false;
+
+ return;
+}
diff --git a/arch/arm/mach-picoxcell/Makefile b/arch/arm/mach-picoxcell/Makefile
new file mode 100644
index 0000000..c550b63
--- /dev/null
+++ b/arch/arm/mach-picoxcell/Makefile
@@ -0,0 +1,3 @@
+obj-y := common.o
+obj-y += time.o
+obj-y += io.o
diff --git a/arch/arm/mach-picoxcell/Makefile.boot b/arch/arm/mach-picoxcell/Makefile.boot
new file mode 100644
index 0000000..b327175
--- /dev/null
+++ b/arch/arm/mach-picoxcell/Makefile.boot
@@ -0,0 +1 @@
+zreladdr-y := 0x00008000
diff --git a/arch/arm/mach-picoxcell/common.c b/arch/arm/mach-picoxcell/common.c
new file mode 100644
index 0000000..34d0834
--- /dev/null
+++ b/arch/arm/mach-picoxcell/common.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/hardware/vic.h>
+
+#include <mach/map.h>
+#include <mach/picoxcell_soc.h>
+
+#include "common.h"
+
+static void __init picoxcell_init_machine(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *picoxcell_dt_match[] = {
+ "picochip,pc3x2",
+ "picochip,pc3x3",
+ NULL
+};
+
+static const struct of_device_id vic_of_match[] __initconst = {
+ { .compatible = "arm,pl192-vic" },
+ { /* Sentinel */ }
+};
+
+static void __init picoxcell_init_irq(void)
+{
+ vic_init(IO_ADDRESS(PICOXCELL_VIC0_BASE), 0, ~0, 0);
+ vic_init(IO_ADDRESS(PICOXCELL_VIC1_BASE), 32, ~0, 0);
+ irq_domain_generate_simple(vic_of_match, PICOXCELL_VIC0_BASE, 0);
+ irq_domain_generate_simple(vic_of_match, PICOXCELL_VIC1_BASE, 32);
+}
+
+DT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
+ .map_io = picoxcell_map_io,
+ .nr_irqs = ARCH_NR_IRQS,
+ .init_irq = picoxcell_init_irq,
+ .timer = &picoxcell_timer,
+ .init_machine = picoxcell_init_machine,
+ .dt_compat = picoxcell_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-picoxcell/common.h b/arch/arm/mach-picoxcell/common.h
new file mode 100644
index 0000000..5263f0f
--- /dev/null
+++ b/arch/arm/mach-picoxcell/common.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * All enquiries to support@picochip.com
+ */
+#ifndef __PICOXCELL_COMMON_H__
+#define __PICOXCELL_COMMON_H__
+
+#include <asm/mach/time.h>
+
+extern struct sys_timer picoxcell_timer;
+extern void picoxcell_map_io(void);
+
+#endif /* __PICOXCELL_COMMON_H__ */
diff --git a/arch/arm/mach-picoxcell/include/mach/debug-macro.S b/arch/arm/mach-picoxcell/include/mach/debug-macro.S
new file mode 100644
index 0000000..58d4ee3
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/debug-macro.S
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
+ * accesses to the 8250.
+ */
+#include <linux/serial_reg.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#define UART_SHIFT 2
+
+ .macro addruart, rp, rv, tmp
+ ldr \rv, =PHYS_TO_IO(PICOXCELL_UART1_BASE)
+ ldr \rp, =PICOXCELL_UART1_BASE
+ .endm
+
+ .macro senduart,rd,rx
+ str \rd, [\rx, #UART_TX << UART_SHIFT]
+ .endm
+
+ .macro busyuart,rd,rx
+1002: ldr \rd, [\rx, #UART_LSR << UART_SHIFT]
+ and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+ teq \rd, #UART_LSR_TEMT | UART_LSR_THRE
+ bne 1002b
+ .endm
+
+ /* The UART's don't have any flow control IO's wired up. */
+ .macro waituart,rd,rx
+ .endm
diff --git a/arch/arm/mach-picoxcell/include/mach/entry-macro.S b/arch/arm/mach-picoxcell/include/mach/entry-macro.S
new file mode 100644
index 0000000..a6b09f7
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/entry-macro.S
@@ -0,0 +1,19 @@
+/*
+ * entry-macro.S
+ *
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * Low-level IRQ helper macros for picoXcell platforms
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#define VA_VIC0 IO_ADDRESS(PICOXCELL_VIC0_BASE)
+#define VA_VIC1 IO_ADDRESS(PICOXCELL_VIC1_BASE)
+
+#include <asm/entry-macro-vic2.S>
diff --git a/arch/arm/mach-picoxcell/include/mach/gpio.h b/arch/arm/mach-picoxcell/include/mach/gpio.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/gpio.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-picoxcell/include/mach/hardware.h b/arch/arm/mach-picoxcell/include/mach/hardware.h
new file mode 100644
index 0000000..70ff581
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/hardware.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC devices.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <mach/picoxcell_soc.h>
+
+#endif
diff --git a/arch/arm/mach-picoxcell/include/mach/io.h b/arch/arm/mach-picoxcell/include/mach/io.h
new file mode 100644
index 0000000..7573ec7
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/io.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/* No ioports, but needed for driver compatibility. */
+#define __io(a) __typesafe_io(a)
+/* No PCI possible on picoxcell. */
+#define __mem_pci(a) (a)
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff --git a/arch/arm/mach-picoxcell/include/mach/irqs.h b/arch/arm/mach-picoxcell/include/mach/irqs.h
new file mode 100644
index 0000000..4d13ed9
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/irqs.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC devices.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define ARCH_NR_IRQS 64
+#define NR_IRQS (128 + ARCH_NR_IRQS)
+
+#define IRQ_VIC0_BASE 0
+#define IRQ_VIC1_BASE 32
+
+#endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-picoxcell/include/mach/map.h b/arch/arm/mach-picoxcell/include/mach/map.h
new file mode 100644
index 0000000..c06afad
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/map.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __PICOXCELL_MAP_H__
+#define __PICOXCELL_MAP_H__
+
+#define PHYS_TO_IO(x) (((x) & 0x00ffffff) | 0xfe000000)
+
+#ifdef __ASSEMBLY__
+#define IO_ADDRESS(x) PHYS_TO_IO((x))
+#else
+#define IO_ADDRESS(x) (void __iomem __force *)(PHYS_TO_IO((x)))
+#endif
+
+#endif /* __PICOXCELL_MAP_H__ */
diff --git a/arch/arm/mach-picoxcell/include/mach/memory.h b/arch/arm/mach-picoxcell/include/mach/memory.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/memory.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h b/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h
new file mode 100644
index 0000000..5566fc8
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC devices.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __PICOXCELL_SOC_H__
+#define __PICOXCELL_SOC_H__
+
+#define PICOXCELL_UART1_BASE 0x80230000
+#define PICOXCELL_PERIPH_BASE 0x80000000
+#define PICOXCELL_PERIPH_LENGTH SZ_4M
+#define PICOXCELL_VIC0_BASE 0x80060000
+#define PICOXCELL_VIC1_BASE 0x80064000
+
+#endif /* __PICOXCELL_SOC_H__ */
diff --git a/arch/arm/mach-picoxcell/include/mach/system.h b/arch/arm/mach-picoxcell/include/mach/system.h
new file mode 100644
index 0000000..67c589b
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/system.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+ /*
+ * This should do all the clock switching and wait for interrupt
+ * tricks.
+ */
+ cpu_do_idle();
+}
+
+static inline void arch_reset(int mode, const char *cmd)
+{
+ /* Watchdog reset to go here. */
+}
+
+#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/arch/arm/mach-picoxcell/include/mach/timex.h b/arch/arm/mach-picoxcell/include/mach/timex.h
new file mode 100644
index 0000000..6c540a6
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/timex.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __TIMEX_H__
+#define __TIMEX_H__
+
+/* Bogus value to allow the kernel to compile. */
+#define CLOCK_TICK_RATE 1000000
+
+#endif /* __TIMEX_H__ */
+
diff --git a/arch/arm/mach-picoxcell/include/mach/uncompress.h b/arch/arm/mach-picoxcell/include/mach/uncompress.h
new file mode 100644
index 0000000..b60b19d
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/uncompress.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#define putc(c)
+#define flush()
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-picoxcell/include/mach/vmalloc.h b/arch/arm/mach-picoxcell/include/mach/vmalloc.h
new file mode 100644
index 0000000..0216cc4
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/vmalloc.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#define VMALLOC_END 0xfe000000UL
diff --git a/arch/arm/mach-picoxcell/io.c b/arch/arm/mach-picoxcell/io.c
new file mode 100644
index 0000000..39e9b9e
--- /dev/null
+++ b/arch/arm/mach-picoxcell/io.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/map.h>
+#include <mach/picoxcell_soc.h>
+
+#include "common.h"
+
+void __init picoxcell_map_io(void)
+{
+ struct map_desc io_map = {
+ .virtual = PHYS_TO_IO(PICOXCELL_PERIPH_BASE),
+ .pfn = __phys_to_pfn(PICOXCELL_PERIPH_BASE),
+ .length = PICOXCELL_PERIPH_LENGTH,
+ .type = MT_DEVICE,
+ };
+
+ iotable_init(&io_map, 1);
+}
diff --git a/arch/arm/mach-picoxcell/time.c b/arch/arm/mach-picoxcell/time.c
new file mode 100644
index 0000000..90a554f
--- /dev/null
+++ b/arch/arm/mach-picoxcell/time.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/dw_apb_timer.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched.h>
+
+#include <asm/mach/time.h>
+#include <asm/sched_clock.h>
+
+#include "common.h"
+
+static void timer_get_base_and_rate(struct device_node *np,
+ void __iomem **base, u32 *rate)
+{
+ *base = of_iomap(np, 0);
+
+ if (!*base)
+ panic("Unable to map regs for %s", np->name);
+
+ if (of_property_read_u32(np, "clock-freq", rate))
+ panic("No clock-freq property for %s", np->name);
+}
+
+static void picoxcell_add_clockevent(struct device_node *event_timer)
+{
+ void __iomem *iobase;
+ struct dw_apb_clock_event_device *ced;
+ u32 irq, rate;
+
+ irq = irq_of_parse_and_map(event_timer, 0);
+ if (irq == NO_IRQ)
+ panic("No IRQ for clock event timer");
+
+ timer_get_base_and_rate(event_timer, &iobase, &rate);
+
+ ced = dw_apb_clockevent_init(0, event_timer->name, 300, iobase, irq,
+ rate);
+ if (!ced)
+ panic("Unable to initialise clockevent device");
+
+ dw_apb_clockevent_register(ced);
+}
+
+static void picoxcell_add_clocksource(struct device_node *source_timer)
+{
+ void __iomem *iobase;
+ struct dw_apb_clocksource *cs;
+ u32 rate;
+
+ timer_get_base_and_rate(source_timer, &iobase, &rate);
+
+ cs = dw_apb_clocksource_init(300, source_timer->name, iobase, rate);
+ if (!cs)
+ panic("Unable to initialise clocksource device");
+
+ dw_apb_clocksource_start(cs);
+ dw_apb_clocksource_register(cs);
+}
+
+static DEFINE_CLOCK_DATA(cd);
+static void __iomem *sched_io_base;
+
+unsigned long long notrace sched_clock(void)
+{
+ cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
+
+ return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace picoxcell_update_sched_clock(void)
+{
+ cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
+
+ update_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static const struct of_device_id picoxcell_rtc_ids[] __initconst = {
+ { .compatible = "picochip,pc3x2-rtc" },
+ { /* Sentinel */ },
+};
+
+static void picoxcell_init_sched_clock(void)
+{
+ struct device_node *sched_timer;
+ u32 rate;
+
+ sched_timer = of_find_matching_node(NULL, picoxcell_rtc_ids);
+ if (!sched_timer)
+ panic("No RTC for sched clock to use");
+
+ timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
+ of_node_put(sched_timer);
+
+ init_sched_clock(&cd, picoxcell_update_sched_clock, 32, rate);
+}
+
+static const struct of_device_id picoxcell_timer_ids[] __initconst = {
+ { .compatible = "picochip,pc3x2-timer" },
+ {},
+};
+
+static void __init picoxcell_timer_init(void)
+{
+ struct device_node *event_timer, *source_timer;
+
+ event_timer = of_find_matching_node(NULL, picoxcell_timer_ids);
+ if (!event_timer)
+ panic("No timer for clockevent");
+ picoxcell_add_clockevent(event_timer);
+
+ source_timer = of_find_matching_node(event_timer, picoxcell_timer_ids);
+ if (!source_timer)
+ panic("No timer for clocksource");
+ picoxcell_add_clocksource(source_timer);
+
+ of_node_put(source_timer);
+
+ picoxcell_init_sched_clock();
+}
+
+struct sys_timer picoxcell_timer = {
+ .init = picoxcell_timer_init,
+};
diff --git a/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h b/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
new file mode 100644
index 0000000..41027dd
--- /dev/null
+++ b/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
@@ -0,0 +1,241 @@
+/*
+ * arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
+ *
+ * PNX4008 GPIO driver - header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef _PNX4008_GPIO_H_
+#define _PNX4008_GPIO_H_
+
+
+/* Block numbers */
+#define GPIO_IN (0)
+#define GPIO_OUT (0x100)
+#define GPIO_BID (0x200)
+#define GPIO_RAM (0x300)
+#define GPIO_MUX (0x400)
+
+#define GPIO_TYPE_MASK(K) ((K) & 0x700)
+
+/* INPUT GPIOs */
+/* GPI */
+#define GPI_00 (GPIO_IN | 0)
+#define GPI_01 (GPIO_IN | 1)
+#define GPI_02 (GPIO_IN | 2)
+#define GPI_03 (GPIO_IN | 3)
+#define GPI_04 (GPIO_IN | 4)
+#define GPI_05 (GPIO_IN | 5)
+#define GPI_06 (GPIO_IN | 6)
+#define GPI_07 (GPIO_IN | 7)
+#define GPI_08 (GPIO_IN | 8)
+#define GPI_09 (GPIO_IN | 9)
+#define U1_RX (GPIO_IN | 15)
+#define U2_HTCS (GPIO_IN | 16)
+#define U2_RX (GPIO_IN | 17)
+#define U3_RX (GPIO_IN | 18)
+#define U4_RX (GPIO_IN | 19)
+#define U5_RX (GPIO_IN | 20)
+#define U6_IRRX (GPIO_IN | 21)
+#define U7_HCTS (GPIO_IN | 22)
+#define U7_RX (GPIO_IN | 23)
+/* MISC IN */
+#define SPI1_DATIN (GPIO_IN | 25)
+#define DISP_SYNC (GPIO_IN | 26)
+#define SPI2_DATIN (GPIO_IN | 27)
+#define GPI_11 (GPIO_IN | 28)
+
+#define GPIO_IN_MASK 0x1eff83ff
+
+/* OUTPUT GPIOs */
+/* GPO */
+#define GPO_00 (GPIO_OUT | 0)
+#define GPO_01 (GPIO_OUT | 1)
+#define GPO_02 (GPIO_OUT | 2)
+#define GPO_03 (GPIO_OUT | 3)
+#define GPO_04 (GPIO_OUT | 4)
+#define GPO_05 (GPIO_OUT | 5)
+#define GPO_06 (GPIO_OUT | 6)
+#define GPO_07 (GPIO_OUT | 7)
+#define GPO_08 (GPIO_OUT | 8)
+#define GPO_09 (GPIO_OUT | 9)
+#define GPO_10 (GPIO_OUT | 10)
+#define GPO_11 (GPIO_OUT | 11)
+#define GPO_12 (GPIO_OUT | 12)
+#define GPO_13 (GPIO_OUT | 13)
+#define GPO_14 (GPIO_OUT | 14)
+#define GPO_15 (GPIO_OUT | 15)
+#define GPO_16 (GPIO_OUT | 16)
+#define GPO_17 (GPIO_OUT | 17)
+#define GPO_18 (GPIO_OUT | 18)
+#define GPO_19 (GPIO_OUT | 19)
+#define GPO_20 (GPIO_OUT | 20)
+#define GPO_21 (GPIO_OUT | 21)
+#define GPO_22 (GPIO_OUT | 22)
+#define GPO_23 (GPIO_OUT | 23)
+
+#define GPIO_OUT_MASK 0xffffff
+
+/* BIDIRECTIONAL GPIOs */
+/* RAM pins */
+#define RAM_D19 (GPIO_RAM | 0)
+#define RAM_D20 (GPIO_RAM | 1)
+#define RAM_D21 (GPIO_RAM | 2)
+#define RAM_D22 (GPIO_RAM | 3)
+#define RAM_D23 (GPIO_RAM | 4)
+#define RAM_D24 (GPIO_RAM | 5)
+#define RAM_D25 (GPIO_RAM | 6)
+#define RAM_D26 (GPIO_RAM | 7)
+#define RAM_D27 (GPIO_RAM | 8)
+#define RAM_D28 (GPIO_RAM | 9)
+#define RAM_D29 (GPIO_RAM | 10)
+#define RAM_D30 (GPIO_RAM | 11)
+#define RAM_D31 (GPIO_RAM | 12)
+
+#define GPIO_RAM_MASK 0x1fff
+
+/* I/O pins */
+#define GPIO_00 (GPIO_BID | 25)
+#define GPIO_01 (GPIO_BID | 26)
+#define GPIO_02 (GPIO_BID | 27)
+#define GPIO_03 (GPIO_BID | 28)
+#define GPIO_04 (GPIO_BID | 29)
+#define GPIO_05 (GPIO_BID | 30)
+
+#define GPIO_BID_MASK 0x7e000000
+
+/* Non-GPIO multiplexed PIOs. For multiplexing with GPIO, please use GPIO macros */
+#define GPIO_SDRAM_SEL (GPIO_MUX | 3)
+
+#define GPIO_MUX_MASK 0x8
+
+/* Extraction/assembly macros */
+#define GPIO_BIT_MASK(K) ((K) & 0x1F)
+#define GPIO_BIT(K) (1 << GPIO_BIT_MASK(K))
+#define GPIO_ISMUX(K) ((GPIO_TYPE_MASK(K) == GPIO_MUX) && (GPIO_BIT(K) & GPIO_MUX_MASK))
+#define GPIO_ISRAM(K) ((GPIO_TYPE_MASK(K) == GPIO_RAM) && (GPIO_BIT(K) & GPIO_RAM_MASK))
+#define GPIO_ISBID(K) ((GPIO_TYPE_MASK(K) == GPIO_BID) && (GPIO_BIT(K) & GPIO_BID_MASK))
+#define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK))
+#define GPIO_ISIN(K) ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK))
+
+/* Start Enable Pin Interrupts - table 58 page 66 */
+
+#define SE_PIN_BASE_INT 32
+
+#define SE_U7_RX_INT 63
+#define SE_U7_HCTS_INT 62
+#define SE_BT_CLKREQ_INT 61
+#define SE_U6_IRRX_INT 60
+/*59 unused*/
+#define SE_U5_RX_INT 58
+#define SE_GPI_11_INT 57
+#define SE_U3_RX_INT 56
+#define SE_U2_HCTS_INT 55
+#define SE_U2_RX_INT 54
+#define SE_U1_RX_INT 53
+#define SE_DISP_SYNC_INT 52
+/*51 unused*/
+#define SE_SDIO_INT_N 50
+#define SE_MSDIO_START_INT 49
+#define SE_GPI_06_INT 48
+#define SE_GPI_05_INT 47
+#define SE_GPI_04_INT 46
+#define SE_GPI_03_INT 45
+#define SE_GPI_02_INT 44
+#define SE_GPI_01_INT 43
+#define SE_GPI_00_INT 42
+#define SE_SYSCLKEN_PIN_INT 41
+#define SE_SPI1_DATAIN_INT 40
+#define SE_GPI_07_INT 39
+#define SE_SPI2_DATAIN_INT 38
+#define SE_GPI_10_INT 37
+#define SE_GPI_09_INT 36
+#define SE_GPI_08_INT 35
+/*34-32 unused*/
+
+/* Start Enable Internal Interrupts - table 57 page 65 */
+
+#define SE_INT_BASE_INT 0
+
+#define SE_TS_IRQ 31
+#define SE_TS_P_INT 30
+#define SE_TS_AUX_INT 29
+/*27-28 unused*/
+#define SE_USB_AHB_NEED_CLK_INT 26
+#define SE_MSTIMER_INT 25
+#define SE_RTC_INT 24
+#define SE_USB_NEED_CLK_INT 23
+#define SE_USB_INT 22
+#define SE_USB_I2C_INT 21
+#define SE_USB_OTG_TIMER_INT 20
+#define SE_USB_OTG_ATX_INT_N 19
+/*18 unused*/
+#define SE_DSP_GPIO4_INT 17
+#define SE_KEY_IRQ 16
+#define SE_DSP_SLAVEPORT_INT 15
+#define SE_DSP_GPIO1_INT 14
+#define SE_DSP_GPIO0_INT 13
+#define SE_DSP_AHB_INT 12
+/*11-6 unused*/
+#define SE_GPIO_05_INT 5
+#define SE_GPIO_04_INT 4
+#define SE_GPIO_03_INT 3
+#define SE_GPIO_02_INT 2
+#define SE_GPIO_01_INT 1
+#define SE_GPIO_00_INT 0
+
+#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
+
+#define START_INT_ER_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_RSR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_SR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_APR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
+
+extern int pnx4008_gpio_register_pin(unsigned short pin);
+extern int pnx4008_gpio_unregister_pin(unsigned short pin);
+extern unsigned long pnx4008_gpio_read_pin(unsigned short pin);
+extern int pnx4008_gpio_write_pin(unsigned short pin, int output);
+extern int pnx4008_gpio_set_pin_direction(unsigned short pin, int output);
+extern int pnx4008_gpio_read_pin_direction(unsigned short pin);
+extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output);
+extern int pnx4008_gpio_read_pin_mux(unsigned short pin);
+
+static inline void start_int_umask(u8 irq)
+{
+ __raw_writel(__raw_readl(START_INT_ER_REG(irq)) |
+ START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
+}
+
+static inline void start_int_mask(u8 irq)
+{
+ __raw_writel(__raw_readl(START_INT_ER_REG(irq)) &
+ ~START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
+}
+
+static inline void start_int_ack(u8 irq)
+{
+ __raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq));
+}
+
+static inline void start_int_set_falling_edge(u8 irq)
+{
+ __raw_writel(__raw_readl(START_INT_APR_REG(irq)) &
+ ~START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
+}
+
+static inline void start_int_set_rising_edge(u8 irq)
+{
+ __raw_writel(__raw_readl(START_INT_APR_REG(irq)) |
+ START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
+}
+
+#endif /* _PNX4008_GPIO_H_ */
diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
new file mode 100644
index 0000000..13dd160
--- /dev/null
+++ b/arch/arm/mach-prima2/Makefile
@@ -0,0 +1,9 @@
+obj-y := timer.o
+obj-y += irq.o
+obj-y += clock.o
+obj-y += rstc.o
+obj-y += prima2.o
+obj-y += rtciobrg.o
+obj-$(CONFIG_DEBUG_LL) += lluart.o
+obj-$(CONFIG_CACHE_L2X0) += l2x0.o
+obj-$(CONFIG_SUSPEND) += pm.o sleep.o
diff --git a/arch/arm/mach-prima2/Makefile.boot b/arch/arm/mach-prima2/Makefile.boot
new file mode 100644
index 0000000..c77a488
--- /dev/null
+++ b/arch/arm/mach-prima2/Makefile.boot
@@ -0,0 +1,3 @@
+zreladdr-y += 0x00008000
+params_phys-y := 0x00000100
+initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-prima2/clock.c b/arch/arm/mach-prima2/clock.c
new file mode 100644
index 0000000..aebad7e
--- /dev/null
+++ b/arch/arm/mach-prima2/clock.c
@@ -0,0 +1,510 @@
+/*
+ * Clock tree for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <asm/mach/map.h>
+#include <mach/map.h>
+
+#define SIRFSOC_CLKC_CLK_EN0 0x0000
+#define SIRFSOC_CLKC_CLK_EN1 0x0004
+#define SIRFSOC_CLKC_REF_CFG 0x0014
+#define SIRFSOC_CLKC_CPU_CFG 0x0018
+#define SIRFSOC_CLKC_MEM_CFG 0x001c
+#define SIRFSOC_CLKC_SYS_CFG 0x0020
+#define SIRFSOC_CLKC_IO_CFG 0x0024
+#define SIRFSOC_CLKC_DSP_CFG 0x0028
+#define SIRFSOC_CLKC_GFX_CFG 0x002c
+#define SIRFSOC_CLKC_MM_CFG 0x0030
+#define SIRFSOC_LKC_LCD_CFG 0x0034
+#define SIRFSOC_CLKC_MMC_CFG 0x0038
+#define SIRFSOC_CLKC_PLL1_CFG0 0x0040
+#define SIRFSOC_CLKC_PLL2_CFG0 0x0044
+#define SIRFSOC_CLKC_PLL3_CFG0 0x0048
+#define SIRFSOC_CLKC_PLL1_CFG1 0x004c
+#define SIRFSOC_CLKC_PLL2_CFG1 0x0050
+#define SIRFSOC_CLKC_PLL3_CFG1 0x0054
+#define SIRFSOC_CLKC_PLL1_CFG2 0x0058
+#define SIRFSOC_CLKC_PLL2_CFG2 0x005c
+#define SIRFSOC_CLKC_PLL3_CFG2 0x0060
+
+#define SIRFSOC_CLOCK_VA_BASE SIRFSOC_VA(0x005000)
+
+#define KHZ 1000
+#define MHZ (KHZ * KHZ)
+
+struct clk_ops {
+ unsigned long (*get_rate)(struct clk *clk);
+ long (*round_rate)(struct clk *clk, unsigned long rate);
+ int (*set_rate)(struct clk *clk, unsigned long rate);
+ int (*enable)(struct clk *clk);
+ int (*disable)(struct clk *clk);
+ struct clk *(*get_parent)(struct clk *clk);
+ int (*set_parent)(struct clk *clk, struct clk *parent);
+};
+
+struct clk {
+ struct clk *parent; /* parent clk */
+ unsigned long rate; /* clock rate in Hz */
+ signed char usage; /* clock enable count */
+ signed char enable_bit; /* enable bit: 0 ~ 63 */
+ unsigned short regofs; /* register offset */
+ struct clk_ops *ops; /* clock operation */
+};
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+static inline unsigned long clkc_readl(unsigned reg)
+{
+ return readl(SIRFSOC_CLOCK_VA_BASE + reg);
+}
+
+static inline void clkc_writel(u32 val, unsigned reg)
+{
+ writel(val, SIRFSOC_CLOCK_VA_BASE + reg);
+}
+
+/*
+ * osc_rtc - real time oscillator - 32.768KHz
+ * osc_sys - high speed oscillator - 26MHz
+ */
+
+static struct clk clk_rtc = {
+ .rate = 32768,
+};
+
+static struct clk clk_osc = {
+ .rate = 26 * MHZ,
+};
+
+/*
+ * std pll
+ */
+static unsigned long std_pll_get_rate(struct clk *clk)
+{
+ unsigned long fin = clk_get_rate(clk->parent);
+ u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 -
+ SIRFSOC_CLKC_PLL1_CFG0;
+
+ if (clkc_readl(regcfg2) & BIT(2)) {
+ /* pll bypass mode */
+ clk->rate = fin;
+ } else {
+ /* fout = fin * nf / nr / od */
+ u32 cfg0 = clkc_readl(clk->regofs);
+ u32 nf = (cfg0 & (BIT(13) - 1)) + 1;
+ u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1;
+ u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1;
+ WARN_ON(fin % MHZ);
+ clk->rate = fin / MHZ * nf / nr / od * MHZ;
+ }
+
+ return clk->rate;
+}
+
+static int std_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long fin, nf, nr, od, reg;
+
+ /*
+ * fout = fin * nf / (nr * od);
+ * set od = 1, nr = fin/MHz, so fout = nf * MHz
+ */
+
+ nf = rate / MHZ;
+ if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1))
+ return -EINVAL;
+
+ fin = clk_get_rate(clk->parent);
+ BUG_ON(fin < MHZ);
+
+ nr = fin / MHZ;
+ BUG_ON((fin % MHZ) || nr > BIT(6));
+
+ od = 1;
+
+ reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19);
+ clkc_writel(reg, clk->regofs);
+
+ reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0;
+ clkc_writel((nf >> 1) - 1, reg);
+
+ reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0;
+ while (!(clkc_readl(reg) & BIT(6)))
+ cpu_relax();
+
+ clk->rate = 0; /* set to zero will force recalculation */
+ return 0;
+}
+
+static struct clk_ops std_pll_ops = {
+ .get_rate = std_pll_get_rate,
+ .set_rate = std_pll_set_rate,
+};
+
+static struct clk clk_pll1 = {
+ .parent = &clk_osc,
+ .regofs = SIRFSOC_CLKC_PLL1_CFG0,
+ .ops = &std_pll_ops,
+};
+
+static struct clk clk_pll2 = {
+ .parent = &clk_osc,
+ .regofs = SIRFSOC_CLKC_PLL2_CFG0,
+ .ops = &std_pll_ops,
+};
+
+static struct clk clk_pll3 = {
+ .parent = &clk_osc,
+ .regofs = SIRFSOC_CLKC_PLL3_CFG0,
+ .ops = &std_pll_ops,
+};
+
+/*
+ * clock domains - cpu, mem, sys/io
+ */
+
+static struct clk clk_mem;
+
+static struct clk *dmn_get_parent(struct clk *clk)
+{
+ struct clk *clks[] = {
+ &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3
+ };
+ u32 cfg = clkc_readl(clk->regofs);
+ WARN_ON((cfg & (BIT(3) - 1)) > 4);
+ return clks[cfg & (BIT(3) - 1)];
+}
+
+static int dmn_set_parent(struct clk *clk, struct clk *parent)
+{
+ const struct clk *clks[] = {
+ &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3
+ };
+ u32 cfg = clkc_readl(clk->regofs);
+ int i;
+ for (i = 0; i < ARRAY_SIZE(clks); i++) {
+ if (clks[i] == parent) {
+ cfg &= ~(BIT(3) - 1);
+ clkc_writel(cfg | i, clk->regofs);
+ /* BIT(3) - switching status: 1 - busy, 0 - done */
+ while (clkc_readl(clk->regofs) & BIT(3))
+ cpu_relax();
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static unsigned long dmn_get_rate(struct clk *clk)
+{
+ unsigned long fin = clk_get_rate(clk->parent);
+ u32 cfg = clkc_readl(clk->regofs);
+ if (cfg & BIT(24)) {
+ /* fcd bypass mode */
+ clk->rate = fin;
+ } else {
+ /*
+ * wait count: bit[19:16], hold count: bit[23:20]
+ */
+ u32 wait = (cfg >> 16) & (BIT(4) - 1);
+ u32 hold = (cfg >> 20) & (BIT(4) - 1);
+
+ clk->rate = fin / (wait + hold + 2);
+ }
+
+ return clk->rate;
+}
+
+static int dmn_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long fin;
+ unsigned ratio, wait, hold, reg;
+ unsigned bits = (clk == &clk_mem) ? 3 : 4;
+
+ fin = clk_get_rate(clk->parent);
+ ratio = fin / rate;
+
+ if (unlikely(ratio < 2 || ratio > BIT(bits + 1)))
+ return -EINVAL;
+
+ WARN_ON(fin % rate);
+
+ wait = (ratio >> 1) - 1;
+ hold = ratio - wait - 2;
+
+ reg = clkc_readl(clk->regofs);
+ reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20));
+ reg |= (wait << 16) | (hold << 20) | BIT(25);
+ clkc_writel(reg, clk->regofs);
+
+ /* waiting FCD been effective */
+ while (clkc_readl(clk->regofs) & BIT(25))
+ cpu_relax();
+
+ clk->rate = 0; /* set to zero will force recalculation */
+
+ return 0;
+}
+
+/*
+ * cpu clock has no FCD register in Prima2, can only change pll
+ */
+static int cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret1, ret2;
+ struct clk *cur_parent, *tmp_parent;
+
+ cur_parent = dmn_get_parent(clk);
+ BUG_ON(cur_parent == NULL || cur_parent->usage > 1);
+
+ /* switch to tmp pll before setting parent clock's rate */
+ tmp_parent = cur_parent == &clk_pll1 ? &clk_pll2 : &clk_pll1;
+ ret1 = dmn_set_parent(clk, tmp_parent);
+ BUG_ON(ret1);
+
+ ret2 = clk_set_rate(cur_parent, rate);
+
+ ret1 = dmn_set_parent(clk, cur_parent);
+
+ clk->rate = 0; /* set to zero will force recalculation */
+
+ return ret2 ? ret2 : ret1;
+}
+
+static struct clk_ops cpu_ops = {
+ .get_parent = dmn_get_parent,
+ .set_parent = dmn_set_parent,
+ .set_rate = cpu_set_rate,
+};
+
+static struct clk clk_cpu = {
+ .parent = &clk_pll1,
+ .regofs = SIRFSOC_CLKC_CPU_CFG,
+ .ops = &cpu_ops,
+};
+
+
+static struct clk_ops msi_ops = {
+ .set_rate = dmn_set_rate,
+ .get_rate = dmn_get_rate,
+ .set_parent = dmn_set_parent,
+ .get_parent = dmn_get_parent,
+};
+
+static struct clk clk_mem = {
+ .parent = &clk_pll2,
+ .regofs = SIRFSOC_CLKC_MEM_CFG,
+ .ops = &msi_ops,
+};
+
+static struct clk clk_sys = {
+ .parent = &clk_pll3,
+ .regofs = SIRFSOC_CLKC_SYS_CFG,
+ .ops = &msi_ops,
+};
+
+static struct clk clk_io = {
+ .parent = &clk_pll3,
+ .regofs = SIRFSOC_CLKC_IO_CFG,
+ .ops = &msi_ops,
+};
+
+/*
+ * on-chip clock sets
+ */
+static struct clk_lookup onchip_clks[] = {
+ {
+ .dev_id = "rtc",
+ .clk = &clk_rtc,
+ }, {
+ .dev_id = "osc",
+ .clk = &clk_osc,
+ }, {
+ .dev_id = "pll1",
+ .clk = &clk_pll1,
+ }, {
+ .dev_id = "pll2",
+ .clk = &clk_pll2,
+ }, {
+ .dev_id = "pll3",
+ .clk = &clk_pll3,
+ }, {
+ .dev_id = "cpu",
+ .clk = &clk_cpu,
+ }, {
+ .dev_id = "mem",
+ .clk = &clk_mem,
+ }, {
+ .dev_id = "sys",
+ .clk = &clk_sys,
+ }, {
+ .dev_id = "io",
+ .clk = &clk_io,
+ },
+};
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return -EINVAL;
+
+ if (clk->parent)
+ clk_enable(clk->parent);
+
+ spin_lock_irqsave(&clocks_lock, flags);
+ if (!clk->usage++ && clk->ops && clk->ops->enable)
+ clk->ops->enable(clk);
+ spin_unlock_irqrestore(&clocks_lock, flags);
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return;
+
+ WARN_ON(!clk->usage);
+
+ spin_lock_irqsave(&clocks_lock, flags);
+ if (--clk->usage == 0 && clk->ops && clk->ops->disable)
+ clk->ops->disable(clk);
+ spin_unlock_irqrestore(&clocks_lock, flags);
+
+ if (clk->parent)
+ clk_disable(clk->parent);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return 0;
+
+ if (clk->rate)
+ return clk->rate;
+
+ if (clk->ops && clk->ops->get_rate)
+ return clk->ops->get_rate(clk);
+
+ return clk_get_rate(clk->parent);
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return 0;
+
+ if (clk->ops && clk->ops->round_rate)
+ return clk->ops->round_rate(clk, rate);
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return -EINVAL;
+
+ if (!clk->ops || !clk->ops->set_rate)
+ return -EINVAL;
+
+ return clk->ops->set_rate(clk, rate);
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ int ret;
+ unsigned long flags;
+
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return -EINVAL;
+
+ if (!clk->ops || !clk->ops->set_parent)
+ return -EINVAL;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+ ret = clk->ops->set_parent(clk, parent);
+ if (!ret) {
+ parent->usage += clk->usage;
+ clk->parent->usage -= clk->usage;
+ BUG_ON(clk->parent->usage < 0);
+ clk->parent = parent;
+ }
+ spin_unlock_irqrestore(&clocks_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return NULL;
+
+ if (!clk->ops || !clk->ops->get_parent)
+ return clk->parent;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+ clk->parent = clk->ops->get_parent(clk);
+ spin_unlock_irqrestore(&clocks_lock, flags);
+ return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+static void __init sirfsoc_clk_init(void)
+{
+ clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks));
+}
+
+static struct of_device_id clkc_ids[] = {
+ { .compatible = "sirf,prima2-clkc" },
+ {},
+};
+
+void __init sirfsoc_of_clk_init(void)
+{
+ struct device_node *np;
+ struct resource res;
+ struct map_desc sirfsoc_clkc_iodesc = {
+ .virtual = SIRFSOC_CLOCK_VA_BASE,
+ .type = MT_DEVICE,
+ };
+
+ np = of_find_matching_node(NULL, clkc_ids);
+ if (!np)
+ panic("unable to find compatible clkc node in dtb\n");
+
+ if (of_address_to_resource(np, 0, &res))
+ panic("unable to find clkc range in dtb");
+ of_node_put(np);
+
+ sirfsoc_clkc_iodesc.pfn = __phys_to_pfn(res.start);
+ sirfsoc_clkc_iodesc.length = 1 + res.end - res.start;
+
+ iotable_init(&sirfsoc_clkc_iodesc, 1);
+
+ sirfsoc_clk_init();
+}
diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h
new file mode 100644
index 0000000..83e5d21
--- /dev/null
+++ b/arch/arm/mach-prima2/common.h
@@ -0,0 +1,26 @@
+/*
+ * This file contains common function prototypes to avoid externs in the c files.
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_COMMON_H__
+#define __MACH_PRIMA2_COMMON_H__
+
+#include <linux/init.h>
+#include <asm/mach/time.h>
+
+extern struct sys_timer sirfsoc_timer;
+
+extern void __init sirfsoc_of_irq_init(void);
+extern void __init sirfsoc_of_clk_init(void);
+
+#ifndef CONFIG_DEBUG_LL
+static inline void sirfsoc_map_lluart(void) {}
+#else
+extern void __init sirfsoc_map_lluart(void);
+#endif
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/clkdev.h b/arch/arm/mach-prima2/include/mach/clkdev.h
new file mode 100644
index 0000000..6693251
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/clkdev.h
@@ -0,0 +1,15 @@
+/*
+ * arch/arm/mach-prima2/include/mach/clkdev.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_CLKDEV_H
+#define __MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/debug-macro.S b/arch/arm/mach-prima2/include/mach/debug-macro.S
new file mode 100644
index 0000000..cd97492
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/debug-macro.S
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <mach/hardware.h>
+#include <mach/uart.h>
+
+ .macro addruart, rp, rv, tmp
+ ldr \rp, =SIRFSOC_UART1_PA_BASE @ physical
+ ldr \rv, =SIRFSOC_UART1_VA_BASE @ virtual
+ .endm
+
+ .macro senduart,rd,rx
+ str \rd, [\rx, #SIRFSOC_UART_TXFIFO_DATA]
+ .endm
+
+ .macro busyuart,rd,rx
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldr \rd, [\rx, #SIRFSOC_UART_TXFIFO_STATUS]
+ tst \rd, #SIRFSOC_UART1_TXFIFO_EMPTY
+ beq 1001b
+ .endm
+
diff --git a/arch/arm/mach-prima2/include/mach/entry-macro.S b/arch/arm/mach-prima2/include/mach/entry-macro.S
new file mode 100644
index 0000000..1c8a50f
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/entry-macro.S
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/include/mach/entry-macro.S
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <mach/hardware.h>
+
+#define SIRFSOC_INT_ID 0x38
+
+ .macro get_irqnr_preamble, base, tmp
+ ldr \base, =sirfsoc_intc_base
+ ldr \base, [\base]
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \irqnr, [\base, #SIRFSOC_INT_ID] @ Get the highest priority irq
+ cmp \irqnr, #0x40 @ the irq num can't be larger than 0x3f
+ movges \irqnr, #0
+ .endm
+
+ .macro disable_fiq
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
diff --git a/arch/arm/mach-prima2/include/mach/hardware.h b/arch/arm/mach-prima2/include/mach/hardware.h
new file mode 100644
index 0000000..105b969
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/hardware.h
@@ -0,0 +1,15 @@
+/*
+ * arch/arm/mach-prima2/include/mach/hardware.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_HARDWARE_H__
+#define __MACH_HARDWARE_H__
+
+#include <asm/sizes.h>
+#include <mach/map.h>
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/io.h b/arch/arm/mach-prima2/include/mach/io.h
new file mode 100644
index 0000000..6c31e9e
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/io.h
@@ -0,0 +1,16 @@
+/*
+ * arch/arm/mach-prima2/include/mach/io.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_IO_H
+#define __MACH_PRIMA2_IO_H
+
+#define IO_SPACE_LIMIT ((resource_size_t)0)
+
+#define __mem_pci(a) (a)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/irqs.h b/arch/arm/mach-prima2/include/mach/irqs.h
new file mode 100644
index 0000000..bb354f9
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/irqs.h
@@ -0,0 +1,17 @@
+/*
+ * arch/arm/mach-prima2/include/mach/irqs.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define SIRFSOC_INTENAL_IRQ_START 0
+#define SIRFSOC_INTENAL_IRQ_END 59
+
+#define NR_IRQS 220
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/map.h b/arch/arm/mach-prima2/include/mach/map.h
new file mode 100644
index 0000000..66b1ae2
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/map.h
@@ -0,0 +1,16 @@
+/*
+ * memory & I/O static mapping definitions for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_MAP_H__
+#define __MACH_PRIMA2_MAP_H__
+
+#include <mach/vmalloc.h>
+
+#define SIRFSOC_VA(x) (VMALLOC_END + ((x) & 0x00FFF000))
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/system.h b/arch/arm/mach-prima2/include/mach/system.h
new file mode 100644
index 0000000..0dbd257
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/system.h
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/include/mach/system.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_SYSTEM_H__
+#define __MACH_SYSTEM_H__
+
+#include <linux/bitops.h>
+#include <mach/hardware.h>
+
+#define SIRFSOC_SYS_RST_BIT BIT(31)
+
+extern void __iomem *sirfsoc_rstc_base;
+
+static inline void arch_idle(void)
+{
+ cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+ writel(SIRFSOC_SYS_RST_BIT, sirfsoc_rstc_base);
+}
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/timex.h b/arch/arm/mach-prima2/include/mach/timex.h
new file mode 100644
index 0000000..d6f98a7
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/timex.h
@@ -0,0 +1,14 @@
+/*
+ * arch/arm/mach-prima2/include/mach/timex.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_TIMEX_H__
+#define __MACH_TIMEX_H__
+
+#define CLOCK_TICK_RATE 1000000
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/uart.h b/arch/arm/mach-prima2/include/mach/uart.h
new file mode 100644
index 0000000..c98b4d5
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/uart.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-prima2/include/mach/uart.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_SIRFSOC_UART_H
+#define __MACH_PRIMA2_SIRFSOC_UART_H
+
+/* UART-1: used as serial debug port */
+#define SIRFSOC_UART1_PA_BASE 0xb0060000
+#define SIRFSOC_UART1_VA_BASE SIRFSOC_VA(0x060000)
+#define SIRFSOC_UART1_SIZE SZ_4K
+
+#define SIRFSOC_UART_TXFIFO_STATUS 0x0114
+#define SIRFSOC_UART_TXFIFO_DATA 0x0118
+
+#define SIRFSOC_UART1_TXFIFO_FULL (1 << 5)
+#define SIRFSOC_UART1_TXFIFO_EMPTY (1 << 6)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/uncompress.h b/arch/arm/mach-prima2/include/mach/uncompress.h
new file mode 100644
index 0000000..83125c6
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/uncompress.h
@@ -0,0 +1,40 @@
+/*
+ * arch/arm/mach-prima2/include/mach/uncompress.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/uart.h>
+
+void arch_decomp_setup(void)
+{
+}
+
+#define arch_decomp_wdog()
+
+static __inline__ void putc(char c)
+{
+ /*
+ * during kernel decompression, all mappings are flat:
+ * virt_addr == phys_addr
+ */
+ while (__raw_readl(SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS)
+ & SIRFSOC_UART1_TXFIFO_FULL)
+ barrier();
+
+ __raw_writel(c, SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_DATA);
+}
+
+static inline void flush(void)
+{
+}
+
+#endif
+
diff --git a/arch/arm/mach-prima2/include/mach/vmalloc.h b/arch/arm/mach-prima2/include/mach/vmalloc.h
new file mode 100644
index 0000000..c9f90fe
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/vmalloc.h
@@ -0,0 +1,16 @@
+/*
+ * arch/arm/ach-prima2/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2010 – 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_VMALLOC_H
+#define __MACH_VMALLOC_H
+
+#include <linux/const.h>
+
+#define VMALLOC_END _AC(0xFEC00000, UL)
+
+#endif
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
new file mode 100644
index 0000000..d93ceef
--- /dev/null
+++ b/arch/arm/mach-prima2/irq.c
@@ -0,0 +1,115 @@
+/*
+ * interrupt controller support for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/irqdomain.h>
+#include <linux/syscore_ops.h>
+
+#define SIRFSOC_INT_RISC_MASK0 0x0018
+#define SIRFSOC_INT_RISC_MASK1 0x001C
+#define SIRFSOC_INT_RISC_LEVEL0 0x0020
+#define SIRFSOC_INT_RISC_LEVEL1 0x0024
+
+void __iomem *sirfsoc_intc_base;
+
+static __init void
+sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+
+ gc = irq_alloc_generic_chip("SIRFINTC", 1, irq_start, base, handle_level_irq);
+ ct = gc->chip_types;
+
+ ct->chip.irq_mask = irq_gc_mask_clr_bit;
+ ct->chip.irq_unmask = irq_gc_mask_set_bit;
+ ct->regs.mask = SIRFSOC_INT_RISC_MASK0;
+
+ irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0);
+}
+
+static __init void sirfsoc_irq_init(void)
+{
+ sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32);
+ sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, SIRFSOC_INTENAL_IRQ_END - 32);
+
+ writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+ writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+
+ writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+ writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+}
+
+static struct of_device_id intc_ids[] = {
+ { .compatible = "sirf,prima2-intc" },
+ {},
+};
+
+void __init sirfsoc_of_irq_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, intc_ids);
+ if (!np)
+ panic("unable to find compatible intc node in dtb\n");
+
+ sirfsoc_intc_base = of_iomap(np, 0);
+ if (!sirfsoc_intc_base)
+ panic("unable to map intc cpu registers\n");
+
+ irq_domain_add_simple(np, 0);
+
+ of_node_put(np);
+
+ sirfsoc_irq_init();
+}
+
+struct sirfsoc_irq_status {
+ u32 mask0;
+ u32 mask1;
+ u32 level0;
+ u32 level1;
+};
+
+static struct sirfsoc_irq_status sirfsoc_irq_st;
+
+static int sirfsoc_irq_suspend(void)
+{
+ sirfsoc_irq_st.mask0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+ sirfsoc_irq_st.mask1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+ sirfsoc_irq_st.level0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+ sirfsoc_irq_st.level1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+
+ return 0;
+}
+
+static void sirfsoc_irq_resume(void)
+{
+ writel_relaxed(sirfsoc_irq_st.mask0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+ writel_relaxed(sirfsoc_irq_st.mask1, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+ writel_relaxed(sirfsoc_irq_st.level0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+ writel_relaxed(sirfsoc_irq_st.level1, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+}
+
+static struct syscore_ops sirfsoc_irq_syscore_ops = {
+ .suspend = sirfsoc_irq_suspend,
+ .resume = sirfsoc_irq_resume,
+};
+
+static int __init sirfsoc_irq_pm_init(void)
+{
+ register_syscore_ops(&sirfsoc_irq_syscore_ops);
+ return 0;
+}
+device_initcall(sirfsoc_irq_pm_init);
diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c
new file mode 100644
index 0000000..c998377
--- /dev/null
+++ b/arch/arm/mach-prima2/l2x0.c
@@ -0,0 +1,31 @@
+/*
+ * l2 cache initialization for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <asm/hardware/cache-l2x0.h>
+
+static struct of_device_id prima2_l2x0_ids[] = {
+ { .compatible = "sirf,prima2-pl310-cache" },
+ {},
+};
+
+static int __init sirfsoc_l2x0_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, prima2_l2x0_ids);
+ if (np) {
+ pr_info("Initializing prima2 L2 cache\n");
+ return l2x0_of_init(0x40000, 0);
+ }
+
+ return 0;
+}
+early_initcall(sirfsoc_l2x0_init);
diff --git a/arch/arm/mach-prima2/lluart.c b/arch/arm/mach-prima2/lluart.c
new file mode 100644
index 0000000..a89f9b3
--- /dev/null
+++ b/arch/arm/mach-prima2/lluart.c
@@ -0,0 +1,25 @@
+/*
+ * Static memory mapping for DEBUG_LL
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <mach/map.h>
+#include <mach/uart.h>
+
+void __init sirfsoc_map_lluart(void)
+{
+ struct map_desc sirfsoc_lluart_map = {
+ .virtual = SIRFSOC_UART1_VA_BASE,
+ .pfn = __phys_to_pfn(SIRFSOC_UART1_PA_BASE),
+ .length = SIRFSOC_UART1_SIZE,
+ .type = MT_DEVICE,
+ };
+
+ iotable_init(&sirfsoc_lluart_map, 1);
+}
diff --git a/arch/arm/mach-prima2/pm.c b/arch/arm/mach-prima2/pm.c
new file mode 100644
index 0000000..26ebb57
--- /dev/null
+++ b/arch/arm/mach-prima2/pm.c
@@ -0,0 +1,151 @@
+/*
+ * power management entry for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/rtc/sirfsoc_rtciobrg.h>
+#include <asm/suspend.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include "pm.h"
+
+/*
+ * suspend asm codes will access these to make DRAM become self-refresh and
+ * system sleep
+ */
+u32 sirfsoc_pwrc_base;
+void __iomem *sirfsoc_memc_base;
+
+static void sirfsoc_set_wakeup_source(void)
+{
+ u32 pwr_trigger_en_reg;
+ pwr_trigger_en_reg = sirfsoc_rtc_iobrg_readl(sirfsoc_pwrc_base +
+ SIRFSOC_PWRC_TRIGGER_EN);
+#define X_ON_KEY_B (1 << 0)
+ sirfsoc_rtc_iobrg_writel(pwr_trigger_en_reg | X_ON_KEY_B,
+ sirfsoc_pwrc_base + SIRFSOC_PWRC_TRIGGER_EN);
+}
+
+static void sirfsoc_set_sleep_mode(u32 mode)
+{
+ u32 sleep_mode = sirfsoc_rtc_iobrg_readl(sirfsoc_pwrc_base +
+ SIRFSOC_PWRC_PDN_CTRL);
+ sleep_mode &= ~(SIRFSOC_SLEEP_MODE_MASK << 1);
+ sleep_mode |= mode << 1;
+ sirfsoc_rtc_iobrg_writel(sleep_mode, sirfsoc_pwrc_base +
+ SIRFSOC_PWRC_PDN_CTRL);
+}
+
+static int sirfsoc_pre_suspend_power_off(void)
+{
+ u32 wakeup_entry = virt_to_phys(cpu_resume);
+
+ sirfsoc_rtc_iobrg_writel(wakeup_entry, sirfsoc_pwrc_base +
+ SIRFSOC_PWRC_SCRATCH_PAD1);
+
+ sirfsoc_set_wakeup_source();
+
+ sirfsoc_set_sleep_mode(SIRFSOC_DEEP_SLEEP_MODE);
+
+ return 0;
+}
+
+static int sirfsoc_pm_enter(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ sirfsoc_pre_suspend_power_off();
+
+ outer_flush_all();
+ outer_disable();
+ /* go zzz */
+ cpu_suspend(0, sirfsoc_finish_suspend);
+ outer_resume();
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static const struct platform_suspend_ops sirfsoc_pm_ops = {
+ .enter = sirfsoc_pm_enter,
+ .valid = suspend_valid_only_mem,
+};
+
+static int __init sirfsoc_pm_init(void)
+{
+ suspend_set_ops(&sirfsoc_pm_ops);
+ return 0;
+}
+late_initcall(sirfsoc_pm_init);
+
+static const struct of_device_id pwrc_ids[] = {
+ { .compatible = "sirf,prima2-pwrc" },
+ {}
+};
+
+static int __init sirfsoc_of_pwrc_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, pwrc_ids);
+ if (!np)
+ panic("unable to find compatible pwrc node in dtb\n");
+
+ /*
+ * pwrc behind rtciobrg is not located in memory space
+ * though the property is named reg. reg only means base
+ * offset for pwrc. then of_iomap is not suitable here.
+ */
+ if (of_property_read_u32(np, "reg", &sirfsoc_pwrc_base))
+ panic("unable to find base address of pwrc node in dtb\n");
+
+ of_node_put(np);
+
+ return 0;
+}
+postcore_initcall(sirfsoc_of_pwrc_init);
+
+static const struct of_device_id memc_ids[] = {
+ { .compatible = "sirf,prima2-memc" },
+ {}
+};
+
+static int __devinit sirfsoc_memc_probe(struct platform_device *op)
+{
+ struct device_node *np = op->dev.of_node;
+
+ sirfsoc_memc_base = of_iomap(np, 0);
+ if (!sirfsoc_memc_base)
+ panic("unable to map memc registers\n");
+
+ return 0;
+}
+
+static struct platform_driver sirfsoc_memc_driver = {
+ .probe = sirfsoc_memc_probe,
+ .driver = {
+ .name = "sirfsoc-memc",
+ .owner = THIS_MODULE,
+ .of_match_table = memc_ids,
+ },
+};
+
+static int __init sirfsoc_memc_init(void)
+{
+ return platform_driver_register(&sirfsoc_memc_driver);
+}
+postcore_initcall(sirfsoc_memc_init);
diff --git a/arch/arm/mach-prima2/pm.h b/arch/arm/mach-prima2/pm.h
new file mode 100644
index 0000000..bae6d77
--- /dev/null
+++ b/arch/arm/mach-prima2/pm.h
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/pm.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef _MACH_PRIMA2_PM_H_
+#define _MACH_PRIMA2_PM_H_
+
+#define SIRFSOC_PWR_SLEEPFORCE 0x01
+
+#define SIRFSOC_SLEEP_MODE_MASK 0x3
+#define SIRFSOC_DEEP_SLEEP_MODE 0x1
+
+#define SIRFSOC_PWRC_PDN_CTRL 0x0
+#define SIRFSOC_PWRC_PON_OFF 0x4
+#define SIRFSOC_PWRC_TRIGGER_EN 0x8
+#define SIRFSOC_PWRC_PIN_STATUS 0x14
+#define SIRFSOC_PWRC_SCRATCH_PAD1 0x18
+#define SIRFSOC_PWRC_SCRATCH_PAD2 0x1C
+
+#ifndef __ASSEMBLY__
+extern int sirfsoc_finish_suspend(unsigned long);
+#endif
+
+#endif
+
diff --git a/arch/arm/mach-prima2/prima2.c b/arch/arm/mach-prima2/prima2.c
new file mode 100644
index 0000000..a12b689
--- /dev/null
+++ b/arch/arm/mach-prima2/prima2.c
@@ -0,0 +1,43 @@
+/*
+ * Defines machines for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/sizes.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include "common.h"
+
+static struct of_device_id sirfsoc_of_bus_ids[] __initdata = {
+ { .compatible = "simple-bus", },
+ {},
+};
+
+void __init sirfsoc_mach_init(void)
+{
+ of_platform_bus_probe(NULL, sirfsoc_of_bus_ids, NULL);
+}
+
+static const char *prima2cb_dt_match[] __initdata = {
+ "sirf,prima2-cb",
+ NULL
+};
+
+MACHINE_START(PRIMA2_EVB, "prima2cb")
+ /* Maintainer: Barry Song <baohua.song@csr.com> */
+ .atag_offset = 0x100,
+ .init_early = sirfsoc_of_clk_init,
+ .map_io = sirfsoc_map_lluart,
+ .init_irq = sirfsoc_of_irq_init,
+ .timer = &sirfsoc_timer,
+ .dma_zone_size = SZ_256M,
+ .init_machine = sirfsoc_mach_init,
+ .dt_compat = prima2cb_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c
new file mode 100644
index 0000000..492cfa8
--- /dev/null
+++ b/arch/arm/mach-prima2/rstc.c
@@ -0,0 +1,70 @@
+/*
+ * reset controller for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __iomem *sirfsoc_rstc_base;
+static DEFINE_MUTEX(rstc_lock);
+
+static struct of_device_id rstc_ids[] = {
+ { .compatible = "sirf,prima2-rstc" },
+ {},
+};
+
+static int __init sirfsoc_of_rstc_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, rstc_ids);
+ if (!np)
+ panic("unable to find compatible rstc node in dtb\n");
+
+ sirfsoc_rstc_base = of_iomap(np, 0);
+ if (!sirfsoc_rstc_base)
+ panic("unable to map rstc cpu registers\n");
+
+ of_node_put(np);
+
+ return 0;
+}
+early_initcall(sirfsoc_of_rstc_init);
+
+int sirfsoc_reset_device(struct device *dev)
+{
+ const unsigned int *prop = of_get_property(dev->of_node, "reset-bit", NULL);
+ unsigned int reset_bit;
+
+ if (!prop)
+ return -ENODEV;
+
+ reset_bit = be32_to_cpup(prop);
+
+ mutex_lock(&rstc_lock);
+
+ /*
+ * Writing 1 to this bit resets corresponding block. Writing 0 to this
+ * bit de-asserts reset signal of the corresponding block.
+ * datasheet doesn't require explicit delay between the set and clear
+ * of reset bit. it could be shorter if tests pass.
+ */
+ writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit,
+ sirfsoc_rstc_base + (reset_bit / 32) * 4);
+ msleep(10);
+ writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit,
+ sirfsoc_rstc_base + (reset_bit / 32) * 4);
+
+ mutex_unlock(&rstc_lock);
+
+ return 0;
+}
diff --git a/arch/arm/mach-prima2/rtciobrg.c b/arch/arm/mach-prima2/rtciobrg.c
new file mode 100644
index 0000000..9d80f1e
--- /dev/null
+++ b/arch/arm/mach-prima2/rtciobrg.c
@@ -0,0 +1,139 @@
+/*
+ * RTC I/O Bridge interfaces for CSR SiRFprimaII
+ * ARM access the registers of SYSRTC, GPSRTC and PWRC through this module
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#define SIRFSOC_CPUIOBRG_CTRL 0x00
+#define SIRFSOC_CPUIOBRG_WRBE 0x04
+#define SIRFSOC_CPUIOBRG_ADDR 0x08
+#define SIRFSOC_CPUIOBRG_DATA 0x0c
+
+/*
+ * suspend asm codes will access this address to make system deepsleep
+ * after DRAM becomes self-refresh
+ */
+void __iomem *sirfsoc_rtciobrg_base;
+static DEFINE_SPINLOCK(rtciobrg_lock);
+
+/*
+ * symbols without lock are only used by suspend asm codes
+ * and these symbols are not exported too
+ */
+void sirfsoc_rtc_iobrg_wait_sync(void)
+{
+ while (readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL))
+ cpu_relax();
+}
+
+void sirfsoc_rtc_iobrg_besyncing(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtciobrg_lock, flags);
+
+ sirfsoc_rtc_iobrg_wait_sync();
+
+ spin_unlock_irqrestore(&rtciobrg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_besyncing);
+
+u32 __sirfsoc_rtc_iobrg_readl(u32 addr)
+{
+ sirfsoc_rtc_iobrg_wait_sync();
+
+ writel_relaxed(0x00, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE);
+ writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR);
+ writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL);
+
+ sirfsoc_rtc_iobrg_wait_sync();
+
+ return readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA);
+}
+
+u32 sirfsoc_rtc_iobrg_readl(u32 addr)
+{
+ unsigned long flags, val;
+
+ spin_lock_irqsave(&rtciobrg_lock, flags);
+
+ val = __sirfsoc_rtc_iobrg_readl(addr);
+
+ spin_unlock_irqrestore(&rtciobrg_lock, flags);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_readl);
+
+void sirfsoc_rtc_iobrg_pre_writel(u32 val, u32 addr)
+{
+ sirfsoc_rtc_iobrg_wait_sync();
+
+ writel_relaxed(0xf1, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE);
+ writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR);
+
+ writel_relaxed(val, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA);
+}
+
+void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtciobrg_lock, flags);
+
+ sirfsoc_rtc_iobrg_pre_writel(val, addr);
+
+ writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL);
+
+ sirfsoc_rtc_iobrg_wait_sync();
+
+ spin_unlock_irqrestore(&rtciobrg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel);
+
+static const struct of_device_id rtciobrg_ids[] = {
+ { .compatible = "sirf,prima2-rtciobg" },
+ {}
+};
+
+static int __devinit sirfsoc_rtciobrg_probe(struct platform_device *op)
+{
+ struct device_node *np = op->dev.of_node;
+
+ sirfsoc_rtciobrg_base = of_iomap(np, 0);
+ if (!sirfsoc_rtciobrg_base)
+ panic("unable to map rtc iobrg registers\n");
+
+ return 0;
+}
+
+static struct platform_driver sirfsoc_rtciobrg_driver = {
+ .probe = sirfsoc_rtciobrg_probe,
+ .driver = {
+ .name = "sirfsoc-rtciobrg",
+ .owner = THIS_MODULE,
+ .of_match_table = rtciobrg_ids,
+ },
+};
+
+static int __init sirfsoc_rtciobrg_init(void)
+{
+ return platform_driver_register(&sirfsoc_rtciobrg_driver);
+}
+postcore_initcall(sirfsoc_rtciobrg_init);
+
+MODULE_AUTHOR("Zhiwu Song <zhiwu.song@csr.com>, "
+ "Barry Song <baohua.song@csr.com>");
+MODULE_DESCRIPTION("CSR SiRFprimaII rtc io bridge");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-prima2/sleep.S b/arch/arm/mach-prima2/sleep.S
new file mode 100644
index 0000000..0745abc
--- /dev/null
+++ b/arch/arm/mach-prima2/sleep.S
@@ -0,0 +1,64 @@
+/*
+ * sleep mode for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/assembler.h>
+
+#include "pm.h"
+
+#define DENALI_CTL_22_OFF 0x58
+#define DENALI_CTL_112_OFF 0x1c0
+
+ .text
+
+ENTRY(sirfsoc_finish_suspend)
+ @ r5: mem controller
+ ldr r0, =sirfsoc_memc_base
+ ldr r5, [r0]
+ @ r6: pwrc base offset
+ ldr r0, =sirfsoc_pwrc_base
+ ldr r6, [r0]
+ @ r7: rtc iobrg controller
+ ldr r0, =sirfsoc_rtciobrg_base
+ ldr r7, [r0]
+
+ @ Read the power control register and set the
+ @ sleep force bit.
+ add r0, r6, #SIRFSOC_PWRC_PDN_CTRL
+ bl __sirfsoc_rtc_iobrg_readl
+ orr r0,r0,#SIRFSOC_PWR_SLEEPFORCE
+ add r1, r6, #SIRFSOC_PWRC_PDN_CTRL
+ bl sirfsoc_rtc_iobrg_pre_writel
+ mov r1, #0x1
+
+ @ read the MEM ctl register and set the self
+ @ refresh bit
+
+ ldr r2, [r5, #DENALI_CTL_22_OFF]
+ orr r2, r2, #0x1
+
+ @ Following code has to run from cache since
+ @ the RAM is going to self refresh mode
+ .align 5
+ str r2, [r5, #DENALI_CTL_22_OFF]
+
+1:
+ ldr r4, [r5, #DENALI_CTL_112_OFF]
+ tst r4, #0x1
+ bne 1b
+
+ @ write SLEEPFORCE through rtc iobridge
+
+ str r1, [r7]
+ @ wait rtc io bridge sync
+1:
+ ldr r3, [r7]
+ tst r3, #0x01
+ bne 1b
+ b .
diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer.c
new file mode 100644
index 0000000..b7a6091
--- /dev/null
+++ b/arch/arm/mach-prima2/timer.c
@@ -0,0 +1,252 @@
+/*
+ * System timer for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <mach/map.h>
+#include <asm/mach/time.h>
+
+#define SIRFSOC_TIMER_COUNTER_LO 0x0000
+#define SIRFSOC_TIMER_COUNTER_HI 0x0004
+#define SIRFSOC_TIMER_MATCH_0 0x0008
+#define SIRFSOC_TIMER_MATCH_1 0x000C
+#define SIRFSOC_TIMER_MATCH_2 0x0010
+#define SIRFSOC_TIMER_MATCH_3 0x0014
+#define SIRFSOC_TIMER_MATCH_4 0x0018
+#define SIRFSOC_TIMER_MATCH_5 0x001C
+#define SIRFSOC_TIMER_STATUS 0x0020
+#define SIRFSOC_TIMER_INT_EN 0x0024
+#define SIRFSOC_TIMER_WATCHDOG_EN 0x0028
+#define SIRFSOC_TIMER_DIV 0x002C
+#define SIRFSOC_TIMER_LATCH 0x0030
+#define SIRFSOC_TIMER_LATCHED_LO 0x0034
+#define SIRFSOC_TIMER_LATCHED_HI 0x0038
+
+#define SIRFSOC_TIMER_WDT_INDEX 5
+
+#define SIRFSOC_TIMER_LATCH_BIT BIT(0)
+
+#define SIRFSOC_TIMER_REG_CNT 11
+
+static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
+ SIRFSOC_TIMER_MATCH_0, SIRFSOC_TIMER_MATCH_1, SIRFSOC_TIMER_MATCH_2,
+ SIRFSOC_TIMER_MATCH_3, SIRFSOC_TIMER_MATCH_4, SIRFSOC_TIMER_MATCH_5,
+ SIRFSOC_TIMER_INT_EN, SIRFSOC_TIMER_WATCHDOG_EN, SIRFSOC_TIMER_DIV,
+ SIRFSOC_TIMER_LATCHED_LO, SIRFSOC_TIMER_LATCHED_HI,
+};
+
+static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
+
+static void __iomem *sirfsoc_timer_base;
+static void __init sirfsoc_of_timer_map(void);
+
+/* timer0 interrupt handler */
+static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *ce = dev_id;
+
+ WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) & BIT(0)));
+
+ /* clear timer0 interrupt */
+ writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
+
+ ce->event_handler(ce);
+
+ return IRQ_HANDLED;
+}
+
+/* read 64-bit timer counter */
+static cycle_t sirfsoc_timer_read(struct clocksource *cs)
+{
+ u64 cycles;
+
+ /* latch the 64-bit timer counter */
+ writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+ cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_HI);
+ cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
+
+ return cycles;
+}
+
+static int sirfsoc_timer_set_next_event(unsigned long delta,
+ struct clock_event_device *ce)
+{
+ unsigned long now, next;
+
+ writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+ now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
+ next = now + delta;
+ writel_relaxed(next, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0);
+ writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+ now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
+
+ return next - now > delta ? -ETIME : 0;
+}
+
+static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *ce)
+{
+ u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ WARN_ON(1);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ writel_relaxed(val & ~BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
+}
+
+static void sirfsoc_clocksource_suspend(struct clocksource *cs)
+{
+ int i;
+
+ writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+
+ for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+ sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+}
+
+static void sirfsoc_clocksource_resume(struct clocksource *cs)
+{
+ int i;
+
+ for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+ writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+
+ writel_relaxed(sirfsoc_timer_reg_val[i - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
+ writel_relaxed(sirfsoc_timer_reg_val[i - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
+}
+
+static struct clock_event_device sirfsoc_clockevent = {
+ .name = "sirfsoc_clockevent",
+ .rating = 200,
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .set_mode = sirfsoc_timer_set_mode,
+ .set_next_event = sirfsoc_timer_set_next_event,
+};
+
+static struct clocksource sirfsoc_clocksource = {
+ .name = "sirfsoc_clocksource",
+ .rating = 200,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .read = sirfsoc_timer_read,
+ .suspend = sirfsoc_clocksource_suspend,
+ .resume = sirfsoc_clocksource_resume,
+};
+
+static struct irqaction sirfsoc_timer_irq = {
+ .name = "sirfsoc_timer0",
+ .flags = IRQF_TIMER,
+ .irq = 0,
+ .handler = sirfsoc_timer_interrupt,
+ .dev_id = &sirfsoc_clockevent,
+};
+
+/* Overwrite weak default sched_clock with more precise one */
+unsigned long long notrace sched_clock(void)
+{
+ static int is_mapped;
+
+ /*
+ * sched_clock is called earlier than .init of sys_timer
+ * if we map timer memory in .init of sys_timer, system
+ * will panic due to illegal memory access
+ */
+ if (!is_mapped) {
+ sirfsoc_of_timer_map();
+ is_mapped = 1;
+ }
+
+ return sirfsoc_timer_read(NULL) * (NSEC_PER_SEC / CLOCK_TICK_RATE);
+}
+
+static void __init sirfsoc_clockevent_init(void)
+{
+ clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
+
+ sirfsoc_clockevent.max_delta_ns =
+ clockevent_delta2ns(-2, &sirfsoc_clockevent);
+ sirfsoc_clockevent.min_delta_ns =
+ clockevent_delta2ns(2, &sirfsoc_clockevent);
+
+ sirfsoc_clockevent.cpumask = cpumask_of(0);
+ clockevents_register_device(&sirfsoc_clockevent);
+}
+
+/* initialize the kernel jiffy timer source */
+static void __init sirfsoc_timer_init(void)
+{
+ unsigned long rate;
+
+ /* timer's input clock is io clock */
+ struct clk *clk = clk_get_sys("io", NULL);
+
+ BUG_ON(IS_ERR(clk));
+
+ rate = clk_get_rate(clk);
+
+ BUG_ON(rate < CLOCK_TICK_RATE);
+ BUG_ON(rate % CLOCK_TICK_RATE);
+
+ writel_relaxed(rate / CLOCK_TICK_RATE / 2 - 1, sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
+ writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
+ writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
+ writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
+
+ BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
+
+ BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
+
+ sirfsoc_clockevent_init();
+}
+
+static struct of_device_id timer_ids[] = {
+ { .compatible = "sirf,prima2-tick" },
+ {},
+};
+
+static void __init sirfsoc_of_timer_map(void)
+{
+ struct device_node *np;
+ const unsigned int *intspec;
+
+ np = of_find_matching_node(NULL, timer_ids);
+ if (!np)
+ panic("unable to find compatible timer node in dtb\n");
+ sirfsoc_timer_base = of_iomap(np, 0);
+ if (!sirfsoc_timer_base)
+ panic("unable to map timer cpu registers\n");
+
+ /* Get the interrupts property */
+ intspec = of_get_property(np, "interrupts", NULL);
+ BUG_ON(!intspec);
+ sirfsoc_timer_irq.irq = be32_to_cpup(intspec);
+
+ of_node_put(np);
+}
+
+struct sys_timer sirfsoc_timer = {
+ .init = sirfsoc_timer_init,
+};
diff --git a/arch/arm/mach-pxa/include/mach/gpio-pxa.h b/arch/arm/mach-pxa/include/mach/gpio-pxa.h
new file mode 100644
index 0000000..41b4c93
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/gpio-pxa.h
@@ -0,0 +1,133 @@
+/*
+ * Written by Philipp Zabel <philipp.zabel@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __MACH_PXA_GPIO_PXA_H
+#define __MACH_PXA_GPIO_PXA_H
+
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+
+#define GPIO_REGS_VIRT io_p2v(0x40E00000)
+
+#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+#define GPIO_REG(x) (*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
+
+/* GPIO Pin Level Registers */
+#define GPLR0 GPIO_REG(BANK_OFF(0) + 0x00)
+#define GPLR1 GPIO_REG(BANK_OFF(1) + 0x00)
+#define GPLR2 GPIO_REG(BANK_OFF(2) + 0x00)
+#define GPLR3 GPIO_REG(BANK_OFF(3) + 0x00)
+
+/* GPIO Pin Direction Registers */
+#define GPDR0 GPIO_REG(BANK_OFF(0) + 0x0c)
+#define GPDR1 GPIO_REG(BANK_OFF(1) + 0x0c)
+#define GPDR2 GPIO_REG(BANK_OFF(2) + 0x0c)
+#define GPDR3 GPIO_REG(BANK_OFF(3) + 0x0c)
+
+/* GPIO Pin Output Set Registers */
+#define GPSR0 GPIO_REG(BANK_OFF(0) + 0x18)
+#define GPSR1 GPIO_REG(BANK_OFF(1) + 0x18)
+#define GPSR2 GPIO_REG(BANK_OFF(2) + 0x18)
+#define GPSR3 GPIO_REG(BANK_OFF(3) + 0x18)
+
+/* GPIO Pin Output Clear Registers */
+#define GPCR0 GPIO_REG(BANK_OFF(0) + 0x24)
+#define GPCR1 GPIO_REG(BANK_OFF(1) + 0x24)
+#define GPCR2 GPIO_REG(BANK_OFF(2) + 0x24)
+#define GPCR3 GPIO_REG(BANK_OFF(3) + 0x24)
+
+/* GPIO Rising Edge Detect Registers */
+#define GRER0 GPIO_REG(BANK_OFF(0) + 0x30)
+#define GRER1 GPIO_REG(BANK_OFF(1) + 0x30)
+#define GRER2 GPIO_REG(BANK_OFF(2) + 0x30)
+#define GRER3 GPIO_REG(BANK_OFF(3) + 0x30)
+
+/* GPIO Falling Edge Detect Registers */
+#define GFER0 GPIO_REG(BANK_OFF(0) + 0x3c)
+#define GFER1 GPIO_REG(BANK_OFF(1) + 0x3c)
+#define GFER2 GPIO_REG(BANK_OFF(2) + 0x3c)
+#define GFER3 GPIO_REG(BANK_OFF(3) + 0x3c)
+
+/* GPIO Edge Detect Status Registers */
+#define GEDR0 GPIO_REG(BANK_OFF(0) + 0x48)
+#define GEDR1 GPIO_REG(BANK_OFF(1) + 0x48)
+#define GEDR2 GPIO_REG(BANK_OFF(2) + 0x48)
+#define GEDR3 GPIO_REG(BANK_OFF(3) + 0x48)
+
+/* GPIO Alternate Function Select Registers */
+#define GAFR0_L GPIO_REG(0x0054)
+#define GAFR0_U GPIO_REG(0x0058)
+#define GAFR1_L GPIO_REG(0x005C)
+#define GAFR1_U GPIO_REG(0x0060)
+#define GAFR2_L GPIO_REG(0x0064)
+#define GAFR2_U GPIO_REG(0x0068)
+#define GAFR3_L GPIO_REG(0x006C)
+#define GAFR3_U GPIO_REG(0x0070)
+
+/* More handy macros. The argument is a literal GPIO number. */
+
+#define GPIO_bit(x) (1 << ((x) & 0x1f))
+
+#define GPLR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
+#define GPDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
+#define GPSR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
+#define GPCR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
+#define GRER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
+#define GFER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
+#define GEDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
+#define GAFR(x) GPIO_REG(0x54 + (((x) & 0x70) >> 2))
+
+
+#define NR_BUILTIN_GPIO PXA_GPIO_IRQ_NUM
+
+#define gpio_to_bank(gpio) ((gpio) >> 5)
+
+#ifdef CONFIG_CPU_PXA26x
+/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
+ * as well as their Alternate Function value being '1' for GPIO in GAFRx.
+ */
+static inline int __gpio_is_inverted(unsigned gpio)
+{
+ return cpu_is_pxa25x() && gpio > 85;
+}
+#else
+static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
+#endif
+
+/*
+ * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
+ * function of a GPIO, and GPDRx cannot be altered once configured. It
+ * is attributed as "occupied" here (I know this terminology isn't
+ * accurate, you are welcome to propose a better one :-)
+ */
+static inline int __gpio_is_occupied(unsigned gpio)
+{
+ if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
+ int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
+ int dir = GPDR(gpio) & GPIO_bit(gpio);
+
+ if (__gpio_is_inverted(gpio))
+ return af != 1 || dir == 0;
+ else
+ return af != 0 || dir != 0;
+ } else
+ return GPDR(gpio) & GPIO_bit(gpio);
+}
+
+#include <plat/gpio-pxa.h>
+#endif /* __MACH_PXA_GPIO_PXA_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx.h b/arch/arm/mach-pxa/include/mach/pxa3xx.h
new file mode 100644
index 0000000..cd3e57f
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa3xx.h
@@ -0,0 +1,14 @@
+#ifndef __MACH_PXA3XX_H
+#define __MACH_PXA3XX_H
+
+#include <mach/hardware.h>
+#include <mach/pxa3xx-regs.h>
+#include <mach/irqs.h>
+
+extern void __init pxa3xx_map_io(void);
+extern void __init pxa3xx_init_irq(void);
+extern void __init pxa95x_init_irq(void);
+
+#define pxa3xx_handle_irq ichp_handle_irq
+
+#endif /* __MACH_PXA3XX_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa95x.h b/arch/arm/mach-pxa/include/mach/pxa95x.h
new file mode 100644
index 0000000..cbb097c
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa95x.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_PXA95X_H
+#define __MACH_PXA95X_H
+
+#include <mach/pxa3xx.h>
+#include <mach/mfp-pxa930.h>
+
+#endif /* __MACH_PXA95X_H */
diff --git a/arch/arm/mach-s3c64xx/include/mach/crag6410.h b/arch/arm/mach-s3c64xx/include/mach/crag6410.h
new file mode 100644
index 0000000..be9074e
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/crag6410.h
@@ -0,0 +1,23 @@
+/* Cragganmore 6410 shared definitions
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ * Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_CRAG6410_H
+#define MACH_CRAG6410_H
+
+#include <linux/gpio.h>
+
+#define BANFF_PMIC_IRQ_BASE IRQ_BOARD_START
+#define GLENFARCLAS_PMIC_IRQ_BASE (IRQ_BOARD_START + 64)
+
+#define PCA935X_GPIO_BASE GPIO_BOARD_START
+#define CODEC_GPIO_BASE (GPIO_BOARD_START + 8)
+#define GLENFARCLAS_PMIC_GPIO_BASE (GPIO_BOARD_START + 16)
+
+#endif
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
new file mode 100644
index 0000000..f208154
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
@@ -0,0 +1,182 @@
+/* Speyside modules for Cragganmore - board data probing
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ * Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/gpio.h>
+
+#include <sound/wm8996.h>
+#include <sound/wm8962.h>
+#include <sound/wm9081.h>
+
+#include <mach/crag6410.h>
+
+static struct wm8996_retune_mobile_config wm8996_retune[] = {
+ {
+ .name = "Sub LPF",
+ .rate = 48000,
+ .regs = {
+ 0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+ 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+ 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+ },
+ },
+ {
+ .name = "Sub HPF",
+ .rate = 48000,
+ .regs = {
+ 0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+ 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+ 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+ },
+ },
+};
+
+static struct wm8996_pdata wm8996_pdata __initdata = {
+ .ldo_ena = S3C64XX_GPN(7),
+ .gpio_base = CODEC_GPIO_BASE,
+ .micdet_def = 1,
+ .inl_mode = WM8996_DIFFERRENTIAL_1,
+ .inr_mode = WM8996_DIFFERRENTIAL_1,
+
+ .irq_flags = IRQF_TRIGGER_RISING,
+
+ .gpio_default = {
+ 0x8001, /* GPIO1 == ADCLRCLK1 */
+ 0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
+ 0x0141, /* GPIO3 == HP_SEL */
+ 0x0002, /* GPIO4 == IRQ */
+ 0x020e, /* GPIO5 == CLKOUT */
+ },
+
+ .retune_mobile_cfgs = wm8996_retune,
+ .num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
+};
+
+static struct wm8962_pdata wm8962_pdata __initdata = {
+ .gpio_init = {
+ 0,
+ WM8962_GPIO_FN_OPCLK,
+ WM8962_GPIO_FN_DMICCLK,
+ 0,
+ 0x8000 | WM8962_GPIO_FN_DMICDAT,
+ WM8962_GPIO_FN_IRQ, /* Open drain mode */
+ },
+ .irq_active_low = true,
+};
+
+static struct wm9081_pdata wm9081_pdata __initdata = {
+ .irq_high = false,
+ .irq_cmos = false,
+};
+
+static const struct i2c_board_info wm1254_devs[] = {
+ { I2C_BOARD_INFO("wm8996", 0x1a),
+ .platform_data = &wm8996_pdata,
+ .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+ },
+ { I2C_BOARD_INFO("wm9081", 0x6c),
+ .platform_data = &wm9081_pdata, },
+};
+
+static const struct i2c_board_info wm1255_devs[] = {
+ { I2C_BOARD_INFO("wm5100", 0x1a),
+ .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+ },
+ { I2C_BOARD_INFO("wm9081", 0x6c),
+ .platform_data = &wm9081_pdata, },
+};
+
+static const struct i2c_board_info wm1259_devs[] = {
+ { I2C_BOARD_INFO("wm8962", 0x1a),
+ .platform_data = &wm8962_pdata,
+ .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+ },
+};
+
+
+static __devinitdata const struct {
+ u8 id;
+ const char *name;
+ const struct i2c_board_info *i2c_devs;
+ int num_i2c_devs;
+} gf_mods[] = {
+ { .id = 0x01, .name = "1250-EV1 Springbank" },
+ { .id = 0x02, .name = "1251-EV1 Jura" },
+ { .id = 0x03, .name = "1252-EV1 Glenlivet" },
+ { .id = 0x11, .name = "6249-EV2 Glenfarclas", },
+ { .id = 0x21, .name = "1275-EV1 Mortlach" },
+ { .id = 0x25, .name = "1274-EV1 Glencadam" },
+ { .id = 0x31, .name = "1253-EV1 Tomatin", },
+ { .id = 0x39, .name = "1254-EV1 Dallas Dhu",
+ .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) },
+ { .id = 0x3a, .name = "1259-EV1 Tobermory",
+ .i2c_devs = wm1259_devs, .num_i2c_devs = ARRAY_SIZE(wm1259_devs) },
+ { .id = 0x3b, .name = "1255-EV1 Kilchoman",
+ .i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
+ { .id = 0x3c, .name = "1273-EV1 Longmorn" },
+};
+
+static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *i2c_id)
+{
+ int ret, i, j, id, rev;
+
+ ret = i2c_smbus_read_byte_data(i2c, 0);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read ID: %d\n", ret);
+ return ret;
+ }
+
+ id = (ret & 0xfe) >> 2;
+ rev = ret & 0x3;
+ for (i = 0; i < ARRAY_SIZE(gf_mods); i++)
+ if (id == gf_mods[i].id)
+ break;
+
+ if (i < ARRAY_SIZE(gf_mods)) {
+ dev_info(&i2c->dev, "%s revision %d\n",
+ gf_mods[i].name, rev + 1);
+ for (j = 0; j < gf_mods[i].num_i2c_devs; j++) {
+ if (!i2c_new_device(i2c->adapter,
+ &(gf_mods[i].i2c_devs[j])))
+ dev_err(&i2c->dev,
+ "Failed to register dev: %d\n", ret);
+ }
+ } else {
+ dev_warn(&i2c->dev, "Unknown module ID %d revision %d\n",
+ id, rev);
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id wlf_gf_module_id[] = {
+ { "wlf-gf-module", 0 },
+ { }
+};
+
+static struct i2c_driver wlf_gf_module_driver = {
+ .driver = {
+ .name = "wlf-gf-module",
+ .owner = THIS_MODULE,
+ },
+ .probe = wlf_gf_module_probe,
+ .id_table = wlf_gf_module_id,
+};
+
+static int __init wlf_gf_module_register(void)
+{
+ return i2c_add_driver(&wlf_gf_module_driver);
+}
+module_init(wlf_gf_module_register);
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
new file mode 100644
index 0000000..d04b654
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -0,0 +1,717 @@
+/* linux/arch/arm/mach-s3c64xx/mach-crag6410.c
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ * Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * Copyright 2011 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/pwm_backlight.h>
+#include <linux/dm9000.h>
+#include <linux/gpio_keys.h>
+#include <linux/basic_mmio_gpio.h>
+#include <linux/spi/spi.h>
+
+#include <linux/i2c/pca953x.h>
+
+#include <video/platform_lcd.h>
+
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <mach/regs-sys.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-modem.h>
+#include <mach/crag6410.h>
+
+#include <mach/regs-gpio-memport.h>
+
+#include <plat/s3c6410.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/fb.h>
+#include <plat/sdhci.h>
+#include <plat/gpio-cfg.h>
+#include <plat/s3c64xx-spi.h>
+
+#include <plat/keypad.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/adc.h>
+#include <plat/iic.h>
+#include <plat/pm.h>
+
+/* serial port setup */
+
+#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
+#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
+#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
+
+static struct s3c2410_uartcfg crag6410_uartcfgs[] __initdata = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ [3] = {
+ .hwport = 3,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+};
+
+static struct platform_pwm_backlight_data crag6410_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 1000,
+ .dft_brightness = 600,
+ .pwm_period_ns = 100000, /* about 1kHz */
+};
+
+static struct platform_device crag6410_backlight_device = {
+ .name = "pwm-backlight",
+ .id = -1,
+ .dev = {
+ .parent = &s3c_device_timer[0].dev,
+ .platform_data = &crag6410_backlight_data,
+ },
+};
+
+static void crag6410_lcd_power_set(struct plat_lcd_data *pd, unsigned int power)
+{
+ pr_debug("%s: setting power %d\n", __func__, power);
+
+ if (power) {
+ gpio_set_value(S3C64XX_GPB(0), 1);
+ msleep(1);
+ s3c_gpio_cfgpin(S3C64XX_GPF(14), S3C_GPIO_SFN(2));
+ } else {
+ gpio_direction_output(S3C64XX_GPF(14), 0);
+ gpio_set_value(S3C64XX_GPB(0), 0);
+ }
+}
+
+static struct platform_device crag6410_lcd_powerdev = {
+ .name = "platform-lcd",
+ .id = -1,
+ .dev.parent = &s3c_device_fb.dev,
+ .dev.platform_data = &(struct plat_lcd_data) {
+ .set_power = crag6410_lcd_power_set,
+ },
+};
+
+/* 640x480 URT */
+static struct s3c_fb_pd_win crag6410_fb_win0 = {
+ /* this is to ensure we use win0 */
+ .win_mode = {
+ .left_margin = 150,
+ .right_margin = 80,
+ .upper_margin = 40,
+ .lower_margin = 5,
+ .hsync_len = 40,
+ .vsync_len = 5,
+ .xres = 640,
+ .yres = 480,
+ },
+ .max_bpp = 32,
+ .default_bpp = 16,
+ .virtual_y = 480 * 2,
+ .virtual_x = 640,
+};
+
+/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
+static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = {
+ .setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
+ .win[0] = &crag6410_fb_win0,
+ .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+ .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+};
+
+/* 2x6 keypad */
+
+static uint32_t crag6410_keymap[] __initdata = {
+ /* KEY(row, col, keycode) */
+ KEY(0, 0, KEY_VOLUMEUP),
+ KEY(0, 1, KEY_HOME),
+ KEY(0, 2, KEY_VOLUMEDOWN),
+ KEY(0, 3, KEY_HELP),
+ KEY(0, 4, KEY_MENU),
+ KEY(0, 5, KEY_MEDIA),
+ KEY(1, 0, 232),
+ KEY(1, 1, KEY_DOWN),
+ KEY(1, 2, KEY_LEFT),
+ KEY(1, 3, KEY_UP),
+ KEY(1, 4, KEY_RIGHT),
+ KEY(1, 5, KEY_CAMERA),
+};
+
+static struct matrix_keymap_data crag6410_keymap_data __initdata = {
+ .keymap = crag6410_keymap,
+ .keymap_size = ARRAY_SIZE(crag6410_keymap),
+};
+
+static struct samsung_keypad_platdata crag6410_keypad_data __initdata = {
+ .keymap_data = &crag6410_keymap_data,
+ .rows = 2,
+ .cols = 6,
+};
+
+static struct gpio_keys_button crag6410_gpio_keys[] = {
+ [0] = {
+ .code = KEY_SUSPEND,
+ .gpio = S3C64XX_GPL(10), /* EINT 18 */
+ .type = EV_KEY,
+ .wakeup = 1,
+ .active_low = 1,
+ },
+ [1] = {
+ .code = SW_FRONT_PROXIMITY,
+ .gpio = S3C64XX_GPN(11), /* EINT 11 */
+ .type = EV_SW,
+ },
+};
+
+static struct gpio_keys_platform_data crag6410_gpio_keydata = {
+ .buttons = crag6410_gpio_keys,
+ .nbuttons = ARRAY_SIZE(crag6410_gpio_keys),
+};
+
+static struct platform_device crag6410_gpio_keydev = {
+ .name = "gpio-keys",
+ .id = 0,
+ .dev.platform_data = &crag6410_gpio_keydata,
+};
+
+static struct resource crag6410_dm9k_resource[] = {
+ [0] = {
+ .start = S3C64XX_PA_XM0CSN5,
+ .end = S3C64XX_PA_XM0CSN5 + 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = S3C64XX_PA_XM0CSN5 + (1 << 8),
+ .end = S3C64XX_PA_XM0CSN5 + (1 << 8) + 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = S3C_EINT(17),
+ .end = S3C_EINT(17),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+};
+
+static struct dm9000_plat_data mini6410_dm9k_pdata = {
+ .flags = DM9000_PLATF_16BITONLY,
+};
+
+static struct platform_device crag6410_dm9k_device = {
+ .name = "dm9000",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(crag6410_dm9k_resource),
+ .resource = crag6410_dm9k_resource,
+ .dev.platform_data = &mini6410_dm9k_pdata,
+};
+
+static struct resource crag6410_mmgpio_resource[] = {
+ [0] = {
+ .start = S3C64XX_PA_XM0CSN4 + 1,
+ .end = S3C64XX_PA_XM0CSN4 + 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device crag6410_mmgpio = {
+ .name = "basic-mmio-gpio",
+ .id = -1,
+ .resource = crag6410_mmgpio_resource,
+ .num_resources = ARRAY_SIZE(crag6410_mmgpio_resource),
+ .dev.platform_data = &(struct bgpio_pdata) {
+ .base = -1,
+ },
+};
+
+static struct platform_device speyside_device = {
+ .name = "speyside",
+ .id = -1,
+};
+
+static struct platform_device lowland_device = {
+ .name = "lowland",
+ .id = -1,
+};
+
+static struct platform_device speyside_wm8962_device = {
+ .name = "speyside-wm8962",
+ .id = -1,
+};
+
+static struct regulator_consumer_supply wallvdd_consumers[] = {
+ REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
+ REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
+ REGULATOR_SUPPLY("SPKVDDL", "1-001a"),
+ REGULATOR_SUPPLY("SPKVDDR", "1-001a"),
+};
+
+static struct regulator_init_data wallvdd_data = {
+ .constraints = {
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(wallvdd_consumers),
+ .consumer_supplies = wallvdd_consumers,
+};
+
+static struct fixed_voltage_config wallvdd_pdata = {
+ .supply_name = "WALLVDD",
+ .microvolts = 5000000,
+ .init_data = &wallvdd_data,
+ .gpio = -EINVAL,
+};
+
+static struct platform_device wallvdd_device = {
+ .name = "reg-fixed-voltage",
+ .id = -1,
+ .dev = {
+ .platform_data = &wallvdd_pdata,
+ },
+};
+
+static struct platform_device *crag6410_devices[] __initdata = {
+ &s3c_device_hsmmc0,
+ &s3c_device_hsmmc1,
+ &s3c_device_hsmmc2,
+ &s3c_device_i2c0,
+ &s3c_device_i2c1,
+ &s3c_device_fb,
+ &s3c_device_ohci,
+ &s3c_device_usb_hsotg,
+ &s3c_device_timer[0],
+ &s3c64xx_device_iis0,
+ &s3c64xx_device_iis1,
+ &samsung_asoc_dma,
+ &samsung_device_keypad,
+ &crag6410_gpio_keydev,
+ &crag6410_dm9k_device,
+ &s3c64xx_device_spi0,
+ &crag6410_mmgpio,
+ &crag6410_lcd_powerdev,
+ &crag6410_backlight_device,
+ &speyside_device,
+ &speyside_wm8962_device,
+ &lowland_device,
+ &wallvdd_device,
+};
+
+static struct pca953x_platform_data crag6410_pca_data = {
+ .gpio_base = PCA935X_GPIO_BASE,
+ .irq_base = 0,
+};
+
+/* VDDARM is controlled by DVS1 connected to GPK(0) */
+static struct wm831x_buckv_pdata vddarm_pdata = {
+ .dvs_control_src = 1,
+ .dvs_gpio = S3C64XX_GPK(0),
+};
+
+static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
+ REGULATOR_SUPPLY("vddarm", NULL),
+};
+
+static struct regulator_init_data vddarm __initdata = {
+ .constraints = {
+ .name = "VDDARM",
+ .min_uV = 1000000,
+ .max_uV = 1300000,
+ .always_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vddarm_consumers),
+ .consumer_supplies = vddarm_consumers,
+ .supply_regulator = "WALLVDD",
+ .driver_data = &vddarm_pdata,
+};
+
+static struct regulator_init_data vddint __initdata = {
+ .constraints = {
+ .name = "VDDINT",
+ .min_uV = 1000000,
+ .max_uV = 1200000,
+ .always_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ },
+};
+
+static struct regulator_init_data vddmem __initdata = {
+ .constraints = {
+ .name = "VDDMEM",
+ .always_on = 1,
+ },
+};
+
+static struct regulator_init_data vddsys __initdata = {
+ .constraints = {
+ .name = "VDDSYS,VDDEXT,VDDPCM,VDDSS",
+ .always_on = 1,
+ },
+};
+
+static struct regulator_consumer_supply vddmmc_consumers[] __initdata = {
+ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
+ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.1"),
+ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
+};
+
+static struct regulator_init_data vddmmc __initdata = {
+ .constraints = {
+ .name = "VDDMMC,UH",
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vddmmc_consumers),
+ .consumer_supplies = vddmmc_consumers,
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddotgi __initdata = {
+ .constraints = {
+ .name = "VDDOTGi",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddotg __initdata = {
+ .constraints = {
+ .name = "VDDOTG",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddhi __initdata = {
+ .constraints = {
+ .name = "VDDHI",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddadc __initdata = {
+ .constraints = {
+ .name = "VDDADC,VDDDAC",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddmem0 __initdata = {
+ .constraints = {
+ .name = "VDDMEM0",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddpll __initdata = {
+ .constraints = {
+ .name = "VDDPLL",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddlcd __initdata = {
+ .constraints = {
+ .name = "VDDLCD",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddalive __initdata = {
+ .constraints = {
+ .name = "VDDALIVE",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct wm831x_backup_pdata banff_backup_pdata __initdata = {
+ .charger_enable = 1,
+ .vlim = 2500, /* mV */
+ .ilim = 200, /* uA */
+};
+
+static struct wm831x_status_pdata banff_red_led __initdata = {
+ .name = "banff:red:",
+ .default_src = WM831X_STATUS_MANUAL,
+};
+
+static struct wm831x_status_pdata banff_green_led __initdata = {
+ .name = "banff:green:",
+ .default_src = WM831X_STATUS_MANUAL,
+};
+
+static struct wm831x_touch_pdata touch_pdata __initdata = {
+ .data_irq = S3C_EINT(26),
+ .pd_irq = S3C_EINT(27),
+};
+
+static struct wm831x_pdata crag_pmic_pdata __initdata = {
+ .wm831x_num = 1,
+ .irq_base = BANFF_PMIC_IRQ_BASE,
+ .gpio_base = GPIO_BOARD_START + 8,
+
+ .backup = &banff_backup_pdata,
+
+ .gpio_defaults = {
+ /* GPIO5: DVS1_REQ - CMOS, DBVDD, active high */
+ [4] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA | 0x8,
+ /* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
+ [10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6,
+ /* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
+ [11] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x7,
+ },
+
+ .dcdc = {
+ &vddarm, /* DCDC1 */
+ &vddint, /* DCDC2 */
+ &vddmem, /* DCDC3 */
+ },
+
+ .ldo = {
+ &vddsys, /* LDO1 */
+ &vddmmc, /* LDO2 */
+ NULL, /* LDO3 */
+ &vddotgi, /* LDO4 */
+ &vddotg, /* LDO5 */
+ &vddhi, /* LDO6 */
+ &vddadc, /* LDO7 */
+ &vddmem0, /* LDO8 */
+ &vddpll, /* LDO9 */
+ &vddlcd, /* LDO10 */
+ &vddalive, /* LDO11 */
+ },
+
+ .status = {
+ &banff_green_led,
+ &banff_red_led,
+ },
+
+ .touch = &touch_pdata,
+};
+
+static struct i2c_board_info i2c_devs0[] __initdata = {
+ { I2C_BOARD_INFO("24c08", 0x50), },
+ { I2C_BOARD_INFO("tca6408", 0x20),
+ .platform_data = &crag6410_pca_data,
+ },
+ { I2C_BOARD_INFO("wm8312", 0x34),
+ .platform_data = &crag_pmic_pdata,
+ .irq = S3C_EINT(23),
+ },
+};
+
+static struct s3c2410_platform_i2c i2c0_pdata = {
+ .frequency = 400000,
+};
+
+static struct regulator_init_data pvdd_1v2 __initdata = {
+ .constraints = {
+ .name = "PVDD_1V2",
+ .always_on = 1,
+ },
+};
+
+static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
+ REGULATOR_SUPPLY("LDOVDD", "1-001a"),
+ REGULATOR_SUPPLY("PLLVDD", "1-001a"),
+ REGULATOR_SUPPLY("DBVDD", "1-001a"),
+ REGULATOR_SUPPLY("DBVDD1", "1-001a"),
+ REGULATOR_SUPPLY("DBVDD2", "1-001a"),
+ REGULATOR_SUPPLY("DBVDD3", "1-001a"),
+ REGULATOR_SUPPLY("CPVDD", "1-001a"),
+ REGULATOR_SUPPLY("AVDD2", "1-001a"),
+ REGULATOR_SUPPLY("DCVDD", "1-001a"),
+ REGULATOR_SUPPLY("AVDD", "1-001a"),
+};
+
+static struct regulator_init_data pvdd_1v8 __initdata = {
+ .constraints = {
+ .name = "PVDD_1V8",
+ .always_on = 1,
+ },
+
+ .consumer_supplies = pvdd_1v8_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(pvdd_1v8_consumers),
+};
+
+static struct regulator_consumer_supply pvdd_3v3_consumers[] __initdata = {
+ REGULATOR_SUPPLY("MICVDD", "1-001a"),
+ REGULATOR_SUPPLY("AVDD1", "1-001a"),
+};
+
+static struct regulator_init_data pvdd_3v3 __initdata = {
+ .constraints = {
+ .name = "PVDD_3V3",
+ .always_on = 1,
+ },
+
+ .consumer_supplies = pvdd_3v3_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(pvdd_3v3_consumers),
+};
+
+static struct wm831x_pdata glenfarclas_pmic_pdata __initdata = {
+ .wm831x_num = 2,
+ .irq_base = GLENFARCLAS_PMIC_IRQ_BASE,
+ .gpio_base = GLENFARCLAS_PMIC_GPIO_BASE,
+
+ .gpio_defaults = {
+ /* GPIO1-3: IRQ inputs, rising edge triggered, CMOS */
+ [0] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
+ [1] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
+ [2] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
+ },
+
+ .dcdc = {
+ &pvdd_1v2, /* DCDC1 */
+ &pvdd_1v8, /* DCDC2 */
+ &pvdd_3v3, /* DCDC3 */
+ },
+
+ .disable_touch = true,
+};
+
+static struct i2c_board_info i2c_devs1[] __initdata = {
+ { I2C_BOARD_INFO("wm8311", 0x34),
+ .irq = S3C_EINT(0),
+ .platform_data = &glenfarclas_pmic_pdata },
+
+ { I2C_BOARD_INFO("wlf-gf-module", 0x24) },
+ { I2C_BOARD_INFO("wlf-gf-module", 0x25) },
+ { I2C_BOARD_INFO("wlf-gf-module", 0x26) },
+
+ { I2C_BOARD_INFO("wm1250-ev1", 0x27) },
+};
+
+static void __init crag6410_map_io(void)
+{
+ s3c64xx_init_io(NULL, 0);
+ s3c24xx_init_clocks(12000000);
+ s3c24xx_init_uarts(crag6410_uartcfgs, ARRAY_SIZE(crag6410_uartcfgs));
+
+ /* LCD type and Bypass set by bootloader */
+}
+
+static struct s3c_sdhci_platdata crag6410_hsmmc2_pdata = {
+ .max_width = 4,
+ .cd_type = S3C_SDHCI_CD_PERMANENT,
+};
+
+static struct s3c_sdhci_platdata crag6410_hsmmc1_pdata = {
+ .max_width = 4,
+ .cd_type = S3C_SDHCI_CD_GPIO,
+ .ext_cd_gpio = S3C64XX_GPF(11),
+};
+
+static void crag6410_cfg_sdhci0(struct platform_device *dev, int width)
+{
+ /* Set all the necessary GPG pins to special-function 2 */
+ s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width, S3C_GPIO_SFN(2));
+
+ /* force card-detected for prototype 0 */
+ s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_DOWN);
+}
+
+static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata = {
+ .max_width = 4,
+ .cd_type = S3C_SDHCI_CD_INTERNAL,
+ .cfg_gpio = crag6410_cfg_sdhci0,
+};
+
+static void __init crag6410_machine_init(void)
+{
+ /* Open drain IRQs need pullups */
+ s3c_gpio_setpull(S3C64XX_GPM(0), S3C_GPIO_PULL_UP);
+ s3c_gpio_setpull(S3C64XX_GPN(0), S3C_GPIO_PULL_UP);
+
+ gpio_request(S3C64XX_GPB(0), "LCD power");
+ gpio_direction_output(S3C64XX_GPB(0), 0);
+
+ gpio_request(S3C64XX_GPF(14), "LCD PWM");
+ gpio_direction_output(S3C64XX_GPF(14), 0); /* turn off */
+
+ gpio_request(S3C64XX_GPB(1), "SD power");
+ gpio_direction_output(S3C64XX_GPB(1), 0);
+
+ gpio_request(S3C64XX_GPF(10), "nRESETSEL");
+ gpio_direction_output(S3C64XX_GPF(10), 1);
+
+ s3c_sdhci0_set_platdata(&crag6410_hsmmc0_pdata);
+ s3c_sdhci1_set_platdata(&crag6410_hsmmc1_pdata);
+ s3c_sdhci2_set_platdata(&crag6410_hsmmc2_pdata);
+
+ s3c_i2c0_set_platdata(&i2c0_pdata);
+ s3c_i2c1_set_platdata(NULL);
+ s3c_fb_set_platdata(&crag6410_lcd_pdata);
+
+ i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
+ i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
+
+ samsung_keypad_set_platdata(&crag6410_keypad_data);
+
+ platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
+
+ regulator_has_full_constraints();
+
+ s3c_pm_init();
+}
+
+MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
+ /* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
+ .atag_offset = 0x100,
+ .init_irq = s3c6410_init_irq,
+ .map_io = crag6410_map_io,
+ .init_machine = crag6410_machine_init,
+ .timer = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s5p64x0/include/mach/pm-core.h b/arch/arm/mach-s5p64x0/include/mach/pm-core.h
new file mode 100644
index 0000000..e52f754
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/pm-core.h
@@ -0,0 +1,117 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/pm-core.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P64X0 - PM core support for arch/arm/plat-samsung/pm.c
+ *
+ * Based on PM core support for S3C64XX by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <mach/regs-gpio.h>
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+ u32 tmp = __raw_readl(S5P64X0_CLK_GATE_PCLK);
+
+ /*
+ * As a note, since the S5P64X0 UARTs generally have multiple
+ * clock sources, we simply enable PCLK at the moment and hope
+ * that the resume settings for the UART are suitable for the
+ * use with PCLK.
+ */
+ tmp |= S5P64X0_CLK_GATE_PCLK_UART0;
+ tmp |= S5P64X0_CLK_GATE_PCLK_UART1;
+ tmp |= S5P64X0_CLK_GATE_PCLK_UART2;
+ tmp |= S5P64X0_CLK_GATE_PCLK_UART3;
+
+ __raw_writel(tmp, S5P64X0_CLK_GATE_PCLK);
+ udelay(10);
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+ /* VIC should have already been taken care of */
+
+ /* clear any pending EINT0 interrupts */
+ __raw_writel(__raw_readl(S5P64X0_EINT0PEND), S5P64X0_EINT0PEND);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void) { }
+static inline void s3c_pm_arch_show_resume_irqs(void) { }
+
+/*
+ * make these defines, we currently do not have any need to change
+ * the IRQ wake controls depending on the CPU we are running on
+ */
+#define s3c_irqwake_eintallow ((1 << 16) - 1)
+#define s3c_irqwake_intallow (~0)
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+ struct pm_uart_save *save)
+{
+ u32 ucon = __raw_readl(regs + S3C2410_UCON);
+ u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
+ u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
+ u32 new_ucon;
+ u32 delta;
+
+ /*
+ * S5P64X0 UART blocks only support level interrupts, so ensure that
+ * when we restore unused UART blocks we force the level interrupt
+ * settings.
+ */
+ save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
+
+ /*
+ * We have a constraint on changing the clock type of the UART
+ * between UCLKx and PCLK, so ensure that when we restore UCON
+ * that the CLK field is correctly modified if the bootloader
+ * has changed anything.
+ */
+ if (ucon_clk != save_clk) {
+ new_ucon = save->ucon;
+ delta = ucon_clk ^ save_clk;
+
+ /*
+ * change from UCLKx => wrong PCLK,
+ * either UCLK can be tested for by a bit-test
+ * with UCLK0
+ */
+ if (ucon_clk & S3C6400_UCON_UCLK0 &&
+ !(save_clk & S3C6400_UCON_UCLK0) &&
+ delta & S3C6400_UCON_PCLK2) {
+ new_ucon &= ~S3C6400_UCON_UCLK0;
+ } else if (delta == S3C6400_UCON_PCLK2) {
+ /*
+ * as a precaution, don't change from
+ * PCLK2 => PCLK or vice-versa
+ */
+ new_ucon ^= S3C6400_UCON_PCLK2;
+ }
+
+ S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
+ ucon, new_ucon, save->ucon);
+ save->ucon = new_ucon;
+ }
+}
+
+static inline void s3c_pm_restored_gpios(void)
+{
+ /* ensure sleep mode has been cleared from the system */
+ __raw_writel(0, S5P64X0_SLPEN);
+}
+
+static inline void samsung_pm_saved_gpios(void)
+{
+ /*
+ * turn on the sleep mode and keep it there, as it seems that during
+ * suspend the xCON registers get re-set and thus you can end up with
+ * problems between going to sleep and resuming.
+ */
+ __raw_writel(S5P64X0_SLPEN_USE_xSLP, S5P64X0_SLPEN);
+}
diff --git a/arch/arm/mach-s5p64x0/irq-eint.c b/arch/arm/mach-s5p64x0/irq-eint.c
new file mode 100644
index 0000000..275dc74
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/irq-eint.c
@@ -0,0 +1,155 @@
+/* arch/arm/mach-s5p64x0/irq-eint.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.com/
+ *
+ * Based on linux/arch/arm/mach-s3c64xx/irq-eint.c
+ *
+ * S5P64X0 - Interrupt handling for External Interrupts.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <plat/cpu.h>
+#include <plat/regs-irqtype.h>
+#include <plat/gpio-cfg.h>
+#include <plat/pm.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+
+#define eint_offset(irq) ((irq) - IRQ_EINT(0))
+
+static int s5p64x0_irq_eint_set_type(struct irq_data *data, unsigned int type)
+{
+ int offs = eint_offset(data->irq);
+ int shift;
+ u32 ctrl, mask;
+ u32 newvalue = 0;
+
+ if (offs > 15)
+ return -EINVAL;
+
+ switch (type) {
+ case IRQ_TYPE_NONE:
+ printk(KERN_WARNING "No edge setting!\n");
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ newvalue = S3C2410_EXTINT_RISEEDGE;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ newvalue = S3C2410_EXTINT_FALLEDGE;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ newvalue = S3C2410_EXTINT_BOTHEDGE;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ newvalue = S3C2410_EXTINT_LOWLEV;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ newvalue = S3C2410_EXTINT_HILEV;
+ break;
+ default:
+ printk(KERN_ERR "No such irq type %d", type);
+ return -EINVAL;
+ }
+
+ shift = (offs / 2) * 4;
+ mask = 0x7 << shift;
+
+ ctrl = __raw_readl(S5P64X0_EINT0CON0) & ~mask;
+ ctrl |= newvalue << shift;
+ __raw_writel(ctrl, S5P64X0_EINT0CON0);
+
+ /* Configure the GPIO pin for 6450 or 6440 based on CPU ID */
+ if (soc_is_s5p6450())
+ s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2));
+ else
+ s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2));
+
+ return 0;
+}
+
+/*
+ * s5p64x0_irq_demux_eint
+ *
+ * This function demuxes the IRQ from the group0 external interrupts,
+ * from IRQ_EINT(0) to IRQ_EINT(15). It is designed to be inlined into
+ * the specific handlers s5p64x0_irq_demux_eintX_Y.
+ */
+static inline void s5p64x0_irq_demux_eint(unsigned int start, unsigned int end)
+{
+ u32 status = __raw_readl(S5P64X0_EINT0PEND);
+ u32 mask = __raw_readl(S5P64X0_EINT0MASK);
+ unsigned int irq;
+
+ status &= ~mask;
+ status >>= start;
+ status &= (1 << (end - start + 1)) - 1;
+
+ for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) {
+ if (status & 1)
+ generic_handle_irq(irq);
+ status >>= 1;
+ }
+}
+
+static void s5p64x0_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+{
+ s5p64x0_irq_demux_eint(0, 3);
+}
+
+static void s5p64x0_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
+{
+ s5p64x0_irq_demux_eint(4, 11);
+}
+
+static void s5p64x0_irq_demux_eint12_15(unsigned int irq,
+ struct irq_desc *desc)
+{
+ s5p64x0_irq_demux_eint(12, 15);
+}
+
+static int s5p64x0_alloc_gc(void)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+
+ gc = irq_alloc_generic_chip("s5p64x0-eint", 1, S5P_IRQ_EINT_BASE,
+ S5P_VA_GPIO, handle_level_irq);
+ if (!gc) {
+ printk(KERN_ERR "%s: irq_alloc_generic_chip for group 0"
+ "external interrupts failed\n", __func__);
+ return -EINVAL;
+ }
+
+ ct = gc->chip_types;
+ ct->chip.irq_ack = irq_gc_ack_set_bit;
+ ct->chip.irq_mask = irq_gc_mask_set_bit;
+ ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+ ct->chip.irq_set_type = s5p64x0_irq_eint_set_type;
+ ct->chip.irq_set_wake = s3c_irqext_wake;
+ ct->regs.ack = EINT0PEND_OFFSET;
+ ct->regs.mask = EINT0MASK_OFFSET;
+ irq_setup_generic_chip(gc, IRQ_MSK(16), IRQ_GC_INIT_MASK_CACHE,
+ IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+ return 0;
+}
+
+static int __init s5p64x0_init_irq_eint(void)
+{
+ int ret = s5p64x0_alloc_gc();
+ irq_set_chained_handler(IRQ_EINT0_3, s5p64x0_irq_demux_eint0_3);
+ irq_set_chained_handler(IRQ_EINT4_11, s5p64x0_irq_demux_eint4_11);
+ irq_set_chained_handler(IRQ_EINT12_15, s5p64x0_irq_demux_eint12_15);
+
+ return ret;
+}
+arch_initcall(s5p64x0_init_irq_eint);
diff --git a/arch/arm/mach-s5p64x0/irq-pm.c b/arch/arm/mach-s5p64x0/irq-pm.c
new file mode 100644
index 0000000..3e6f245
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/irq-pm.c
@@ -0,0 +1,92 @@
+/* linux/arch/arm/mach-s5p64x0/irq-pm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P64X0 - Interrupt handling Power Management
+ *
+ * Based on arch/arm/mach-s3c64xx/irq-pm.c by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/syscore_ops.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#include <plat/regs-serial.h>
+#include <plat/pm.h>
+
+#include <mach/regs-gpio.h>
+
+static struct sleep_save irq_save[] = {
+ SAVE_ITEM(S5P64X0_EINT0CON0),
+ SAVE_ITEM(S5P64X0_EINT0FLTCON0),
+ SAVE_ITEM(S5P64X0_EINT0FLTCON1),
+ SAVE_ITEM(S5P64X0_EINT0MASK),
+};
+
+static struct irq_grp_save {
+ u32 con;
+ u32 fltcon;
+ u32 mask;
+} eint_grp_save[4];
+
+static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
+
+static int s5p64x0_irq_pm_suspend(void)
+{
+ struct irq_grp_save *grp = eint_grp_save;
+ int i;
+
+ S3C_PMDBG("%s: suspending IRQs\n", __func__);
+
+ s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+
+ for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+ irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+ for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+ grp->con = __raw_readl(S5P64X0_EINT12CON + (i * 4));
+ grp->mask = __raw_readl(S5P64X0_EINT12MASK + (i * 4));
+ grp->fltcon = __raw_readl(S5P64X0_EINT12FLTCON + (i * 4));
+ }
+
+ return 0;
+}
+
+static void s5p64x0_irq_pm_resume(void)
+{
+ struct irq_grp_save *grp = eint_grp_save;
+ int i;
+
+ S3C_PMDBG("%s: resuming IRQs\n", __func__);
+
+ s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+
+ for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+ __raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+ for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+ __raw_writel(grp->con, S5P64X0_EINT12CON + (i * 4));
+ __raw_writel(grp->mask, S5P64X0_EINT12MASK + (i * 4));
+ __raw_writel(grp->fltcon, S5P64X0_EINT12FLTCON + (i * 4));
+ }
+
+ S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
+}
+
+static struct syscore_ops s5p64x0_irq_syscore_ops = {
+ .suspend = s5p64x0_irq_pm_suspend,
+ .resume = s5p64x0_irq_pm_resume,
+};
+
+static int __init s5p64x0_syscore_init(void)
+{
+ register_syscore_ops(&s5p64x0_irq_syscore_ops);
+
+ return 0;
+}
+core_initcall(s5p64x0_syscore_init);
diff --git a/arch/arm/mach-s5p64x0/pm.c b/arch/arm/mach-s5p64x0/pm.c
new file mode 100644
index 0000000..6992724
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/pm.c
@@ -0,0 +1,204 @@
+/* linux/arch/arm/mach-s5p64x0/pm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P64X0 Power Management Support
+ *
+ * Based on arch/arm/mach-s3c64xx/pm.c by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/suspend.h>
+#include <linux/syscore_ops.h>
+#include <linux/io.h>
+
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/regs-timer.h>
+#include <plat/wakeup-mask.h>
+
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+
+static struct sleep_save s5p64x0_core_save[] = {
+ SAVE_ITEM(S5P64X0_APLL_CON),
+ SAVE_ITEM(S5P64X0_MPLL_CON),
+ SAVE_ITEM(S5P64X0_EPLL_CON),
+ SAVE_ITEM(S5P64X0_EPLL_CON_K),
+ SAVE_ITEM(S5P64X0_CLK_SRC0),
+ SAVE_ITEM(S5P64X0_CLK_SRC1),
+ SAVE_ITEM(S5P64X0_CLK_DIV0),
+ SAVE_ITEM(S5P64X0_CLK_DIV1),
+ SAVE_ITEM(S5P64X0_CLK_DIV2),
+ SAVE_ITEM(S5P64X0_CLK_DIV3),
+ SAVE_ITEM(S5P64X0_CLK_GATE_MEM0),
+ SAVE_ITEM(S5P64X0_CLK_GATE_HCLK1),
+ SAVE_ITEM(S5P64X0_CLK_GATE_SCLK1),
+};
+
+static struct sleep_save s5p64x0_misc_save[] = {
+ SAVE_ITEM(S5P64X0_AHB_CON0),
+ SAVE_ITEM(S5P64X0_SPCON0),
+ SAVE_ITEM(S5P64X0_SPCON1),
+ SAVE_ITEM(S5P64X0_MEM0CONSLP0),
+ SAVE_ITEM(S5P64X0_MEM0CONSLP1),
+ SAVE_ITEM(S5P64X0_MEM0DRVCON),
+ SAVE_ITEM(S5P64X0_MEM1DRVCON),
+
+ SAVE_ITEM(S3C64XX_TINT_CSTAT),
+};
+
+/* DPLL is present only in S5P6450 */
+static struct sleep_save s5p6450_core_save[] = {
+ SAVE_ITEM(S5P6450_DPLL_CON),
+ SAVE_ITEM(S5P6450_DPLL_CON_K),
+};
+
+void s3c_pm_configure_extint(void)
+{
+ __raw_writel(s3c_irqwake_eintmask, S5P64X0_EINT_WAKEUP_MASK);
+}
+
+void s3c_pm_restore_core(void)
+{
+ __raw_writel(0, S5P64X0_EINT_WAKEUP_MASK);
+
+ s3c_pm_do_restore_core(s5p64x0_core_save,
+ ARRAY_SIZE(s5p64x0_core_save));
+
+ if (soc_is_s5p6450())
+ s3c_pm_do_restore_core(s5p6450_core_save,
+ ARRAY_SIZE(s5p6450_core_save));
+
+ s3c_pm_do_restore(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save));
+}
+
+void s3c_pm_save_core(void)
+{
+ s3c_pm_do_save(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save));
+
+ if (soc_is_s5p6450())
+ s3c_pm_do_save(s5p6450_core_save,
+ ARRAY_SIZE(s5p6450_core_save));
+
+ s3c_pm_do_save(s5p64x0_core_save, ARRAY_SIZE(s5p64x0_core_save));
+}
+
+static int s5p64x0_cpu_suspend(unsigned long arg)
+{
+ unsigned long tmp = 0;
+
+ /*
+ * Issue the standby signal into the pm unit. Note, we
+ * issue a write-buffer drain just in case.
+ */
+ asm("b 1f\n\t"
+ ".align 5\n\t"
+ "1:\n\t"
+ "mcr p15, 0, %0, c7, c10, 5\n\t"
+ "mcr p15, 0, %0, c7, c10, 4\n\t"
+ "mcr p15, 0, %0, c7, c0, 4" : : "r" (tmp));
+
+ /* we should never get past here */
+ panic("sleep resumed to originator?");
+}
+
+/* mapping of interrupts to parts of the wakeup mask */
+static struct samsung_wakeup_mask s5p64x0_wake_irqs[] = {
+ { .irq = IRQ_RTC_ALARM, .bit = S5P64X0_PWR_CFG_RTC_ALRM_DISABLE, },
+ { .irq = IRQ_RTC_TIC, .bit = S5P64X0_PWR_CFG_RTC_TICK_DISABLE, },
+ { .irq = IRQ_HSMMC0, .bit = S5P64X0_PWR_CFG_MMC0_DISABLE, },
+ { .irq = IRQ_HSMMC1, .bit = S5P64X0_PWR_CFG_MMC1_DISABLE, },
+};
+
+static void s5p64x0_pm_prepare(void)
+{
+ u32 tmp;
+
+ samsung_sync_wakemask(S5P64X0_PWR_CFG,
+ s5p64x0_wake_irqs, ARRAY_SIZE(s5p64x0_wake_irqs));
+
+ /* store the resume address in INFORM0 register */
+ __raw_writel(virt_to_phys(s3c_cpu_resume), S5P64X0_INFORM0);
+
+ /* setup clock gating for FIMGVG block */
+ __raw_writel((__raw_readl(S5P64X0_CLK_GATE_HCLK1) | \
+ (S5P64X0_CLK_GATE_HCLK1_FIMGVG)), S5P64X0_CLK_GATE_HCLK1);
+ __raw_writel((__raw_readl(S5P64X0_CLK_GATE_SCLK1) | \
+ (S5P64X0_CLK_GATE_SCLK1_FIMGVG)), S5P64X0_CLK_GATE_SCLK1);
+
+ /* Configure the stabilization counter with wait time required */
+ __raw_writel(S5P64X0_PWR_STABLE_PWR_CNT_VAL4, S5P64X0_PWR_STABLE);
+
+ /* set WFI to SLEEP mode configuration */
+ tmp = __raw_readl(S5P64X0_SLEEP_CFG);
+ tmp &= ~(S5P64X0_SLEEP_CFG_OSC_EN);
+ __raw_writel(tmp, S5P64X0_SLEEP_CFG);
+
+ tmp = __raw_readl(S5P64X0_PWR_CFG);
+ tmp &= ~(S5P64X0_PWR_CFG_WFI_MASK);
+ tmp |= S5P64X0_PWR_CFG_WFI_SLEEP;
+ __raw_writel(tmp, S5P64X0_PWR_CFG);
+
+ /*
+ * set OTHERS register to disable interrupt before going to
+ * sleep. This bit is present only in S5P6450, it is reserved
+ * in S5P6440.
+ */
+ if (soc_is_s5p6450()) {
+ tmp = __raw_readl(S5P64X0_OTHERS);
+ tmp |= S5P6450_OTHERS_DISABLE_INT;
+ __raw_writel(tmp, S5P64X0_OTHERS);
+ }
+
+ /* ensure previous wakeup state is cleared before sleeping */
+ __raw_writel(__raw_readl(S5P64X0_WAKEUP_STAT), S5P64X0_WAKEUP_STAT);
+
+}
+
+static int s5p64x0_pm_add(struct sys_device *sysdev)
+{
+ pm_cpu_prep = s5p64x0_pm_prepare;
+ pm_cpu_sleep = s5p64x0_cpu_suspend;
+ pm_uart_udivslot = 1;
+
+ return 0;
+}
+
+static struct sysdev_driver s5p64x0_pm_driver = {
+ .add = s5p64x0_pm_add,
+};
+
+static __init int s5p64x0_pm_drvinit(void)
+{
+ s3c_pm_init();
+
+ return sysdev_driver_register(&s5p64x0_sysclass, &s5p64x0_pm_driver);
+}
+arch_initcall(s5p64x0_pm_drvinit);
+
+static void s5p64x0_pm_resume(void)
+{
+ u32 tmp;
+
+ tmp = __raw_readl(S5P64X0_OTHERS);
+ tmp |= (S5P64X0_OTHERS_RET_MMC0 | S5P64X0_OTHERS_RET_MMC1 | \
+ S5P64X0_OTHERS_RET_UART);
+ __raw_writel(tmp , S5P64X0_OTHERS);
+}
+
+static struct syscore_ops s5p64x0_pm_syscore_ops = {
+ .resume = s5p64x0_pm_resume,
+};
+
+static __init int s5p64x0_pm_syscore_init(void)
+{
+ register_syscore_ops(&s5p64x0_pm_syscore_ops);
+
+ return 0;
+}
+arch_initcall(s5p64x0_pm_syscore_init);
diff --git a/arch/arm/mach-s5p64x0/setup-fb-24bpp.c b/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
new file mode 100644
index 0000000..f346ee4
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Base S5P64X0 GPIO setup information for LCD framebuffer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/fb.h>
+#include <linux/gpio.h>
+
+#include <plat/cpu.h>
+#include <plat/fb.h>
+#include <plat/gpio-cfg.h>
+
+void s5p64x0_fb_gpio_setup_24bpp(void)
+{
+ if (soc_is_s5p6440()) {
+ s3c_gpio_cfgrange_nopull(S5P6440_GPI(0), 16, S3C_GPIO_SFN(2));
+ s3c_gpio_cfgrange_nopull(S5P6440_GPJ(0), 12, S3C_GPIO_SFN(2));
+ } else if (soc_is_s5p6450()) {
+ s3c_gpio_cfgrange_nopull(S5P6450_GPI(0), 16, S3C_GPIO_SFN(2));
+ s3c_gpio_cfgrange_nopull(S5P6450_GPJ(0), 12, S3C_GPIO_SFN(2));
+ }
+}
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-audss.h b/arch/arm/mach-s5pv210/include/mach/regs-audss.h
new file mode 100644
index 0000000..eacc1f7
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/regs-audss.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-s5pv210/include/mach/regs-audss.h
+ *
+ * Copyright (c) 2011 Samsung Electronics
+ * http://www.samsung.com
+ *
+ * S5PV210 Audio SubSystem clock register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_REGS_AUDSS_H
+#define __PLAT_REGS_AUDSS_H __FILE__
+
+#define S5PV210_AUDSS_INT_MEM (0xC0000000)
+
+#endif /* _PLAT_REGS_AUDSS_H */
diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c
new file mode 100644
index 0000000..f44150b
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-kota2.c
@@ -0,0 +1,557 @@
+/*
+ * kota2 board support
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Magnus Damm
+ * Copyright (C) 2010 Takashi Yoshii <yoshii.takashi.zj@renesas.com>
+ * Copyright (C) 2009 Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/smsc911x.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/input/sh_keysc.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <linux/platform_data/leds-renesas-tpu.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <mach/hardware.h>
+#include <mach/sh73a0.h>
+#include <mach/common.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/traps.h>
+
+/* SMSC 9220 */
+static struct resource smsc9220_resources[] = {
+ [0] = {
+ .start = 0x14000000, /* CS5A */
+ .end = 0x140000ff, /* A1->A7 */
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = SH73A0_PINT0_IRQ(2), /* PINTA2 */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct smsc911x_platform_config smsc9220_platdata = {
+ .flags = SMSC911X_USE_32BIT, /* 32-bit SW on 16-bit HW bus */
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+};
+
+static struct platform_device eth_device = {
+ .name = "smsc911x",
+ .id = 0,
+ .dev = {
+ .platform_data = &smsc9220_platdata,
+ },
+ .resource = smsc9220_resources,
+ .num_resources = ARRAY_SIZE(smsc9220_resources),
+};
+
+/* KEYSC */
+static struct sh_keysc_info keysc_platdata = {
+ .mode = SH_KEYSC_MODE_6,
+ .scan_timing = 3,
+ .delay = 100,
+ .keycodes = {
+ KEY_NUMERIC_STAR, KEY_NUMERIC_0, KEY_NUMERIC_POUND,
+ 0, 0, 0, 0, 0,
+ KEY_NUMERIC_7, KEY_NUMERIC_8, KEY_NUMERIC_9,
+ 0, KEY_DOWN, 0, 0, 0,
+ KEY_NUMERIC_4, KEY_NUMERIC_5, KEY_NUMERIC_6,
+ KEY_LEFT, KEY_ENTER, KEY_RIGHT, 0, 0,
+ KEY_NUMERIC_1, KEY_NUMERIC_2, KEY_NUMERIC_3,
+ 0, KEY_UP, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+};
+
+static struct resource keysc_resources[] = {
+ [0] = {
+ .name = "KEYSC",
+ .start = 0xe61b0000,
+ .end = 0xe61b0098 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(71),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device keysc_device = {
+ .name = "sh_keysc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(keysc_resources),
+ .resource = keysc_resources,
+ .dev = {
+ .platform_data = &keysc_platdata,
+ },
+};
+
+/* GPIO KEY */
+#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
+
+static struct gpio_keys_button gpio_buttons[] = {
+ GPIO_KEY(KEY_VOLUMEUP, GPIO_PORT56, "+"), /* S2: VOL+ [IRQ9] */
+ GPIO_KEY(KEY_VOLUMEDOWN, GPIO_PORT54, "-"), /* S3: VOL- [IRQ10] */
+ GPIO_KEY(KEY_MENU, GPIO_PORT27, "Menu"), /* S4: MENU [IRQ30] */
+ GPIO_KEY(KEY_HOMEPAGE, GPIO_PORT26, "Home"), /* S5: HOME [IRQ31] */
+ GPIO_KEY(KEY_BACK, GPIO_PORT11, "Back"), /* S6: BACK [IRQ0] */
+ GPIO_KEY(KEY_PHONE, GPIO_PORT238, "Tel"), /* S7: TEL [IRQ11] */
+ GPIO_KEY(KEY_POWER, GPIO_PORT239, "C1"), /* S8: CAM [IRQ13] */
+ GPIO_KEY(KEY_MAIL, GPIO_PORT224, "Mail"), /* S9: MAIL [IRQ3] */
+ /* Omitted button "C3?": GPIO_PORT223 - S10: CUST [IRQ8] */
+ GPIO_KEY(KEY_CAMERA, GPIO_PORT164, "C2"), /* S11: CAM_HALF [IRQ25] */
+ /* Omitted button "?": GPIO_PORT152 - S12: CAM_FULL [No IRQ] */
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+ .buttons = gpio_buttons,
+ .nbuttons = ARRAY_SIZE(gpio_buttons),
+ .poll_interval = 250, /* polled for now */
+};
+
+static struct platform_device gpio_keys_device = {
+ .name = "gpio-keys-polled", /* polled for now */
+ .id = -1,
+ .dev = {
+ .platform_data = &gpio_key_info,
+ },
+};
+
+/* GPIO LED */
+#define GPIO_LED(n, g) { .name = n, .gpio = g }
+
+static struct gpio_led gpio_leds[] = {
+ GPIO_LED("G", GPIO_PORT20), /* PORT20 [GPO0] -> LED7 -> "G" */
+ GPIO_LED("H", GPIO_PORT21), /* PORT21 [GPO1] -> LED8 -> "H" */
+ GPIO_LED("J", GPIO_PORT22), /* PORT22 [GPO2] -> LED9 -> "J" */
+};
+
+static struct gpio_led_platform_data gpio_leds_info = {
+ .leds = gpio_leds,
+ .num_leds = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device gpio_leds_device = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &gpio_leds_info,
+ },
+};
+
+/* TPU LED */
+static struct led_renesas_tpu_config led_renesas_tpu12_pdata = {
+ .name = "V2513",
+ .pin_gpio_fn = GPIO_FN_TPU1TO2,
+ .pin_gpio = GPIO_PORT153,
+ .channel_offset = 0x90,
+ .timer_bit = 2,
+ .max_brightness = 1000,
+};
+
+static struct resource tpu12_resources[] = {
+ [0] = {
+ .name = "TPU12",
+ .start = 0xe6610090,
+ .end = 0xe66100b5,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device leds_tpu12_device = {
+ .name = "leds-renesas-tpu",
+ .id = 12,
+ .dev = {
+ .platform_data = &led_renesas_tpu12_pdata,
+ },
+ .num_resources = ARRAY_SIZE(tpu12_resources),
+ .resource = tpu12_resources,
+};
+
+static struct led_renesas_tpu_config led_renesas_tpu41_pdata = {
+ .name = "V2514",
+ .pin_gpio_fn = GPIO_FN_TPU4TO1,
+ .pin_gpio = GPIO_PORT199,
+ .channel_offset = 0x50,
+ .timer_bit = 1,
+ .max_brightness = 1000,
+};
+
+static struct resource tpu41_resources[] = {
+ [0] = {
+ .name = "TPU41",
+ .start = 0xe6640050,
+ .end = 0xe6640075,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device leds_tpu41_device = {
+ .name = "leds-renesas-tpu",
+ .id = 41,
+ .dev = {
+ .platform_data = &led_renesas_tpu41_pdata,
+ },
+ .num_resources = ARRAY_SIZE(tpu41_resources),
+ .resource = tpu41_resources,
+};
+
+static struct led_renesas_tpu_config led_renesas_tpu21_pdata = {
+ .name = "V2515",
+ .pin_gpio_fn = GPIO_FN_TPU2TO1,
+ .pin_gpio = GPIO_PORT197,
+ .channel_offset = 0x50,
+ .timer_bit = 1,
+ .max_brightness = 1000,
+};
+
+static struct resource tpu21_resources[] = {
+ [0] = {
+ .name = "TPU21",
+ .start = 0xe6620050,
+ .end = 0xe6620075,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device leds_tpu21_device = {
+ .name = "leds-renesas-tpu",
+ .id = 21,
+ .dev = {
+ .platform_data = &led_renesas_tpu21_pdata,
+ },
+ .num_resources = ARRAY_SIZE(tpu21_resources),
+ .resource = tpu21_resources,
+};
+
+static struct led_renesas_tpu_config led_renesas_tpu30_pdata = {
+ .name = "KEYLED",
+ .pin_gpio_fn = GPIO_FN_TPU3TO0,
+ .pin_gpio = GPIO_PORT163,
+ .channel_offset = 0x10,
+ .timer_bit = 0,
+ .max_brightness = 1000,
+};
+
+static struct resource tpu30_resources[] = {
+ [0] = {
+ .name = "TPU30",
+ .start = 0xe6630010,
+ .end = 0xe6630035,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device leds_tpu30_device = {
+ .name = "leds-renesas-tpu",
+ .id = 30,
+ .dev = {
+ .platform_data = &led_renesas_tpu30_pdata,
+ },
+ .num_resources = ARRAY_SIZE(tpu30_resources),
+ .resource = tpu30_resources,
+};
+
+/* MMCIF */
+static struct resource mmcif_resources[] = {
+ [0] = {
+ .name = "MMCIF",
+ .start = 0xe6bd0000,
+ .end = 0xe6bd00ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(140),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = gic_spi(141),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct sh_mmcif_plat_data mmcif_info = {
+ .ocr = MMC_VDD_165_195,
+ .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+};
+
+static struct platform_device mmcif_device = {
+ .name = "sh_mmcif",
+ .id = 0,
+ .dev = {
+ .platform_data = &mmcif_info,
+ },
+ .num_resources = ARRAY_SIZE(mmcif_resources),
+ .resource = mmcif_resources,
+};
+
+/* SDHI0 */
+static struct sh_mobile_sdhi_info sdhi0_info = {
+ .tmio_caps = MMC_CAP_SD_HIGHSPEED,
+ .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
+};
+
+static struct resource sdhi0_resources[] = {
+ [0] = {
+ .name = "SDHI0",
+ .start = 0xee100000,
+ .end = 0xee1000ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(83),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = gic_spi(84),
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = gic_spi(85),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sdhi0_device = {
+ .name = "sh_mobile_sdhi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(sdhi0_resources),
+ .resource = sdhi0_resources,
+ .dev = {
+ .platform_data = &sdhi0_info,
+ },
+};
+
+/* SDHI1 */
+static struct sh_mobile_sdhi_info sdhi1_info = {
+ .tmio_caps = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ,
+ .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
+};
+
+static struct resource sdhi1_resources[] = {
+ [0] = {
+ .name = "SDHI1",
+ .start = 0xee120000,
+ .end = 0xee1200ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(87),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = gic_spi(88),
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = gic_spi(89),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sdhi1_device = {
+ .name = "sh_mobile_sdhi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(sdhi1_resources),
+ .resource = sdhi1_resources,
+ .dev = {
+ .platform_data = &sdhi1_info,
+ },
+};
+
+static struct platform_device *kota2_devices[] __initdata = {
+ &eth_device,
+ &keysc_device,
+ &gpio_keys_device,
+ &gpio_leds_device,
+ &leds_tpu12_device,
+ &leds_tpu41_device,
+ &leds_tpu21_device,
+ &leds_tpu30_device,
+ &mmcif_device,
+ &sdhi0_device,
+ &sdhi1_device,
+};
+
+static struct map_desc kota2_io_desc[] __initdata = {
+ /* create a 1:1 entity map for 0xe6xxxxxx
+ * used by CPGA, INTC and PFC.
+ */
+ {
+ .virtual = 0xe6000000,
+ .pfn = __phys_to_pfn(0xe6000000),
+ .length = 256 << 20,
+ .type = MT_DEVICE_NONSHARED
+ },
+};
+
+static void __init kota2_map_io(void)
+{
+ iotable_init(kota2_io_desc, ARRAY_SIZE(kota2_io_desc));
+
+ /* setup early devices and console here as well */
+ sh73a0_add_early_devices();
+ shmobile_setup_console();
+}
+
+static void __init kota2_init(void)
+{
+ sh73a0_pinmux_init();
+
+ /* SCIFA2 (UART2) */
+ gpio_request(GPIO_FN_SCIFA2_TXD1, NULL);
+ gpio_request(GPIO_FN_SCIFA2_RXD1, NULL);
+ gpio_request(GPIO_FN_SCIFA2_RTS1_, NULL);
+ gpio_request(GPIO_FN_SCIFA2_CTS1_, NULL);
+
+ /* SCIFA4 (UART1) */
+ gpio_request(GPIO_FN_SCIFA4_TXD, NULL);
+ gpio_request(GPIO_FN_SCIFA4_RXD, NULL);
+ gpio_request(GPIO_FN_SCIFA4_RTS_, NULL);
+ gpio_request(GPIO_FN_SCIFA4_CTS_, NULL);
+
+ /* SMSC911X */
+ gpio_request(GPIO_FN_D0_NAF0, NULL);
+ gpio_request(GPIO_FN_D1_NAF1, NULL);
+ gpio_request(GPIO_FN_D2_NAF2, NULL);
+ gpio_request(GPIO_FN_D3_NAF3, NULL);
+ gpio_request(GPIO_FN_D4_NAF4, NULL);
+ gpio_request(GPIO_FN_D5_NAF5, NULL);
+ gpio_request(GPIO_FN_D6_NAF6, NULL);
+ gpio_request(GPIO_FN_D7_NAF7, NULL);
+ gpio_request(GPIO_FN_D8_NAF8, NULL);
+ gpio_request(GPIO_FN_D9_NAF9, NULL);
+ gpio_request(GPIO_FN_D10_NAF10, NULL);
+ gpio_request(GPIO_FN_D11_NAF11, NULL);
+ gpio_request(GPIO_FN_D12_NAF12, NULL);
+ gpio_request(GPIO_FN_D13_NAF13, NULL);
+ gpio_request(GPIO_FN_D14_NAF14, NULL);
+ gpio_request(GPIO_FN_D15_NAF15, NULL);
+ gpio_request(GPIO_FN_CS5A_, NULL);
+ gpio_request(GPIO_FN_WE0__FWE, NULL);
+ gpio_request(GPIO_PORT144, NULL); /* PINTA2 */
+ gpio_direction_input(GPIO_PORT144);
+ gpio_request(GPIO_PORT145, NULL); /* RESET */
+ gpio_direction_output(GPIO_PORT145, 1);
+
+ /* KEYSC */
+ gpio_request(GPIO_FN_KEYIN0_PU, NULL);
+ gpio_request(GPIO_FN_KEYIN1_PU, NULL);
+ gpio_request(GPIO_FN_KEYIN2_PU, NULL);
+ gpio_request(GPIO_FN_KEYIN3_PU, NULL);
+ gpio_request(GPIO_FN_KEYIN4_PU, NULL);
+ gpio_request(GPIO_FN_KEYIN5_PU, NULL);
+ gpio_request(GPIO_FN_KEYIN6_PU, NULL);
+ gpio_request(GPIO_FN_KEYIN7_PU, NULL);
+ gpio_request(GPIO_FN_KEYOUT0, NULL);
+ gpio_request(GPIO_FN_KEYOUT1, NULL);
+ gpio_request(GPIO_FN_KEYOUT2, NULL);
+ gpio_request(GPIO_FN_KEYOUT3, NULL);
+ gpio_request(GPIO_FN_KEYOUT4, NULL);
+ gpio_request(GPIO_FN_KEYOUT5, NULL);
+ gpio_request(GPIO_FN_PORT59_KEYOUT6, NULL);
+ gpio_request(GPIO_FN_PORT58_KEYOUT7, NULL);
+ gpio_request(GPIO_FN_KEYOUT8, NULL);
+
+ /* MMCIF */
+ gpio_request(GPIO_FN_MMCCLK0, NULL);
+ gpio_request(GPIO_FN_MMCD0_0, NULL);
+ gpio_request(GPIO_FN_MMCD0_1, NULL);
+ gpio_request(GPIO_FN_MMCD0_2, NULL);
+ gpio_request(GPIO_FN_MMCD0_3, NULL);
+ gpio_request(GPIO_FN_MMCD0_4, NULL);
+ gpio_request(GPIO_FN_MMCD0_5, NULL);
+ gpio_request(GPIO_FN_MMCD0_6, NULL);
+ gpio_request(GPIO_FN_MMCD0_7, NULL);
+ gpio_request(GPIO_FN_MMCCMD0, NULL);
+ gpio_request(GPIO_PORT208, NULL); /* Reset */
+ gpio_direction_output(GPIO_PORT208, 1);
+
+ /* SDHI0 (microSD) */
+ gpio_request(GPIO_FN_SDHICD0_PU, NULL);
+ gpio_request(GPIO_FN_SDHICMD0_PU, NULL);
+ gpio_request(GPIO_FN_SDHICLK0, NULL);
+ gpio_request(GPIO_FN_SDHID0_3_PU, NULL);
+ gpio_request(GPIO_FN_SDHID0_2_PU, NULL);
+ gpio_request(GPIO_FN_SDHID0_1_PU, NULL);
+ gpio_request(GPIO_FN_SDHID0_0_PU, NULL);
+
+ /* SCIFB (BT) */
+ gpio_request(GPIO_FN_PORT159_SCIFB_SCK, NULL);
+ gpio_request(GPIO_FN_PORT160_SCIFB_TXD, NULL);
+ gpio_request(GPIO_FN_PORT161_SCIFB_CTS_, NULL);
+ gpio_request(GPIO_FN_PORT162_SCIFB_RXD, NULL);
+ gpio_request(GPIO_FN_PORT163_SCIFB_RTS_, NULL);
+
+ /* SDHI1 (BCM4330) */
+ gpio_request(GPIO_FN_SDHICLK1, NULL);
+ gpio_request(GPIO_FN_SDHICMD1_PU, NULL);
+ gpio_request(GPIO_FN_SDHID1_3_PU, NULL);
+ gpio_request(GPIO_FN_SDHID1_2_PU, NULL);
+ gpio_request(GPIO_FN_SDHID1_1_PU, NULL);
+ gpio_request(GPIO_FN_SDHID1_0_PU, NULL);
+
+#ifdef CONFIG_CACHE_L2X0
+ /* Early BRESP enable, Shared attribute override enable, 64K*8way */
+ l2x0_init(__io(0xf0100000), 0x40460000, 0x82000fff);
+#endif
+ sh73a0_add_standard_devices();
+ platform_add_devices(kota2_devices, ARRAY_SIZE(kota2_devices));
+}
+
+static void __init kota2_timer_init(void)
+{
+ sh73a0_clock_init();
+ shmobile_timer.init();
+ return;
+}
+
+struct sys_timer kota2_timer = {
+ .init = kota2_timer_init,
+};
+
+MACHINE_START(KOTA2, "kota2")
+ .map_io = kota2_map_io,
+ .nr_irqs = NR_IRQS_LEGACY,
+ .init_irq = sh73a0_init_irq,
+ .handle_irq = shmobile_handle_irq_gic,
+ .init_machine = kota2_init,
+ .timer = &kota2_timer,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/include/mach/intc.h b/arch/arm/mach-shmobile/include/mach/intc.h
new file mode 100644
index 0000000..8b22258
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/intc.h
@@ -0,0 +1,246 @@
+#ifndef __ASM_MACH_INTC_H
+#define __ASM_MACH_INTC_H
+#include <linux/sh_intc.h>
+
+#define INTC_IRQ_PINS_ENUM_16L(p) \
+ p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \
+ p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7, \
+ p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \
+ p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15
+
+#define INTC_IRQ_PINS_ENUM_16H(p) \
+ p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \
+ p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23, \
+ p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \
+ p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31
+
+#define INTC_IRQ_PINS_VECT_16L(p, vect) \
+ vect(p ## _IRQ0, 0x0200), vect(p ## _IRQ1, 0x0220), \
+ vect(p ## _IRQ2, 0x0240), vect(p ## _IRQ3, 0x0260), \
+ vect(p ## _IRQ4, 0x0280), vect(p ## _IRQ5, 0x02a0), \
+ vect(p ## _IRQ6, 0x02c0), vect(p ## _IRQ7, 0x02e0), \
+ vect(p ## _IRQ8, 0x0300), vect(p ## _IRQ9, 0x0320), \
+ vect(p ## _IRQ10, 0x0340), vect(p ## _IRQ11, 0x0360), \
+ vect(p ## _IRQ12, 0x0380), vect(p ## _IRQ13, 0x03a0), \
+ vect(p ## _IRQ14, 0x03c0), vect(p ## _IRQ15, 0x03e0)
+
+#define INTC_IRQ_PINS_VECT_16H(p, vect) \
+ vect(p ## _IRQ16, 0x3200), vect(p ## _IRQ17, 0x3220), \
+ vect(p ## _IRQ18, 0x3240), vect(p ## _IRQ19, 0x3260), \
+ vect(p ## _IRQ20, 0x3280), vect(p ## _IRQ21, 0x32a0), \
+ vect(p ## _IRQ22, 0x32c0), vect(p ## _IRQ23, 0x32e0), \
+ vect(p ## _IRQ24, 0x3300), vect(p ## _IRQ25, 0x3320), \
+ vect(p ## _IRQ26, 0x3340), vect(p ## _IRQ27, 0x3360), \
+ vect(p ## _IRQ28, 0x3380), vect(p ## _IRQ29, 0x33a0), \
+ vect(p ## _IRQ30, 0x33c0), vect(p ## _IRQ31, 0x33e0)
+
+#define INTC_IRQ_PINS_MASK_16L(p, base) \
+ { base + 0x40, base + 0x60, 8, /* INTMSK00A / INTMSKCLR00A */ \
+ { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \
+ p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } }, \
+ { base + 0x44, base + 0x64, 8, /* INTMSK10A / INTMSKCLR10A */ \
+ { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \
+ p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_MASK_16H(p, base) \
+ { base + 0x48, base + 0x68, 8, /* INTMSK20A / INTMSKCLR20A */ \
+ { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \
+ p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } }, \
+ { base + 0x4c, base + 0x6c, 8, /* INTMSK30A / INTMSKCLR30A */ \
+ { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \
+ p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_PRIO_16L(p, base) \
+ { base + 0x10, 0, 32, 4, /* INTPRI00A */ \
+ { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \
+ p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } }, \
+ { base + 0x14, 0, 32, 4, /* INTPRI10A */ \
+ { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \
+ p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_PRIO_16H(p, base) \
+ { base + 0x18, 0, 32, 4, /* INTPRI20A */ \
+ { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \
+ p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } }, \
+ { base + 0x1c, 0, 32, 4, /* INTPRI30A */ \
+ { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \
+ p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_SENSE_16L(p, base) \
+ { base + 0x00, 32, 4, /* ICR1A */ \
+ { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \
+ p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } }, \
+ { base + 0x04, 32, 4, /* ICR2A */ \
+ { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \
+ p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_SENSE_16H(p, base) \
+ { base + 0x08, 32, 4, /* ICR3A */ \
+ { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \
+ p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } }, \
+ { base + 0x0c, 32, 4, /* ICR4A */ \
+ { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \
+ p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_ACK_16L(p, base) \
+ { base + 0x20, 0, 8, /* INTREQ00A */ \
+ { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \
+ p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } }, \
+ { base + 0x24, 0, 8, /* INTREQ10A */ \
+ { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \
+ p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_ACK_16H(p, base) \
+ { base + 0x28, 0, 8, /* INTREQ20A */ \
+ { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \
+ p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } }, \
+ { base + 0x2c, 0, 8, /* INTREQ30A */ \
+ { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \
+ p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_16(p, base, vect, str) \
+ \
+static struct resource p ## _resources[] __initdata = { \
+ [0] = { \
+ .start = base, \
+ .end = base + 0x64, \
+ .flags = IORESOURCE_MEM, \
+ }, \
+}; \
+ \
+enum { \
+ p ## _UNUSED = 0, \
+ INTC_IRQ_PINS_ENUM_16L(p), \
+}; \
+ \
+static struct intc_vect p ## _vectors[] __initdata = { \
+ INTC_IRQ_PINS_VECT_16L(p, vect), \
+}; \
+ \
+static struct intc_mask_reg p ## _mask_registers[] __initdata = { \
+ INTC_IRQ_PINS_MASK_16L(p, base), \
+}; \
+ \
+static struct intc_prio_reg p ## _prio_registers[] __initdata = { \
+ INTC_IRQ_PINS_PRIO_16L(p, base), \
+}; \
+ \
+static struct intc_sense_reg p ## _sense_registers[] __initdata = { \
+ INTC_IRQ_PINS_SENSE_16L(p, base), \
+}; \
+ \
+static struct intc_mask_reg p ## _ack_registers[] __initdata = { \
+ INTC_IRQ_PINS_ACK_16L(p, base), \
+}; \
+ \
+static struct intc_desc p ## _desc __initdata = { \
+ .name = str, \
+ .resource = p ## _resources, \
+ .num_resources = ARRAY_SIZE(p ## _resources), \
+ .hw = INTC_HW_DESC(p ## _vectors, NULL, \
+ p ## _mask_registers, p ## _prio_registers, \
+ p ## _sense_registers, p ## _ack_registers) \
+}
+
+#define INTC_IRQ_PINS_32(p, base, vect, str) \
+ \
+static struct resource p ## _resources[] __initdata = { \
+ [0] = { \
+ .start = base, \
+ .end = base + 0x6c, \
+ .flags = IORESOURCE_MEM, \
+ }, \
+}; \
+ \
+enum { \
+ p ## _UNUSED = 0, \
+ INTC_IRQ_PINS_ENUM_16L(p), \
+ INTC_IRQ_PINS_ENUM_16H(p), \
+}; \
+ \
+static struct intc_vect p ## _vectors[] __initdata = { \
+ INTC_IRQ_PINS_VECT_16L(p, vect), \
+ INTC_IRQ_PINS_VECT_16H(p, vect), \
+}; \
+ \
+static struct intc_mask_reg p ## _mask_registers[] __initdata = { \
+ INTC_IRQ_PINS_MASK_16L(p, base), \
+ INTC_IRQ_PINS_MASK_16H(p, base), \
+}; \
+ \
+static struct intc_prio_reg p ## _prio_registers[] __initdata = { \
+ INTC_IRQ_PINS_PRIO_16L(p, base), \
+ INTC_IRQ_PINS_PRIO_16H(p, base), \
+}; \
+ \
+static struct intc_sense_reg p ## _sense_registers[] __initdata = { \
+ INTC_IRQ_PINS_SENSE_16L(p, base), \
+ INTC_IRQ_PINS_SENSE_16H(p, base), \
+}; \
+ \
+static struct intc_mask_reg p ## _ack_registers[] __initdata = { \
+ INTC_IRQ_PINS_ACK_16L(p, base), \
+ INTC_IRQ_PINS_ACK_16H(p, base), \
+}; \
+ \
+static struct intc_desc p ## _desc __initdata = { \
+ .name = str, \
+ .resource = p ## _resources, \
+ .num_resources = ARRAY_SIZE(p ## _resources), \
+ .hw = INTC_HW_DESC(p ## _vectors, NULL, \
+ p ## _mask_registers, p ## _prio_registers, \
+ p ## _sense_registers, p ## _ack_registers) \
+}
+
+#define INTC_PINT_E_EMPTY
+#define INTC_PINT_E_NONE 0, 0, 0, 0, 0, 0, 0, 0,
+#define INTC_PINT_E(p) \
+ PINT ## p ## 0, PINT ## p ## 1, PINT ## p ## 2, PINT ## p ## 3, \
+ PINT ## p ## 4, PINT ## p ## 5, PINT ## p ## 6, PINT ## p ## 7,
+
+#define INTC_PINT_V_NONE
+#define INTC_PINT_V(p, vect) \
+ vect(PINT ## p ## 0, 0), vect(PINT ## p ## 1, 1), \
+ vect(PINT ## p ## 2, 2), vect(PINT ## p ## 3, 3), \
+ vect(PINT ## p ## 4, 4), vect(PINT ## p ## 5, 5), \
+ vect(PINT ## p ## 6, 6), vect(PINT ## p ## 7, 7),
+
+#define INTC_PINT(p, mask_reg, sense_base, str, \
+ enums_1, enums_2, enums_3, enums_4, \
+ vect_1, vect_2, vect_3, vect_4, \
+ mask_a, mask_b, mask_c, mask_d, \
+ sense_a, sense_b, sense_c, sense_d) \
+ \
+enum { \
+ PINT ## p ## _UNUSED = 0, \
+ enums_1 enums_2 enums_3 enums_4 \
+}; \
+ \
+static struct intc_vect p ## _vectors[] __initdata = { \
+ vect_1 vect_2 vect_3 vect_4 \
+}; \
+ \
+static struct intc_mask_reg p ## _mask_registers[] __initdata = { \
+ { mask_reg, 0, 32, /* PINTER */ \
+ { mask_a mask_b mask_c mask_d } } \
+}; \
+ \
+static struct intc_sense_reg p ## _sense_registers[] __initdata = { \
+ { sense_base + 0x00, 16, 2, /* PINTCR */ \
+ { sense_a } }, \
+ { sense_base + 0x04, 16, 2, /* PINTCR */ \
+ { sense_b } }, \
+ { sense_base + 0x08, 16, 2, /* PINTCR */ \
+ { sense_c } }, \
+ { sense_base + 0x0c, 16, 2, /* PINTCR */ \
+ { sense_d } }, \
+}; \
+ \
+static struct intc_desc p ## _desc __initdata = { \
+ .name = str, \
+ .hw = INTC_HW_DESC(p ## _vectors, NULL, \
+ p ## _mask_registers, NULL, \
+ p ## _sense_registers, NULL), \
+}
+
+#endif /* __ASM_MACH_INTC_H */
diff --git a/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h b/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h
new file mode 100644
index 0000000..4a81b01
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h
@@ -0,0 +1,21 @@
+#ifndef SDHI_SH7372_H
+#define SDHI_SH7372_H
+
+#define SDGENCNTA 0xfe40009c
+
+/* The countdown of SDGENCNTA is controlled by
+ * ZB3D2CLK which runs at 149.5MHz.
+ * That is 149.5ticks/us. Approximate this as 150ticks/us.
+ */
+static void udelay(int us)
+{
+ __raw_writel(us * 150, SDGENCNTA);
+ while(__raw_readl(SDGENCNTA)) ;
+}
+
+static void msleep(int ms)
+{
+ udelay(ms * 1000);
+}
+
+#endif
diff --git a/arch/arm/mach-shmobile/include/mach/sdhi.h b/arch/arm/mach-shmobile/include/mach/sdhi.h
new file mode 100644
index 0000000..0ec9e69
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/sdhi.h
@@ -0,0 +1,16 @@
+#ifndef SDHI_H
+#define SDHI_H
+
+/**************************************************
+ *
+ * CPU specific settings
+ *
+ **************************************************/
+
+#ifdef CONFIG_ARCH_SH7372
+#include "mach/sdhi-sh7372.h"
+#else
+#error "unsupported CPU."
+#endif
+
+#endif /* SDHI_H */
diff --git a/arch/arm/mach-tegra/board-dt.c b/arch/arm/mach-tegra/board-dt.c
new file mode 100644
index 0000000..74743ad
--- /dev/null
+++ b/arch/arm/mach-tegra/board-dt.c
@@ -0,0 +1,136 @@
+/*
+ * nVidia Tegra device tree board support
+ *
+ * Copyright (C) 2010 Secret Lab Technologies, Ltd.
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/pda_power.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/i2c-tegra.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/setup.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+
+#include "board.h"
+#include "board-harmony.h"
+#include "clock.h"
+#include "devices.h"
+
+void harmony_pinmux_init(void);
+void seaboard_pinmux_init(void);
+void ventana_pinmux_init(void);
+
+struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
+ OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC3_BASE, "sdhci-tegra.2", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC4_BASE, "sdhci-tegra.3", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C_BASE, "tegra-i2c.0", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C2_BASE, "tegra-i2c.1", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C3_BASE, "tegra-i2c.2", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_DVC_BASE, "tegra-i2c.3", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.0", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.1", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL),
+ {}
+};
+
+static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
+ /* name parent rate enabled */
+ { "uartd", "pll_p", 216000000, true },
+ { NULL, NULL, 0, 0},
+};
+
+static struct of_device_id tegra_dt_match_table[] __initdata = {
+ { .compatible = "simple-bus", },
+ {}
+};
+
+static struct of_device_id tegra_dt_gic_match[] __initdata = {
+ { .compatible = "nvidia,tegra20-gic", },
+ {}
+};
+
+static struct {
+ char *machine;
+ void (*init)(void);
+} pinmux_configs[] = {
+ { "nvidia,harmony", harmony_pinmux_init },
+ { "nvidia,seaboard", seaboard_pinmux_init },
+ { "nvidia,ventana", ventana_pinmux_init },
+};
+
+static void __init tegra_dt_init(void)
+{
+ struct device_node *node;
+ int i;
+
+ node = of_find_matching_node_by_address(NULL, tegra_dt_gic_match,
+ TEGRA_ARM_INT_DIST_BASE);
+ if (node)
+ irq_domain_add_simple(node, INT_GIC_BASE);
+
+ tegra_clk_init_from_table(tegra_dt_clk_init_table);
+
+ /*
+ * Finished with the static registrations now; fill in the missing
+ * devices
+ */
+ of_platform_populate(NULL, tegra_dt_match_table,
+ tegra20_auxdata_lookup, NULL);
+
+ for (i = 0; i < ARRAY_SIZE(pinmux_configs); i++) {
+ if (of_machine_is_compatible(pinmux_configs[i].machine)) {
+ pinmux_configs[i].init();
+ break;
+ }
+ }
+
+ WARN(i == ARRAY_SIZE(pinmux_configs),
+ "Unknown platform! Pinmuxing not initialized\n");
+}
+
+static const char * tegra_dt_board_compat[] = {
+ "nvidia,harmony",
+ "nvidia,seaboard",
+ "nvidia,ventana",
+ NULL
+};
+
+DT_MACHINE_START(TEGRA_DT, "nVidia Tegra (Flattened Device Tree)")
+ .map_io = tegra_map_common_io,
+ .init_early = tegra_init_early,
+ .init_irq = tegra_init_irq,
+ .timer = &tegra_timer,
+ .init_machine = tegra_dt_init,
+ .dt_compat = tegra_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-tegra/include/mach/gpio-tegra.h b/arch/arm/mach-tegra/include/mach/gpio-tegra.h
new file mode 100644
index 0000000..87d37fd
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/gpio-tegra.h
@@ -0,0 +1,39 @@
+/*
+ * arch/arm/mach-tegra/include/mach/gpio.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ * Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_TEGRA_GPIO_TEGRA_H
+#define __MACH_TEGRA_GPIO_TEGRA_H
+
+#include <linux/types.h>
+#include <mach/irqs.h>
+
+#define TEGRA_NR_GPIOS INT_GPIO_NR
+
+#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
+
+struct tegra_gpio_table {
+ int gpio; /* GPIO number */
+ bool enable; /* Enable for GPIO at init? */
+};
+
+void tegra_gpio_config(struct tegra_gpio_table *table, int num);
+void tegra_gpio_enable(int gpio);
+void tegra_gpio_disable(int gpio);
+
+#endif
diff --git a/arch/arm/mach-u300/include/mach/gpio-u300.h b/arch/arm/mach-u300/include/mach/gpio-u300.h
new file mode 100644
index 0000000..0c2b202
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/gpio-u300.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2007-2011 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * GPIO block resgister definitions and inline macros for
+ * U300 GPIO COH 901 335 or COH 901 571/3
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#ifndef __MACH_U300_GPIO_U300_H
+#define __MACH_U300_GPIO_U300_H
+
+/*
+ * Individual pin assignments for the B26/S26. Notice that the
+ * actual usage of these pins depends on the PAD MUX settings, that
+ * is why the same number can potentially appear several times.
+ * In the reference design each pin is only used for one purpose.
+ * These were determined by inspecting the B26/S26 schematic:
+ * 2/1911-ROA 128 1603
+ */
+#ifdef CONFIG_MACH_U300_BS2X
+#define U300_GPIO_PIN_UART_RX 0
+#define U300_GPIO_PIN_UART_TX 1
+#define U300_GPIO_PIN_GPIO02 2 /* Unrouted */
+#define U300_GPIO_PIN_GPIO03 3 /* Unrouted */
+#define U300_GPIO_PIN_CAM_SLEEP 4
+#define U300_GPIO_PIN_CAM_REG_EN 5
+#define U300_GPIO_PIN_GPIO06 6 /* Unrouted */
+#define U300_GPIO_PIN_GPIO07 7 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO08 8 /* Service point SP2321 */
+#define U300_GPIO_PIN_GPIO09 9 /* Service point SP2322 */
+#define U300_GPIO_PIN_PHFSENSE 10 /* Headphone jack sensing */
+#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */
+#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */
+#define U300_GPIO_PIN_FLIPSENSE 13 /* Mechanical flip sensing */
+#define U300_GPIO_PIN_GPIO14 14 /* DSP JTAG Port RTCK */
+#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO16 16 /* Unrouted */
+#define U300_GPIO_PIN_GPIO17 17 /* Unrouted */
+#define U300_GPIO_PIN_GPIO18 18 /* Unrouted */
+#define U300_GPIO_PIN_GPIO19 19 /* Unrouted */
+#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */
+#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */
+#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */
+#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */
+#endif
+
+/*
+ * Individual pin assignments for the B330/S330 and B365/S365.
+ * Notice that the actual usage of these pins depends on the
+ * PAD MUX settings, that is why the same number can potentially
+ * appear several times. In the reference design each pin is only
+ * used for one purpose. These were determined by inspecting the
+ * S365 schematic.
+ */
+#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \
+ defined(CONFIG_MACH_U300_BS335)
+#define U300_GPIO_PIN_UART_RX 0
+#define U300_GPIO_PIN_UART_TX 1
+#define U300_GPIO_PIN_UART_CTS 2
+#define U300_GPIO_PIN_UART_RTS 3
+#define U300_GPIO_PIN_CAM_MAIN_STANDBY 4 /* Camera MAIN standby */
+#define U300_GPIO_PIN_GPIO05 5 /* Unrouted */
+#define U300_GPIO_PIN_MS_CD 6 /* Memory Stick Card insertion */
+#define U300_GPIO_PIN_GPIO07 7 /* Test point TP2430 */
+
+#define U300_GPIO_PIN_GPIO08 8 /* Test point TP2437 */
+#define U300_GPIO_PIN_GPIO09 9 /* Test point TP2431 */
+#define U300_GPIO_PIN_GPIO10 10 /* Test point TP2432 */
+#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */
+#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */
+#define U300_GPIO_PIN_CAM_SUB_STANDBY 13 /* Camera SUB standby */
+#define U300_GPIO_PIN_GPIO14 14 /* Test point TP2436 */
+#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO16 16 /* Test point TP2438 */
+#define U300_GPIO_PIN_PHFSENSE 17 /* Headphone jack sensing */
+#define U300_GPIO_PIN_GPIO18 18 /* Test point TP2439 */
+#define U300_GPIO_PIN_GPIO19 19 /* Routed somewhere */
+#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */
+#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */
+#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */
+#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO24 24 /* Unrouted */
+#define U300_GPIO_PIN_GPIO25 25 /* Unrouted */
+#define U300_GPIO_PIN_GPIO26 26 /* Unrouted */
+#define U300_GPIO_PIN_GPIO27 27 /* Unrouted */
+#define U300_GPIO_PIN_GPIO28 28 /* Unrouted */
+#define U300_GPIO_PIN_GPIO29 29 /* Unrouted */
+#define U300_GPIO_PIN_GPIO30 30 /* Unrouted */
+#define U300_GPIO_PIN_GPIO31 31 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO32 32 /* Unrouted */
+#define U300_GPIO_PIN_GPIO33 33 /* Unrouted */
+#define U300_GPIO_PIN_GPIO34 34 /* Unrouted */
+#define U300_GPIO_PIN_GPIO35 35 /* Unrouted */
+#define U300_GPIO_PIN_GPIO36 36 /* Unrouted */
+#define U300_GPIO_PIN_GPIO37 37 /* Unrouted */
+#define U300_GPIO_PIN_GPIO38 38 /* Unrouted */
+#define U300_GPIO_PIN_GPIO39 39 /* Unrouted */
+
+#ifdef CONFIG_MACH_U300_BS335
+
+#define U300_GPIO_PIN_GPIO40 40 /* Unrouted */
+#define U300_GPIO_PIN_GPIO41 41 /* Unrouted */
+#define U300_GPIO_PIN_GPIO42 42 /* Unrouted */
+#define U300_GPIO_PIN_GPIO43 43 /* Unrouted */
+#define U300_GPIO_PIN_GPIO44 44 /* Unrouted */
+#define U300_GPIO_PIN_GPIO45 45 /* Unrouted */
+#define U300_GPIO_PIN_GPIO46 46 /* Unrouted */
+#define U300_GPIO_PIN_GPIO47 47 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO48 48 /* Unrouted */
+#define U300_GPIO_PIN_GPIO49 49 /* Unrouted */
+#define U300_GPIO_PIN_GPIO50 50 /* Unrouted */
+#define U300_GPIO_PIN_GPIO51 51 /* Unrouted */
+#define U300_GPIO_PIN_GPIO52 52 /* Unrouted */
+#define U300_GPIO_PIN_GPIO53 53 /* Unrouted */
+#define U300_GPIO_PIN_GPIO54 54 /* Unrouted */
+#define U300_GPIO_PIN_GPIO55 55 /* Unrouted */
+#endif
+
+#endif
+
+/**
+ * enum u300_gpio_variant - the type of U300 GPIO employed
+ */
+enum u300_gpio_variant {
+ U300_GPIO_COH901335,
+ U300_GPIO_COH901571_3_BS335,
+ U300_GPIO_COH901571_3_BS365,
+};
+
+/**
+ * struct u300_gpio_platform - U300 GPIO platform data
+ * @variant: IP block variant
+ * @ports: number of GPIO block ports
+ * @gpio_base: first GPIO number for this block (use a free range)
+ * @gpio_irq_base: first GPIO IRQ number for this block (use a free range)
+ */
+struct u300_gpio_platform {
+ enum u300_gpio_variant variant;
+ u8 ports;
+ int gpio_base;
+ int gpio_irq_base;
+};
+
+#endif /* __MACH_U300_GPIO_U300_H */
diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c
new file mode 100644
index 0000000..122ddde
--- /dev/null
+++ b/arch/arm/mach-ux500/cache-l2x0.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/hardware.h>
+#include <mach/id.h>
+
+static void __iomem *l2x0_base;
+
+static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
+{
+ /* wait for the operation to complete */
+ while (readl_relaxed(reg) & mask)
+ cpu_relax();
+}
+
+static inline void ux500_cache_sync(void)
+{
+ writel_relaxed(0, l2x0_base + L2X0_CACHE_SYNC);
+ ux500_cache_wait(l2x0_base + L2X0_CACHE_SYNC, 1);
+}
+
+/*
+ * The L2 cache cannot be turned off in the non-secure world.
+ * Dummy until a secure service is in place.
+ */
+static void ux500_l2x0_disable(void)
+{
+}
+
+/*
+ * This is only called when doing a kexec, just after turning off the L2
+ * and L1 cache, and it is surrounded by a spinlock in the generic version.
+ * However, we're not really turning off the L2 cache right now and the
+ * PL310 does not support exclusive accesses (used to implement the spinlock).
+ * So, the invalidation needs to be done without the spinlock.
+ */
+static void ux500_l2x0_inv_all(void)
+{
+ uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */
+
+ /* invalidate all ways */
+ writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
+ ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
+ ux500_cache_sync();
+}
+
+static int __init ux500_l2x0_unlock(void)
+{
+ int i;
+
+ /*
+ * Unlock Data and Instruction Lock if locked. Ux500 U-Boot versions
+ * apparently locks both caches before jumping to the kernel. The
+ * l2x0 core will not touch the unlock registers if the l2x0 is
+ * already enabled, so we do it right here instead. The PL310 has
+ * 8 sets of registers, one per possible CPU.
+ */
+ for (i = 0; i < 8; i++) {
+ writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
+ i * L2X0_LOCKDOWN_STRIDE);
+ writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
+ i * L2X0_LOCKDOWN_STRIDE);
+ }
+ return 0;
+}
+
+static int __init ux500_l2x0_init(void)
+{
+ if (cpu_is_u5500())
+ l2x0_base = __io_address(U5500_L2CC_BASE);
+ else if (cpu_is_u8500())
+ l2x0_base = __io_address(U8500_L2CC_BASE);
+ else
+ ux500_unknown_soc();
+
+ /* Unlock before init */
+ ux500_l2x0_unlock();
+
+ /* 64KB way size, 8 way associativity, force WA */
+ l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
+
+ /* Override invalidate function */
+ outer_cache.disable = ux500_l2x0_disable;
+ outer_cache.inv_all = ux500_l2x0_inv_all;
+
+ return 0;
+}
+
+early_initcall(ux500_l2x0_init);
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
new file mode 100644
index 0000000..aea467d
--- /dev/null
+++ b/arch/arm/mach-ux500/timer.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson
+ */
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/clksrc-dbx500-prcmu.h>
+
+#include <asm/localtimer.h>
+
+#include <plat/mtu.h>
+
+#include <mach/setup.h>
+#include <mach/hardware.h>
+
+static void __init ux500_timer_init(void)
+{
+ void __iomem *prcmu_timer_base;
+
+ if (cpu_is_u5500()) {
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = __io_address(U5500_TWD_BASE);
+#endif
+ mtu_base = __io_address(U5500_MTU0_BASE);
+ prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE);
+ } else if (cpu_is_u8500()) {
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = __io_address(U8500_TWD_BASE);
+#endif
+ mtu_base = __io_address(U8500_MTU0_BASE);
+ prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
+ } else {
+ ux500_unknown_soc();
+ }
+
+ /*
+ * Here we register the timerblocks active in the system.
+ * Localtimers (twd) is started when both cpu is up and running.
+ * MTU register a clocksource, clockevent and sched_clock.
+ * Since the MTU is located in the VAPE power domain
+ * it will be cleared in sleep which makes it unsuitable.
+ * We however need it as a timer tick (clockevent)
+ * during boot to calibrate delay until twd is started.
+ * RTC-RTT have problems as timer tick during boot since it is
+ * depending on delay which is not yet calibrated. RTC-RTT is in the
+ * always-on powerdomain and is used as clockevent instead of twd when
+ * sleeping.
+ * The PRCMU timer 4(3 for DB5500) register a clocksource and
+ * sched_clock with higher rating then MTU since is always-on.
+ *
+ */
+
+ nmdk_timer_init();
+ clksrc_dbx500_prcmu_init(prcmu_timer_base);
+}
+
+static void ux500_timer_reset(void)
+{
+ nmdk_clkevt_reset();
+ nmdk_clksrc_reset();
+}
+
+struct sys_timer ux500_timer = {
+ .init = ux500_timer_init,
+ .resume = ux500_timer_reset,
+};
diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c
new file mode 100644
index 0000000..54e037c
--- /dev/null
+++ b/arch/arm/mach-versatile/versatile_dt.c
@@ -0,0 +1,51 @@
+/*
+ * Versatile board support using the device tree
+ *
+ * Copyright (C) 2010 Secret Lab Technologies Ltd.
+ * Copyright (C) 2009 Jeremy Kerr <jeremy.kerr@canonical.com>
+ * Copyright (C) 2004 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "core.h"
+
+static void __init versatile_dt_init(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table,
+ versatile_auxdata_lookup, NULL);
+}
+
+static const char *versatile_dt_match[] __initconst = {
+ "arm,versatile-ab",
+ "arm,versatile-pb",
+ NULL,
+};
+
+DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)")
+ .map_io = versatile_map_io,
+ .init_early = versatile_init_early,
+ .init_irq = versatile_init_irq,
+ .timer = &versatile_timer,
+ .init_machine = versatile_dt_init,
+ .dt_compat = versatile_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-vexpress/include/mach/gpio.h b/arch/arm/mach-vexpress/include/mach/gpio.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/arch/arm/mach-vexpress/include/mach/gpio.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
new file mode 100644
index 0000000..397268c
--- /dev/null
+++ b/arch/arm/mach-zynq/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support
+obj-y := common.o timer.o
diff --git a/arch/arm/mach-zynq/Makefile.boot b/arch/arm/mach-zynq/Makefile.boot
new file mode 100644
index 0000000..760a0ef
--- /dev/null
+++ b/arch/arm/mach-zynq/Makefile.boot
@@ -0,0 +1,3 @@
+ zreladdr-y += 0x00008000
+params_phys-y := 0x00000100
+initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
new file mode 100644
index 0000000..73e9368
--- /dev/null
+++ b/arch/arm/mach-zynq/common.c
@@ -0,0 +1,118 @@
+/*
+ * This file contains common code that is intended to be used across
+ * boards so that it's not replicated.
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/cpumask.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <mach/zynq_soc.h>
+#include <mach/clkdev.h>
+#include "common.h"
+
+static struct of_device_id zynq_of_bus_ids[] __initdata = {
+ { .compatible = "simple-bus", },
+ {}
+};
+
+/**
+ * xilinx_init_machine() - System specific initialization, intended to be
+ * called from board specific initialization.
+ */
+static void __init xilinx_init_machine(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * 64KB way size, 8-way associativity, parity disabled
+ */
+ l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF);
+#endif
+
+ of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
+}
+
+/**
+ * xilinx_irq_init() - Interrupt controller initialization for the GIC.
+ */
+static void __init xilinx_irq_init(void)
+{
+ gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE);
+}
+
+/* The minimum devices needed to be mapped before the VM system is up and
+ * running include the GIC, UART and Timer Counter.
+ */
+
+static struct map_desc io_desc[] __initdata = {
+ {
+ .virtual = TTC0_VIRT,
+ .pfn = __phys_to_pfn(TTC0_PHYS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = SCU_PERIPH_VIRT,
+ .pfn = __phys_to_pfn(SCU_PERIPH_PHYS),
+ .length = SZ_8K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = PL310_L2CC_VIRT,
+ .pfn = __phys_to_pfn(PL310_L2CC_PHYS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+
+#ifdef CONFIG_DEBUG_LL
+ {
+ .virtual = UART0_VIRT,
+ .pfn = __phys_to_pfn(UART0_PHYS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+#endif
+
+};
+
+/**
+ * xilinx_map_io() - Create memory mappings needed for early I/O.
+ */
+static void __init xilinx_map_io(void)
+{
+ iotable_init(io_desc, ARRAY_SIZE(io_desc));
+}
+
+static const char *xilinx_dt_match[] = {
+ "xlnx,zynq-ep107",
+ NULL
+};
+
+MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
+ .map_io = xilinx_map_io,
+ .init_irq = xilinx_irq_init,
+ .init_machine = xilinx_init_machine,
+ .timer = &xttcpss_sys_timer,
+ .dt_compat = xilinx_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
new file mode 100644
index 0000000..a009644
--- /dev/null
+++ b/arch/arm/mach-zynq/common.h
@@ -0,0 +1,24 @@
+/*
+ * This file contains common function prototypes to avoid externs
+ * in the c files.
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_ZYNQ_COMMON_H__
+#define __MACH_ZYNQ_COMMON_H__
+
+#include <asm/mach/time.h>
+
+extern struct sys_timer xttcpss_sys_timer;
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/clkdev.h b/arch/arm/mach-zynq/include/mach/clkdev.h
new file mode 100644
index 0000000..c6e73d8
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/clkdev.h
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-zynq/include/mach/clkdev.h
+ *
+ * Copyright (C) 2011 Xilinx, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#include <plat/clock.h>
+
+struct clk {
+ unsigned long rate;
+ const struct clk_ops *ops;
+ const struct icst_params *params;
+ void __iomem *vcoreg;
+};
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/debug-macro.S b/arch/arm/mach-zynq/include/mach/debug-macro.S
new file mode 100644
index 0000000..3ab0be1
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/debug-macro.S
@@ -0,0 +1,36 @@
+/* arch/arm/mach-zynq/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <mach/zynq_soc.h>
+#include <mach/uart.h>
+
+ .macro addruart, rp, rv, tmp
+ ldr \rp, =LL_UART_PADDR @ physical
+ ldr \rv, =LL_UART_VADDR @ virtual
+ .endm
+
+ .macro senduart,rd,rx
+ str \rd, [\rx, #UART_FIFO_OFFSET] @ TXDATA
+ .endm
+
+ .macro waituart,rd,rx
+ .endm
+
+ .macro busyuart,rd,rx
+1002: ldr \rd, [\rx, #UART_SR_OFFSET] @ get status register
+ tst \rd, #UART_SR_TXFULL @
+ bne 1002b @ wait if FIFO is full
+ .endm
diff --git a/arch/arm/mach-zynq/include/mach/entry-macro.S b/arch/arm/mach-zynq/include/mach/entry-macro.S
new file mode 100644
index 0000000..3cfc01b
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/entry-macro.S
@@ -0,0 +1,30 @@
+/*
+ * arch/arm/mach-zynq/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * based on arch/plat-mxc/include/mach/entry-macro.S
+ *
+ * Copyright (C) 2007 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <mach/hardware.h>
+#include <asm/hardware/entry-macro-gic.S>
+
+ .macro disable_fiq
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
diff --git a/arch/arm/mach-zynq/include/mach/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h
new file mode 100644
index 0000000..d558d8a
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/hardware.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-zynq/include/mach/hardware.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_HARDWARE_H__
+#define __MACH_HARDWARE_H__
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/io.h b/arch/arm/mach-zynq/include/mach/io.h
new file mode 100644
index 0000000..39d9885
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/io.h
@@ -0,0 +1,33 @@
+/* arch/arm/mach-zynq/include/mach/io.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_IO_H__
+#define __MACH_IO_H__
+
+/* Allow IO space to be anywhere in the memory */
+
+#define IO_SPACE_LIMIT 0xffff
+
+/* IO address mapping macros, nothing special at this time but required */
+
+#ifdef __ASSEMBLER__
+#define IOMEM(x) (x)
+#else
+#define IOMEM(x) ((void __force __iomem *)(x))
+#endif
+
+#define __io(a) __typesafe_io(a)
+#define __mem_pci(a) (a)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/irqs.h b/arch/arm/mach-zynq/include/mach/irqs.h
new file mode 100644
index 0000000..5fb04fd
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/irqs.h
@@ -0,0 +1,21 @@
+/* arch/arm/mach-zynq/include/mach/irqs.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define ARCH_NR_GPIOS 118
+#define NR_IRQS (128 + ARCH_NR_GPIOS)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/system.h b/arch/arm/mach-zynq/include/mach/system.h
new file mode 100644
index 0000000..1b84d70
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/system.h
@@ -0,0 +1,28 @@
+/* arch/arm/mach-zynq/include/mach/system.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_SYSTEM_H__
+#define __MACH_SYSTEM_H__
+
+static inline void arch_idle(void)
+{
+ cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+ /* Add architecture specific reset processing here */
+}
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/timex.h b/arch/arm/mach-zynq/include/mach/timex.h
new file mode 100644
index 0000000..6c0245e
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/timex.h
@@ -0,0 +1,23 @@
+/* arch/arm/mach-zynq/include/mach/timex.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_TIMEX_H__
+#define __MACH_TIMEX_H__
+
+/* the following is needed for the system to build but will be removed
+ in the future, the value is not important but won't hurt
+*/
+#define CLOCK_TICK_RATE (100 * HZ)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/uart.h b/arch/arm/mach-zynq/include/mach/uart.h
new file mode 100644
index 0000000..5c47c97
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/uart.h
@@ -0,0 +1,25 @@
+/* arch/arm/mach-zynq/include/mach/uart.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_UART_H__
+#define __MACH_UART_H__
+
+#define UART_CR_OFFSET 0x00 /* Control Register [8:0] */
+#define UART_SR_OFFSET 0x2C /* Channel Status [11:0] */
+#define UART_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */
+
+#define UART_SR_TXFULL 0x00000010 /* TX FIFO full */
+#define UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/uncompress.h b/arch/arm/mach-zynq/include/mach/uncompress.h
new file mode 100644
index 0000000..af4e844
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/uncompress.h
@@ -0,0 +1,51 @@
+/* arch/arm/mach-zynq/include/mach/uncompress.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_UNCOMPRESS_H__
+#define __MACH_UNCOMPRESS_H__
+
+#include <linux/io.h>
+#include <asm/processor.h>
+#include <mach/zynq_soc.h>
+#include <mach/uart.h>
+
+void arch_decomp_setup(void)
+{
+}
+
+static inline void flush(void)
+{
+ /*
+ * Wait while the FIFO is not empty
+ */
+ while (!(__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
+ UART_SR_TXEMPTY))
+ cpu_relax();
+}
+
+#define arch_decomp_wdog()
+
+static void putc(char ch)
+{
+ /*
+ * Wait for room in the FIFO, then write the char into the FIFO
+ */
+ while (__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
+ UART_SR_TXFULL)
+ cpu_relax();
+
+ __raw_writel(ch, IOMEM(LL_UART_PADDR + UART_FIFO_OFFSET));
+}
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/vmalloc.h b/arch/arm/mach-zynq/include/mach/vmalloc.h
new file mode 100644
index 0000000..2398eff
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/* arch/arm/mach-zynq/include/mach/vmalloc.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_VMALLOC_H__
+#define __MACH_VMALLOC_H__
+
+#define VMALLOC_END 0xE0000000UL
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/zynq_soc.h b/arch/arm/mach-zynq/include/mach/zynq_soc.h
new file mode 100644
index 0000000..d0d3f8f
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/zynq_soc.h
@@ -0,0 +1,48 @@
+/* arch/arm/mach-zynq/include/mach/zynq_soc.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_XILINX_SOC_H__
+#define __MACH_XILINX_SOC_H__
+
+#define PERIPHERAL_CLOCK_RATE 2500000
+
+/* For now, all mappings are flat (physical = virtual)
+ */
+#define UART0_PHYS 0xE0000000
+#define UART0_VIRT UART0_PHYS
+
+#define TTC0_PHYS 0xF8001000
+#define TTC0_VIRT TTC0_PHYS
+
+#define PL310_L2CC_PHYS 0xF8F02000
+#define PL310_L2CC_VIRT PL310_L2CC_PHYS
+
+#define SCU_PERIPH_PHYS 0xF8F00000
+#define SCU_PERIPH_VIRT SCU_PERIPH_PHYS
+
+/* The following are intended for the devices that are mapped early */
+
+#define TTC0_BASE IOMEM(TTC0_VIRT)
+#define SCU_PERIPH_BASE IOMEM(SCU_PERIPH_VIRT)
+#define SCU_GIC_CPU_BASE (SCU_PERIPH_BASE + 0x100)
+#define SCU_GIC_DIST_BASE (SCU_PERIPH_BASE + 0x1000)
+#define PL310_L2CC_BASE IOMEM(PL310_L2CC_VIRT)
+
+/*
+ * Mandatory for CONFIG_LL_DEBUG, UART is mapped virtual = physical
+ */
+#define LL_UART_PADDR UART0_PHYS
+#define LL_UART_VADDR UART0_VIRT
+
+#endif
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
new file mode 100644
index 0000000..c2c96cc
--- /dev/null
+++ b/arch/arm/mach-zynq/timer.c
@@ -0,0 +1,298 @@
+/*
+ * This file contains driver for the Xilinx PS Timer Counter IP.
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * based on arch/mips/kernel/time.c timer driver
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+
+#include <asm/mach/time.h>
+#include <mach/zynq_soc.h>
+#include "common.h"
+
+#define IRQ_TIMERCOUNTER0 42
+
+/*
+ * This driver configures the 2 16-bit count-up timers as follows:
+ *
+ * T1: Timer 1, clocksource for generic timekeeping
+ * T2: Timer 2, clockevent source for hrtimers
+ * T3: Timer 3, <unused>
+ *
+ * The input frequency to the timer module for emulation is 2.5MHz which is
+ * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
+ * the timers are clocked at 78.125KHz (12.8 us resolution).
+ *
+ * The input frequency to the timer module in silicon will be 200MHz. With the
+ * pre-scaler of 32, the timers are clocked at 6.25MHz (160ns resolution).
+ */
+#define XTTCPSS_CLOCKSOURCE 0 /* Timer 1 as a generic timekeeping */
+#define XTTCPSS_CLOCKEVENT 1 /* Timer 2 as a clock event */
+
+#define XTTCPSS_TIMER_BASE TTC0_BASE
+#define XTTCPCC_EVENT_TIMER_IRQ (IRQ_TIMERCOUNTER0 + 1)
+/*
+ * Timer Register Offset Definitions of Timer 1, Increment base address by 4
+ * and use same offsets for Timer 2
+ */
+#define XTTCPSS_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */
+#define XTTCPSS_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */
+#define XTTCPSS_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */
+#define XTTCPSS_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */
+#define XTTCPSS_MATCH_1_OFFSET 0x30 /* Match 1 Value Reg, RW */
+#define XTTCPSS_MATCH_2_OFFSET 0x3C /* Match 2 Value Reg, RW */
+#define XTTCPSS_MATCH_3_OFFSET 0x48 /* Match 3 Value Reg, RW */
+#define XTTCPSS_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */
+#define XTTCPSS_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */
+
+#define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1
+
+/* Setup the timers to use pre-scaling */
+
+#define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32)
+
+/**
+ * struct xttcpss_timer - This definition defines local timer structure
+ *
+ * @base_addr: Base address of timer
+ **/
+struct xttcpss_timer {
+ void __iomem *base_addr;
+};
+
+static struct xttcpss_timer timers[2];
+static struct clock_event_device xttcpss_clockevent;
+
+/**
+ * xttcpss_set_interval - Set the timer interval value
+ *
+ * @timer: Pointer to the timer instance
+ * @cycles: Timer interval ticks
+ **/
+static void xttcpss_set_interval(struct xttcpss_timer *timer,
+ unsigned long cycles)
+{
+ u32 ctrl_reg;
+
+ /* Disable the counter, set the counter value and re-enable counter */
+ ctrl_reg = __raw_readl(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+ ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+ __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+
+ __raw_writel(cycles, timer->base_addr + XTTCPSS_INTR_VAL_OFFSET);
+
+ /* Reset the counter (0x10) so that it starts from 0, one-shot
+ mode makes this needed for timing to be right. */
+ ctrl_reg |= 0x10;
+ ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+ __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+}
+
+/**
+ * xttcpss_clock_event_interrupt - Clock event timer interrupt handler
+ *
+ * @irq: IRQ number of the Timer
+ * @dev_id: void pointer to the xttcpss_timer instance
+ *
+ * returns: Always IRQ_HANDLED - success
+ **/
+static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &xttcpss_clockevent;
+ struct xttcpss_timer *timer = dev_id;
+
+ /* Acknowledge the interrupt and call event handler */
+ __raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
+ timer->base_addr + XTTCPSS_ISR_OFFSET);
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction event_timer_irq = {
+ .name = "xttcpss clockevent",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = xttcpss_clock_event_interrupt,
+};
+
+/**
+ * xttcpss_timer_hardware_init - Initialize the timer hardware
+ *
+ * Initialize the hardware to start the clock source, get the clock
+ * event timer ready to use, and hook up the interrupt.
+ **/
+static void __init xttcpss_timer_hardware_init(void)
+{
+ /* Setup the clock source counter to be an incrementing counter
+ * with no interrupt and it rolls over at 0xFFFF. Pre-scale
+ it by 32 also. Let it start running now.
+ */
+ timers[XTTCPSS_CLOCKSOURCE].base_addr = XTTCPSS_TIMER_BASE;
+
+ __raw_writel(0x0, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+ XTTCPSS_IER_OFFSET);
+ __raw_writel(0x9, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+ XTTCPSS_CLK_CNTRL_OFFSET);
+ __raw_writel(0x10, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+ XTTCPSS_CNT_CNTRL_OFFSET);
+
+ /* Setup the clock event timer to be an interval timer which
+ * is prescaled by 32 using the interval interrupt. Leave it
+ * disabled for now.
+ */
+
+ timers[XTTCPSS_CLOCKEVENT].base_addr = XTTCPSS_TIMER_BASE + 4;
+
+ __raw_writel(0x23, timers[XTTCPSS_CLOCKEVENT].base_addr +
+ XTTCPSS_CNT_CNTRL_OFFSET);
+ __raw_writel(0x9, timers[XTTCPSS_CLOCKEVENT].base_addr +
+ XTTCPSS_CLK_CNTRL_OFFSET);
+ __raw_writel(0x1, timers[XTTCPSS_CLOCKEVENT].base_addr +
+ XTTCPSS_IER_OFFSET);
+
+ /* Setup IRQ the clock event timer */
+ event_timer_irq.dev_id = &timers[XTTCPSS_CLOCKEVENT];
+ setup_irq(XTTCPCC_EVENT_TIMER_IRQ, &event_timer_irq);
+}
+
+/**
+ * __raw_readl_cycles - Reads the timer counter register
+ *
+ * returns: Current timer counter register value
+ **/
+static cycle_t __raw_readl_cycles(struct clocksource *cs)
+{
+ struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
+
+ return (cycle_t)__raw_readl(timer->base_addr +
+ XTTCPSS_COUNT_VAL_OFFSET);
+}
+
+
+/*
+ * Instantiate and initialize the clock source structure
+ */
+static struct clocksource clocksource_xttcpss = {
+ .name = "xttcpss_timer1",
+ .rating = 200, /* Reasonable clock source */
+ .read = __raw_readl_cycles,
+ .mask = CLOCKSOURCE_MASK(16),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+
+/**
+ * xttcpss_set_next_event - Sets the time interval for next event
+ *
+ * @cycles: Timer interval ticks
+ * @evt: Address of clock event instance
+ *
+ * returns: Always 0 - success
+ **/
+static int xttcpss_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+
+ xttcpss_set_interval(timer, cycles);
+ return 0;
+}
+
+/**
+ * xttcpss_set_mode - Sets the mode of timer
+ *
+ * @mode: Mode to be set
+ * @evt: Address of clock event instance
+ **/
+static void xttcpss_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+ u32 ctrl_reg;
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ xttcpss_set_interval(timer, TIMER_RATE / HZ);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ ctrl_reg = __raw_readl(timer->base_addr +
+ XTTCPSS_CNT_CNTRL_OFFSET);
+ ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+ __raw_writel(ctrl_reg,
+ timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ ctrl_reg = __raw_readl(timer->base_addr +
+ XTTCPSS_CNT_CNTRL_OFFSET);
+ ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+ __raw_writel(ctrl_reg,
+ timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+ break;
+ }
+}
+
+/*
+ * Instantiate and initialize the clock event structure
+ */
+static struct clock_event_device xttcpss_clockevent = {
+ .name = "xttcpss_timer2",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_next_event = xttcpss_set_next_event,
+ .set_mode = xttcpss_set_mode,
+ .rating = 200,
+};
+
+/**
+ * xttcpss_timer_init - Initialize the timer
+ *
+ * Initializes the timer hardware and register the clock source and clock event
+ * timers with Linux kernal timer framework
+ **/
+static void __init xttcpss_timer_init(void)
+{
+ xttcpss_timer_hardware_init();
+ clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
+
+ /* Calculate the parameters to allow the clockevent to operate using
+ integer math
+ */
+ clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4);
+
+ xttcpss_clockevent.max_delta_ns =
+ clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
+ xttcpss_clockevent.min_delta_ns =
+ clockevent_delta2ns(1, &xttcpss_clockevent);
+
+ /* Indicate that clock event is on 1st CPU as SMP boot needs it */
+
+ xttcpss_clockevent.cpumask = cpumask_of(0);
+ clockevents_register_device(&xttcpss_clockevent);
+}
+
+/*
+ * Instantiate and initialize the system timer structure
+ */
+struct sys_timer xttcpss_sys_timer = {
+ .init = xttcpss_timer_init,
+};
diff --git a/arch/arm/plat-mxc/devices/platform-ahci-imx.c b/arch/arm/plat-mxc/devices/platform-ahci-imx.c
new file mode 100644
index 0000000..d8a56ae
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-ahci-imx.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_ahci_imx_data_entry_single(soc, _devid) \
+ { \
+ .devid = _devid, \
+ .iobase = soc ## _SATA_BASE_ADDR, \
+ .irq = soc ## _INT_SATA, \
+ }
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_ahci_imx_data imx53_ahci_imx_data __initconst =
+ imx_ahci_imx_data_entry_single(MX53, "imx53-ahci");
+#endif
+
+enum {
+ HOST_CAP = 0x00,
+ HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
+ HOST_PORTS_IMPL = 0x0c,
+ HOST_TIMER1MS = 0xe0, /* Timer 1-ms */
+};
+
+static struct clk *sata_clk, *sata_ref_clk;
+
+/* AHCI module Initialization, if return 0, initialization is successful. */
+static int imx_sata_init(struct device *dev, void __iomem *addr)
+{
+ u32 tmpdata;
+ int ret = 0;
+ struct clk *clk;
+
+ sata_clk = clk_get(dev, "ahci");
+ if (IS_ERR(sata_clk)) {
+ dev_err(dev, "no sata clock.\n");
+ return PTR_ERR(sata_clk);
+ }
+ ret = clk_enable(sata_clk);
+ if (ret) {
+ dev_err(dev, "can't enable sata clock.\n");
+ goto put_sata_clk;
+ }
+
+ /* Get the AHCI SATA PHY CLK */
+ sata_ref_clk = clk_get(dev, "ahci_phy");
+ if (IS_ERR(sata_ref_clk)) {
+ dev_err(dev, "no sata ref clock.\n");
+ ret = PTR_ERR(sata_ref_clk);
+ goto release_sata_clk;
+ }
+ ret = clk_enable(sata_ref_clk);
+ if (ret) {
+ dev_err(dev, "can't enable sata ref clock.\n");
+ goto put_sata_ref_clk;
+ }
+
+ /* Get the AHB clock rate, and configure the TIMER1MS reg later */
+ clk = clk_get(dev, "ahci_dma");
+ if (IS_ERR(clk)) {
+ dev_err(dev, "no dma clock.\n");
+ ret = PTR_ERR(clk);
+ goto release_sata_ref_clk;
+ }
+ tmpdata = clk_get_rate(clk) / 1000;
+ clk_put(clk);
+
+ writel(tmpdata, addr + HOST_TIMER1MS);
+
+ tmpdata = readl(addr + HOST_CAP);
+ if (!(tmpdata & HOST_CAP_SSS)) {
+ tmpdata |= HOST_CAP_SSS;
+ writel(tmpdata, addr + HOST_CAP);
+ }
+
+ if (!(readl(addr + HOST_PORTS_IMPL) & 0x1))
+ writel((readl(addr + HOST_PORTS_IMPL) | 0x1),
+ addr + HOST_PORTS_IMPL);
+
+ return 0;
+
+release_sata_ref_clk:
+ clk_disable(sata_ref_clk);
+put_sata_ref_clk:
+ clk_put(sata_ref_clk);
+release_sata_clk:
+ clk_disable(sata_clk);
+put_sata_clk:
+ clk_put(sata_clk);
+
+ return ret;
+}
+
+static void imx_sata_exit(struct device *dev)
+{
+ clk_disable(sata_ref_clk);
+ clk_put(sata_ref_clk);
+
+ clk_disable(sata_clk);
+ clk_put(sata_clk);
+
+}
+struct platform_device *__init imx_add_ahci_imx(
+ const struct imx_ahci_imx_data *data,
+ const struct ahci_platform_data *pdata)
+{
+ struct resource res[] = {
+ {
+ .start = data->iobase,
+ .end = data->iobase + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return imx_add_platform_device_dmamask(data->devid, 0,
+ res, ARRAY_SIZE(res),
+ pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
+
+struct platform_device *__init imx53_add_ahci_imx(void)
+{
+ struct ahci_platform_data pdata = {
+ .init = imx_sata_init,
+ .exit = imx_sata_exit,
+ };
+
+ return imx_add_ahci_imx(&imx53_ahci_imx_data, &pdata);
+}
diff --git a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
new file mode 100644
index 0000000..a7919a2
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/devices-common.h>
+
+struct platform_device *__init mxc_register_gpio(char *name, int id,
+ resource_size_t iobase, resource_size_t iosize, int irq, int irq_high)
+{
+ struct resource res[] = {
+ {
+ .start = iobase,
+ .end = iobase + iosize - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = irq,
+ .end = irq,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .start = irq_high,
+ .end = irq_high,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return platform_device_register_resndata(&mxc_aips_bus,
+ name, id, res, ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/plat-mxc/devices/platform-pata_imx.c b/arch/arm/plat-mxc/devices/platform-pata_imx.c
new file mode 100644
index 0000000..70e2f2a
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-pata_imx.c
@@ -0,0 +1,59 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_pata_imx_data_entry_single(soc, _size) \
+ { \
+ .iobase = soc ## _ATA_BASE_ADDR, \
+ .iosize = _size, \
+ .irq = soc ## _INT_ATA, \
+ }
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_pata_imx_data imx27_pata_imx_data __initconst =
+ imx_pata_imx_data_entry_single(MX27, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_pata_imx_data imx31_pata_imx_data __initconst =
+ imx_pata_imx_data_entry_single(MX31, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_pata_imx_data imx35_pata_imx_data __initconst =
+ imx_pata_imx_data_entry_single(MX35, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_pata_imx_data imx51_pata_imx_data __initconst =
+ imx_pata_imx_data_entry_single(MX51, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_pata_imx_data imx53_pata_imx_data __initconst =
+ imx_pata_imx_data_entry_single(MX53, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_pata_imx(
+ const struct imx_pata_imx_data *data)
+{
+ struct resource res[] = {
+ {
+ .start = data->iobase,
+ .end = data->iobase + data->iosize - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+ return imx_add_platform_device("pata_imx", -1,
+ res, ARRAY_SIZE(res), NULL, 0);
+}
+
diff --git a/arch/arm/plat-mxc/gic.c b/arch/arm/plat-mxc/gic.c
new file mode 100644
index 0000000..12f8f81
--- /dev/null
+++ b/arch/arm/plat-mxc/gic.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <asm/exception.h>
+#include <asm/localtimer.h>
+#include <asm/hardware/gic.h>
+#ifdef CONFIG_SMP
+#include <asm/smp.h>
+#endif
+
+asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+{
+ u32 irqstat, irqnr;
+
+ do {
+ irqstat = readl_relaxed(gic_cpu_base_addr + GIC_CPU_INTACK);
+ irqnr = irqstat & 0x3ff;
+ if (irqnr == 1023)
+ break;
+
+ if (irqnr > 15 && irqnr < 1021)
+ handle_IRQ(irqnr, regs);
+#ifdef CONFIG_SMP
+ else {
+ writel_relaxed(irqstat, gic_cpu_base_addr +
+ GIC_CPU_EOI);
+ handle_IPI(irqnr, regs);
+ }
+#endif
+ } while (1);
+}
diff --git a/arch/arm/plat-mxc/include/mach/mx6q.h b/arch/arm/plat-mxc/include/mach/mx6q.h
new file mode 100644
index 0000000..254a561
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx6q.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __MACH_MX6Q_H__
+#define __MACH_MX6Q_H__
+
+#define MX6Q_IO_P2V(x) IMX_IO_P2V(x)
+#define MX6Q_IO_ADDRESS(x) IOMEM(MX6Q_IO_P2V(x))
+
+/*
+ * The following are the blocks that need to be statically mapped.
+ * For other blocks, the base address really should be retrieved from
+ * device tree.
+ */
+#define MX6Q_SCU_BASE_ADDR 0x00a00000
+#define MX6Q_SCU_SIZE 0x1000
+#define MX6Q_CCM_BASE_ADDR 0x020c4000
+#define MX6Q_CCM_SIZE 0x4000
+#define MX6Q_ANATOP_BASE_ADDR 0x020c8000
+#define MX6Q_ANATOP_SIZE 0x1000
+#define MX6Q_UART4_BASE_ADDR 0x021f0000
+#define MX6Q_UART4_SIZE 0x4000
+
+#endif /* __MACH_MX6Q_H__ */
diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
new file mode 100644
index 0000000..9605bf2
--- /dev/null
+++ b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
@@ -0,0 +1,88 @@
+/*
+ * Structures and registers for GPIO access in the Nomadik SoC
+ *
+ * Copyright (C) 2008 STMicroelectronics
+ * Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
+ * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_NOMADIK_GPIO
+#define __PLAT_NOMADIK_GPIO
+
+/*
+ * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
+ * the "gpio" namespace for generic and cross-machine functions
+ */
+
+/* Register in the logic block */
+#define NMK_GPIO_DAT 0x00
+#define NMK_GPIO_DATS 0x04
+#define NMK_GPIO_DATC 0x08
+#define NMK_GPIO_PDIS 0x0c
+#define NMK_GPIO_DIR 0x10
+#define NMK_GPIO_DIRS 0x14
+#define NMK_GPIO_DIRC 0x18
+#define NMK_GPIO_SLPC 0x1c
+#define NMK_GPIO_AFSLA 0x20
+#define NMK_GPIO_AFSLB 0x24
+
+#define NMK_GPIO_RIMSC 0x40
+#define NMK_GPIO_FIMSC 0x44
+#define NMK_GPIO_IS 0x48
+#define NMK_GPIO_IC 0x4c
+#define NMK_GPIO_RWIMSC 0x50
+#define NMK_GPIO_FWIMSC 0x54
+#define NMK_GPIO_WKS 0x58
+
+/* Alternate functions: function C is set in hw by setting both A and B */
+#define NMK_GPIO_ALT_GPIO 0
+#define NMK_GPIO_ALT_A 1
+#define NMK_GPIO_ALT_B 2
+#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
+
+/* Pull up/down values */
+enum nmk_gpio_pull {
+ NMK_GPIO_PULL_NONE,
+ NMK_GPIO_PULL_UP,
+ NMK_GPIO_PULL_DOWN,
+};
+
+/* Sleep mode */
+enum nmk_gpio_slpm {
+ NMK_GPIO_SLPM_INPUT,
+ NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
+ NMK_GPIO_SLPM_NOCHANGE,
+ NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
+};
+
+extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
+extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
+extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
+extern int nmk_gpio_get_mode(int gpio);
+
+extern void nmk_gpio_wakeups_suspend(void);
+extern void nmk_gpio_wakeups_resume(void);
+
+extern void nmk_gpio_clocks_enable(void);
+extern void nmk_gpio_clocks_disable(void);
+
+extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
+
+/*
+ * Platform data to register a block: only the initial gpio/irq number.
+ */
+struct nmk_gpio_platform_data {
+ char *name;
+ int first_gpio;
+ int first_irq;
+ int num_gpio;
+ u32 (*get_secondary_status)(unsigned int bank);
+ void (*set_ioforce)(bool enable);
+ bool supports_sleepmode;
+};
+
+#endif /* __PLAT_NOMADIK_GPIO */
diff --git a/arch/arm/plat-omap/include/plat/iopgtable.h b/arch/arm/plat-omap/include/plat/iopgtable.h
new file mode 100644
index 0000000..66a8139
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/iopgtable.h
@@ -0,0 +1,120 @@
+/*
+ * omap iommu: pagetable definitions
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_OMAP_IOMMU_H
+#define __PLAT_OMAP_IOMMU_H
+
+/*
+ * "L2 table" address mask and size definitions.
+ */
+#define IOPGD_SHIFT 20
+#define IOPGD_SIZE (1UL << IOPGD_SHIFT)
+#define IOPGD_MASK (~(IOPGD_SIZE - 1))
+
+/*
+ * "section" address mask and size definitions.
+ */
+#define IOSECTION_SHIFT 20
+#define IOSECTION_SIZE (1UL << IOSECTION_SHIFT)
+#define IOSECTION_MASK (~(IOSECTION_SIZE - 1))
+
+/*
+ * "supersection" address mask and size definitions.
+ */
+#define IOSUPER_SHIFT 24
+#define IOSUPER_SIZE (1UL << IOSUPER_SHIFT)
+#define IOSUPER_MASK (~(IOSUPER_SIZE - 1))
+
+#define PTRS_PER_IOPGD (1UL << (32 - IOPGD_SHIFT))
+#define IOPGD_TABLE_SIZE (PTRS_PER_IOPGD * sizeof(u32))
+
+/*
+ * "small page" address mask and size definitions.
+ */
+#define IOPTE_SHIFT 12
+#define IOPTE_SIZE (1UL << IOPTE_SHIFT)
+#define IOPTE_MASK (~(IOPTE_SIZE - 1))
+
+/*
+ * "large page" address mask and size definitions.
+ */
+#define IOLARGE_SHIFT 16
+#define IOLARGE_SIZE (1UL << IOLARGE_SHIFT)
+#define IOLARGE_MASK (~(IOLARGE_SIZE - 1))
+
+#define PTRS_PER_IOPTE (1UL << (IOPGD_SHIFT - IOPTE_SHIFT))
+#define IOPTE_TABLE_SIZE (PTRS_PER_IOPTE * sizeof(u32))
+
+#define IOPAGE_MASK IOPTE_MASK
+
+/**
+ * omap_iommu_translate() - va to pa translation
+ * @d: omap iommu descriptor
+ * @va: virtual address
+ * @mask: omap iommu descriptor mask
+ *
+ * va to pa translation
+ */
+static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask)
+{
+ return (d & mask) | (va & (~mask));
+}
+
+/*
+ * some descriptor attributes.
+ */
+#define IOPGD_TABLE (1 << 0)
+#define IOPGD_SECTION (2 << 0)
+#define IOPGD_SUPER (1 << 18 | 2 << 0)
+
+#define iopgd_is_table(x) (((x) & 3) == IOPGD_TABLE)
+#define iopgd_is_section(x) (((x) & (1 << 18 | 3)) == IOPGD_SECTION)
+#define iopgd_is_super(x) (((x) & (1 << 18 | 3)) == IOPGD_SUPER)
+
+#define IOPTE_SMALL (2 << 0)
+#define IOPTE_LARGE (1 << 0)
+
+#define iopte_is_small(x) (((x) & 2) == IOPTE_SMALL)
+#define iopte_is_large(x) (((x) & 3) == IOPTE_LARGE)
+
+/* to find an entry in a page-table-directory */
+#define iopgd_index(da) (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
+#define iopgd_offset(obj, da) ((obj)->iopgd + iopgd_index(da))
+
+#define iopgd_page_paddr(iopgd) (*iopgd & ~((1 << 10) - 1))
+#define iopgd_page_vaddr(iopgd) ((u32 *)phys_to_virt(iopgd_page_paddr(iopgd)))
+
+/* to find an entry in the second-level page table. */
+#define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
+#define iopte_offset(iopgd, da) (iopgd_page_vaddr(iopgd) + iopte_index(da))
+
+static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
+ u32 flags)
+{
+ memset(e, 0, sizeof(*e));
+
+ e->da = da;
+ e->pa = pa;
+ e->valid = 1;
+ /* FIXME: add OMAP1 support */
+ e->pgsz = flags & MMU_CAM_PGSZ_MASK;
+ e->endian = flags & MMU_RAM_ENDIAN_MASK;
+ e->elsz = flags & MMU_RAM_ELSZ_MASK;
+ e->mixed = flags & MMU_RAM_MIXED_MASK;
+
+ return iopgsz_to_bytes(e->pgsz);
+}
+
+#define to_iommu(dev) \
+ (struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))
+
+#endif /* __PLAT_OMAP_IOMMU_H */
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
new file mode 100644
index 0000000..0a6a482
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/voltage.h
@@ -0,0 +1,20 @@
+/*
+ * OMAP Voltage Management Routines
+ *
+ * Copyright (C) 2011, Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_OMAP_VOLTAGE_H
+#define __ARCH_ARM_OMAP_VOLTAGE_H
+
+struct voltagedomain;
+
+struct voltagedomain *voltdm_lookup(const char *name);
+int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
+
+#endif
diff --git a/arch/arm/plat-pxa/include/plat/gpio-pxa.h b/arch/arm/plat-pxa/include/plat/gpio-pxa.h
new file mode 100644
index 0000000..b6390be
--- /dev/null
+++ b/arch/arm/plat-pxa/include/plat/gpio-pxa.h
@@ -0,0 +1,44 @@
+#ifndef __PLAT_PXA_GPIO_H
+#define __PLAT_PXA_GPIO_H
+
+struct irq_data;
+
+/*
+ * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
+ * one set of registers. The register offsets are organized below:
+ *
+ * GPLR GPDR GPSR GPCR GRER GFER GEDR
+ * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048
+ * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C
+ * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050
+ *
+ * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148
+ * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C
+ * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150
+ *
+ * NOTE:
+ * BANK 3 is only available on PXA27x and later processors.
+ * BANK 4 and 5 are only available on PXA935
+ */
+
+#define GPIO_BANK(n) (GPIO_REGS_VIRT + BANK_OFF(n))
+
+#define GPLR_OFFSET 0x00
+#define GPDR_OFFSET 0x0C
+#define GPSR_OFFSET 0x18
+#define GPCR_OFFSET 0x24
+#define GRER_OFFSET 0x30
+#define GFER_OFFSET 0x3C
+#define GEDR_OFFSET 0x48
+
+/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
+ * Those cases currently cause holes in the GPIO number space, the
+ * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
+ */
+extern int pxa_last_gpio;
+
+typedef int (*set_wake_t)(struct irq_data *d, unsigned int on);
+
+extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn);
+
+#endif /* __PLAT_PXA_GPIO_H */
diff --git a/arch/arm/plat-s3c24xx/dev-uart.c b/arch/arm/plat-s3c24xx/dev-uart.c
new file mode 100644
index 0000000..9ab22e6
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/dev-uart.c
@@ -0,0 +1,100 @@
+/* linux/arch/arm/plat-s3c24xx/dev-uart.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Base S3C24XX UART resource and platform device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+#include <plat/regs-serial.h>
+
+/* Serial port registrations */
+
+static struct resource s3c2410_uart0_resource[] = {
+ [0] = {
+ .start = S3C2410_PA_UART0,
+ .end = S3C2410_PA_UART0 + 0x3fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_S3CUART_RX0,
+ .end = IRQ_S3CUART_ERR0,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource s3c2410_uart1_resource[] = {
+ [0] = {
+ .start = S3C2410_PA_UART1,
+ .end = S3C2410_PA_UART1 + 0x3fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_S3CUART_RX1,
+ .end = IRQ_S3CUART_ERR1,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource s3c2410_uart2_resource[] = {
+ [0] = {
+ .start = S3C2410_PA_UART2,
+ .end = S3C2410_PA_UART2 + 0x3fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_S3CUART_RX2,
+ .end = IRQ_S3CUART_ERR2,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource s3c2410_uart3_resource[] = {
+ [0] = {
+ .start = S3C2443_PA_UART3,
+ .end = S3C2443_PA_UART3 + 0x3fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_S3CUART_RX3,
+ .end = IRQ_S3CUART_ERR3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
+ [0] = {
+ .resources = s3c2410_uart0_resource,
+ .nr_resources = ARRAY_SIZE(s3c2410_uart0_resource),
+ },
+ [1] = {
+ .resources = s3c2410_uart1_resource,
+ .nr_resources = ARRAY_SIZE(s3c2410_uart1_resource),
+ },
+ [2] = {
+ .resources = s3c2410_uart2_resource,
+ .nr_resources = ARRAY_SIZE(s3c2410_uart2_resource),
+ },
+ [3] = {
+ .resources = s3c2410_uart3_resource,
+ .nr_resources = ARRAY_SIZE(s3c2410_uart3_resource),
+ },
+};
diff --git a/arch/arm/plat-s5p/sleep.S b/arch/arm/plat-s5p/sleep.S
new file mode 100644
index 0000000..0fd591b
--- /dev/null
+++ b/arch/arm/plat-s5p/sleep.S
@@ -0,0 +1,49 @@
+/* linux/arch/arm/plat-s5p/sleep.S
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Common S5P Sleep Code
+ * Based on S3C64XX sleep code by:
+ * Ben Dooks, (c) 2008 Simtec Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ .text
+
+ /*
+ * sleep magic, to allow the bootloader to check for an valid
+ * image to resume to. Must be the first word before the
+ * s3c_cpu_resume entry.
+ */
+
+ .word 0x2bedf00d
+
+ /*
+ * s3c_cpu_resume
+ *
+ * resume code entry for bootloader to call
+ *
+ * we must put this code here in the data segment as we have no
+ * other way of restoring the stack pointer after sleep, and we
+ * must not write to the code segment (code is read-only)
+ */
+
+ENTRY(s3c_cpu_resume)
+ b cpu_resume
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
new file mode 100644
index 0000000..4ca8b57
--- /dev/null
+++ b/arch/arm/plat-samsung/devs.c
@@ -0,0 +1,1463 @@
+/* linux/arch/arm/plat-samsung/devs.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Base SAMSUNG platform device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/gfp.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mmc/host.h>
+#include <linux/ioport.h>
+
+#include <asm/irq.h>
+#include <asm/pmu.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/adc.h>
+#include <plat/ata.h>
+#include <plat/ehci.h>
+#include <plat/fb.h>
+#include <plat/fb-s3c2410.h>
+#include <plat/hwmon.h>
+#include <plat/iic.h>
+#include <plat/keypad.h>
+#include <plat/mci.h>
+#include <plat/nand.h>
+#include <plat/sdhci.h>
+#include <plat/ts.h>
+#include <plat/udc.h>
+#include <plat/usb-control.h>
+#include <plat/usb-phy.h>
+#include <plat/regs-iic.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-spi.h>
+
+static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
+
+/* AC97 */
+#ifdef CONFIG_CPU_S3C2440
+static struct resource s3c_ac97_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C2440_PA_AC97, S3C2440_SZ_AC97),
+ [1] = DEFINE_RES_IRQ(IRQ_S3C244X_AC97),
+ [2] = DEFINE_RES_DMA_NAMED(DMACH_PCM_OUT, "PCM out"),
+ [3] = DEFINE_RES_DMA_NAMED(DMACH_PCM_IN, "PCM in"),
+ [4] = DEFINE_RES_DMA_NAMED(DMACH_MIC_IN, "Mic in"),
+};
+
+struct platform_device s3c_device_ac97 = {
+ .name = "samsung-ac97",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_ac97_resource),
+ .resource = s3c_ac97_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+#endif /* CONFIG_CPU_S3C2440 */
+
+/* ADC */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_adc_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C24XX_PA_ADC, S3C24XX_SZ_ADC),
+ [1] = DEFINE_RES_IRQ(IRQ_TC),
+ [2] = DEFINE_RES_IRQ(IRQ_ADC),
+};
+
+struct platform_device s3c_device_adc = {
+ .name = "s3c24xx-adc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_adc_resource),
+ .resource = s3c_adc_resource,
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#if defined(CONFIG_SAMSUNG_DEV_ADC)
+static struct resource s3c_adc_resource[] = {
+ [0] = DEFINE_RES_MEM(SAMSUNG_PA_ADC, SZ_256),
+ [1] = DEFINE_RES_IRQ(IRQ_TC),
+ [2] = DEFINE_RES_IRQ(IRQ_ADC),
+};
+
+struct platform_device s3c_device_adc = {
+ .name = "samsung-adc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_adc_resource),
+ .resource = s3c_adc_resource,
+};
+#endif /* CONFIG_SAMSUNG_DEV_ADC */
+
+/* Camif Controller */
+
+#ifdef CONFIG_CPU_S3C2440
+static struct resource s3c_camif_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF),
+ [1] = DEFINE_RES_IRQ(IRQ_CAM),
+};
+
+struct platform_device s3c_device_camif = {
+ .name = "s3c2440-camif",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_camif_resource),
+ .resource = s3c_camif_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+#endif /* CONFIG_CPU_S3C2440 */
+
+/* ASOC DMA */
+
+struct platform_device samsung_asoc_dma = {
+ .name = "samsung-audio",
+ .id = -1,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+
+struct platform_device samsung_asoc_idma = {
+ .name = "samsung-idma",
+ .id = -1,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+
+/* FB */
+
+#ifdef CONFIG_S3C_DEV_FB
+static struct resource s3c_fb_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_FB, SZ_16K),
+ [1] = DEFINE_RES_IRQ(IRQ_LCD_VSYNC),
+ [2] = DEFINE_RES_IRQ(IRQ_LCD_FIFO),
+ [3] = DEFINE_RES_IRQ(IRQ_LCD_SYSTEM),
+};
+
+struct platform_device s3c_device_fb = {
+ .name = "s3c-fb",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_fb_resource),
+ .resource = s3c_fb_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd)
+{
+ s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+ &s3c_device_fb);
+}
+#endif /* CONFIG_S3C_DEV_FB */
+
+/* FIMC */
+
+#ifdef CONFIG_S5P_DEV_FIMC0
+static struct resource s5p_fimc0_resource[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_FIMC0, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_FIMC0),
+};
+
+struct platform_device s5p_device_fimc0 = {
+ .name = "s5p-fimc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5p_fimc0_resource),
+ .resource = s5p_fimc0_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+struct platform_device s5p_device_fimc_md = {
+ .name = "s5p-fimc-md",
+ .id = -1,
+};
+#endif /* CONFIG_S5P_DEV_FIMC0 */
+
+#ifdef CONFIG_S5P_DEV_FIMC1
+static struct resource s5p_fimc1_resource[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_FIMC1, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_FIMC1),
+};
+
+struct platform_device s5p_device_fimc1 = {
+ .name = "s5p-fimc",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s5p_fimc1_resource),
+ .resource = s5p_fimc1_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+#endif /* CONFIG_S5P_DEV_FIMC1 */
+
+#ifdef CONFIG_S5P_DEV_FIMC2
+static struct resource s5p_fimc2_resource[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_FIMC2, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_FIMC2),
+};
+
+struct platform_device s5p_device_fimc2 = {
+ .name = "s5p-fimc",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(s5p_fimc2_resource),
+ .resource = s5p_fimc2_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+#endif /* CONFIG_S5P_DEV_FIMC2 */
+
+#ifdef CONFIG_S5P_DEV_FIMC3
+static struct resource s5p_fimc3_resource[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_FIMC3, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_FIMC3),
+};
+
+struct platform_device s5p_device_fimc3 = {
+ .name = "s5p-fimc",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(s5p_fimc3_resource),
+ .resource = s5p_fimc3_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+#endif /* CONFIG_S5P_DEV_FIMC3 */
+
+/* FIMD0 */
+
+#ifdef CONFIG_S5P_DEV_FIMD0
+static struct resource s5p_fimd0_resource[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_FIMD0, SZ_32K),
+ [1] = DEFINE_RES_IRQ(IRQ_FIMD0_VSYNC),
+ [2] = DEFINE_RES_IRQ(IRQ_FIMD0_FIFO),
+ [3] = DEFINE_RES_IRQ(IRQ_FIMD0_SYSTEM),
+};
+
+struct platform_device s5p_device_fimd0 = {
+ .name = "s5p-fb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5p_fimd0_resource),
+ .resource = s5p_fimd0_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
+{
+ s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+ &s5p_device_fimd0);
+}
+#endif /* CONFIG_S5P_DEV_FIMD0 */
+
+/* HWMON */
+
+#ifdef CONFIG_S3C_DEV_HWMON
+struct platform_device s3c_device_hwmon = {
+ .name = "s3c-hwmon",
+ .id = -1,
+ .dev.parent = &s3c_device_adc.dev,
+};
+
+void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd)
+{
+ s3c_set_platdata(pd, sizeof(struct s3c_hwmon_pdata),
+ &s3c_device_hwmon);
+}
+#endif /* CONFIG_S3C_DEV_HWMON */
+
+/* HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC
+static struct resource s3c_hsmmc_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_HSMMC0, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_HSMMC0),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = {
+ .max_width = 4,
+ .host_caps = (MMC_CAP_4_BIT_DATA |
+ MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+ .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc0 = {
+ .name = "s3c-sdhci",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s3c_hsmmc_resource),
+ .resource = s3c_hsmmc_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &s3c_hsmmc0_def_platdata,
+ },
+};
+
+void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+ s3c_sdhci_set_platdata(pd, &s3c_hsmmc0_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC1
+static struct resource s3c_hsmmc1_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_HSMMC1, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_HSMMC1),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = {
+ .max_width = 4,
+ .host_caps = (MMC_CAP_4_BIT_DATA |
+ MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+ .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc1 = {
+ .name = "s3c-sdhci",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s3c_hsmmc1_resource),
+ .resource = s3c_hsmmc1_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &s3c_hsmmc1_def_platdata,
+ },
+};
+
+void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+ s3c_sdhci_set_platdata(pd, &s3c_hsmmc1_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC1 */
+
+/* HSMMC2 */
+
+#ifdef CONFIG_S3C_DEV_HSMMC2
+static struct resource s3c_hsmmc2_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_HSMMC2, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_HSMMC2),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = {
+ .max_width = 4,
+ .host_caps = (MMC_CAP_4_BIT_DATA |
+ MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+ .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc2 = {
+ .name = "s3c-sdhci",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(s3c_hsmmc2_resource),
+ .resource = s3c_hsmmc2_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &s3c_hsmmc2_def_platdata,
+ },
+};
+
+void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+ s3c_sdhci_set_platdata(pd, &s3c_hsmmc2_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC2 */
+
+#ifdef CONFIG_S3C_DEV_HSMMC3
+static struct resource s3c_hsmmc3_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_HSMMC3, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_HSMMC3),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = {
+ .max_width = 4,
+ .host_caps = (MMC_CAP_4_BIT_DATA |
+ MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+ .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc3 = {
+ .name = "s3c-sdhci",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(s3c_hsmmc3_resource),
+ .resource = s3c_hsmmc3_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &s3c_hsmmc3_def_platdata,
+ },
+};
+
+void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+ s3c_sdhci_set_platdata(pd, &s3c_hsmmc3_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC3 */
+
+/* I2C */
+
+static struct resource s3c_i2c0_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_IIC, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_IIC),
+};
+
+struct platform_device s3c_device_i2c0 = {
+ .name = "s3c2410-i2c",
+#ifdef CONFIG_S3C_DEV_I2C1
+ .id = 0,
+#else
+ .id = -1,
+#endif
+ .num_resources = ARRAY_SIZE(s3c_i2c0_resource),
+ .resource = s3c_i2c0_resource,
+};
+
+struct s3c2410_platform_i2c default_i2c_data __initdata = {
+ .flags = 0,
+ .slave_addr = 0x10,
+ .frequency = 100*1000,
+ .sda_delay = 100,
+};
+
+void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+ struct s3c2410_platform_i2c *npd;
+
+ if (!pd)
+ pd = &default_i2c_data;
+
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c0);
+
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c0_cfg_gpio;
+}
+
+#ifdef CONFIG_S3C_DEV_I2C1
+static struct resource s3c_i2c1_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_IIC1, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_IIC1),
+};
+
+struct platform_device s3c_device_i2c1 = {
+ .name = "s3c2410-i2c",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s3c_i2c1_resource),
+ .resource = s3c_i2c1_resource,
+};
+
+void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+ struct s3c2410_platform_i2c *npd;
+
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 1;
+ }
+
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c1);
+
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c1_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C1 */
+
+#ifdef CONFIG_S3C_DEV_I2C2
+static struct resource s3c_i2c2_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_IIC2, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_IIC2),
+};
+
+struct platform_device s3c_device_i2c2 = {
+ .name = "s3c2410-i2c",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(s3c_i2c2_resource),
+ .resource = s3c_i2c2_resource,
+};
+
+void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+ struct s3c2410_platform_i2c *npd;
+
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 2;
+ }
+
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c2);
+
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c2_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C2 */
+
+#ifdef CONFIG_S3C_DEV_I2C3
+static struct resource s3c_i2c3_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_IIC3, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_IIC3),
+};
+
+struct platform_device s3c_device_i2c3 = {
+ .name = "s3c2440-i2c",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(s3c_i2c3_resource),
+ .resource = s3c_i2c3_resource,
+};
+
+void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+ struct s3c2410_platform_i2c *npd;
+
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 3;
+ }
+
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c3);
+
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c3_cfg_gpio;
+}
+#endif /*CONFIG_S3C_DEV_I2C3 */
+
+#ifdef CONFIG_S3C_DEV_I2C4
+static struct resource s3c_i2c4_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_IIC4, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_IIC4),
+};
+
+struct platform_device s3c_device_i2c4 = {
+ .name = "s3c2440-i2c",
+ .id = 4,
+ .num_resources = ARRAY_SIZE(s3c_i2c4_resource),
+ .resource = s3c_i2c4_resource,
+};
+
+void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+ struct s3c2410_platform_i2c *npd;
+
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 4;
+ }
+
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c4);
+
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c4_cfg_gpio;
+}
+#endif /*CONFIG_S3C_DEV_I2C4 */
+
+#ifdef CONFIG_S3C_DEV_I2C5
+static struct resource s3c_i2c5_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_IIC5, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_IIC5),
+};
+
+struct platform_device s3c_device_i2c5 = {
+ .name = "s3c2440-i2c",
+ .id = 5,
+ .num_resources = ARRAY_SIZE(s3c_i2c5_resource),
+ .resource = s3c_i2c5_resource,
+};
+
+void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+ struct s3c2410_platform_i2c *npd;
+
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 5;
+ }
+
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c5);
+
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c5_cfg_gpio;
+}
+#endif /*CONFIG_S3C_DEV_I2C5 */
+
+#ifdef CONFIG_S3C_DEV_I2C6
+static struct resource s3c_i2c6_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_IIC6, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_IIC6),
+};
+
+struct platform_device s3c_device_i2c6 = {
+ .name = "s3c2440-i2c",
+ .id = 6,
+ .num_resources = ARRAY_SIZE(s3c_i2c6_resource),
+ .resource = s3c_i2c6_resource,
+};
+
+void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+ struct s3c2410_platform_i2c *npd;
+
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 6;
+ }
+
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c6);
+
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c6_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C6 */
+
+#ifdef CONFIG_S3C_DEV_I2C7
+static struct resource s3c_i2c7_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_IIC7, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_IIC7),
+};
+
+struct platform_device s3c_device_i2c7 = {
+ .name = "s3c2440-i2c",
+ .id = 7,
+ .num_resources = ARRAY_SIZE(s3c_i2c7_resource),
+ .resource = s3c_i2c7_resource,
+};
+
+void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+ struct s3c2410_platform_i2c *npd;
+
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 7;
+ }
+
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c7);
+
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c7_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C7 */
+
+/* I2C HDMIPHY */
+
+#ifdef CONFIG_S5P_DEV_I2C_HDMIPHY
+static struct resource s5p_i2c_resource[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_IIC_HDMIPHY, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_IIC_HDMIPHY),
+};
+
+struct platform_device s5p_device_i2c_hdmiphy = {
+ .name = "s3c2440-hdmiphy-i2c",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_i2c_resource),
+ .resource = s5p_i2c_resource,
+};
+
+void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+ struct s3c2410_platform_i2c *npd;
+
+ if (!pd) {
+ pd = &default_i2c_data;
+
+ if (soc_is_exynos4210())
+ pd->bus_num = 8;
+ else if (soc_is_s5pv210())
+ pd->bus_num = 3;
+ else
+ pd->bus_num = 0;
+ }
+
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s5p_device_i2c_hdmiphy);
+}
+#endif /* CONFIG_S5P_DEV_I2C_HDMIPHY */
+
+/* I2S */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_iis_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C24XX_PA_IIS, S3C24XX_SZ_IIS),
+};
+
+struct platform_device s3c_device_iis = {
+ .name = "s3c24xx-iis",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_iis_resource),
+ .resource = s3c_iis_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#ifdef CONFIG_CPU_S3C2440
+struct platform_device s3c2412_device_iis = {
+ .name = "s3c2412-iis",
+ .id = -1,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+#endif /* CONFIG_CPU_S3C2440 */
+
+/* IDE CFCON */
+
+#ifdef CONFIG_SAMSUNG_DEV_IDE
+static struct resource s3c_cfcon_resource[] = {
+ [0] = DEFINE_RES_MEM(SAMSUNG_PA_CFCON, SZ_16K),
+ [1] = DEFINE_RES_IRQ(IRQ_CFCON),
+};
+
+struct platform_device s3c_device_cfcon = {
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s3c_cfcon_resource),
+ .resource = s3c_cfcon_resource,
+};
+
+void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata)
+{
+ s3c_set_platdata(pdata, sizeof(struct s3c_ide_platdata),
+ &s3c_device_cfcon);
+}
+#endif /* CONFIG_SAMSUNG_DEV_IDE */
+
+/* KEYPAD */
+
+#ifdef CONFIG_SAMSUNG_DEV_KEYPAD
+static struct resource samsung_keypad_resources[] = {
+ [0] = DEFINE_RES_MEM(SAMSUNG_PA_KEYPAD, SZ_32),
+ [1] = DEFINE_RES_IRQ(IRQ_KEYPAD),
+};
+
+struct platform_device samsung_device_keypad = {
+ .name = "samsung-keypad",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(samsung_keypad_resources),
+ .resource = samsung_keypad_resources,
+};
+
+void __init samsung_keypad_set_platdata(struct samsung_keypad_platdata *pd)
+{
+ struct samsung_keypad_platdata *npd;
+
+ npd = s3c_set_platdata(pd, sizeof(struct samsung_keypad_platdata),
+ &samsung_device_keypad);
+
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = samsung_keypad_cfg_gpio;
+}
+#endif /* CONFIG_SAMSUNG_DEV_KEYPAD */
+
+/* LCD Controller */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_lcd_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C24XX_PA_LCD, S3C24XX_SZ_LCD),
+ [1] = DEFINE_RES_IRQ(IRQ_LCD),
+};
+
+struct platform_device s3c_device_lcd = {
+ .name = "s3c2410-lcd",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_lcd_resource),
+ .resource = s3c_lcd_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+
+void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
+{
+ struct s3c2410fb_mach_info *npd;
+
+ npd = s3c_set_platdata(pd, sizeof(*npd), &s3c_device_lcd);
+ if (npd) {
+ npd->displays = kmemdup(pd->displays,
+ sizeof(struct s3c2410fb_display) * npd->num_displays,
+ GFP_KERNEL);
+ if (!npd->displays)
+ printk(KERN_ERR "no memory for LCD display data\n");
+ } else {
+ printk(KERN_ERR "no memory for LCD platform data\n");
+ }
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* MFC */
+
+#ifdef CONFIG_S5P_DEV_MFC
+static struct resource s5p_mfc_resource[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_MFC, SZ_64K),
+ [1] = DEFINE_RES_IRQ(IRQ_MFC),
+};
+
+struct platform_device s5p_device_mfc = {
+ .name = "s5p-mfc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_mfc_resource),
+ .resource = s5p_mfc_resource,
+};
+
+/*
+ * MFC hardware has 2 memory interfaces which are modelled as two separate
+ * platform devices to let dma-mapping distinguish between them.
+ *
+ * MFC parent device (s5p_device_mfc) must be registered before memory
+ * interface specific devices (s5p_device_mfc_l and s5p_device_mfc_r).
+ */
+
+struct platform_device s5p_device_mfc_l = {
+ .name = "s5p-mfc-l",
+ .id = -1,
+ .dev = {
+ .parent = &s5p_device_mfc.dev,
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+struct platform_device s5p_device_mfc_r = {
+ .name = "s5p-mfc-r",
+ .id = -1,
+ .dev = {
+ .parent = &s5p_device_mfc.dev,
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+#endif /* CONFIG_S5P_DEV_MFC */
+
+/* MIPI CSIS */
+
+#ifdef CONFIG_S5P_DEV_CSIS0
+static struct resource s5p_mipi_csis0_resource[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_MIPI_CSIS0, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_MIPI_CSIS0),
+};
+
+struct platform_device s5p_device_mipi_csis0 = {
+ .name = "s5p-mipi-csis",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5p_mipi_csis0_resource),
+ .resource = s5p_mipi_csis0_resource,
+};
+#endif /* CONFIG_S5P_DEV_CSIS0 */
+
+#ifdef CONFIG_S5P_DEV_CSIS1
+static struct resource s5p_mipi_csis1_resource[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_MIPI_CSIS1, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_MIPI_CSIS1),
+};
+
+struct platform_device s5p_device_mipi_csis1 = {
+ .name = "s5p-mipi-csis",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s5p_mipi_csis1_resource),
+ .resource = s5p_mipi_csis1_resource,
+};
+#endif
+
+/* NAND */
+
+#ifdef CONFIG_S3C_DEV_NAND
+static struct resource s3c_nand_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_NAND, SZ_1M),
+};
+
+struct platform_device s3c_device_nand = {
+ .name = "s3c2410-nand",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_nand_resource),
+ .resource = s3c_nand_resource,
+};
+
+/*
+ * s3c_nand_copy_set() - copy nand set data
+ * @set: The new structure, directly copied from the old.
+ *
+ * Copy all the fields from the NAND set field from what is probably __initdata
+ * to new kernel memory. The code returns 0 if the copy happened correctly or
+ * an error code for the calling function to display.
+ *
+ * Note, we currently do not try and look to see if we've already copied the
+ * data in a previous set.
+ */
+static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set)
+{
+ void *ptr;
+ int size;
+
+ size = sizeof(struct mtd_partition) * set->nr_partitions;
+ if (size) {
+ ptr = kmemdup(set->partitions, size, GFP_KERNEL);
+ set->partitions = ptr;
+
+ if (!ptr)
+ return -ENOMEM;
+ }
+
+ if (set->nr_map && set->nr_chips) {
+ size = sizeof(int) * set->nr_chips;
+ ptr = kmemdup(set->nr_map, size, GFP_KERNEL);
+ set->nr_map = ptr;
+
+ if (!ptr)
+ return -ENOMEM;
+ }
+
+ if (set->ecc_layout) {
+ ptr = kmemdup(set->ecc_layout,
+ sizeof(struct nand_ecclayout), GFP_KERNEL);
+ set->ecc_layout = ptr;
+
+ if (!ptr)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
+{
+ struct s3c2410_platform_nand *npd;
+ int size;
+ int ret;
+
+ /* note, if we get a failure in allocation, we simply drop out of the
+ * function. If there is so little memory available at initialisation
+ * time then there is little chance the system is going to run.
+ */
+
+ npd = s3c_set_platdata(nand, sizeof(struct s3c2410_platform_nand),
+ &s3c_device_nand);
+ if (!npd)
+ return;
+
+ /* now see if we need to copy any of the nand set data */
+
+ size = sizeof(struct s3c2410_nand_set) * npd->nr_sets;
+ if (size) {
+ struct s3c2410_nand_set *from = npd->sets;
+ struct s3c2410_nand_set *to;
+ int i;
+
+ to = kmemdup(from, size, GFP_KERNEL);
+ npd->sets = to; /* set, even if we failed */
+
+ if (!to) {
+ printk(KERN_ERR "%s: no memory for sets\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < npd->nr_sets; i++) {
+ ret = s3c_nand_copy_set(to);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to copy set %d\n",
+ __func__, i);
+ return;
+ }
+ to++;
+ }
+ }
+}
+#endif /* CONFIG_S3C_DEV_NAND */
+
+/* ONENAND */
+
+#ifdef CONFIG_S3C_DEV_ONENAND
+static struct resource s3c_onenand_resources[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_ONENAND, SZ_1K),
+ [1] = DEFINE_RES_MEM(S3C_PA_ONENAND_BUF, S3C_SZ_ONENAND_BUF),
+ [2] = DEFINE_RES_IRQ(IRQ_ONENAND),
+};
+
+struct platform_device s3c_device_onenand = {
+ .name = "samsung-onenand",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s3c_onenand_resources),
+ .resource = s3c_onenand_resources,
+};
+#endif /* CONFIG_S3C_DEV_ONENAND */
+
+#ifdef CONFIG_S3C64XX_DEV_ONENAND1
+static struct resource s3c64xx_onenand1_resources[] = {
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_ONENAND1, SZ_1K),
+ [1] = DEFINE_RES_MEM(S3C64XX_PA_ONENAND1_BUF, S3C64XX_SZ_ONENAND1_BUF),
+ [2] = DEFINE_RES_IRQ(IRQ_ONENAND1),
+};
+
+struct platform_device s3c64xx_device_onenand1 = {
+ .name = "samsung-onenand",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s3c64xx_onenand1_resources),
+ .resource = s3c64xx_onenand1_resources,
+};
+
+void s3c64xx_onenand1_set_platdata(struct onenand_platform_data *pdata)
+{
+ s3c_set_platdata(pdata, sizeof(struct onenand_platform_data),
+ &s3c64xx_device_onenand1);
+}
+#endif /* CONFIG_S3C64XX_DEV_ONENAND1 */
+
+#ifdef CONFIG_S5P_DEV_ONENAND
+static struct resource s5p_onenand_resources[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_ONENAND, SZ_128K),
+ [1] = DEFINE_RES_MEM(S5P_PA_ONENAND_DMA, SZ_8K),
+ [2] = DEFINE_RES_IRQ(IRQ_ONENAND_AUDI),
+};
+
+struct platform_device s5p_device_onenand = {
+ .name = "s5pc110-onenand",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_onenand_resources),
+ .resource = s5p_onenand_resources,
+};
+#endif /* CONFIG_S5P_DEV_ONENAND */
+
+/* PMU */
+
+#ifdef CONFIG_PLAT_S5P
+static struct resource s5p_pmu_resource[] = {
+ DEFINE_RES_IRQ(IRQ_PMU)
+};
+
+struct platform_device s5p_device_pmu = {
+ .name = "arm-pmu",
+ .id = ARM_PMU_DEVICE_CPU,
+ .num_resources = ARRAY_SIZE(s5p_pmu_resource),
+ .resource = s5p_pmu_resource,
+};
+
+static int __init s5p_pmu_init(void)
+{
+ platform_device_register(&s5p_device_pmu);
+ return 0;
+}
+arch_initcall(s5p_pmu_init);
+#endif /* CONFIG_PLAT_S5P */
+
+/* PWM Timer */
+
+#ifdef CONFIG_SAMSUNG_DEV_PWM
+
+#define TIMER_RESOURCE_SIZE (1)
+
+#define TIMER_RESOURCE(_tmr, _irq) \
+ (struct resource [TIMER_RESOURCE_SIZE]) { \
+ [0] = { \
+ .start = _irq, \
+ .end = _irq, \
+ .flags = IORESOURCE_IRQ \
+ } \
+ }
+
+#define DEFINE_S3C_TIMER(_tmr_no, _irq) \
+ .name = "s3c24xx-pwm", \
+ .id = _tmr_no, \
+ .num_resources = TIMER_RESOURCE_SIZE, \
+ .resource = TIMER_RESOURCE(_tmr_no, _irq), \
+
+/*
+ * since we already have an static mapping for the timer,
+ * we do not bother setting any IO resource for the base.
+ */
+
+struct platform_device s3c_device_timer[] = {
+ [0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },
+ [1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },
+ [2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },
+ [3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },
+ [4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },
+};
+#endif /* CONFIG_SAMSUNG_DEV_PWM */
+
+/* RTC */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_rtc_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C24XX_PA_RTC, SZ_256),
+ [1] = DEFINE_RES_IRQ(IRQ_RTC),
+ [2] = DEFINE_RES_IRQ(IRQ_TICK),
+};
+
+struct platform_device s3c_device_rtc = {
+ .name = "s3c2410-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_rtc_resource),
+ .resource = s3c_rtc_resource,
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#ifdef CONFIG_S3C_DEV_RTC
+static struct resource s3c_rtc_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_RTC, SZ_256),
+ [1] = DEFINE_RES_IRQ(IRQ_RTC_ALARM),
+ [2] = DEFINE_RES_IRQ(IRQ_RTC_TIC),
+};
+
+struct platform_device s3c_device_rtc = {
+ .name = "s3c64xx-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_rtc_resource),
+ .resource = s3c_rtc_resource,
+};
+#endif /* CONFIG_S3C_DEV_RTC */
+
+/* SDI */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_sdi_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C24XX_PA_SDI, S3C24XX_SZ_SDI),
+ [1] = DEFINE_RES_IRQ(IRQ_SDI),
+};
+
+struct platform_device s3c_device_sdi = {
+ .name = "s3c2410-sdi",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_sdi_resource),
+ .resource = s3c_sdi_resource,
+};
+
+void __init s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
+{
+ s3c_set_platdata(pdata, sizeof(struct s3c24xx_mci_pdata),
+ &s3c_device_sdi);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* SPI */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_spi0_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C24XX_PA_SPI, SZ_32),
+ [1] = DEFINE_RES_IRQ(IRQ_SPI0),
+};
+
+struct platform_device s3c_device_spi0 = {
+ .name = "s3c2410-spi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s3c_spi0_resource),
+ .resource = s3c_spi0_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+
+static struct resource s3c_spi1_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C24XX_PA_SPI1, SZ_32),
+ [1] = DEFINE_RES_IRQ(IRQ_SPI1),
+};
+
+struct platform_device s3c_device_spi1 = {
+ .name = "s3c2410-spi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s3c_spi1_resource),
+ .resource = s3c_spi1_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* Touchscreen */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_ts_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C24XX_PA_ADC, S3C24XX_SZ_ADC),
+ [1] = DEFINE_RES_IRQ(IRQ_TC),
+};
+
+struct platform_device s3c_device_ts = {
+ .name = "s3c2410-ts",
+ .id = -1,
+ .dev.parent = &s3c_device_adc.dev,
+ .num_resources = ARRAY_SIZE(s3c_ts_resource),
+ .resource = s3c_ts_resource,
+};
+
+void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
+{
+ s3c_set_platdata(hard_s3c2410ts_info,
+ sizeof(struct s3c2410_ts_mach_info), &s3c_device_ts);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#ifdef CONFIG_SAMSUNG_DEV_TS
+static struct resource s3c_ts_resource[] = {
+ [0] = DEFINE_RES_MEM(SAMSUNG_PA_ADC, SZ_256),
+ [1] = DEFINE_RES_IRQ(IRQ_TC),
+};
+
+static struct s3c2410_ts_mach_info default_ts_data __initdata = {
+ .delay = 10000,
+ .presc = 49,
+ .oversampling_shift = 2,
+};
+
+struct platform_device s3c_device_ts = {
+ .name = "s3c64xx-ts",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_ts_resource),
+ .resource = s3c_ts_resource,
+};
+
+void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
+{
+ if (!pd)
+ pd = &default_ts_data;
+
+ s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info),
+ &s3c_device_ts);
+}
+#endif /* CONFIG_SAMSUNG_DEV_TS */
+
+/* TV */
+
+#ifdef CONFIG_S5P_DEV_TV
+
+static struct resource s5p_hdmi_resources[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_HDMI, SZ_1M),
+ [1] = DEFINE_RES_IRQ(IRQ_HDMI),
+};
+
+struct platform_device s5p_device_hdmi = {
+ .name = "s5p-hdmi",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_hdmi_resources),
+ .resource = s5p_hdmi_resources,
+};
+
+static struct resource s5p_sdo_resources[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_SDO, SZ_64K),
+ [1] = DEFINE_RES_IRQ(IRQ_SDO),
+};
+
+struct platform_device s5p_device_sdo = {
+ .name = "s5p-sdo",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_sdo_resources),
+ .resource = s5p_sdo_resources,
+};
+
+static struct resource s5p_mixer_resources[] = {
+ [0] = DEFINE_RES_MEM_NAMED(S5P_PA_MIXER, SZ_64K, "mxr"),
+ [1] = DEFINE_RES_MEM_NAMED(S5P_PA_VP, SZ_64K, "vp"),
+ [2] = DEFINE_RES_IRQ_NAMED(IRQ_MIXER, "irq"),
+};
+
+struct platform_device s5p_device_mixer = {
+ .name = "s5p-mixer",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_mixer_resources),
+ .resource = s5p_mixer_resources,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+#endif /* CONFIG_S5P_DEV_TV */
+
+/* USB */
+
+#ifdef CONFIG_S3C_DEV_USB_HOST
+static struct resource s3c_usb_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_USBHOST, SZ_256),
+ [1] = DEFINE_RES_IRQ(IRQ_USBH),
+};
+
+struct platform_device s3c_device_ohci = {
+ .name = "s3c2410-ohci",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_usb_resource),
+ .resource = s3c_usb_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+
+/*
+ * s3c_ohci_set_platdata - initialise OHCI device platform data
+ * @info: The platform data.
+ *
+ * This call copies the @info passed in and sets the device .platform_data
+ * field to that copy. The @info is copied so that the original can be marked
+ * __initdata.
+ */
+
+void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info)
+{
+ s3c_set_platdata(info, sizeof(struct s3c2410_hcd_info),
+ &s3c_device_ohci);
+}
+#endif /* CONFIG_S3C_DEV_USB_HOST */
+
+/* USB Device (Gadget) */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_usbgadget_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C24XX_PA_USBDEV, S3C24XX_SZ_USBDEV),
+ [1] = DEFINE_RES_IRQ(IRQ_USBD),
+};
+
+struct platform_device s3c_device_usbgadget = {
+ .name = "s3c2410-usbgadget",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_usbgadget_resource),
+ .resource = s3c_usbgadget_resource,
+};
+
+void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
+{
+ s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usbgadget);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* USB EHCI Host Controller */
+
+#ifdef CONFIG_S5P_DEV_USB_EHCI
+static struct resource s5p_ehci_resource[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_EHCI, SZ_256),
+ [1] = DEFINE_RES_IRQ(IRQ_USB_HOST),
+};
+
+struct platform_device s5p_device_ehci = {
+ .name = "s5p-ehci",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_ehci_resource),
+ .resource = s5p_ehci_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+
+void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd)
+{
+ struct s5p_ehci_platdata *npd;
+
+ npd = s3c_set_platdata(pd, sizeof(struct s5p_ehci_platdata),
+ &s5p_device_ehci);
+
+ if (!npd->phy_init)
+ npd->phy_init = s5p_usb_phy_init;
+ if (!npd->phy_exit)
+ npd->phy_exit = s5p_usb_phy_exit;
+}
+#endif /* CONFIG_S5P_DEV_USB_EHCI */
+
+/* USB HSOTG */
+
+#ifdef CONFIG_S3C_DEV_USB_HSOTG
+static struct resource s3c_usb_hsotg_resources[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_USB_HSOTG, SZ_16K),
+ [1] = DEFINE_RES_IRQ(IRQ_OTG),
+};
+
+struct platform_device s3c_device_usb_hsotg = {
+ .name = "s3c-hsotg",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_usb_hsotg_resources),
+ .resource = s3c_usb_hsotg_resources,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+#endif /* CONFIG_S3C_DEV_USB_HSOTG */
+
+/* USB High Spped 2.0 Device (Gadget) */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_hsudc_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C2416_PA_HSUDC, S3C2416_SZ_HSUDC),
+ [1] = DEFINE_RES_IRQ(IRQ_USBD),
+};
+
+struct platform_device s3c_device_usb_hsudc = {
+ .name = "s3c-hsudc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_hsudc_resource),
+ .resource = s3c_hsudc_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd)
+{
+ s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usb_hsudc);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* WDT */
+
+#ifdef CONFIG_S3C_DEV_WDT
+static struct resource s3c_wdt_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C_PA_WDT, SZ_1K),
+ [1] = DEFINE_RES_IRQ(IRQ_WDT),
+};
+
+struct platform_device s3c_device_wdt = {
+ .name = "s3c2410-wdt",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_wdt_resource),
+ .resource = s3c_wdt_resource,
+};
+#endif /* CONFIG_S3C_DEV_WDT */
diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
new file mode 100644
index 0000000..93a994a
--- /dev/null
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -0,0 +1,132 @@
+/* linux/arch/arm/plat-samsung/dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Samsung DMA Operations
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/amba/pl330.h>
+#include <linux/scatterlist.h>
+#include <linux/export.h>
+
+#include <mach/dma.h>
+
+static inline bool pl330_filter(struct dma_chan *chan, void *param)
+{
+ struct dma_pl330_peri *peri = chan->private;
+ return peri->peri_id == (unsigned)param;
+}
+
+static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
+ struct samsung_dma_info *info)
+{
+ struct dma_chan *chan;
+ dma_cap_mask_t mask;
+ struct dma_slave_config slave_config;
+
+ dma_cap_zero(mask);
+ dma_cap_set(info->cap, mask);
+
+ chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
+
+ if (info->direction == DMA_FROM_DEVICE) {
+ memset(&slave_config, 0, sizeof(struct dma_slave_config));
+ slave_config.direction = info->direction;
+ slave_config.src_addr = info->fifo;
+ slave_config.src_addr_width = info->width;
+ slave_config.src_maxburst = 1;
+ dmaengine_slave_config(chan, &slave_config);
+ } else if (info->direction == DMA_TO_DEVICE) {
+ memset(&slave_config, 0, sizeof(struct dma_slave_config));
+ slave_config.direction = info->direction;
+ slave_config.dst_addr = info->fifo;
+ slave_config.dst_addr_width = info->width;
+ slave_config.dst_maxburst = 1;
+ dmaengine_slave_config(chan, &slave_config);
+ }
+
+ return (unsigned)chan;
+}
+
+static int samsung_dmadev_release(unsigned ch,
+ struct s3c2410_dma_client *client)
+{
+ dma_release_channel((struct dma_chan *)ch);
+
+ return 0;
+}
+
+static int samsung_dmadev_prepare(unsigned ch,
+ struct samsung_dma_prep_info *info)
+{
+ struct scatterlist sg;
+ struct dma_chan *chan = (struct dma_chan *)ch;
+ struct dma_async_tx_descriptor *desc;
+
+ switch (info->cap) {
+ case DMA_SLAVE:
+ sg_init_table(&sg, 1);
+ sg_dma_len(&sg) = info->len;
+ sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)),
+ info->len, offset_in_page(info->buf));
+ sg_dma_address(&sg) = info->buf;
+
+ desc = chan->device->device_prep_slave_sg(chan,
+ &sg, 1, info->direction, DMA_PREP_INTERRUPT);
+ break;
+ case DMA_CYCLIC:
+ desc = chan->device->device_prep_dma_cyclic(chan,
+ info->buf, info->len, info->period, info->direction);
+ break;
+ default:
+ dev_err(&chan->dev->device, "unsupported format\n");
+ return -EFAULT;
+ }
+
+ if (!desc) {
+ dev_err(&chan->dev->device, "cannot prepare cyclic dma\n");
+ return -EFAULT;
+ }
+
+ desc->callback = info->fp;
+ desc->callback_param = info->fp_param;
+
+ dmaengine_submit((struct dma_async_tx_descriptor *)desc);
+
+ return 0;
+}
+
+static inline int samsung_dmadev_trigger(unsigned ch)
+{
+ dma_async_issue_pending((struct dma_chan *)ch);
+
+ return 0;
+}
+
+static inline int samsung_dmadev_flush(unsigned ch)
+{
+ return dmaengine_terminate_all((struct dma_chan *)ch);
+}
+
+struct samsung_dma_ops dmadev_ops = {
+ .request = samsung_dmadev_request,
+ .release = samsung_dmadev_release,
+ .prepare = samsung_dmadev_prepare,
+ .trigger = samsung_dmadev_trigger,
+ .started = NULL,
+ .flush = samsung_dmadev_flush,
+ .stop = samsung_dmadev_flush,
+};
+
+void *samsung_dmadev_get_ops(void)
+{
+ return &dmadev_ops;
+}
+EXPORT_SYMBOL(samsung_dmadev_get_ops);
diff --git a/arch/arm/plat-samsung/include/plat/audio-simtec.h b/arch/arm/plat-samsung/include/plat/audio-simtec.h
new file mode 100644
index 0000000..5345364
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/audio-simtec.h
@@ -0,0 +1,37 @@
+/* arch/arm/plat-samsung/include/plat/audio-simtec.h
+ *
+ * Copyright 2008 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Simtec Audio support.
+*/
+
+/**
+ * struct s3c24xx_audio_simtec_pdata - platform data for simtec audio
+ * @use_mpllin: Select codec clock from MPLLin
+ * @output_cdclk: Need to output CDCLK to the codec
+ * @have_mic: Set if we have a MIC socket
+ * @have_lout: Set if we have a LineOut socket
+ * @amp_gpio: GPIO pin to enable the AMP
+ * @amp_gain: Option GPIO to control AMP gain
+ */
+struct s3c24xx_audio_simtec_pdata {
+ unsigned int use_mpllin:1;
+ unsigned int output_cdclk:1;
+
+ unsigned int have_mic:1;
+ unsigned int have_lout:1;
+
+ int amp_gpio;
+ int amp_gain[2];
+
+ void (*startup)(void);
+};
+
+extern int simtec_audio_add(const char *codec_name, bool has_lr_routing,
+ struct s3c24xx_audio_simtec_pdata *pdata);
diff --git a/arch/arm/plat-samsung/include/plat/camport.h b/arch/arm/plat-samsung/include/plat/camport.h
new file mode 100644
index 0000000..a5708bf
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/camport.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * S5P series camera interface helper functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_SAMSUNG_CAMPORT_H_
+#define __PLAT_SAMSUNG_CAMPORT_H_ __FILE__
+
+enum s5p_camport_id {
+ S5P_CAMPORT_A,
+ S5P_CAMPORT_B,
+};
+
+/*
+ * The helper functions to configure GPIO for the camera parallel bus.
+ * The camera port can be multiplexed with any FIMC entity, even multiple
+ * FIMC entities are allowed to be attached to a single port simultaneously.
+ * These functions are to be used in the board setup code.
+ */
+int s5pv210_fimc_setup_gpio(enum s5p_camport_id id);
+int exynos4_fimc_setup_gpio(enum s5p_camport_id id);
+
+#endif /* __PLAT_SAMSUNG_CAMPORT_H */
diff --git a/arch/arm/plat-samsung/include/plat/common-smdk.h b/arch/arm/plat-samsung/include/plat/common-smdk.h
new file mode 100644
index 0000000..ba028f1
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/common-smdk.h
@@ -0,0 +1,15 @@
+/* linux/arch/arm/plat-samsung/include/plat/common-smdk.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+extern void smdk_machine_init(void);
diff --git a/arch/arm/plat-samsung/include/plat/cpu-freq-core.h b/arch/arm/plat-samsung/include/plat/cpu-freq-core.h
new file mode 100644
index 0000000..95509d8
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/cpu-freq-core.h
@@ -0,0 +1,293 @@
+/* arch/arm/plat-samsung/include/plat/cpu-freq-core.h
+ *
+ * Copyright (c) 2006-2009 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C CPU frequency scaling support - core support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <plat/cpu-freq.h>
+
+struct seq_file;
+
+#define MAX_BANKS (8)
+#define S3C2412_MAX_IO (8)
+
+/**
+ * struct s3c2410_iobank_timing - IO bank timings for S3C2410 style timings
+ * @bankcon: The cached version of settings in this structure.
+ * @tacp:
+ * @tacs: Time from address valid to nCS asserted.
+ * @tcos: Time from nCS asserted to nOE or nWE asserted.
+ * @tacc: Time that nOE or nWE is asserted.
+ * @tcoh: Time nCS is held after nOE or nWE are released.
+ * @tcah: Time address is held for after
+ * @nwait_en: Whether nWAIT is enabled for this bank.
+ *
+ * This structure represents the IO timings for a S3C2410 style IO bank
+ * used by the CPU frequency support if it needs to change the settings
+ * of the IO.
+ */
+struct s3c2410_iobank_timing {
+ unsigned long bankcon;
+ unsigned int tacp;
+ unsigned int tacs;
+ unsigned int tcos;
+ unsigned int tacc;
+ unsigned int tcoh; /* nCS hold afrer nOE/nWE */
+ unsigned int tcah; /* Address hold after nCS */
+ unsigned char nwait_en; /* nWait enabled for bank. */
+};
+
+/**
+ * struct s3c2412_iobank_timing - io timings for PL092 (S3C2412) style IO
+ * @idcy: The idle cycle time between transactions.
+ * @wstrd: nCS release to end of read cycle.
+ * @wstwr: nCS release to end of write cycle.
+ * @wstoen: nCS assertion to nOE assertion time.
+ * @wstwen: nCS assertion to nWE assertion time.
+ * @wstbrd: Burst ready delay.
+ * @smbidcyr: Register cache for smbidcyr value.
+ * @smbwstrd: Register cache for smbwstrd value.
+ * @smbwstwr: Register cache for smbwstwr value.
+ * @smbwstoen: Register cache for smbwstoen value.
+ * @smbwstwen: Register cache for smbwstwen value.
+ * @smbwstbrd: Register cache for smbwstbrd value.
+ *
+ * Timing information for a IO bank on an S3C2412 or similar system which
+ * uses a PL093 block.
+ */
+struct s3c2412_iobank_timing {
+ unsigned int idcy;
+ unsigned int wstrd;
+ unsigned int wstwr;
+ unsigned int wstoen;
+ unsigned int wstwen;
+ unsigned int wstbrd;
+
+ /* register cache */
+ unsigned char smbidcyr;
+ unsigned char smbwstrd;
+ unsigned char smbwstwr;
+ unsigned char smbwstoen;
+ unsigned char smbwstwen;
+ unsigned char smbwstbrd;
+};
+
+union s3c_iobank {
+ struct s3c2410_iobank_timing *io_2410;
+ struct s3c2412_iobank_timing *io_2412;
+};
+
+/**
+ * struct s3c_iotimings - Chip IO timings holder
+ * @bank: The timings for each IO bank.
+ */
+struct s3c_iotimings {
+ union s3c_iobank bank[MAX_BANKS];
+};
+
+/**
+ * struct s3c_plltab - PLL table information.
+ * @vals: List of PLL values.
+ * @size: Size of the PLL table @vals.
+ */
+struct s3c_plltab {
+ struct s3c_pllval *vals;
+ int size;
+};
+
+/**
+ * struct s3c_cpufreq_config - current cpu frequency configuration
+ * @freq: The current settings for the core clocks.
+ * @max: Maxium settings, derived from core, board and user settings.
+ * @pll: The PLL table entry for the current PLL settings.
+ * @divs: The divisor settings for the core clocks.
+ * @info: The current core driver information.
+ * @board: The information for the board we are running on.
+ * @lock_pll: Set if the PLL settings cannot be changed.
+ *
+ * This is for the core drivers that need to know information about
+ * the current settings and values. It should not be needed by any
+ * device drivers.
+*/
+struct s3c_cpufreq_config {
+ struct s3c_freq freq;
+ struct s3c_freq max;
+ struct cpufreq_frequency_table pll;
+ struct s3c_clkdivs divs;
+ struct s3c_cpufreq_info *info; /* for core, not drivers */
+ struct s3c_cpufreq_board *board;
+
+ unsigned int lock_pll:1;
+};
+
+/**
+ * struct s3c_cpufreq_info - Information for the CPU frequency driver.
+ * @name: The name of this implementation.
+ * @max: The maximum frequencies for the system.
+ * @latency: Transition latency to give to cpufreq.
+ * @locktime_m: The lock-time in uS for the MPLL.
+ * @locktime_u: The lock-time in uS for the UPLL.
+ * @locttime_bits: The number of bits each LOCKTIME field.
+ * @need_pll: Set if this driver needs to change the PLL values to achieve
+ * any frequency changes. This is really only need by devices like the
+ * S3C2410 where there is no or limited divider between the PLL and the
+ * ARMCLK.
+ * @resume_clocks: Update the clocks on resume.
+ * @get_iotiming: Get the current IO timing data, mainly for use at start.
+ * @set_iotiming: Update the IO timings from the cached copies calculated
+ * from the @calc_iotiming entry when changing the frequency.
+ * @calc_iotiming: Calculate and update the cached copies of the IO timings
+ * from the newly calculated frequencies.
+ * @calc_freqtable: Calculate (fill in) the given frequency table from the
+ * current frequency configuration. If the table passed in is NULL,
+ * then the return is the number of elements to be filled for allocation
+ * of the table.
+ * @set_refresh: Set the memory refresh configuration.
+ * @set_fvco: Set the PLL frequencies.
+ * @set_divs: Update the clock divisors.
+ * @calc_divs: Calculate the clock divisors.
+ */
+struct s3c_cpufreq_info {
+ const char *name;
+ struct s3c_freq max;
+
+ unsigned int latency;
+
+ unsigned int locktime_m;
+ unsigned int locktime_u;
+ unsigned char locktime_bits;
+
+ unsigned int need_pll:1;
+
+ /* driver routines */
+
+ void (*resume_clocks)(void);
+
+ int (*get_iotiming)(struct s3c_cpufreq_config *cfg,
+ struct s3c_iotimings *timings);
+
+ void (*set_iotiming)(struct s3c_cpufreq_config *cfg,
+ struct s3c_iotimings *timings);
+
+ int (*calc_iotiming)(struct s3c_cpufreq_config *cfg,
+ struct s3c_iotimings *timings);
+
+ int (*calc_freqtable)(struct s3c_cpufreq_config *cfg,
+ struct cpufreq_frequency_table *t,
+ size_t table_size);
+
+ void (*debug_io_show)(struct seq_file *seq,
+ struct s3c_cpufreq_config *cfg,
+ union s3c_iobank *iob);
+
+ void (*set_refresh)(struct s3c_cpufreq_config *cfg);
+ void (*set_fvco)(struct s3c_cpufreq_config *cfg);
+ void (*set_divs)(struct s3c_cpufreq_config *cfg);
+ int (*calc_divs)(struct s3c_cpufreq_config *cfg);
+};
+
+extern int s3c_cpufreq_register(struct s3c_cpufreq_info *info);
+
+extern int s3c_plltab_register(struct cpufreq_frequency_table *plls,
+ unsigned int plls_no);
+
+/* exports and utilities for debugfs */
+extern struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void);
+extern struct s3c_iotimings *s3c_cpufreq_getiotimings(void);
+
+#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS
+#define s3c_cpufreq_debugfs_call(x) x
+#else
+#define s3c_cpufreq_debugfs_call(x) NULL
+#endif
+
+/* Useful utility functions. */
+
+extern struct clk *s3c_cpufreq_clk_get(struct device *, const char *);
+
+/* S3C2410 and compatible exported functions */
+
+extern void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg);
+extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg);
+
+#ifdef CONFIG_S3C2410_IOTIMING
+extern void s3c2410_iotiming_debugfs(struct seq_file *seq,
+ struct s3c_cpufreq_config *cfg,
+ union s3c_iobank *iob);
+
+extern int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg,
+ struct s3c_iotimings *iot);
+
+extern int s3c2410_iotiming_get(struct s3c_cpufreq_config *cfg,
+ struct s3c_iotimings *timings);
+
+extern void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg,
+ struct s3c_iotimings *iot);
+#else
+#define s3c2410_iotiming_debugfs NULL
+#define s3c2410_iotiming_calc NULL
+#define s3c2410_iotiming_get NULL
+#define s3c2410_iotiming_set NULL
+#endif /* CONFIG_S3C2410_IOTIMING */
+
+/* S3C2412 compatible routines */
+
+#ifdef CONFIG_S3C2412_IOTIMING
+extern void s3c2412_iotiming_debugfs(struct seq_file *seq,
+ struct s3c_cpufreq_config *cfg,
+ union s3c_iobank *iob);
+
+extern int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg,
+ struct s3c_iotimings *timings);
+
+extern int s3c2412_iotiming_calc(struct s3c_cpufreq_config *cfg,
+ struct s3c_iotimings *iot);
+
+extern void s3c2412_iotiming_set(struct s3c_cpufreq_config *cfg,
+ struct s3c_iotimings *iot);
+#else
+#define s3c2412_iotiming_debugfs NULL
+#define s3c2412_iotiming_calc NULL
+#define s3c2412_iotiming_get NULL
+#define s3c2412_iotiming_set NULL
+#endif /* CONFIG_S3C2412_IOTIMING */
+
+#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUG
+#define s3c_freq_dbg(x...) printk(KERN_INFO x)
+#else
+#define s3c_freq_dbg(x...) do { if (0) printk(x); } while (0)
+#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUG */
+
+#ifdef CONFIG_CPU_FREQ_S3C24XX_IODEBUG
+#define s3c_freq_iodbg(x...) printk(KERN_INFO x)
+#else
+#define s3c_freq_iodbg(x...) do { if (0) printk(x); } while (0)
+#endif /* CONFIG_CPU_FREQ_S3C24XX_IODEBUG */
+
+static inline int s3c_cpufreq_addfreq(struct cpufreq_frequency_table *table,
+ int index, size_t table_size,
+ unsigned int freq)
+{
+ if (index < 0)
+ return index;
+
+ if (table) {
+ if (index >= table_size)
+ return -ENOMEM;
+
+ s3c_freq_dbg("%s: { %d = %u kHz }\n",
+ __func__, index, freq);
+
+ table[index].index = index;
+ table[index].frequency = freq;
+ }
+
+ return index + 1;
+}
diff --git a/arch/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h
new file mode 100644
index 0000000..4c1a363
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/dma-ops.h
@@ -0,0 +1,63 @@
+/* arch/arm/plat-samsung/include/plat/dma-ops.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Samsung DMA support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __SAMSUNG_DMA_OPS_H_
+#define __SAMSUNG_DMA_OPS_H_ __FILE__
+
+#include <linux/dmaengine.h>
+
+struct samsung_dma_prep_info {
+ enum dma_transaction_type cap;
+ enum dma_data_direction direction;
+ dma_addr_t buf;
+ unsigned long period;
+ unsigned long len;
+ void (*fp)(void *data);
+ void *fp_param;
+};
+
+struct samsung_dma_info {
+ enum dma_transaction_type cap;
+ enum dma_data_direction direction;
+ enum dma_slave_buswidth width;
+ dma_addr_t fifo;
+ struct s3c2410_dma_client *client;
+};
+
+struct samsung_dma_ops {
+ unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);
+ int (*release)(unsigned ch, struct s3c2410_dma_client *client);
+ int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);
+ int (*trigger)(unsigned ch);
+ int (*started)(unsigned ch);
+ int (*flush)(unsigned ch);
+ int (*stop)(unsigned ch);
+};
+
+extern void *samsung_dmadev_get_ops(void);
+extern void *s3c_dma_get_ops(void);
+
+static inline void *__samsung_dma_get_ops(void)
+{
+ if (samsung_dma_is_dmadev())
+ return samsung_dmadev_get_ops();
+ else
+ return s3c_dma_get_ops();
+}
+
+/*
+ * samsung_dma_get_ops
+ * get the set of samsung dma operations
+ */
+#define samsung_dma_get_ops() __samsung_dma_get_ops()
+
+#endif /* __SAMSUNG_DMA_OPS_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
new file mode 100644
index 0000000..2e55e59
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ * Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __DMA_PL330_H_
+#define __DMA_PL330_H_ __FILE__
+
+/*
+ * PL330 can assign any channel to communicate with
+ * any of the peripherals attched to the DMAC.
+ * For the sake of consistency across client drivers,
+ * We keep the channel names unchanged and only add
+ * missing peripherals are added.
+ * Order is not important since DMA PL330 API driver
+ * use these just as IDs.
+ */
+enum dma_ch {
+ DMACH_UART0_RX,
+ DMACH_UART0_TX,
+ DMACH_UART1_RX,
+ DMACH_UART1_TX,
+ DMACH_UART2_RX,
+ DMACH_UART2_TX,
+ DMACH_UART3_RX,
+ DMACH_UART3_TX,
+ DMACH_UART4_RX,
+ DMACH_UART4_TX,
+ DMACH_UART5_RX,
+ DMACH_UART5_TX,
+ DMACH_USI_RX,
+ DMACH_USI_TX,
+ DMACH_IRDA,
+ DMACH_I2S0_RX,
+ DMACH_I2S0_TX,
+ DMACH_I2S0S_TX,
+ DMACH_I2S1_RX,
+ DMACH_I2S1_TX,
+ DMACH_I2S2_RX,
+ DMACH_I2S2_TX,
+ DMACH_SPI0_RX,
+ DMACH_SPI0_TX,
+ DMACH_SPI1_RX,
+ DMACH_SPI1_TX,
+ DMACH_SPI2_RX,
+ DMACH_SPI2_TX,
+ DMACH_AC97_MICIN,
+ DMACH_AC97_PCMIN,
+ DMACH_AC97_PCMOUT,
+ DMACH_EXTERNAL,
+ DMACH_PWM,
+ DMACH_SPDIF,
+ DMACH_HSI_RX,
+ DMACH_HSI_TX,
+ DMACH_PCM0_TX,
+ DMACH_PCM0_RX,
+ DMACH_PCM1_TX,
+ DMACH_PCM1_RX,
+ DMACH_PCM2_TX,
+ DMACH_PCM2_RX,
+ DMACH_MSM_REQ3,
+ DMACH_MSM_REQ2,
+ DMACH_MSM_REQ1,
+ DMACH_MSM_REQ0,
+ DMACH_SLIMBUS0_RX,
+ DMACH_SLIMBUS0_TX,
+ DMACH_SLIMBUS0AUX_RX,
+ DMACH_SLIMBUS0AUX_TX,
+ DMACH_SLIMBUS1_RX,
+ DMACH_SLIMBUS1_TX,
+ DMACH_SLIMBUS2_RX,
+ DMACH_SLIMBUS2_TX,
+ DMACH_SLIMBUS3_RX,
+ DMACH_SLIMBUS3_TX,
+ DMACH_SLIMBUS4_RX,
+ DMACH_SLIMBUS4_TX,
+ DMACH_SLIMBUS5_RX,
+ DMACH_SLIMBUS5_TX,
+ /* END Marker, also used to denote a reserved channel */
+ DMACH_MAX,
+};
+
+struct s3c2410_dma_client {
+ char *name;
+};
+
+static inline bool samsung_dma_has_circular(void)
+{
+ return true;
+}
+
+static inline bool samsung_dma_is_dmadev(void)
+{
+ return true;
+}
+
+#include <plat/dma-ops.h>
+
+#endif /* __DMA_PL330_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/ehci.h b/arch/arm/plat-samsung/include/plat/ehci.h
new file mode 100644
index 0000000..5f28cae
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/ehci.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PLAT_SAMSUNG_EHCI_H
+#define __PLAT_SAMSUNG_EHCI_H __FILE__
+
+struct s5p_ehci_platdata {
+ int (*phy_init)(struct platform_device *pdev, int type);
+ int (*phy_exit)(struct platform_device *pdev, int type);
+};
+
+extern void s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd);
+
+#endif /* __PLAT_SAMSUNG_EHCI_H */
diff --git a/arch/arm/plat-samsung/include/plat/exynos4.h b/arch/arm/plat-samsung/include/plat/exynos4.h
new file mode 100644
index 0000000..f546e88
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/exynos4.h
@@ -0,0 +1,35 @@
+/* linux/arch/arm/plat-samsung/include/plat/exynos4.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Header file for exynos4 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Common init code for EXYNOS4 related SoCs */
+
+extern void exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void exynos4_register_clocks(void);
+extern void exynos4210_register_clocks(void);
+extern void exynos4212_register_clocks(void);
+extern void exynos4_setup_clocks(void);
+
+#ifdef CONFIG_ARCH_EXYNOS
+extern int exynos_init(void);
+extern void exynos4_init_irq(void);
+extern void exynos4_map_io(void);
+extern void exynos4_init_clocks(int xtal);
+extern struct sys_timer exynos4_timer;
+
+#define exynos4_init_uarts exynos4_common_init_uarts
+
+#else
+#define exynos4_init_clocks NULL
+#define exynos4_init_uarts NULL
+#define exynos4_map_io NULL
+#define exynos_init NULL
+#endif
diff --git a/arch/arm/plat-samsung/include/plat/fb-s3c2410.h b/arch/arm/plat-samsung/include/plat/fb-s3c2410.h
new file mode 100644
index 0000000..4e5d958
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/fb-s3c2410.h
@@ -0,0 +1,72 @@
+/* arch/arm/plat-samsung/include/plat/fb-s3c2410.h
+ *
+ * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * Inspired by pxafb.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_FB_S3C2410_H
+#define __ASM_PLAT_FB_S3C2410_H __FILE__
+
+struct s3c2410fb_hw {
+ unsigned long lcdcon1;
+ unsigned long lcdcon2;
+ unsigned long lcdcon3;
+ unsigned long lcdcon4;
+ unsigned long lcdcon5;
+};
+
+/* LCD description */
+struct s3c2410fb_display {
+ /* LCD type */
+ unsigned type;
+
+ /* Screen size */
+ unsigned short width;
+ unsigned short height;
+
+ /* Screen info */
+ unsigned short xres;
+ unsigned short yres;
+ unsigned short bpp;
+
+ unsigned pixclock; /* pixclock in picoseconds */
+ unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */
+ unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
+ unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */
+ unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */
+ unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */
+ unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */
+
+ /* lcd configuration registers */
+ unsigned long lcdcon5;
+};
+
+struct s3c2410fb_mach_info {
+
+ struct s3c2410fb_display *displays; /* attached diplays info */
+ unsigned num_displays; /* number of defined displays */
+ unsigned default_display;
+
+ /* GPIOs */
+
+ unsigned long gpcup;
+ unsigned long gpcup_mask;
+ unsigned long gpccon;
+ unsigned long gpccon_mask;
+ unsigned long gpdup;
+ unsigned long gpdup_mask;
+ unsigned long gpdcon;
+ unsigned long gpdcon_mask;
+
+ /* lpc3600 control register */
+ unsigned long lpcsel;
+};
+
+extern void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *);
+
+#endif /* __ASM_PLAT_FB_S3C2410_H */
diff --git a/arch/arm/plat-samsung/include/plat/fiq.h b/arch/arm/plat-samsung/include/plat/fiq.h
new file mode 100644
index 0000000..535d06a
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/fiq.h
@@ -0,0 +1,13 @@
+/* linux/arch/arm/plat-samsung/include/plat/fiq.h
+ *
+ * Copyright (c) 2009 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C24XX CPU FIQ support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+extern int s3c24xx_set_fiq(unsigned int irq, bool on);
diff --git a/arch/arm/plat-samsung/include/plat/gpio-fns.h b/arch/arm/plat-samsung/include/plat/gpio-fns.h
new file mode 100644
index 0000000..bab1392
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/gpio-fns.h
@@ -0,0 +1,98 @@
+/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h
+ *
+ * Copyright (c) 2003-2009 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - hardware
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __MACH_GPIO_FNS_H
+#define __MACH_GPIO_FNS_H __FILE__
+
+/* These functions are in the to-be-removed category and it is strongly
+ * encouraged not to use these in new code. They will be marked deprecated
+ * very soon.
+ *
+ * Most of the functionality can be either replaced by the gpiocfg calls
+ * for the s3c platform or by the generic GPIOlib API.
+ *
+ * As of 2.6.35-rc, these will be removed, with the few drivers using them
+ * either replaced or given a wrapper until the calls can be removed.
+*/
+
+#include <plat/gpio-cfg.h>
+
+static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
+{
+ /* 1:1 mapping between cfgpin and setcfg calls at the moment */
+ s3c_gpio_cfgpin(pin, cfg);
+}
+
+/* external functions for GPIO support
+ *
+ * These allow various different clients to access the same GPIO
+ * registers without conflicting. If your driver only owns the entire
+ * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
+*/
+
+extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
+
+/* s3c2410_gpio_getirq
+ *
+ * turn the given pin number into the corresponding IRQ number
+ *
+ * returns:
+ * < 0 = no interrupt for this pin
+ * >=0 = interrupt number for the pin
+*/
+
+extern int s3c2410_gpio_getirq(unsigned int pin);
+
+/* s3c2410_gpio_irqfilter
+ *
+ * set the irq filtering on the given pin
+ *
+ * on = 0 => disable filtering
+ * 1 => enable filtering
+ *
+ * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
+ * width of filter (0 through 63)
+ *
+ *
+*/
+
+extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+ unsigned int config);
+
+/* s3c2410_gpio_pullup
+ *
+ * This call should be replaced with s3c_gpio_setpull().
+ *
+ * As a note, there is currently no distinction between pull-up and pull-down
+ * in the s3c24xx series devices with only an on/off configuration.
+ */
+
+/* s3c2410_gpio_pullup
+ *
+ * configure the pull-up control on the given pin
+ *
+ * to = 1 => disable the pull-up
+ * 0 => enable the pull-up
+ *
+ * eg;
+ *
+ * s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
+ * s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
+*/
+
+extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
+
+extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
+
+extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
+
+#endif /* __MACH_GPIO_FNS_H */
diff --git a/arch/arm/plat-samsung/include/plat/irq.h b/arch/arm/plat-samsung/include/plat/irq.h
new file mode 100644
index 0000000..e21a89b
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/irq.h
@@ -0,0 +1,116 @@
+/* linux/arch/arm/plat-samsung/include/plat/irq.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C24XX CPU IRQ support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
+
+#define irqdbf(x...)
+#define irqdbf2(x...)
+
+#define EXTINT_OFF (IRQ_EINT4 - 4)
+
+/* these are exported for arch/arm/mach-* usage */
+extern struct irq_chip s3c_irq_level_chip;
+extern struct irq_chip s3c_irq_chip;
+
+static inline void s3c_irqsub_mask(unsigned int irqno,
+ unsigned int parentbit,
+ int subcheck)
+{
+ unsigned long mask;
+ unsigned long submask;
+
+ submask = __raw_readl(S3C2410_INTSUBMSK);
+ mask = __raw_readl(S3C2410_INTMSK);
+
+ submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
+
+ /* check to see if we need to mask the parent IRQ */
+
+ if ((submask & subcheck) == subcheck)
+ __raw_writel(mask | parentbit, S3C2410_INTMSK);
+
+ /* write back masks */
+ __raw_writel(submask, S3C2410_INTSUBMSK);
+
+}
+
+static inline void s3c_irqsub_unmask(unsigned int irqno,
+ unsigned int parentbit)
+{
+ unsigned long mask;
+ unsigned long submask;
+
+ submask = __raw_readl(S3C2410_INTSUBMSK);
+ mask = __raw_readl(S3C2410_INTMSK);
+
+ submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
+ mask &= ~parentbit;
+
+ /* write back masks */
+ __raw_writel(submask, S3C2410_INTSUBMSK);
+ __raw_writel(mask, S3C2410_INTMSK);
+}
+
+
+static inline void s3c_irqsub_maskack(unsigned int irqno,
+ unsigned int parentmask,
+ unsigned int group)
+{
+ unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
+
+ s3c_irqsub_mask(irqno, parentmask, group);
+
+ __raw_writel(bit, S3C2410_SUBSRCPND);
+
+ /* only ack parent if we've got all the irqs (seems we must
+ * ack, all and hope that the irq system retriggers ok when
+ * the interrupt goes off again)
+ */
+
+ if (1) {
+ __raw_writel(parentmask, S3C2410_SRCPND);
+ __raw_writel(parentmask, S3C2410_INTPND);
+ }
+}
+
+static inline void s3c_irqsub_ack(unsigned int irqno,
+ unsigned int parentmask,
+ unsigned int group)
+{
+ unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
+
+ __raw_writel(bit, S3C2410_SUBSRCPND);
+
+ /* only ack parent if we've got all the irqs (seems we must
+ * ack, all and hope that the irq system retriggers ok when
+ * the interrupt goes off again)
+ */
+
+ if (1) {
+ __raw_writel(parentmask, S3C2410_SRCPND);
+ __raw_writel(parentmask, S3C2410_INTPND);
+ }
+}
+
+/* exported for use in arch/arm/mach-s3c2410 */
+
+#ifdef CONFIG_PM
+extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
+#else
+#define s3c_irq_wake NULL
+#endif
+
+extern int s3c_irqext_type(struct irq_data *d, unsigned int type);
diff --git a/arch/arm/plat-samsung/include/plat/irqs.h b/arch/arm/plat-samsung/include/plat/irqs.h
new file mode 100644
index 0000000..08d1a7e
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/irqs.h
@@ -0,0 +1,80 @@
+/* linux/arch/arm/plat-samsung/include/plat/irqs.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5P Common IRQ support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_SAMSUNG_IRQS_H
+#define __PLAT_SAMSUNG_IRQS_H __FILE__
+
+/* we keep the first set of CPU IRQs out of the range of
+ * the ISA space, so that the PC104 has them to itself
+ * and we don't end up having to do horrible things to the
+ * standard ISA drivers....
+ *
+ * note, since we're using the VICs, our start must be a
+ * mulitple of 32 to allow the common code to work
+ */
+
+#define S5P_IRQ_OFFSET (32)
+
+#define S5P_IRQ(x) ((x) + S5P_IRQ_OFFSET)
+
+#define S5P_VIC0_BASE S5P_IRQ(0)
+#define S5P_VIC1_BASE S5P_IRQ(32)
+#define S5P_VIC2_BASE S5P_IRQ(64)
+#define S5P_VIC3_BASE S5P_IRQ(96)
+
+#define VIC_BASE(x) (S5P_VIC0_BASE + ((x)*32))
+
+#define IRQ_VIC0_BASE S5P_VIC0_BASE
+#define IRQ_VIC1_BASE S5P_VIC1_BASE
+#define IRQ_VIC2_BASE S5P_VIC2_BASE
+
+/* VIC based IRQs */
+
+#define S5P_IRQ_VIC0(x) (S5P_VIC0_BASE + (x))
+#define S5P_IRQ_VIC1(x) (S5P_VIC1_BASE + (x))
+#define S5P_IRQ_VIC2(x) (S5P_VIC2_BASE + (x))
+#define S5P_IRQ_VIC3(x) (S5P_VIC3_BASE + (x))
+
+#define S5P_TIMER_IRQ(x) (11 + (x))
+
+#define IRQ_TIMER0 S5P_TIMER_IRQ(0)
+#define IRQ_TIMER1 S5P_TIMER_IRQ(1)
+#define IRQ_TIMER2 S5P_TIMER_IRQ(2)
+#define IRQ_TIMER3 S5P_TIMER_IRQ(3)
+#define IRQ_TIMER4 S5P_TIMER_IRQ(4)
+
+#define IRQ_EINT(x) ((x) < 16 ? ((x) + S5P_EINT_BASE1) \
+ : ((x) - 16 + S5P_EINT_BASE2))
+
+#define EINT_OFFSET(irq) ((irq) < S5P_EINT_BASE2 ? \
+ ((irq) - S5P_EINT_BASE1) : \
+ ((irq) + 16 - S5P_EINT_BASE2))
+
+#define IRQ_EINT_BIT(x) EINT_OFFSET(x)
+
+/* Typically only a few gpio chips require gpio interrupt support.
+ To avoid memory waste irq descriptors are allocated only for
+ S5P_GPIOINT_GROUP_COUNT chips, each with total number of
+ S5P_GPIOINT_GROUP_SIZE pins/irqs. Each GPIOINT group can be assiged
+ to any gpio chip with the s5p_register_gpio_interrupt() function */
+#define S5P_GPIOINT_GROUP_COUNT 4
+#define S5P_GPIOINT_GROUP_SIZE 8
+#define S5P_GPIOINT_COUNT (S5P_GPIOINT_GROUP_COUNT * S5P_GPIOINT_GROUP_SIZE)
+
+/* IRQ types common for all s5p platforms */
+#define S5P_IRQ_TYPE_LEVEL_LOW (0x00)
+#define S5P_IRQ_TYPE_LEVEL_HIGH (0x01)
+#define S5P_IRQ_TYPE_EDGE_FALLING (0x02)
+#define S5P_IRQ_TYPE_EDGE_RISING (0x03)
+#define S5P_IRQ_TYPE_EDGE_BOTH (0x04)
+
+#endif /* __PLAT_SAMSUNG_IRQS_H */
diff --git a/arch/arm/plat-samsung/include/plat/map-s3c.h b/arch/arm/plat-samsung/include/plat/map-s3c.h
new file mode 100644
index 0000000..c0c70a8
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/map-s3c.h
@@ -0,0 +1,84 @@
+/* linux/arch/arm/plat-samsung/include/plat/map-s3c.h
+ *
+ * Copyright (c) 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_MAP_S3C_H
+#define __ASM_PLAT_MAP_S3C_H __FILE__
+
+#define S3C24XX_VA_IRQ S3C_VA_IRQ
+#define S3C24XX_VA_MEMCTRL S3C_VA_MEM
+#define S3C24XX_VA_UART S3C_VA_UART
+
+#define S3C24XX_VA_TIMER S3C_VA_TIMER
+#define S3C24XX_VA_CLKPWR S3C_VA_SYS
+#define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG
+
+#define S3C2412_VA_SSMC S3C_ADDR_CPU(0x00000000)
+#define S3C2412_VA_EBI S3C_ADDR_CPU(0x00100000)
+
+#define S3C2410_PA_UART (0x50000000)
+#define S3C24XX_PA_UART S3C2410_PA_UART
+
+#ifndef S3C_UART_OFFSET
+#define S3C_UART_OFFSET (0x400)
+#endif
+
+/*
+ * GPIO ports
+ *
+ * the calculation for the VA of this must ensure that
+ * it is the same distance apart from the UART in the
+ * phsyical address space, as the initial mapping for the IO
+ * is done as a 1:1 mapping. This puts it (currently) at
+ * 0xFA800000, which is not in the way of any current mapping
+ * by the base system.
+*/
+
+#define S3C2410_PA_GPIO (0x56000000)
+#define S3C24XX_PA_GPIO S3C2410_PA_GPIO
+
+#define S3C24XX_VA_GPIO ((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
+#define S3C64XX_VA_GPIO S3C_ADDR_CPU(0x00000000)
+
+#define S3C64XX_VA_MODEM S3C_ADDR_CPU(0x00100000)
+#define S3C64XX_VA_USB_HSPHY S3C_ADDR_CPU(0x00200000)
+
+#define S3C_VA_USB_HSPHY S3C64XX_VA_USB_HSPHY
+
+/*
+ * ISA style IO, for each machine to sort out mappings for,
+ * if it implements it. We reserve two 16M regions for ISA.
+ */
+
+#define S3C2410_ADDR(x) S3C_ADDR(x)
+
+#define S3C24XX_VA_ISA_WORD S3C2410_ADDR(0x02000000)
+#define S3C24XX_VA_ISA_BYTE S3C2410_ADDR(0x03000000)
+
+/* deal with the registers that move under the 2412/2413 */
+
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+#ifndef __ASSEMBLY__
+extern void __iomem *s3c24xx_va_gpio2;
+#endif
+#ifdef CONFIG_CPU_S3C2412_ONLY
+#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10)
+#else
+#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
+#endif
+#else
+#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
+#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
+#endif
+
+#include <plat/map-s5p.h>
+
+#endif /* __ASM_PLAT_MAP_S3C_H */
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
new file mode 100644
index 0000000..c2d7bda
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -0,0 +1,61 @@
+/* linux/arch/arm/plat-samsung/include/plat/map-s5p.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5P - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_MAP_S5P_H
+#define __ASM_PLAT_MAP_S5P_H __FILE__
+
+#define S5P_VA_CHIPID S3C_ADDR(0x02000000)
+#define S5P_VA_CMU S3C_ADDR(0x02100000)
+#define S5P_VA_PMU S3C_ADDR(0x02180000)
+#define S5P_VA_GPIO S3C_ADDR(0x02200000)
+#define S5P_VA_GPIO1 S5P_VA_GPIO
+#define S5P_VA_GPIO2 S3C_ADDR(0x02240000)
+#define S5P_VA_GPIO3 S3C_ADDR(0x02280000)
+
+#define S5P_VA_SYSRAM S3C_ADDR(0x02400000)
+#define S5P_VA_DMC0 S3C_ADDR(0x02440000)
+#define S5P_VA_DMC1 S3C_ADDR(0x02480000)
+#define S5P_VA_SROMC S3C_ADDR(0x024C0000)
+
+#define S5P_VA_SYSTIMER S3C_ADDR(0x02500000)
+#define S5P_VA_L2CC S3C_ADDR(0x02600000)
+
+#define S5P_VA_COMBINER_BASE S3C_ADDR(0x02700000)
+#define S5P_VA_COMBINER(x) (S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10)
+
+#define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000)
+#define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x))
+#define S5P_VA_SCU S5P_VA_COREPERI(0x0)
+#define S5P_VA_TWD S5P_VA_COREPERI(0x600)
+
+#define S5P_VA_GIC_CPU S3C_ADDR(0x02810000)
+#define S5P_VA_GIC_DIST S3C_ADDR(0x02820000)
+
+#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000))
+#define VA_VIC0 VA_VIC(0)
+#define VA_VIC1 VA_VIC(1)
+#define VA_VIC2 VA_VIC(2)
+#define VA_VIC3 VA_VIC(3)
+
+#define S5P_VA_UART(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
+#define S5P_VA_UART0 S5P_VA_UART(0)
+#define S5P_VA_UART1 S5P_VA_UART(1)
+#define S5P_VA_UART2 S5P_VA_UART(2)
+#define S5P_VA_UART3 S5P_VA_UART(3)
+
+#ifndef S3C_UART_OFFSET
+#define S3C_UART_OFFSET (0x400)
+#endif
+
+#include <plat/map-s3c.h>
+
+#endif /* __ASM_PLAT_MAP_S5P_H */
diff --git a/arch/arm/plat-samsung/include/plat/mci.h b/arch/arm/plat-samsung/include/plat/mci.h
new file mode 100644
index 0000000..c42d317
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/mci.h
@@ -0,0 +1,52 @@
+#ifndef _ARCH_MCI_H
+#define _ARCH_MCI_H
+
+/**
+ * struct s3c24xx_mci_pdata - sd/mmc controller platform data
+ * @no_wprotect: Set this to indicate there is no write-protect switch.
+ * @no_detect: Set this if there is no detect switch.
+ * @wprotect_invert: Invert the default sense of the write protect switch.
+ * @detect_invert: Invert the default sense of the write protect switch.
+ * @use_dma: Set to allow the use of DMA.
+ * @gpio_detect: GPIO number for the card detect line.
+ * @gpio_wprotect: GPIO number for the write protect line.
+ * @ocr_avail: The mask of the available power states, non-zero to use.
+ * @set_power: Callback to control the power mode.
+ *
+ * The @gpio_detect is used for card detection when @no_wprotect is unset,
+ * and the default sense is that 0 returned from gpio_get_value() means
+ * that a card is inserted. If @detect_invert is set, then the value from
+ * gpio_get_value() is inverted, which makes 1 mean card inserted.
+ *
+ * The driver will use @gpio_wprotect to signal whether the card is write
+ * protected if @no_wprotect is not set. A 0 returned from gpio_get_value()
+ * means the card is read/write, and 1 means read-only. The @wprotect_invert
+ * will invert the value returned from gpio_get_value().
+ *
+ * Card power is set by @ocr_availa, using MCC_VDD_ constants if it is set
+ * to a non-zero value, otherwise the default of 3.2-3.4V is used.
+ */
+struct s3c24xx_mci_pdata {
+ unsigned int no_wprotect:1;
+ unsigned int no_detect:1;
+ unsigned int wprotect_invert:1;
+ unsigned int detect_invert:1; /* set => detect active high */
+ unsigned int use_dma:1;
+
+ unsigned int gpio_detect;
+ unsigned int gpio_wprotect;
+ unsigned long ocr_avail;
+ void (*set_power)(unsigned char power_mode,
+ unsigned short vdd);
+};
+
+/**
+ * s3c24xx_mci_set_platdata - set platform data for mmc/sdi device
+ * @pdata: The platform data
+ *
+ * Copy the platform data supplied by @pdata so that this can be marked
+ * __initdata.
+ */
+extern void s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata);
+
+#endif /* _ARCH_NCI_H */
diff --git a/arch/arm/plat-samsung/include/plat/mfc.h b/arch/arm/plat-samsung/include/plat/mfc.h
new file mode 100644
index 0000000..ac13227
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/mfc.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PLAT_SAMSUNG_MFC_H
+#define __PLAT_SAMSUNG_MFC_H __FILE__
+
+/**
+ * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
+ * @rbase: base address for MFC 'right' memory interface
+ * @rsize: size of the memory reserved for MFC 'right' interface
+ * @lbase: base address for MFC 'left' memory interface
+ * @lsize: size of the memory reserved for MFC 'left' interface
+ *
+ * This function reserves system memory for both MFC device memory
+ * interfaces and registers it to respective struct device entries as
+ * coherent memory.
+ */
+void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
+ phys_addr_t lbase, unsigned int lsize);
+
+#endif /* __PLAT_SAMSUNG_MFC_H */
diff --git a/arch/arm/plat-samsung/include/plat/mipi_csis.h b/arch/arm/plat-samsung/include/plat/mipi_csis.h
new file mode 100644
index 0000000..c45b1e8
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/mipi_csis.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
+ *
+ * S5P series MIPI CSI slave device support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_SAMSUNG_MIPI_CSIS_H_
+#define __PLAT_SAMSUNG_MIPI_CSIS_H_ __FILE__
+
+struct platform_device;
+
+/**
+ * struct s5p_platform_mipi_csis - platform data for S5P MIPI-CSIS driver
+ * @clk_rate: bus clock frequency
+ * @lanes: number of data lanes used
+ * @alignment: data alignment in bits
+ * @hs_settle: HS-RX settle time
+ * @fixed_phy_vdd: false to enable external D-PHY regulator management in the
+ * driver or true in case this regulator has no enable function
+ * @phy_enable: pointer to a callback controlling D-PHY enable/reset
+ */
+struct s5p_platform_mipi_csis {
+ unsigned long clk_rate;
+ u8 lanes;
+ u8 alignment;
+ u8 hs_settle;
+ bool fixed_phy_vdd;
+ int (*phy_enable)(struct platform_device *pdev, bool on);
+};
+
+/**
+ * s5p_csis_phy_enable - global MIPI-CSI receiver D-PHY control
+ * @pdev: MIPI-CSIS platform device
+ * @on: true to enable D-PHY and deassert its reset
+ * false to disable D-PHY
+ */
+int s5p_csis_phy_enable(struct platform_device *pdev, bool on);
+
+#endif /* __PLAT_SAMSUNG_MIPI_CSIS_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/pll.h b/arch/arm/plat-samsung/include/plat/pll.h
new file mode 100644
index 0000000..357af7c
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/pll.h
@@ -0,0 +1,323 @@
+/* linux/arch/arm/plat-samsung/include/plat/pll.h
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * Samsung PLL codes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <asm/div64.h>
+
+#define S3C24XX_PLL_MDIV_MASK (0xFF)
+#define S3C24XX_PLL_PDIV_MASK (0x1F)
+#define S3C24XX_PLL_SDIV_MASK (0x3)
+#define S3C24XX_PLL_MDIV_SHIFT (12)
+#define S3C24XX_PLL_PDIV_SHIFT (4)
+#define S3C24XX_PLL_SDIV_SHIFT (0)
+
+static inline unsigned int s3c24xx_get_pll(unsigned int pllval,
+ unsigned int baseclk)
+{
+ unsigned int mdiv, pdiv, sdiv;
+ uint64_t fvco;
+
+ mdiv = (pllval >> S3C24XX_PLL_MDIV_SHIFT) & S3C24XX_PLL_MDIV_MASK;
+ pdiv = (pllval >> S3C24XX_PLL_PDIV_SHIFT) & S3C24XX_PLL_PDIV_MASK;
+ sdiv = (pllval >> S3C24XX_PLL_SDIV_SHIFT) & S3C24XX_PLL_SDIV_MASK;
+
+ fvco = (uint64_t)baseclk * (mdiv + 8);
+ do_div(fvco, (pdiv + 2) << sdiv);
+
+ return (unsigned int)fvco;
+}
+
+#define S3C2416_PLL_MDIV_MASK (0x3FF)
+#define S3C2416_PLL_PDIV_MASK (0x3F)
+#define S3C2416_PLL_SDIV_MASK (0x7)
+#define S3C2416_PLL_MDIV_SHIFT (14)
+#define S3C2416_PLL_PDIV_SHIFT (5)
+#define S3C2416_PLL_SDIV_SHIFT (0)
+
+static inline unsigned int s3c2416_get_pll(unsigned int pllval,
+ unsigned int baseclk)
+{
+ unsigned int mdiv, pdiv, sdiv;
+ uint64_t fvco;
+
+ mdiv = (pllval >> S3C2416_PLL_MDIV_SHIFT) & S3C2416_PLL_MDIV_MASK;
+ pdiv = (pllval >> S3C2416_PLL_PDIV_SHIFT) & S3C2416_PLL_PDIV_MASK;
+ sdiv = (pllval >> S3C2416_PLL_SDIV_SHIFT) & S3C2416_PLL_SDIV_MASK;
+
+ fvco = (uint64_t)baseclk * mdiv;
+ do_div(fvco, (pdiv << sdiv));
+
+ return (unsigned int)fvco;
+}
+
+#define S3C6400_PLL_MDIV_MASK (0x3FF)
+#define S3C6400_PLL_PDIV_MASK (0x3F)
+#define S3C6400_PLL_SDIV_MASK (0x7)
+#define S3C6400_PLL_MDIV_SHIFT (16)
+#define S3C6400_PLL_PDIV_SHIFT (8)
+#define S3C6400_PLL_SDIV_SHIFT (0)
+
+static inline unsigned long s3c6400_get_pll(unsigned long baseclk,
+ u32 pllcon)
+{
+ u32 mdiv, pdiv, sdiv;
+ u64 fvco = baseclk;
+
+ mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK;
+ pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK;
+ sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK;
+
+ fvco *= mdiv;
+ do_div(fvco, (pdiv << sdiv));
+
+ return (unsigned long)fvco;
+}
+
+#define PLL6553X_MDIV_MASK (0x7F)
+#define PLL6553X_PDIV_MASK (0x1F)
+#define PLL6553X_SDIV_MASK (0x3)
+#define PLL6553X_KDIV_MASK (0xFFFF)
+#define PLL6553X_MDIV_SHIFT (16)
+#define PLL6553X_PDIV_SHIFT (8)
+#define PLL6553X_SDIV_SHIFT (0)
+
+static inline unsigned long s3c_get_pll6553x(unsigned long baseclk,
+ u32 pll_con0, u32 pll_con1)
+{
+ unsigned long result;
+ u32 mdiv, pdiv, sdiv, kdiv;
+ u64 tmp;
+
+ mdiv = (pll_con0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
+ pdiv = (pll_con0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
+ sdiv = (pll_con0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
+ kdiv = pll_con1 & PLL6553X_KDIV_MASK;
+
+ /*
+ * We need to multiple baseclk by mdiv (the integer part) and kdiv
+ * which is in 2^16ths, so shift mdiv up (does not overflow) and
+ * add kdiv before multiplying. The use of tmp is to avoid any
+ * overflows before shifting bac down into result when multipling
+ * by the mdiv and kdiv pair.
+ */
+
+ tmp = baseclk;
+ tmp *= (mdiv << 16) + kdiv;
+ do_div(tmp, (pdiv << sdiv));
+ result = tmp >> 16;
+
+ return result;
+}
+
+#define PLL35XX_MDIV_MASK (0x3FF)
+#define PLL35XX_PDIV_MASK (0x3F)
+#define PLL35XX_SDIV_MASK (0x7)
+#define PLL35XX_MDIV_SHIFT (16)
+#define PLL35XX_PDIV_SHIFT (8)
+#define PLL35XX_SDIV_SHIFT (0)
+
+static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con)
+{
+ u32 mdiv, pdiv, sdiv;
+ u64 fvco = baseclk;
+
+ mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
+ pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
+ sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
+
+ fvco *= mdiv;
+ do_div(fvco, (pdiv << sdiv));
+
+ return (unsigned long)fvco;
+}
+
+#define PLL36XX_KDIV_MASK (0xFFFF)
+#define PLL36XX_MDIV_MASK (0x1FF)
+#define PLL36XX_PDIV_MASK (0x3F)
+#define PLL36XX_SDIV_MASK (0x7)
+#define PLL36XX_MDIV_SHIFT (16)
+#define PLL36XX_PDIV_SHIFT (8)
+#define PLL36XX_SDIV_SHIFT (0)
+
+static inline unsigned long s5p_get_pll36xx(unsigned long baseclk,
+ u32 pll_con0, u32 pll_con1)
+{
+ unsigned long result;
+ u32 mdiv, pdiv, sdiv, kdiv;
+ u64 tmp;
+
+ mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
+ pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
+ sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
+ kdiv = pll_con1 & PLL36XX_KDIV_MASK;
+
+ tmp = baseclk;
+
+ tmp *= (mdiv << 16) + kdiv;
+ do_div(tmp, (pdiv << sdiv));
+ result = tmp >> 16;
+
+ return result;
+}
+
+#define PLL45XX_MDIV_MASK (0x3FF)
+#define PLL45XX_PDIV_MASK (0x3F)
+#define PLL45XX_SDIV_MASK (0x7)
+#define PLL45XX_MDIV_SHIFT (16)
+#define PLL45XX_PDIV_SHIFT (8)
+#define PLL45XX_SDIV_SHIFT (0)
+
+enum pll45xx_type_t {
+ pll_4500,
+ pll_4502,
+ pll_4508
+};
+
+static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
+ enum pll45xx_type_t pll_type)
+{
+ u32 mdiv, pdiv, sdiv;
+ u64 fvco = baseclk;
+
+ mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
+ pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
+ sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
+
+ if (pll_type == pll_4508)
+ sdiv = sdiv - 1;
+
+ fvco *= mdiv;
+ do_div(fvco, (pdiv << sdiv));
+
+ return (unsigned long)fvco;
+}
+
+/* CON0 bit-fields */
+#define PLL46XX_MDIV_MASK (0x1FF)
+#define PLL46XX_PDIV_MASK (0x3F)
+#define PLL46XX_SDIV_MASK (0x7)
+#define PLL46XX_LOCKED_SHIFT (29)
+#define PLL46XX_MDIV_SHIFT (16)
+#define PLL46XX_PDIV_SHIFT (8)
+#define PLL46XX_SDIV_SHIFT (0)
+
+/* CON1 bit-fields */
+#define PLL46XX_MRR_MASK (0x1F)
+#define PLL46XX_MFR_MASK (0x3F)
+#define PLL46XX_KDIV_MASK (0xFFFF)
+#define PLL4650C_KDIV_MASK (0xFFF)
+#define PLL46XX_MRR_SHIFT (24)
+#define PLL46XX_MFR_SHIFT (16)
+#define PLL46XX_KDIV_SHIFT (0)
+
+enum pll46xx_type_t {
+ pll_4600,
+ pll_4650,
+ pll_4650c,
+};
+
+static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
+ u32 pll_con0, u32 pll_con1,
+ enum pll46xx_type_t pll_type)
+{
+ unsigned long result;
+ u32 mdiv, pdiv, sdiv, kdiv;
+ u64 tmp;
+
+ mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
+ pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
+ sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
+ kdiv = pll_con1 & PLL46XX_KDIV_MASK;
+
+ if (pll_type == pll_4650c)
+ kdiv = pll_con1 & PLL4650C_KDIV_MASK;
+ else
+ kdiv = pll_con1 & PLL46XX_KDIV_MASK;
+
+ tmp = baseclk;
+
+ if (pll_type == pll_4600) {
+ tmp *= (mdiv << 16) + kdiv;
+ do_div(tmp, (pdiv << sdiv));
+ result = tmp >> 16;
+ } else {
+ tmp *= (mdiv << 10) + kdiv;
+ do_div(tmp, (pdiv << sdiv));
+ result = tmp >> 10;
+ }
+
+ return result;
+}
+
+#define PLL90XX_MDIV_MASK (0xFF)
+#define PLL90XX_PDIV_MASK (0x3F)
+#define PLL90XX_SDIV_MASK (0x7)
+#define PLL90XX_KDIV_MASK (0xffff)
+#define PLL90XX_LOCKED_SHIFT (29)
+#define PLL90XX_MDIV_SHIFT (16)
+#define PLL90XX_PDIV_SHIFT (8)
+#define PLL90XX_SDIV_SHIFT (0)
+#define PLL90XX_KDIV_SHIFT (0)
+
+static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
+ u32 pll_con, u32 pll_conk)
+{
+ unsigned long result;
+ u32 mdiv, pdiv, sdiv, kdiv;
+ u64 tmp;
+
+ mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
+ pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
+ sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
+ kdiv = pll_conk & PLL90XX_KDIV_MASK;
+
+ /*
+ * We need to multiple baseclk by mdiv (the integer part) and kdiv
+ * which is in 2^16ths, so shift mdiv up (does not overflow) and
+ * add kdiv before multiplying. The use of tmp is to avoid any
+ * overflows before shifting bac down into result when multipling
+ * by the mdiv and kdiv pair.
+ */
+
+ tmp = baseclk;
+ tmp *= (mdiv << 16) + kdiv;
+ do_div(tmp, (pdiv << sdiv));
+ result = tmp >> 16;
+
+ return result;
+}
+
+#define PLL65XX_MDIV_MASK (0x3FF)
+#define PLL65XX_PDIV_MASK (0x3F)
+#define PLL65XX_SDIV_MASK (0x7)
+#define PLL65XX_MDIV_SHIFT (16)
+#define PLL65XX_PDIV_SHIFT (8)
+#define PLL65XX_SDIV_SHIFT (0)
+
+static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
+{
+ u32 mdiv, pdiv, sdiv;
+ u64 fvco = baseclk;
+
+ mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
+ pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
+ sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
+
+ fvco *= mdiv;
+ do_div(fvco, (pdiv << sdiv));
+
+ return (unsigned long)fvco;
+}
diff --git a/arch/arm/plat-samsung/include/plat/pwm-clock.h b/arch/arm/plat-samsung/include/plat/pwm-clock.h
new file mode 100644
index 0000000..bf6a60e
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/pwm-clock.h
@@ -0,0 +1,81 @@
+/* linux/arch/arm/plat-samsung/include/plat/pwm-clock.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * SAMSUNG - pwm clock and timer support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_PWM_CLOCK_H
+#define __ASM_PLAT_PWM_CLOCK_H __FILE__
+
+/**
+ * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
+ * @tcfg: The timer TCFG1 register bits shifted down to 0.
+ *
+ * Return true if the given configuration from TCFG1 is a TCLK instead
+ * any of the TDIV clocks.
+ */
+static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
+{
+ if (soc_is_s3c24xx())
+ return tcfg == S3C2410_TCFG1_MUX_TCLK;
+ else if (soc_is_s3c64xx() || soc_is_s5pc100())
+ return tcfg >= S3C64XX_TCFG1_MUX_TCLK;
+ else if (soc_is_s5p6440() || soc_is_s5p6450())
+ return 0;
+ else
+ return tcfg == S3C64XX_TCFG1_MUX_TCLK;
+}
+
+/**
+ * tcfg_to_divisor() - convert tcfg1 setting to a divisor
+ * @tcfg1: The tcfg1 setting, shifted down.
+ *
+ * Get the divisor value for the given tcfg1 setting. We assume the
+ * caller has already checked to see if this is not a TCLK source.
+ */
+static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
+{
+ if (soc_is_s3c24xx())
+ return 1 << (tcfg1 + 1);
+ else
+ return 1 << tcfg1;
+}
+
+/**
+ * pwm_tdiv_has_div1() - does the tdiv setting have a /1
+ *
+ * Return true if we have a /1 in the tdiv setting.
+ */
+static inline unsigned int pwm_tdiv_has_div1(void)
+{
+ if (soc_is_s3c24xx())
+ return 0;
+ else
+ return 1;
+}
+
+/**
+ * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
+ * @div: The divisor to calculate the bit information for.
+ *
+ * Turn a divisor into the necessary bit field for TCFG1.
+ */
+static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
+{
+ if (soc_is_s3c24xx())
+ return ilog2(div) - 1;
+ else
+ return ilog2(div);
+}
+#endif /* __ASM_PLAT_PWM_CLOCK_H */
diff --git a/arch/arm/plat-samsung/include/plat/regs-dma.h b/arch/arm/plat-samsung/include/plat/regs-dma.h
new file mode 100644
index 0000000..178bccb
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-dma.h
@@ -0,0 +1,151 @@
+/* arch/arm/plat-samsung/include/plat/regs-dma.h
+ *
+ * Copyright (C) 2003-2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C24XX DMA support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_REGS_DMA_H
+#define __ASM_PLAT_REGS_DMA_H __FILE__
+
+#define S3C2410_DMA_DISRC (0x00)
+#define S3C2410_DMA_DISRCC (0x04)
+#define S3C2410_DMA_DIDST (0x08)
+#define S3C2410_DMA_DIDSTC (0x0C)
+#define S3C2410_DMA_DCON (0x10)
+#define S3C2410_DMA_DSTAT (0x14)
+#define S3C2410_DMA_DCSRC (0x18)
+#define S3C2410_DMA_DCDST (0x1C)
+#define S3C2410_DMA_DMASKTRIG (0x20)
+#define S3C2412_DMA_DMAREQSEL (0x24)
+#define S3C2443_DMA_DMAREQSEL (0x24)
+
+#define S3C2410_DISRCC_INC (1 << 0)
+#define S3C2410_DISRCC_APB (1 << 1)
+
+#define S3C2410_DMASKTRIG_STOP (1 << 2)
+#define S3C2410_DMASKTRIG_ON (1 << 1)
+#define S3C2410_DMASKTRIG_SWTRIG (1 << 0)
+
+#define S3C2410_DCON_DEMAND (0 << 31)
+#define S3C2410_DCON_HANDSHAKE (1 << 31)
+#define S3C2410_DCON_SYNC_PCLK (0 << 30)
+#define S3C2410_DCON_SYNC_HCLK (1 << 30)
+
+#define S3C2410_DCON_INTREQ (1 << 29)
+
+#define S3C2410_DCON_CH0_XDREQ0 (0 << 24)
+#define S3C2410_DCON_CH0_UART0 (1 << 24)
+#define S3C2410_DCON_CH0_SDI (2 << 24)
+#define S3C2410_DCON_CH0_TIMER (3 << 24)
+#define S3C2410_DCON_CH0_USBEP1 (4 << 24)
+
+#define S3C2410_DCON_CH1_XDREQ1 (0 << 24)
+#define S3C2410_DCON_CH1_UART1 (1 << 24)
+#define S3C2410_DCON_CH1_I2SSDI (2 << 24)
+#define S3C2410_DCON_CH1_SPI (3 << 24)
+#define S3C2410_DCON_CH1_USBEP2 (4 << 24)
+
+#define S3C2410_DCON_CH2_I2SSDO (0 << 24)
+#define S3C2410_DCON_CH2_I2SSDI (1 << 24)
+#define S3C2410_DCON_CH2_SDI (2 << 24)
+#define S3C2410_DCON_CH2_TIMER (3 << 24)
+#define S3C2410_DCON_CH2_USBEP3 (4 << 24)
+
+#define S3C2410_DCON_CH3_UART2 (0 << 24)
+#define S3C2410_DCON_CH3_SDI (1 << 24)
+#define S3C2410_DCON_CH3_SPI (2 << 24)
+#define S3C2410_DCON_CH3_TIMER (3 << 24)
+#define S3C2410_DCON_CH3_USBEP4 (4 << 24)
+
+#define S3C2410_DCON_SRCSHIFT (24)
+#define S3C2410_DCON_SRCMASK (7 << 24)
+
+#define S3C2410_DCON_BYTE (0 << 20)
+#define S3C2410_DCON_HALFWORD (1 << 20)
+#define S3C2410_DCON_WORD (2 << 20)
+
+#define S3C2410_DCON_AUTORELOAD (0 << 22)
+#define S3C2410_DCON_NORELOAD (1 << 22)
+#define S3C2410_DCON_HWTRIG (1 << 23)
+
+#ifdef CONFIG_CPU_S3C2440
+
+#define S3C2440_DIDSTC_CHKINT (1 << 2)
+
+#define S3C2440_DCON_CH0_I2SSDO (5 << 24)
+#define S3C2440_DCON_CH0_PCMIN (6 << 24)
+
+#define S3C2440_DCON_CH1_PCMOUT (5 << 24)
+#define S3C2440_DCON_CH1_SDI (6 << 24)
+
+#define S3C2440_DCON_CH2_PCMIN (5 << 24)
+#define S3C2440_DCON_CH2_MICIN (6 << 24)
+
+#define S3C2440_DCON_CH3_MICIN (5 << 24)
+#define S3C2440_DCON_CH3_PCMOUT (6 << 24)
+#endif /* CONFIG_CPU_S3C2440 */
+
+#ifdef CONFIG_CPU_S3C2412
+
+#define S3C2412_DMAREQSEL_SRC(x) ((x) << 1)
+
+#define S3C2412_DMAREQSEL_HW (1)
+
+#define S3C2412_DMAREQSEL_SPI0TX S3C2412_DMAREQSEL_SRC(0)
+#define S3C2412_DMAREQSEL_SPI0RX S3C2412_DMAREQSEL_SRC(1)
+#define S3C2412_DMAREQSEL_SPI1TX S3C2412_DMAREQSEL_SRC(2)
+#define S3C2412_DMAREQSEL_SPI1RX S3C2412_DMAREQSEL_SRC(3)
+#define S3C2412_DMAREQSEL_I2STX S3C2412_DMAREQSEL_SRC(4)
+#define S3C2412_DMAREQSEL_I2SRX S3C2412_DMAREQSEL_SRC(5)
+#define S3C2412_DMAREQSEL_TIMER S3C2412_DMAREQSEL_SRC(9)
+#define S3C2412_DMAREQSEL_SDI S3C2412_DMAREQSEL_SRC(10)
+#define S3C2412_DMAREQSEL_USBEP1 S3C2412_DMAREQSEL_SRC(13)
+#define S3C2412_DMAREQSEL_USBEP2 S3C2412_DMAREQSEL_SRC(14)
+#define S3C2412_DMAREQSEL_USBEP3 S3C2412_DMAREQSEL_SRC(15)
+#define S3C2412_DMAREQSEL_USBEP4 S3C2412_DMAREQSEL_SRC(16)
+#define S3C2412_DMAREQSEL_XDREQ0 S3C2412_DMAREQSEL_SRC(17)
+#define S3C2412_DMAREQSEL_XDREQ1 S3C2412_DMAREQSEL_SRC(18)
+#define S3C2412_DMAREQSEL_UART0_0 S3C2412_DMAREQSEL_SRC(19)
+#define S3C2412_DMAREQSEL_UART0_1 S3C2412_DMAREQSEL_SRC(20)
+#define S3C2412_DMAREQSEL_UART1_0 S3C2412_DMAREQSEL_SRC(21)
+#define S3C2412_DMAREQSEL_UART1_1 S3C2412_DMAREQSEL_SRC(22)
+#define S3C2412_DMAREQSEL_UART2_0 S3C2412_DMAREQSEL_SRC(23)
+#define S3C2412_DMAREQSEL_UART2_1 S3C2412_DMAREQSEL_SRC(24)
+#endif /* CONFIG_CPU_S3C2412 */
+
+#ifdef CONFIG_CPU_S3C2443
+
+#define S3C2443_DMAREQSEL_SRC(x) ((x) << 1)
+
+#define S3C2443_DMAREQSEL_HW (1)
+
+#define S3C2443_DMAREQSEL_SPI0TX S3C2443_DMAREQSEL_SRC(0)
+#define S3C2443_DMAREQSEL_SPI0RX S3C2443_DMAREQSEL_SRC(1)
+#define S3C2443_DMAREQSEL_SPI1TX S3C2443_DMAREQSEL_SRC(2)
+#define S3C2443_DMAREQSEL_SPI1RX S3C2443_DMAREQSEL_SRC(3)
+#define S3C2443_DMAREQSEL_I2STX S3C2443_DMAREQSEL_SRC(4)
+#define S3C2443_DMAREQSEL_I2SRX S3C2443_DMAREQSEL_SRC(5)
+#define S3C2443_DMAREQSEL_TIMER S3C2443_DMAREQSEL_SRC(9)
+#define S3C2443_DMAREQSEL_SDI S3C2443_DMAREQSEL_SRC(10)
+#define S3C2443_DMAREQSEL_XDREQ0 S3C2443_DMAREQSEL_SRC(17)
+#define S3C2443_DMAREQSEL_XDREQ1 S3C2443_DMAREQSEL_SRC(18)
+#define S3C2443_DMAREQSEL_UART0_0 S3C2443_DMAREQSEL_SRC(19)
+#define S3C2443_DMAREQSEL_UART0_1 S3C2443_DMAREQSEL_SRC(20)
+#define S3C2443_DMAREQSEL_UART1_0 S3C2443_DMAREQSEL_SRC(21)
+#define S3C2443_DMAREQSEL_UART1_1 S3C2443_DMAREQSEL_SRC(22)
+#define S3C2443_DMAREQSEL_UART2_0 S3C2443_DMAREQSEL_SRC(23)
+#define S3C2443_DMAREQSEL_UART2_1 S3C2443_DMAREQSEL_SRC(24)
+#define S3C2443_DMAREQSEL_UART3_0 S3C2443_DMAREQSEL_SRC(25)
+#define S3C2443_DMAREQSEL_UART3_1 S3C2443_DMAREQSEL_SRC(26)
+#define S3C2443_DMAREQSEL_PCMOUT S3C2443_DMAREQSEL_SRC(27)
+#define S3C2443_DMAREQSEL_PCMIN S3C2443_DMAREQSEL_SRC(28)
+#define S3C2443_DMAREQSEL_MICIN S3C2443_DMAREQSEL_SRC(29)
+#endif /* CONFIG_CPU_S3C2443 */
+
+#endif /* __ASM_PLAT_REGS_DMA_H */
diff --git a/arch/arm/plat-samsung/include/plat/regs-iis.h b/arch/arm/plat-samsung/include/plat/regs-iis.h
new file mode 100644
index 0000000..a18d35e
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-iis.h
@@ -0,0 +1,70 @@
+/* arch/arm/plat-samsung/include/plat/regs-iis.h
+ *
+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
+ * http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * S3C2410 IIS register definition
+*/
+
+#ifndef __ASM_ARCH_REGS_IIS_H
+#define __ASM_ARCH_REGS_IIS_H
+
+#define S3C2410_IISCON (0x00)
+
+#define S3C2410_IISCON_LRINDEX (1 << 8)
+#define S3C2410_IISCON_TXFIFORDY (1 << 7)
+#define S3C2410_IISCON_RXFIFORDY (1 << 6)
+#define S3C2410_IISCON_TXDMAEN (1 << 5)
+#define S3C2410_IISCON_RXDMAEN (1 << 4)
+#define S3C2410_IISCON_TXIDLE (1 << 3)
+#define S3C2410_IISCON_RXIDLE (1 << 2)
+#define S3C2410_IISCON_PSCEN (1 << 1)
+#define S3C2410_IISCON_IISEN (1 << 0)
+
+#define S3C2410_IISMOD (0x04)
+
+#define S3C2440_IISMOD_MPLL (1 << 9)
+#define S3C2410_IISMOD_SLAVE (1 << 8)
+#define S3C2410_IISMOD_NOXFER (0 << 6)
+#define S3C2410_IISMOD_RXMODE (1 << 6)
+#define S3C2410_IISMOD_TXMODE (2 << 6)
+#define S3C2410_IISMOD_TXRXMODE (3 << 6)
+#define S3C2410_IISMOD_LR_LLOW (0 << 5)
+#define S3C2410_IISMOD_LR_RLOW (1 << 5)
+#define S3C2410_IISMOD_IIS (0 << 4)
+#define S3C2410_IISMOD_MSB (1 << 4)
+#define S3C2410_IISMOD_8BIT (0 << 3)
+#define S3C2410_IISMOD_16BIT (1 << 3)
+#define S3C2410_IISMOD_BITMASK (1 << 3)
+#define S3C2410_IISMOD_256FS (0 << 2)
+#define S3C2410_IISMOD_384FS (1 << 2)
+#define S3C2410_IISMOD_16FS (0 << 0)
+#define S3C2410_IISMOD_32FS (1 << 0)
+#define S3C2410_IISMOD_48FS (2 << 0)
+#define S3C2410_IISMOD_FS_MASK (3 << 0)
+
+#define S3C2410_IISPSR (0x08)
+
+#define S3C2410_IISPSR_INTMASK (31 << 5)
+#define S3C2410_IISPSR_INTSHIFT (5)
+#define S3C2410_IISPSR_EXTMASK (31 << 0)
+#define S3C2410_IISPSR_EXTSHFIT (0)
+
+#define S3C2410_IISFCON (0x0c)
+
+#define S3C2410_IISFCON_TXDMA (1 << 15)
+#define S3C2410_IISFCON_RXDMA (1 << 14)
+#define S3C2410_IISFCON_TXENABLE (1 << 13)
+#define S3C2410_IISFCON_RXENABLE (1 << 12)
+#define S3C2410_IISFCON_TXMASK (0x3f << 6)
+#define S3C2410_IISFCON_TXSHIFT (6)
+#define S3C2410_IISFCON_RXMASK (0x3f)
+#define S3C2410_IISFCON_RXSHIFT (0)
+
+#define S3C2410_IISFIFO (0x10)
+
+#endif /* __ASM_ARCH_REGS_IIS_H */
diff --git a/arch/arm/plat-samsung/include/plat/regs-spi.h b/arch/arm/plat-samsung/include/plat/regs-spi.h
new file mode 100644
index 0000000..552fe7c
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-spi.h
@@ -0,0 +1,48 @@
+/* arch/arm/plat-samsung/include/plat/regs-spi.h
+ *
+ * Copyright (c) 2004 Fetron GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * S3C2410 SPI register definition
+*/
+
+#ifndef __ASM_ARCH_REGS_SPI_H
+#define __ASM_ARCH_REGS_SPI_H
+
+#define S3C2410_SPI1 (0x20)
+#define S3C2412_SPI1 (0x100)
+
+#define S3C2410_SPCON (0x00)
+
+#define S3C2410_SPCON_SMOD_DMA (2 << 5) /* DMA mode */
+#define S3C2410_SPCON_SMOD_INT (1 << 5) /* interrupt mode */
+#define S3C2410_SPCON_SMOD_POLL (0 << 5) /* polling mode */
+#define S3C2410_SPCON_ENSCK (1 << 4) /* Enable SCK */
+#define S3C2410_SPCON_MSTR (1 << 3) /* Master:1, Slave:0 select */
+#define S3C2410_SPCON_CPOL_HIGH (1 << 2) /* Clock polarity select */
+#define S3C2410_SPCON_CPOL_LOW (0 << 2) /* Clock polarity select */
+
+#define S3C2410_SPCON_CPHA_FMTB (1 << 1) /* Clock Phase Select */
+#define S3C2410_SPCON_CPHA_FMTA (0 << 1) /* Clock Phase Select */
+
+#define S3C2410_SPSTA (0x04)
+
+#define S3C2410_SPSTA_DCOL (1 << 2) /* Data Collision Error */
+#define S3C2410_SPSTA_MULD (1 << 1) /* Multi Master Error */
+#define S3C2410_SPSTA_READY (1 << 0) /* Data Tx/Rx ready */
+#define S3C2412_SPSTA_READY_ORG (1 << 3)
+
+#define S3C2410_SPPIN (0x08)
+
+#define S3C2410_SPPIN_ENMUL (1 << 2) /* Multi Master Error detect */
+#define S3C2410_SPPIN_RESERVED (1 << 1)
+#define S3C2410_SPPIN_KEEP (1 << 0) /* Master Out keep */
+
+#define S3C2410_SPPRE (0x0C)
+#define S3C2410_SPTDAT (0x10)
+#define S3C2410_SPRDAT (0x14)
+
+#endif /* __ASM_ARCH_REGS_SPI_H */
diff --git a/arch/arm/plat-samsung/include/plat/regs-srom.h b/arch/arm/plat-samsung/include/plat/regs-srom.h
new file mode 100644
index 0000000..9b6729c
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-srom.h
@@ -0,0 +1,54 @@
+/* linux/arch/arm/plat-samsung/include/plat/regs-srom.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P SROMC register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_SAMSUNG_REGS_SROM_H
+#define __PLAT_SAMSUNG_REGS_SROM_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_SROMREG(x) (S5P_VA_SROMC + (x))
+
+#define S5P_SROM_BW S5P_SROMREG(0x0)
+#define S5P_SROM_BC0 S5P_SROMREG(0x4)
+#define S5P_SROM_BC1 S5P_SROMREG(0x8)
+#define S5P_SROM_BC2 S5P_SROMREG(0xc)
+#define S5P_SROM_BC3 S5P_SROMREG(0x10)
+#define S5P_SROM_BC4 S5P_SROMREG(0x14)
+#define S5P_SROM_BC5 S5P_SROMREG(0x18)
+
+/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */
+
+#define S5P_SROM_BW__DATAWIDTH__SHIFT 0
+#define S5P_SROM_BW__ADDRMODE__SHIFT 1
+#define S5P_SROM_BW__WAITENABLE__SHIFT 2
+#define S5P_SROM_BW__BYTEENABLE__SHIFT 3
+
+#define S5P_SROM_BW__CS_MASK 0xf
+
+#define S5P_SROM_BW__NCS0__SHIFT 0
+#define S5P_SROM_BW__NCS1__SHIFT 4
+#define S5P_SROM_BW__NCS2__SHIFT 8
+#define S5P_SROM_BW__NCS3__SHIFT 12
+#define S5P_SROM_BW__NCS4__SHIFT 16
+#define S5P_SROM_BW__NCS5__SHIFT 20
+
+/* applies to same to BCS0 - BCS3 */
+
+#define S5P_SROM_BCX__PMC__SHIFT 0
+#define S5P_SROM_BCX__TACP__SHIFT 4
+#define S5P_SROM_BCX__TCAH__SHIFT 8
+#define S5P_SROM_BCX__TCOH__SHIFT 12
+#define S5P_SROM_BCX__TACC__SHIFT 16
+#define S5P_SROM_BCX__TCOS__SHIFT 24
+#define S5P_SROM_BCX__TACS__SHIFT 28
+
+#endif /* __PLAT_SAMSUNG_REGS_SROM_H */
diff --git a/arch/arm/plat-samsung/include/plat/regs-udc.h b/arch/arm/plat-samsung/include/plat/regs-udc.h
new file mode 100644
index 0000000..4003d3d
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-udc.h
@@ -0,0 +1,151 @@
+/* arch/arm/plat-samsung/include/plat/regs-udc.h
+ *
+ * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
+ *
+ * This include file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+*/
+
+#ifndef __ASM_ARCH_REGS_UDC_H
+#define __ASM_ARCH_REGS_UDC_H
+
+#define S3C2410_USBDREG(x) (x)
+
+#define S3C2410_UDC_FUNC_ADDR_REG S3C2410_USBDREG(0x0140)
+#define S3C2410_UDC_PWR_REG S3C2410_USBDREG(0x0144)
+#define S3C2410_UDC_EP_INT_REG S3C2410_USBDREG(0x0148)
+
+#define S3C2410_UDC_USB_INT_REG S3C2410_USBDREG(0x0158)
+#define S3C2410_UDC_EP_INT_EN_REG S3C2410_USBDREG(0x015c)
+
+#define S3C2410_UDC_USB_INT_EN_REG S3C2410_USBDREG(0x016c)
+
+#define S3C2410_UDC_FRAME_NUM1_REG S3C2410_USBDREG(0x0170)
+#define S3C2410_UDC_FRAME_NUM2_REG S3C2410_USBDREG(0x0174)
+
+#define S3C2410_UDC_EP0_FIFO_REG S3C2410_USBDREG(0x01c0)
+#define S3C2410_UDC_EP1_FIFO_REG S3C2410_USBDREG(0x01c4)
+#define S3C2410_UDC_EP2_FIFO_REG S3C2410_USBDREG(0x01c8)
+#define S3C2410_UDC_EP3_FIFO_REG S3C2410_USBDREG(0x01cc)
+#define S3C2410_UDC_EP4_FIFO_REG S3C2410_USBDREG(0x01d0)
+
+#define S3C2410_UDC_EP1_DMA_CON S3C2410_USBDREG(0x0200)
+#define S3C2410_UDC_EP1_DMA_UNIT S3C2410_USBDREG(0x0204)
+#define S3C2410_UDC_EP1_DMA_FIFO S3C2410_USBDREG(0x0208)
+#define S3C2410_UDC_EP1_DMA_TTC_L S3C2410_USBDREG(0x020c)
+#define S3C2410_UDC_EP1_DMA_TTC_M S3C2410_USBDREG(0x0210)
+#define S3C2410_UDC_EP1_DMA_TTC_H S3C2410_USBDREG(0x0214)
+
+#define S3C2410_UDC_EP2_DMA_CON S3C2410_USBDREG(0x0218)
+#define S3C2410_UDC_EP2_DMA_UNIT S3C2410_USBDREG(0x021c)
+#define S3C2410_UDC_EP2_DMA_FIFO S3C2410_USBDREG(0x0220)
+#define S3C2410_UDC_EP2_DMA_TTC_L S3C2410_USBDREG(0x0224)
+#define S3C2410_UDC_EP2_DMA_TTC_M S3C2410_USBDREG(0x0228)
+#define S3C2410_UDC_EP2_DMA_TTC_H S3C2410_USBDREG(0x022c)
+
+#define S3C2410_UDC_EP3_DMA_CON S3C2410_USBDREG(0x0240)
+#define S3C2410_UDC_EP3_DMA_UNIT S3C2410_USBDREG(0x0244)
+#define S3C2410_UDC_EP3_DMA_FIFO S3C2410_USBDREG(0x0248)
+#define S3C2410_UDC_EP3_DMA_TTC_L S3C2410_USBDREG(0x024c)
+#define S3C2410_UDC_EP3_DMA_TTC_M S3C2410_USBDREG(0x0250)
+#define S3C2410_UDC_EP3_DMA_TTC_H S3C2410_USBDREG(0x0254)
+
+#define S3C2410_UDC_EP4_DMA_CON S3C2410_USBDREG(0x0258)
+#define S3C2410_UDC_EP4_DMA_UNIT S3C2410_USBDREG(0x025c)
+#define S3C2410_UDC_EP4_DMA_FIFO S3C2410_USBDREG(0x0260)
+#define S3C2410_UDC_EP4_DMA_TTC_L S3C2410_USBDREG(0x0264)
+#define S3C2410_UDC_EP4_DMA_TTC_M S3C2410_USBDREG(0x0268)
+#define S3C2410_UDC_EP4_DMA_TTC_H S3C2410_USBDREG(0x026c)
+
+#define S3C2410_UDC_INDEX_REG S3C2410_USBDREG(0x0178)
+
+/* indexed registers */
+
+#define S3C2410_UDC_MAXP_REG S3C2410_USBDREG(0x0180)
+
+#define S3C2410_UDC_EP0_CSR_REG S3C2410_USBDREG(0x0184)
+
+#define S3C2410_UDC_IN_CSR1_REG S3C2410_USBDREG(0x0184)
+#define S3C2410_UDC_IN_CSR2_REG S3C2410_USBDREG(0x0188)
+
+#define S3C2410_UDC_OUT_CSR1_REG S3C2410_USBDREG(0x0190)
+#define S3C2410_UDC_OUT_CSR2_REG S3C2410_USBDREG(0x0194)
+#define S3C2410_UDC_OUT_FIFO_CNT1_REG S3C2410_USBDREG(0x0198)
+#define S3C2410_UDC_OUT_FIFO_CNT2_REG S3C2410_USBDREG(0x019c)
+
+#define S3C2410_UDC_FUNCADDR_UPDATE (1 << 7)
+
+#define S3C2410_UDC_PWR_ISOUP (1 << 7) /* R/W */
+#define S3C2410_UDC_PWR_RESET (1 << 3) /* R */
+#define S3C2410_UDC_PWR_RESUME (1 << 2) /* R/W */
+#define S3C2410_UDC_PWR_SUSPEND (1 << 1) /* R */
+#define S3C2410_UDC_PWR_ENSUSPEND (1 << 0) /* R/W */
+
+#define S3C2410_UDC_PWR_DEFAULT (0x00)
+
+#define S3C2410_UDC_INT_EP4 (1 << 4) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP3 (1 << 3) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP2 (1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP1 (1 << 1) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP0 (1 << 0) /* R/W (clear only) */
+
+#define S3C2410_UDC_USBINT_RESET (1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_USBINT_RESUME (1 << 1) /* R/W (clear only) */
+#define S3C2410_UDC_USBINT_SUSPEND (1 << 0) /* R/W (clear only) */
+
+#define S3C2410_UDC_INTE_EP4 (1 << 4) /* R/W */
+#define S3C2410_UDC_INTE_EP3 (1 << 3) /* R/W */
+#define S3C2410_UDC_INTE_EP2 (1 << 2) /* R/W */
+#define S3C2410_UDC_INTE_EP1 (1 << 1) /* R/W */
+#define S3C2410_UDC_INTE_EP0 (1 << 0) /* R/W */
+
+#define S3C2410_UDC_USBINTE_RESET (1 << 2) /* R/W */
+#define S3C2410_UDC_USBINTE_SUSPEND (1 << 0) /* R/W */
+
+#define S3C2410_UDC_INDEX_EP0 (0x00)
+#define S3C2410_UDC_INDEX_EP1 (0x01)
+#define S3C2410_UDC_INDEX_EP2 (0x02)
+#define S3C2410_UDC_INDEX_EP3 (0x03)
+#define S3C2410_UDC_INDEX_EP4 (0x04)
+
+#define S3C2410_UDC_ICSR1_CLRDT (1 << 6) /* R/W */
+#define S3C2410_UDC_ICSR1_SENTSTL (1 << 5) /* R/W (clear only) */
+#define S3C2410_UDC_ICSR1_SENDSTL (1 << 4) /* R/W */
+#define S3C2410_UDC_ICSR1_FFLUSH (1 << 3) /* W (set only) */
+#define S3C2410_UDC_ICSR1_UNDRUN (1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_ICSR1_PKTRDY (1 << 0) /* R/W (set only) */
+
+#define S3C2410_UDC_ICSR2_AUTOSET (1 << 7) /* R/W */
+#define S3C2410_UDC_ICSR2_ISO (1 << 6) /* R/W */
+#define S3C2410_UDC_ICSR2_MODEIN (1 << 5) /* R/W */
+#define S3C2410_UDC_ICSR2_DMAIEN (1 << 4) /* R/W */
+
+#define S3C2410_UDC_OCSR1_CLRDT (1 << 7) /* R/W */
+#define S3C2410_UDC_OCSR1_SENTSTL (1 << 6) /* R/W (clear only) */
+#define S3C2410_UDC_OCSR1_SENDSTL (1 << 5) /* R/W */
+#define S3C2410_UDC_OCSR1_FFLUSH (1 << 4) /* R/W */
+#define S3C2410_UDC_OCSR1_DERROR (1 << 3) /* R */
+#define S3C2410_UDC_OCSR1_OVRRUN (1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_OCSR1_PKTRDY (1 << 0) /* R/W (clear only) */
+
+#define S3C2410_UDC_OCSR2_AUTOCLR (1 << 7) /* R/W */
+#define S3C2410_UDC_OCSR2_ISO (1 << 6) /* R/W */
+#define S3C2410_UDC_OCSR2_DMAIEN (1 << 5) /* R/W */
+
+#define S3C2410_UDC_EP0_CSR_OPKRDY (1 << 0)
+#define S3C2410_UDC_EP0_CSR_IPKRDY (1 << 1)
+#define S3C2410_UDC_EP0_CSR_SENTSTL (1 << 2)
+#define S3C2410_UDC_EP0_CSR_DE (1 << 3)
+#define S3C2410_UDC_EP0_CSR_SE (1 << 4)
+#define S3C2410_UDC_EP0_CSR_SENDSTL (1 << 5)
+#define S3C2410_UDC_EP0_CSR_SOPKTRDY (1 << 6)
+#define S3C2410_UDC_EP0_CSR_SSE (1 << 7)
+
+#define S3C2410_UDC_MAXP_8 (1 << 0)
+#define S3C2410_UDC_MAXP_16 (1 << 1)
+#define S3C2410_UDC_MAXP_32 (1 << 2)
+#define S3C2410_UDC_MAXP_64 (1 << 3)
+
+#endif
diff --git a/arch/arm/plat-samsung/include/plat/reset.h b/arch/arm/plat-samsung/include/plat/reset.h
new file mode 100644
index 0000000..32ca517
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/reset.h
@@ -0,0 +1,16 @@
+/* linux/arch/arm/plat-samsung/include/plat/reset.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_SAMSUNG_RESET_H
+#define __PLAT_SAMSUNG_RESET_H __FILE__
+
+extern void (*s5p_reset_hook)(void);
+
+#endif /* __PLAT_SAMSUNG_RESET_H */
diff --git a/arch/arm/plat-samsung/include/plat/s3c2410.h b/arch/arm/plat-samsung/include/plat/s3c2410.h
new file mode 100644
index 0000000..3986497
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s3c2410.h
@@ -0,0 +1,33 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c2410.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2410 machine directory
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#ifdef CONFIG_CPU_S3C2410
+
+extern int s3c2410_init(void);
+extern int s3c2410a_init(void);
+
+extern void s3c2410_map_io(void);
+
+extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2410_init_clocks(int xtal);
+
+#else
+#define s3c2410_init_clocks NULL
+#define s3c2410_init_uarts NULL
+#define s3c2410_map_io NULL
+#define s3c2410_init NULL
+#define s3c2410a_init NULL
+#endif
+
+extern int s3c2410_baseclk_add(void);
diff --git a/arch/arm/plat-samsung/include/plat/s3c2412.h b/arch/arm/plat-samsung/include/plat/s3c2412.h
new file mode 100644
index 0000000..5bcfd14
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s3c2412.h
@@ -0,0 +1,29 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c2412.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2412 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C2412
+
+extern int s3c2412_init(void);
+
+extern void s3c2412_map_io(void);
+
+extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2412_init_clocks(int xtal);
+
+extern int s3c2412_baseclk_add(void);
+#else
+#define s3c2412_init_clocks NULL
+#define s3c2412_init_uarts NULL
+#define s3c2412_map_io NULL
+#define s3c2412_init NULL
+#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c2416.h b/arch/arm/plat-samsung/include/plat/s3c2416.h
new file mode 100644
index 0000000..a764f85
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s3c2416.h
@@ -0,0 +1,31 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c2416.h
+ *
+ * Copyright (c) 2009 Yauhen Kharuzhy <jekhor@gmail.com>
+ *
+ * Header file for s3c2416 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C2416
+
+struct s3c2410_uartcfg;
+
+extern int s3c2416_init(void);
+
+extern void s3c2416_map_io(void);
+
+extern void s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2416_init_clocks(int xtal);
+
+extern int s3c2416_baseclk_add(void);
+
+#else
+#define s3c2416_init_clocks NULL
+#define s3c2416_init_uarts NULL
+#define s3c2416_map_io NULL
+#define s3c2416_init NULL
+#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c2443.h b/arch/arm/plat-samsung/include/plat/s3c2443.h
new file mode 100644
index 0000000..7fae1a0
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s3c2443.h
@@ -0,0 +1,52 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c2443.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2443 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C2443
+
+struct s3c2410_uartcfg;
+
+extern int s3c2443_init(void);
+
+extern void s3c2443_map_io(void);
+
+extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2443_init_clocks(int xtal);
+
+extern int s3c2443_baseclk_add(void);
+
+#else
+#define s3c2443_init_clocks NULL
+#define s3c2443_init_uarts NULL
+#define s3c2443_map_io NULL
+#define s3c2443_init NULL
+#endif
+
+/* common code used by s3c2443 and others.
+ * note, not to be used outside of arch/arm/mach-s3c* */
+
+struct clk; /* some files don't need clk.h otherwise */
+
+typedef unsigned int (*pll_fn)(unsigned int reg, unsigned int base);
+
+extern void s3c2443_common_setup_clocks(pll_fn get_mpll);
+extern void s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
+ unsigned int *divs, int nr_divs,
+ int divmask);
+
+extern int s3c2443_clkcon_enable_h(struct clk *clk, int enable);
+extern int s3c2443_clkcon_enable_p(struct clk *clk, int enable);
+extern int s3c2443_clkcon_enable_s(struct clk *clk, int enable);
+
+extern struct clksrc_clk clk_epllref;
+extern struct clksrc_clk clk_esysclk;
+extern struct clksrc_clk clk_msysclk;
diff --git a/arch/arm/plat-samsung/include/plat/s3c244x.h b/arch/arm/plat-samsung/include/plat/s3c244x.h
new file mode 100644
index 0000000..ea0c961
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s3c244x.h
@@ -0,0 +1,42 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c244x.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C2440 and S3C2442 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
+
+extern void s3c244x_map_io(void);
+
+extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c244x_init_clocks(int xtal);
+
+#else
+#define s3c244x_init_clocks NULL
+#define s3c244x_init_uarts NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2440
+extern int s3c2440_init(void);
+
+extern void s3c2440_map_io(void);
+#else
+#define s3c2440_init NULL
+#define s3c2440_map_io NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2442
+extern int s3c2442_init(void);
+
+extern void s3c2442_map_io(void);
+#else
+#define s3c2442_init NULL
+#define s3c2442_map_io NULL
+#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c6400.h b/arch/arm/plat-samsung/include/plat/s3c6400.h
new file mode 100644
index 0000000..37d428a
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s3c6400.h
@@ -0,0 +1,36 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c6400.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * Header file for s3c6400 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Common init code for S3C6400 related SoCs */
+
+extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s3c6400_setup_clocks(void);
+
+extern void s3c64xx_register_clocks(unsigned long xtal, unsigned armclk_limit);
+
+#ifdef CONFIG_CPU_S3C6400
+
+extern int s3c6400_init(void);
+extern void s3c6400_init_irq(void);
+extern void s3c6400_map_io(void);
+extern void s3c6400_init_clocks(int xtal);
+
+#define s3c6400_init_uarts s3c6400_common_init_uarts
+
+#else
+#define s3c6400_init_clocks NULL
+#define s3c6400_init_uarts NULL
+#define s3c6400_map_io NULL
+#define s3c6400_init NULL
+#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c6410.h b/arch/arm/plat-samsung/include/plat/s3c6410.h
new file mode 100644
index 0000000..20a6675
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s3c6410.h
@@ -0,0 +1,29 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c6410.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * Header file for s3c6410 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C6410
+
+extern int s3c6410_init(void);
+extern void s3c6410_init_irq(void);
+extern void s3c6410_map_io(void);
+extern void s3c6410_init_clocks(int xtal);
+
+#define s3c6410_init_uarts s3c6400_common_init_uarts
+
+#else
+#define s3c6410_init_clocks NULL
+#define s3c6410_init_uarts NULL
+#define s3c6410_map_io NULL
+#define s3c6410_init NULL
+#endif
diff --git a/arch/arm/plat-samsung/include/plat/s5p-clock.h b/arch/arm/plat-samsung/include/plat/s5p-clock.h
new file mode 100644
index 0000000..984bf9e
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s5p-clock.h
@@ -0,0 +1,55 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5p-clock.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Header file for s5p clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_S5P_CLOCK_H
+#define __ASM_PLAT_S5P_CLOCK_H __FILE__
+
+#include <linux/clk.h>
+
+#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
+
+#define clk_fin_apll clk_ext_xtal_mux
+#define clk_fin_mpll clk_ext_xtal_mux
+#define clk_fin_epll clk_ext_xtal_mux
+#define clk_fin_dpll clk_ext_xtal_mux
+#define clk_fin_vpll clk_ext_xtal_mux
+#define clk_fin_hpll clk_ext_xtal_mux
+
+extern struct clk clk_ext_xtal_mux;
+extern struct clk clk_xusbxti;
+extern struct clk clk_48m;
+extern struct clk s5p_clk_27m;
+extern struct clk clk_fout_apll;
+extern struct clk clk_fout_mpll;
+extern struct clk clk_fout_epll;
+extern struct clk clk_fout_dpll;
+extern struct clk clk_fout_vpll;
+extern struct clk clk_arm;
+extern struct clk clk_vpll;
+
+extern struct clksrc_sources clk_src_apll;
+extern struct clksrc_sources clk_src_mpll;
+extern struct clksrc_sources clk_src_epll;
+extern struct clksrc_sources clk_src_dpll;
+
+extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
+
+/* Common EPLL operations for S5P platform */
+extern int s5p_epll_enable(struct clk *clk, int enable);
+extern unsigned long s5p_epll_get_rate(struct clk *clk);
+
+/* SPDIF clk operations common for S5PC100/V210/C110 and Exynos4 */
+extern int s5p_spdif_set_rate(struct clk *clk, unsigned long rate);
+extern unsigned long s5p_spdif_get_rate(struct clk *clk);
+
+extern struct clk_ops s5p_sclk_spdif_ops;
+#endif /* __ASM_PLAT_S5P_CLOCK_H */
diff --git a/arch/arm/plat-samsung/include/plat/s5p-time.h b/arch/arm/plat-samsung/include/plat/s5p-time.h
new file mode 100644
index 0000000..3a70aeb
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s5p-time.h
@@ -0,0 +1,40 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5p-time.h
+ *
+ * Copyright 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for s5p time support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_S5P_TIME_H
+#define __ASM_PLAT_S5P_TIME_H __FILE__
+
+/* S5P HR-Timer Clock mode */
+enum s5p_timer_mode {
+ S5P_PWM0,
+ S5P_PWM1,
+ S5P_PWM2,
+ S5P_PWM3,
+ S5P_PWM4,
+};
+
+struct s5p_timer_source {
+ unsigned int event_id;
+ unsigned int source_id;
+};
+
+/* Be able to sleep for atleast 4 seconds (usually more) */
+#define S5PTIMER_MIN_RANGE 4
+
+#define TCNT_MAX 0xffffffff
+#define NON_PERIODIC 0
+#define PERIODIC 1
+
+extern void __init s5p_set_timer_source(enum s5p_timer_mode event,
+ enum s5p_timer_mode source);
+extern struct sys_timer s5p_timer;
+#endif /* __ASM_PLAT_S5P_TIME_H */
diff --git a/arch/arm/plat-samsung/include/plat/s5p6440.h b/arch/arm/plat-samsung/include/plat/s5p6440.h
new file mode 100644
index 0000000..bf85ebb
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s5p6440.h
@@ -0,0 +1,36 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5p6440.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for s5p6440 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+ /* Common init code for S5P6440 related SoCs */
+
+extern void s5p6440_register_clocks(void);
+extern void s5p6440_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5P6440
+
+extern int s5p64x0_init(void);
+extern void s5p6440_init_irq(void);
+extern void s5p6440_map_io(void);
+extern void s5p6440_init_clocks(int xtal);
+
+extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+#else
+#define s5p6440_init_clocks NULL
+#define s5p6440_init_uarts NULL
+#define s5p6440_map_io NULL
+#define s5p64x0_init NULL
+#endif
+
+/* S5P6440 timer */
+
+extern struct sys_timer s5p6440_timer;
diff --git a/arch/arm/plat-samsung/include/plat/s5p6450.h b/arch/arm/plat-samsung/include/plat/s5p6450.h
new file mode 100644
index 0000000..da25f9a
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s5p6450.h
@@ -0,0 +1,36 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5p6450.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Header file for s5p6450 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Common init code for S5P6450 related SoCs */
+
+extern void s5p6450_register_clocks(void);
+extern void s5p6450_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5P6450
+
+extern int s5p64x0_init(void);
+extern void s5p6450_init_irq(void);
+extern void s5p6450_map_io(void);
+extern void s5p6450_init_clocks(int xtal);
+
+extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+#else
+#define s5p6450_init_clocks NULL
+#define s5p6450_init_uarts NULL
+#define s5p6450_map_io NULL
+#define s5p64x0_init NULL
+#endif
+
+/* S5P6450 timer */
+
+extern struct sys_timer s5p6450_timer;
diff --git a/arch/arm/plat-samsung/include/plat/s5pc100.h b/arch/arm/plat-samsung/include/plat/s5pc100.h
new file mode 100644
index 0000000..9a21aea
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s5pc100.h
@@ -0,0 +1,33 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5pc100.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for s5pc100 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Common init code for S5PC100 related SoCs */
+
+extern void s5pc100_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s5pc100_register_clocks(void);
+extern void s5pc100_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5PC100
+
+extern int s5pc100_init(void);
+extern void s5pc100_init_irq(void);
+extern void s5pc100_map_io(void);
+extern void s5pc100_init_clocks(int xtal);
+
+#define s5pc100_init_uarts s5pc100_common_init_uarts
+
+#else
+#define s5pc100_init_clocks NULL
+#define s5pc100_init_uarts NULL
+#define s5pc100_map_io NULL
+#define s5pc100_init NULL
+#endif
diff --git a/arch/arm/plat-samsung/include/plat/s5pv210.h b/arch/arm/plat-samsung/include/plat/s5pv210.h
new file mode 100644
index 0000000..b4bc6be7
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s5pv210.h
@@ -0,0 +1,33 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5pv210.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for s5pv210 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Common init code for S5PV210 related SoCs */
+
+extern void s5pv210_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s5pv210_register_clocks(void);
+extern void s5pv210_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5PV210
+
+extern int s5pv210_init(void);
+extern void s5pv210_init_irq(void);
+extern void s5pv210_map_io(void);
+extern void s5pv210_init_clocks(int xtal);
+
+#define s5pv210_init_uarts s5pv210_common_init_uarts
+
+#else
+#define s5pv210_init_clocks NULL
+#define s5pv210_init_uarts NULL
+#define s5pv210_map_io NULL
+#define s5pv210_init NULL
+#endif
diff --git a/arch/arm/plat-samsung/include/plat/system-reset.h b/arch/arm/plat-samsung/include/plat/system-reset.h
new file mode 100644
index 0000000..a448e99
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/system-reset.h
@@ -0,0 +1,31 @@
+/* linux/arch/arm/plat-samsung/include/plat/system-reset.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Based on arch/arm/mach-s3c2410/include/mach/system-reset.h
+ *
+ * S5P - System define for arch_reset()
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <plat/watchdog-reset.h>
+
+void (*s5p_reset_hook)(void);
+
+static void arch_reset(char mode, const char *cmd)
+{
+ /* SWRESET support in s5p_reset_hook() */
+
+ if (s5p_reset_hook)
+ s5p_reset_hook();
+
+ /* Perform reset using Watchdog reset
+ * if there is no s5p_reset_hook()
+ */
+
+ arch_wdt_reset();
+}
diff --git a/arch/arm/plat-samsung/include/plat/udc.h b/arch/arm/plat-samsung/include/plat/udc.h
new file mode 100644
index 0000000..8c22d58
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/udc.h
@@ -0,0 +1,57 @@
+/* arch/arm/plat-samsung/include/plat/udc.h
+ *
+ * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ * Changelog:
+ * 14-Mar-2005 RTP Created file
+ * 02-Aug-2005 RTP File rename
+ * 07-Sep-2005 BJD Minor cleanups, changed cmd to enum
+ * 18-Jan-2007 HMW Add per-platform vbus_draw function
+*/
+
+#ifndef __ASM_ARM_ARCH_UDC_H
+#define __ASM_ARM_ARCH_UDC_H
+
+enum s3c2410_udc_cmd_e {
+ S3C2410_UDC_P_ENABLE = 1, /* Pull-up enable */
+ S3C2410_UDC_P_DISABLE = 2, /* Pull-up disable */
+ S3C2410_UDC_P_RESET = 3, /* UDC reset, in case of */
+};
+
+struct s3c2410_udc_mach_info {
+ void (*udc_command)(enum s3c2410_udc_cmd_e);
+ void (*vbus_draw)(unsigned int ma);
+
+ unsigned int pullup_pin;
+ unsigned int pullup_pin_inverted;
+
+ unsigned int vbus_pin;
+ unsigned char vbus_pin_inverted;
+};
+
+extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
+
+/**
+ * s3c24xx_hsudc_platdata - Platform data for USB High-Speed gadget controller.
+ * @epnum: Number of endpoints to be instantiated by the controller driver.
+ * @gpio_init: Platform specific USB related GPIO initialization.
+ * @gpio_uninit: Platform specific USB releted GPIO uninitialzation.
+ *
+ * Representation of platform data for the S3C24XX USB 2.0 High Speed gadget
+ * controllers.
+ */
+struct s3c24xx_hsudc_platdata {
+ unsigned int epnum;
+ void (*gpio_init)(void);
+ void (*gpio_uninit)(void);
+};
+
+extern void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd);
+
+#endif /* __ASM_ARM_ARCH_UDC_H */
diff --git a/arch/arm/plat-samsung/include/plat/usb-phy.h b/arch/arm/plat-samsung/include/plat/usb-phy.h
new file mode 100644
index 0000000..959bcdb
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/usb-phy.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PLAT_SAMSUNG_USB_PHY_H
+#define __PLAT_SAMSUNG_USB_PHY_H __FILE__
+
+enum s5p_usb_phy_type {
+ S5P_USB_PHY_DEVICE,
+ S5P_USB_PHY_HOST,
+};
+
+extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
+extern int s5p_usb_phy_exit(struct platform_device *pdev, int type);
+
+#endif /* __PLAT_SAMSUNG_USB_PHY_H */
diff --git a/arch/arm/plat-samsung/s3c-dma-ops.c b/arch/arm/plat-samsung/s3c-dma-ops.c
new file mode 100644
index 0000000..7814949
--- /dev/null
+++ b/arch/arm/plat-samsung/s3c-dma-ops.c
@@ -0,0 +1,131 @@
+/* linux/arch/arm/plat-samsung/s3c-dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Samsung S3C-DMA Operations
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/export.h>
+
+#include <mach/dma.h>
+
+struct cb_data {
+ void (*fp) (void *);
+ void *fp_param;
+ unsigned ch;
+ struct list_head node;
+};
+
+static LIST_HEAD(dma_list);
+
+static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
+ int size, enum s3c2410_dma_buffresult res)
+{
+ struct cb_data *data = param;
+
+ data->fp(data->fp_param);
+}
+
+static unsigned s3c_dma_request(enum dma_ch dma_ch,
+ struct samsung_dma_info *info)
+{
+ struct cb_data *data;
+
+ if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {
+ s3c2410_dma_free(dma_ch, info->client);
+ return 0;
+ }
+
+ data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
+ data->ch = dma_ch;
+ list_add_tail(&data->node, &dma_list);
+
+ s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
+
+ if (info->cap == DMA_CYCLIC)
+ s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
+
+ s3c2410_dma_config(dma_ch, info->width);
+
+ return (unsigned)dma_ch;
+}
+
+static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
+{
+ struct cb_data *data;
+
+ list_for_each_entry(data, &dma_list, node)
+ if (data->ch == ch)
+ break;
+ list_del(&data->node);
+
+ s3c2410_dma_free(ch, client);
+ kfree(data);
+
+ return 0;
+}
+
+static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
+{
+ struct cb_data *data;
+ int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;
+
+ list_for_each_entry(data, &dma_list, node)
+ if (data->ch == ch)
+ break;
+
+ if (!data->fp) {
+ s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
+ data->fp = info->fp;
+ data->fp_param = info->fp_param;
+ }
+
+ s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);
+
+ return 0;
+}
+
+static inline int s3c_dma_trigger(unsigned ch)
+{
+ return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
+}
+
+static inline int s3c_dma_started(unsigned ch)
+{
+ return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
+}
+
+static inline int s3c_dma_flush(unsigned ch)
+{
+ return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
+}
+
+static inline int s3c_dma_stop(unsigned ch)
+{
+ return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
+}
+
+static struct samsung_dma_ops s3c_dma_ops = {
+ .request = s3c_dma_request,
+ .release = s3c_dma_release,
+ .prepare = s3c_dma_prepare,
+ .trigger = s3c_dma_trigger,
+ .started = s3c_dma_started,
+ .flush = s3c_dma_flush,
+ .stop = s3c_dma_stop,
+};
+
+void *s3c_dma_get_ops(void)
+{
+ return &s3c_dma_ops;
+}
+EXPORT_SYMBOL(s3c_dma_get_ops);